How To Create A Simple 2D iPhone Game with OpenGL ES 2.0 and GLKit – Part 2

This is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer. In this tutorial series, we are creating a very simple game for the iPhone using the lowest level APIs on iOS – OpenGL ES 2.0 and GLKit. In the first part of the series, we created a basic OpenGL […] By Ray Wenderlich.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Creating a Win/Lose Scene

To allow replacing the scene, we’re going to make the scene property on SGGViewController public. Then other classes can get a reference to the SGGViewController and replace it directly. There are better ways to do this, but again – keeping it simple ;]

So go to SGGViewController.h and add the following property:

@property (strong) SGGNode * scene;

And switch to SGGViewController.m and comment it out in the private interface:

//@property (strong) SGGNode * scene;

OK cool – now let’s create our Game Overs scene. Create a new file with the iOS\Cocoa Touch\Objective-C class template. Enter SGGGameOverScene for the Class, SGGNode for the Subclass, click Next, and click Create.

Open SGGGameOverScene.h and replace it with the following:

#import "SGGNode.h"

@interface SGGGameOverScene : SGGNode

- (id)initWithEffect:(GLKBaseEffect *)effect win:(BOOL)win;

@end

Then open SGGGameOverScene.m and replace it with the following:

#import "SGGGameOverScene.h"
#import "SGGSprite.h"
#import "SGGViewController.h"
#import "SGGActionScene.h"
#import "SGGAppDelegate.h"

@interface SGGGameOverScene ()
@property (assign) float timeSinceInit;
@property (strong) GLKBaseEffect * effect;
@end

@implementation SGGGameOverScene
@synthesize timeSinceInit = _timeSinceInit;
@synthesize effect = _effect;

- (id)initWithEffect:(GLKBaseEffect *)effect win:(BOOL)win {
    if ((self = [super init])) {

        self.effect = effect;
        if (win) {
            SGGSprite * winSprite = [[SGGSprite alloc] initWithFile:@"YouWin.png" effect:effect];
            winSprite.position = GLKVector2Make(240, 160);
            [self addChild:winSprite];
        } else {
            SGGSprite * loseSprite = [[SGGSprite alloc] initWithFile:@"YouLose.png" effect:effect];
            loseSprite.position = GLKVector2Make(240, 160);
            [self addChild:loseSprite];
        }
        
    }
    return self;
}

- (void)update:(float)dt {
    
    self.timeSinceInit += dt;
    if (self.timeSinceInit > 3.0) {
        SGGActionScene * scene = [[SGGActionScene alloc] initWithEffect:self.effect];
        SGGAppDelegate * delegate = [[UIApplication sharedApplication] delegate];
        UIWindow * mainWindow = [delegate window];
        SGGViewController * viewController = (SGGViewController *) mainWindow.rootViewController;
        viewController.scene = scene;
    }
    
}

@end

This simply places a premade image of “You Win” or “You Lose” in the middle of the screen on startup. After a certain amount of time elapses, it creates a new ActionScene and sets the currently running scene to this new scene.

Only thing left to do is run the GameOverScene on win or lose! Open up SGGActionScene.m and make the following changes:

// Add to top of file
#import "SGGGameOverScene.h"
#import "SGGAppDelegate.h"
#import "SGGViewController.h"

// Add new method, before update method
- (void)gameOver:(BOOL)win {
    SGGGameOverScene * gameOver = [[SGGGameOverScene alloc] initWithEffect:self.effect win:win];

    SGGAppDelegate * delegate = [[UIApplication sharedApplication] delegate];
    UIWindow * mainWindow = [delegate window];
    SGGViewController * viewController = (SGGViewController *) mainWindow.rootViewController;
    viewController.scene = gameOver;
}

// Add at bottom of update method
if (_targetsDestroyed > 5) {
    [self gameOver:YES];
    return;        
}

BOOL lose = NO;    
for (int i = self.children.count - 1; i >= 0; i--) {
    
    SGGSprite * sprite = [self.children objectAtIndex:i];
    
    if (sprite.position.x <= -sprite.contentSize.width/2 ||
        sprite.position.x > 480 + sprite.contentSize.width/2 ||
        sprite.position.y <= -sprite.contentSize.height/2 ||
        sprite.position.y >= 320 + sprite.contentSize.height/2) {
        
        if ([self.targets containsObject:sprite]) {
            [self.targets removeObject:sprite];
            [self.children removeObjectAtIndex:i];
            lose = YES;
        } else if ([self.projectiles containsObject:sprite]) {
            [self.projectiles removeObject:sprite];
            [self.children removeObjectAtIndex:i];
        }
    } 
}
if (lose) {
    [self gameOver:NO];
}

Here we add the game logic. If the player destroys more than 5 targets, they win, so create and display a game over scene.

We also add some cleanup code to remove sprites that are outside the bounds of the scene to avoid endless memory allocations. If a monster escapes the boundary of the screen, the game is over.

Guess what – you’re done! Compile and run, and see if you can beat the game!

You Win!

Where To Go From Here?

Here is the finished and refactored project from this tutorial.

Congratulations, you have made a complete game with OpenGL ES 2.0 and GLKit! You now have experience with creating a very simple game engine, and if you like you could use this as the basis for your own game engine.

This tutorial should also have given you a better appreciation for Cocos2D and all that it does for you :] Since this engine is organized somewhat similarly to Cocos2D, you should also better understand how it works.

If you have any questions or comments on OpenGL ES 2.0, GLKit, or this tutorial, please join the forum discussion below!


This is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer.

Contributors

Over 300 content creators. Join our team.