iOS OpenGL 2D旋转图像(不是屏幕)

时间:2012-06-29 18:52:10

标签: ios image opengl-es screen rotation

我有以下代码(例如,我正在构建不是游戏,我正在尝试通过OpenGL ES构建KNOB控件,Quartz2D不适合,不要问为什么):

此处的原始代码:
http://www.raywenderlich.com/9743/how-to-create-a-simple-2d-iphone-game-with-opengl-es-2-0-and-glkit-part-1

在屏幕上对图像进行代码绘制,将来我将用我的KNOB替换这些图像:
screenshot

基本上我有兴趣只旋转玩家(左侧区域的男人)。 我希望他从0度到360度连续旋转。我尝试了以下代码,但是......

    self.effect.transform.modelviewMatrix = GLKMatrix4Rotate(self.effect.transform.modelviewMatrix, radians(10), 0, 0, -1);

我全屏旋转(也有怪物),但我想只旋转一个物体(在这个例子中只有左侧区域的玩家)。还要注意怪物正在移动。

函数代码[sprite render];见下文。

这是主要代码:

    //
//  SGGViewController.m
//  SimpleGLKitGame
//
//  Created by Ray Wenderlich on 1/30/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "SGGViewController.h"
#import "SGGSprite.h"

@interface SGGViewController ()
@property (strong, nonatomic) EAGLContext *context;
@property (strong) GLKBaseEffect * effect;
@property (strong) SGGSprite * player;
@property (strong) NSMutableArray * children;
@property (assign) float timeSinceLastSpawn;
@end

@implementation SGGViewController
@synthesize effect = _effect;
@synthesize context = _context;
@synthesize player = _player;
@synthesize children = _children;
@synthesize timeSinceLastSpawn = _timeSinceLastSpawn;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];


    if (!self.context) {
        NSLog(@"Failed to create ES context");
    }

    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    [EAGLContext setCurrentContext:self.context];

    self.effect = [[GLKBaseEffect alloc] init];

    GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, 1024, 0, 768, -1, 1);
    self.effect.transform.projectionMatrix = projectionMatrix;

    self.player = [[SGGSprite alloc] initWithFile:@"2.png" effect:self.effect];
    self.player.position = GLKVector2Make(self.player.contentSize.width/2, 160);

    self.children = [NSMutableArray array];
    [self.children addObject:self.player];


}

- (void)addTarget {
    SGGSprite * target = [[SGGSprite alloc] initWithFile:@"Target.png" effect:self.effect];
    [self.children addObject:target];

    int minY = target.contentSize.height/2;
    int maxY = 320 - target.contentSize.height/2;
    int rangeY = maxY - minY;
    int actualY = (arc4random() % rangeY) + minY;

    target.position = GLKVector2Make(480 + (target.contentSize.width/2), actualY);    

    int minVelocity = 480.0/4.0;
    int maxVelocity = 480.0/2.0;
    int rangeVelocity = maxVelocity - minVelocity;
    int actualVelocity = (arc4random() % rangeVelocity) + minVelocity;

    target.moveVelocity = GLKVector2Make(-actualVelocity, 0);
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}

#pragma mark - GLKViewDelegate


static inline double radians (double degrees) {return degrees * M_PI/180;}


- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {    



    glClearColor(1, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);    
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    for (SGGSprite * sprite in self.children) {
        [sprite render];
    }
}

- (void)update {    

    self.timeSinceLastSpawn += self.timeSinceLastUpdate;
    if (self.timeSinceLastSpawn > 1.0) {
        self.timeSinceLastSpawn = 0;
        [self addTarget];
    }

    for (SGGSprite * sprite in self.children) {
        [sprite update:self.timeSinceLastUpdate];
    }
}

@end

这是函数[sprite render];

的代码
//
//  SGGSprite.m
//  SimpleGLKitGame
//
//  Created by Ray Wenderlich on 1/30/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "SGGSprite.h"

typedef struct {
    CGPoint geometryVertex;
    CGPoint textureVertex;
} TexturedVertex;

typedef struct {
    TexturedVertex bl;
    TexturedVertex br;    
    TexturedVertex tl;
    TexturedVertex tr;    
} TexturedQuad;

@interface SGGSprite()

@property (strong) GLKBaseEffect * effect;
@property (assign) TexturedQuad quad;
@property (strong) GLKTextureInfo * textureInfo;

@end

@implementation SGGSprite
@synthesize position = _position;
@synthesize contentSize = _contentSize;
@synthesize effect = _effect;
@synthesize quad = _quad;
@synthesize textureInfo = _textureInfo;
@synthesize moveVelocity = _moveVelocity;

- (id)initWithFile:(NSString *)fileName effect:(GLKBaseEffect *)effect {
    if ((self = [super init])) {
        self.effect = effect;

        NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithBool:YES],
                                  GLKTextureLoaderOriginBottomLeft, 
                                  nil];

        NSError * error;    
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
        self.textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
        if (self.textureInfo == nil) {
            NSLog(@"Error loading file: %@", [error localizedDescription]);
            return nil;
        }

        self.contentSize = CGSizeMake(self.textureInfo.width, self.textureInfo.height);

        TexturedQuad newQuad;
        newQuad.bl.geometryVertex = CGPointMake(0, 0);
        newQuad.br.geometryVertex = CGPointMake(self.textureInfo.width, 0);
        newQuad.tl.geometryVertex = CGPointMake(0, self.textureInfo.height);
        newQuad.tr.geometryVertex = CGPointMake(self.textureInfo.width, self.textureInfo.height);

        newQuad.bl.textureVertex = CGPointMake(0, 0);
        newQuad.br.textureVertex = CGPointMake(1, 0);
        newQuad.tl.textureVertex = CGPointMake(0, 1);
        newQuad.tr.textureVertex = CGPointMake(1, 1);
        self.quad = newQuad;

    }
    return self;
}

- (GLKMatrix4) modelMatrix {

    GLKMatrix4 modelMatrix = GLKMatrix4Identity;    
    modelMatrix = GLKMatrix4Translate(modelMatrix, self.position.x, self.position.y, 0);
    modelMatrix = GLKMatrix4Translate(modelMatrix, -self.contentSize.width/2, -self.contentSize.height/2, 0);
    return modelMatrix;

}


static inline double radians (double degrees) {return degrees * M_PI/180;}

- (void)render { 

    self.effect.texture2d0.name = self.textureInfo.name;
    self.effect.texture2d0.enabled = YES;
    self.effect.transform.modelviewMatrix = self.modelMatrix;

    [self.effect prepareToDraw];
    long offset = (long)&_quad;


    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

}

- (void)update:(float)dt {

    GLKVector2 curMove = GLKVector2MultiplyScalar(self.moveVelocity, dt);



    self.position = GLKVector2Add(self.position, curMove);

}

@end

1 个答案:

答案 0 :(得分:0)

在此示例中,您将共享相同的功能来绘制播放器,目标和背景。 你必须独立定义一个新的效果和矩阵,让玩家应用一个单独的效果,如旋转。

例如,这里是SGGViewController.m:

//
//  SGGViewController.m
//  SimpleGLKitGame
//
//  Created by Ray Wenderlich on 1/30/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "SGGViewController.h"
#import "SGGSprite.h"

float _rotation;

@interface SGGViewController ()
@property (strong, nonatomic) EAGLContext *context;
@property (strong) GLKBaseEffect * effect;
@property (strong) GLKBaseEffect * effectPlayer;  //Added For The Player
@property (strong) SGGSprite * player;
@property (strong) NSMutableArray * children;
@property (strong) NSMutableArray * childrenPlayer; //Added For The Player
@property (assign) float timeSinceLastSpawn;
@end

@implementation SGGViewController
@synthesize effect = _effect;
@synthesize effectPlayer = _effectPlayer;
@synthesize context = _context;
@synthesize player = _player;
@synthesize children = _children;
@synthesize childrenPlayer = _childrenPlayer;
@synthesize timeSinceLastSpawn = _timeSinceLastSpawn;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];


    if (!self.context) {
        NSLog(@"Failed to create ES context");
    }

    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    [EAGLContext setCurrentContext:self.context];

    //--------------------This Is To Define Effect For The background-------------------
    self.effect = [[GLKBaseEffect alloc] init];
    GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, 480, 0, 320, -1024, 1024);
    self.effect.transform.projectionMatrix = projectionMatrix;
    //----------------------------------------------------------------------------------

    //--------This One For The Player ---------
    self.effectPlayer = [[GLKBaseEffect alloc] init];
    GLKMatrix4 projectionMatrixPlay = GLKMatrix4MakeOrtho(0, 480, 0, 320, -1024, 1024);
    self.effectPlayer.transform.projectionMatrix = projectionMatrixPlay;
    //----------------------------------------------------------------------------------

    //----Note Here I Have Uses Another Separate Function To Init The Texture File----
    self.player = [[SGGSprite alloc] initWithFilePlayer:@"2.png" effectPlayer:self.effectPlayer];
    self.player.positionPlayer = GLKVector2Make(self.player.contentSizePlayer.width/2, 160);

    //--The Array Setting For Target And Anything Else (Background, Splash, Etc.)---
    self.children = [NSMutableArray array];

    //---And This Is The Array Setting For The Player---
    self.childrenPlayer = [NSMutableArray array];
    [self.childrenPlayer addObject:self.player];


}

//-----While The Target As Usual--------
- (void)addTarget 
{
    SGGSprite * target = [[SGGSprite alloc] initWithFile:@"Target.png" effect:self.effect];
    [self.children addObject:target];

    int minY = target.contentSize.height/2;
    int maxY = 320 - target.contentSize.height/2;
    int rangeY = maxY - minY;
    int actualY = (arc4random() % rangeY) + minY;

    target.position = GLKVector2Make(480 + (target.contentSize.width/2), actualY);    

    int minVelocity = 480.0/4.0;
    int maxVelocity = 480.0/2.0;
    int rangeVelocity = maxVelocity - minVelocity;
    int actualVelocity = (arc4random() % rangeVelocity) + minVelocity;

    target.moveVelocity = GLKVector2Make(-actualVelocity, 0);
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}

#pragma mark - GLKViewDelegate


static inline double radians (double degrees) {return degrees * M_PI/180;}


- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {    



    glClearColor(1, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);    
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    for (SGGSprite * sprite in self.children) {
        [sprite render];
    }
    //--------Separate Rendering For The Player In A New Function RenderPlayer-----------
    for (SGGSprite * sprite in self.childrenPlayer) {
        [sprite renderPlayer];
    }

}

- (void)update 
{    

    self.timeSinceLastSpawn += self.timeSinceLastUpdate;
    _rotation += self.timeSinceLastUpdate * 20;  //Speed And Angle Of Rotation

    if (self.timeSinceLastSpawn > 1.0) {
        self.timeSinceLastSpawn = 0;
        [self addTarget];
    }

    for (SGGSprite * sprite in self.children) 
    {
        [sprite update:self.timeSinceLastUpdate];
    }

    //---Another One For The Player Note Theres A New Function Called updatePlayer---
    for (SGGSprite * sprite in self.childrenPlayer) 
    {
        [sprite updatePlayer:self.timeSinceLastUpdate rotationPlayer:_rotation];
    }
}

@end

现在为SGGSprite.m

//
//  SGGSprite.m
//  SimpleGLKitGame
//
//  Created by Ray Wenderlich on 1/30/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "SGGSprite.h"

typedef struct {
    CGPoint geometryVertex;
    CGPoint textureVertex;
} TexturedVertex;

typedef struct {
    TexturedVertex bl;
    TexturedVertex br;    
    TexturedVertex tl;
    TexturedVertex tr;    
} TexturedQuad;

typedef struct {
    CGPoint geometryVertexPlayer;
    CGPoint textureVertexPlayer;
} TexturedVertexPlayer;

typedef struct {
    TexturedVertexPlayer bl;
    TexturedVertexPlayer br;    
    TexturedVertexPlayer tl;
    TexturedVertexPlayer tr;    
} TexturedQuadPlayer;




@interface SGGSprite()

@property (strong) GLKBaseEffect * effect;
@property (strong) GLKBaseEffect * effectPlayer;  //Added
@property (assign) TexturedQuad quad;
@property (strong) GLKTextureInfo * textureInfo;
@property (assign) TexturedQuadPlayer quadPlayer; //Added
@property (strong) GLKTextureInfo * textureInfoPlayer; //Added

@end

@implementation SGGSprite
@synthesize position = _position;
@synthesize positionPlayer = _positionPlayer;  //Added
@synthesize contentSize = _contentSize;
@synthesize contentSizePlayer = _contentSizePlayer;  //Added
@synthesize effect = _effect;
@synthesize effectPlayer = _effectPlayer; //Added
@synthesize quad = _quad;
@synthesize quadPlayer = _quadPlayer; //Added
@synthesize textureInfo = _textureInfo;
@synthesize moveVelocity = _moveVelocity;
@synthesize textureInfoPlayer = _textureInfoPlayer;  //Added
@synthesize moveVelocityPlayer = _moveVelocityPlayer;  //Added

int moved = 0;   // to make sure the game just started

- (id)initWithFile:(NSString *)fileName effect:(GLKBaseEffect *)effect 
{
    if ((self = [super init])) 
    {
        self.effect = effect;

        NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithBool:YES],
                                  GLKTextureLoaderOriginBottomLeft, 
                                  nil];

        NSError * error;    
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
        self.textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
        if (self.textureInfo == nil) 
        {
            NSLog(@"Error loading file: %@", [error localizedDescription]);
            return nil;
        }

        self.contentSize = CGSizeMake(self.textureInfo.width, self.textureInfo.height);

        TexturedQuad newQuad;
        newQuad.bl.geometryVertex = CGPointMake(0, 0);
        newQuad.br.geometryVertex = CGPointMake(self.textureInfo.width, 0);
        newQuad.tl.geometryVertex = CGPointMake(0, self.textureInfo.height);
        newQuad.tr.geometryVertex = CGPointMake(self.textureInfo.width, self.textureInfo.height);

        newQuad.bl.textureVertex = CGPointMake(0, 0);
        newQuad.br.textureVertex = CGPointMake(1, 0);
        newQuad.tl.textureVertex = CGPointMake(0, 1);
        newQuad.tr.textureVertex = CGPointMake(1, 1);
        self.quad = newQuad;
    }
    return self;
}
//----------The Init Function For The Player Only-------------
- (id)initWithFilePlayer:(NSString *)fileName effectPlayer:(GLKBaseEffect *)effectPlayer 
{
    if ((self = [super init])) 
    {
        self.effectPlayer = effectPlayer;

        NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithBool:YES],
                                  GLKTextureLoaderOriginBottomLeft, 
                                  nil];

        NSError * error;    
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
        self.textureInfoPlayer = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
        if (self.textureInfoPlayer == nil) 
        {
            NSLog(@"Error loading file: %@", [error localizedDescription]);
            return nil;
        }

        self.contentSizePlayer = CGSizeMake(self.textureInfoPlayer.width, self.textureInfoPlayer.height);

        TexturedQuadPlayer newQuad;
        newQuad.bl.geometryVertexPlayer = CGPointMake(0, 0);
        newQuad.br.geometryVertexPlayer = CGPointMake(self.textureInfoPlayer.width, 0);
        newQuad.tl.geometryVertexPlayer = CGPointMake(0, self.textureInfoPlayer.height);
        newQuad.tr.geometryVertexPlayer = CGPointMake(self.textureInfoPlayer.width, self.textureInfoPlayer.height);
        newQuad.bl.textureVertexPlayer = CGPointMake(0, 0);
        newQuad.br.textureVertexPlayer = CGPointMake(1, 0);
        newQuad.tl.textureVertexPlayer = CGPointMake(0, 1);
        newQuad.tr.textureVertexPlayer = CGPointMake(1, 1);
        self.quadPlayer = newQuad;
    }
    return self;
}


- (GLKMatrix4) modelMatrix 
{

    GLKMatrix4 modelMatrix = GLKMatrix4Identity;    
    modelMatrix = GLKMatrix4Translate(modelMatrix, self.position.x, self.position.y, 0);
    modelMatrix = GLKMatrix4Translate(modelMatrix, -self.contentSize.width/2, -self.contentSize.height/2, 0);
    return modelMatrix;

} 

//-------------Added For The Player-----------------
- (GLKMatrix4) modelMatrixPlayer 
{

    GLKMatrix4 modelMatrixPlayer = GLKMatrix4Identity;    
    modelMatrixPlayer = GLKMatrix4Translate(modelMatrixPlayer, self.positionPlayer.x, self.positionPlayer.y, 0);
    modelMatrixPlayer = GLKMatrix4Translate(modelMatrixPlayer, -self.contentSizePlayer.width/2, -self.contentSizePlayer.height/2, 0);
    return modelMatrixPlayer;

} 


static inline double radians (double degrees) {return degrees * M_PI/180;}

- (void)render 
{ 

    self.effect.texture2d0.name = self.textureInfo.name;
    self.effect.texture2d0.enabled = YES;
    self.effect.transform.modelviewMatrix = self.modelMatrix;

    [self.effect prepareToDraw];
    long offset = (long)&_quad;


    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

}

- (void)renderPlayer 
{ 

    self.effectPlayer.texture2d0.name = self.textureInfoPlayer.name;
    self.effectPlayer.texture2d0.enabled = YES;

    if (moved == 0) // Only Applied When You Restart Game To Position The Player In The Center
    {
        self.effectPlayer.transform.modelviewMatrix = self.modelMatrixPlayer;
    }

    [self.effectPlayer prepareToDraw];
    long offset = (long)&_quadPlayer;


    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertexPlayer), (void *) (offset + offsetof(TexturedVertexPlayer, geometryVertexPlayer)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertexPlayer), (void *) (offset + offsetof(TexturedVertexPlayer, textureVertexPlayer)));

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

}


- (void)update:(float)dt 
{

    GLKVector2 curMove = GLKVector2MultiplyScalar(self.moveVelocity, dt);
    self.position = GLKVector2Add(self.position, curMove);

}

// ------------- Rotate The Object --------------------------------------------

- (void)updatePlayer:(float)rt rotationPlayer:(float)rotate
{

    moved = 1;

    self.effectPlayer.transform.modelviewMatrix = self.modelMatrixPlayer; //Adjust the player Location And Ready To Move 

    //Moving The Object 
    GLKVector2 curRotate = GLKVector2MultiplyScalar(self.moveVelocityPlayer, rt);
    self.positionPlayer = GLKVector2Add(self.positionPlayer, curRotate);     

    //Rotation Section
    self.effectPlayer.transform.modelviewMatrix = GLKMatrix4Rotate(self.effectPlayer.transform.modelviewMatrix, rotate, 0, 0, -1);

}

@end

嗯,这里不是所有东西都是SGGSprite.h

//
//  SGGSprite.h
//  SimpleGLKitGame
//
//  Created by Ray Wenderlich on 1/30/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import <GLKit/GLKit.h>
#import <Foundation/Foundation.h>

@interface SGGSprite : NSObject
@property (assign) GLKVector2 position; 
@property (assign) GLKVector2 positionPlayer; //Position For The Player
@property (assign) CGSize contentSize;  
@property (assign) CGSize contentSizePlayer;  //Size Of The Player
@property (assign) GLKVector2 moveVelocity; 
@property (assign) GLKVector2 moveVelocityPlayer; //Speed Of The Player If Moved

- (id)initWithFile:(NSString *)fileName effect:(GLKBaseEffect *)effect;
- (id)initWithFilePlayer:(NSString *)fileName effectPlayer:(GLKBaseEffect *)effectPlayer;
- (void)render;
- (void)renderPlayer;

- (void)update:(float)dt;  //Move Object
- (void)updatePlayer:(float)rt rotationPlayer:(float)rotate; //Rotate Object
@end