Search This Blog

Monday, October 25, 2010

Tutorial: iPhone Game Programming- professional Bricks (Part I)

(Read Part II here)

Bricks - my all time favorite game (just after Tetris). So this post is a tutorial on how to write your own 'bricks' for iphone

But....

What's a game tutorial that:

a) Does not look professional?

b) Does not have multiple levels?

c) Does not have ghastly sound effects?

d) Does not have explosions?

e) Does not have  missiles?

f) Does not have a "Hack Mode"? (w00t)

Before we get anywhere, lets take a look at what we will be building. Its a 3:30 min video which I strongly recommend you see first so you can related explanations easier. (And also, it took me all of 10 minutes to create it, so you better spend 3:30 admiring it :-D)


History & Disclaimer


I am by no means an iPhone developer. Actually, I am by no means a developer. While I've been involved in technology very deeply, my work does not require me to code, and so, I've mostly been out of coding for the past 12 years (with the exception of the occasional perl coding for personal projects).  But there is just too much going on in the mobile space for me not to get my hands dirty again. So, with that in mind, I took it upon myself to learn basic iPhone programming and what better way than to define a project? My project was "Bricks".

The disclaimer part: Since this is pretty much my first attempt, I can't comment on this tutorial being a "good approach". All I can say is,  "if I can code for iPhone, you can too" !

Finally, this is not a "from scratch how to code for iphone" tutorial. I assume you know about Xcode, Views, Interface Builder etc.




Tutorial Credits


When you go about learning, google is your friend. A lot of what I gleaned came from different sites and one book. While I based my initial game on things I learned from them, once I got the basic approach, I took off on my own. For that I thank them:

  1. Ping Pong tutorial

  2. Beginning iPhone game programming by Apress (they also have a super elementary bricks game, but I think I found the ping pong tutorial better. I found the book useful to understand CoreAnimation/Quartz 2D)

  3. And the biggest thanks goes to StackOverflow - whenever I faced a problem I could be sure this site had an answer :)

Resource Credits


The tutorial includes images, sounds and a special background music class. Here are their credits directly from my .h file

[objc]
// Explosion sprites credit:
// http://homepage.ntlworld.com/david.howe50
//
// Other tutorial credits:
// http://icodeblog.com/2009/01/15/iphone-game-programming-tutorial-part-1/
// and Beginning iPhone Game Development by Apress
//
// Background images:
// http://openclipart.org
//
// Music:
// Jake Peterson's GBMusicTrack for background MP3 (classical music is "Minuet in G Major" by Bach from my personal collection)
// clap: http://www.pacdv.com/sounds/applause-sounds.html
// other sounds: http://www.wavsource.com/sfx/sfx3.htm
// http://simplythebest.net/sounds/WAV/sound_effects_WAV
[/objc]

Screen Elements


Let's first look at the screen layout of the game to give you an idea of the elements of the game. (Click on image for larger version)



So as you see, the game has several things going on that we want to achieve (well, some you don't see above, so I'll just tell you)

  1. This is a multi-layer game - when you kill all the bricks, we will move the player to the next level

  2. To differentiate between levels, we would like to use a different background image and some animation of the background (right now, I switch between "rain" and "clouds moving")

  3. You see bricks have different "powers" - the red bricks are normal. We also want bricks that give you missile power (these are the green bricks). Then there are yellow patterned bricks that give you an extra life. Finally, there are steel bricks, who  can't be killed (the metal ones)

  4. We want explosions each time a missile or the ball hits the screen

  5. At the bottom row of the game, we want to enable several icons that do special stuff:

    1. If you triple tap the lower left corner, we want to enable a 'hack mode' - when on, you can skip levels by killing 4 bricks

    2. We want to enable/disable sound by tapping on the volume icon

    3. We want to see how to play the game (as if its hard!) by tapping the info button

    4. When we get missile power, we want to know that we have missile power! (so the missile icon on the lower right)

  6. And finally, we want SOUND EFFECTS! What's a game without some blood curdling sound?

Game Controls


Here is the help screen directly from the game so you get a feel of the controls we plan to use to play this game




Creating your images


When I showed the game to some colleague with a crappy looking line for a paddle and no background and simple bricks, their reaction was "Ah, nice because its your first game". When I added all the images, suddenly, they looked amazed at how professional the game looked and that it should be on the app store (well, that's their opinion). I cannot stress how important it is to select the right images.

There are some great resource available on the net. However, before you swipe them, remember to check their copyright information and what you can/cannot do with them. In my case, I designed the paddle, ball and bricks myself. For the level backgrounds and icons, I used images from http://www.openclipart.org/ . As the credits earlier state, I took the explosion image from here. There are around 100 images there in the sequence - I cut it down to 34 for my game by deleting interim sprites.

On creating the ball and bricks:

You can transform a simple pattern to a convincing brick very easily. Once you have a pattern made, simply apply a "Beveled" edge filter effect and it looks like a brick. (All photo editors have a bevel filter - gimp, Photoshop are the ones I've used)

As far as the ball goes, really simple. Draw an ellipse, fill it with a radial gradient from red to dark red. Then add a while spot somewhere to show reflection. That's all.

For the paddle, I started with a rounded rectangle, filled it with a vertical gradient of blue and dark blue, then drew two yellow lines on each side and finally applied a texture on top. Finished off with a bevel effect.

I know I've skimmed through the details here, but I want to get to the main code tutorial sooner.

Creating your sounds


I first went down the path of recording my own voice. Not good. There are excellent resource available for sounds. Check the credits for where I got them from.

Most .WAV files will not work when you take them to the iPhone


I am probably skipping ahead, but I wanted to mention that most of the sites I visited had great sound. I am using AudioServicesPlaySystemSound to play my sound. But when I imported the sounds to my project most of them just would not play! I found out later that this is because many of the WAV files are recorded as a Mono track, while AudioServicesPlaySystemSound works with Stereo track WAV files (or, I don't know enough of the API to make it work with mono). Anyway, what works for me, works. To make all the sounds work for my game, all I had to do was convert the mono tracks to stereo. And how do you do that? With just a few clicks, thanks to Audacity. Here is now:

a) Load the WAV file in audacity

b) Project->New Audio Track. (This will create an empty audio track below your mono track

c) Click on the old audio track, cmd+a, cmd+c (copy the full track)

d) Click on new audio track, cmd+v (paste)

e) Click on the "down arrow" on the top left of the old audio track (right next to the name) and select "Make Stereo Track"

f) Export as Wav.

Ta-dah. You now have great working sound you can use with your iphone.

As a side note, I also wanted some background music to play continuously. I just took Jake Peterson's GBMusic Track .m and .h files and imported it into my project. All you need to do is point it at any mp3 and away it goes. I later disabled background music - got too boring for me :-) but its in the code and you can enable it. Jake's class is great. It just works (not in the simulator though) and I could focus on the game right away.

Now, with all your images and sounds loaded into the project, lets get started on the game logic

So which graphics engine do I use?


The iPhone SDK gives you various options for graphics. You can use:

  1. UIKit

  2. Quartz 2D

  3. Open GL ES

This game has been developed completely using UIKit and a bit of Quartz 2D to animate some UI Views. I've not even begun to explore the rest. Why did I select UIKit? Because it seemed perfect for this game (and likely many games like this), is simple to understand and very high level. At an abstract level, when you use UIKit, all your graphics  are represented as "Image Views".  Think of each Image View as a "sheet". Each "sheet" can consist of one or more images and each "sheet" can be stack on top of each other, moved around and/or animated. If you are used to photoshop or Gimp, the concept of layers will be natural to you. Then, to tie things in nicely, iPhone SDK also ties in Quartz 2D with the UIKit very well - you can do some pretty advanced animation automatically simply by defining a "start state" , "end state" and "transition logic" for a UIView and let the Quartz 2D engine take care of the animation from start to end with the requested logic. More on that later.

A few words on the game logic


When you start reading the code, you will notice a few things upfront:

  1. I am (was) a C coder. Whenever I get the chance, I use as much C as possible.

  2. The game grew in spurts. I started off by wanting to make a simple ball-hit-brick game but then I decided to add powers, missiles, etc. later. I did not necessarily think the design through. If I were to do it again (I won't), I'd probably make a better design. Further, my complete lack of knowledge of Objective C also accounted for the choices I made (learn as you go).

Having said all of that, the lines of code is pretty small and you should not have issues following it.

Game Design


This is a small game. It was created as a "view controller" based game in Xcode and all the code is stuffed into "BricksViewController.h" and "BrickViewController.m". All other files in the project are wav files for sound, png for images and one mp3 for the background music (you will also see GBMusicTrack.h and .m which are Jake's files for background music playback)

BricksAppDelegate.m


Well, there is a teeny-weeny bit of code that I added to BricksAppDelegate.m. It is not critical, but makes the game better. Let me discuss that first. Basically, I want my game to pause if the application is interrupted (example, you hit the home button). While iphone freezes the game by default, what happens is that if I don't pause the game, the moment you switch back to the game, the ball moves. You may not have enough time to react. So, instead, I override some key callbacks so that the iphone tells my app when I am pushed out of the front view. When I get this notification, I quickly put the game in pause mode.

As it turns out, when IOS4 introduced background support, it changed the callback that is invoked. So, to make sure it works for IOS 3.x and 4.x, I just put in the same code in both APIs

[objc]
- (void)applicationWillTerminate:(UIApplication *)application {
/*
Called when the application is about to terminate.
See also applicationDidEnterBackground:.
*/
[viewController saveState];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
*/

[viewController saveState];

}
[/objc]

  1. applicationWillTerminate is called by IOS 3.x while applicationDidEnterBackground is what iOS 4.x calls. All I do is invoke the saveState method of my viewController (the app delegate has a convenient instance reference to viewController which contains my core game logic)

  2. You may think why not simply override these APIs in BricksViewController.m? Well, if you first read the Apple documentation, it will tell you these callbacks are only invoked on the delegate which happens to be BricksAppDelegate. Or, if you are like me, and never read, just implement and then wonder why your callback is not being called, stackOverflow.com will bring up threads where other n00bs like me made the same mistake and suffered several minutes of complete cluelessness...

BricksViewController.h


The best way for me to explain the game design is to explain BricksViewController.h to you. First, here is the full dump so you can copy paste it if you need.
(click on show source below)

[objc collapse="true"]
//
// BricksViewController.h
// Bricks
//
// Created by Arjun on 10/15/10.
// All rights reserved.
//

// Explosion sprites credit:
// http://homepage.ntlworld.com/david.howe50
//
// Other tutorial credits:
// http://icodeblog.com/2009/01/15/iphone-game-programming-tutorial-part-1/
// and Beginning iPhone Game Development by Apress
//
// Background images:
// http://openclipart.org
//
// Music:
// Jake Peterson's GBMusicTrack for background MP3 (classical music is "Minuet in G Major" by Bach from my personal collection)
// clap: http://www.pacdv.com/sounds/applause-sounds.html
// other sounds: http://www.wavsource.com/sfx/sfx3.htm
// http://simplythebest.net/sounds/WAV/sound_effects_WAV

#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#import "GBMusicTrack.h" // Using GBMusicTrack to play background MP3 (does NOT work in simulator)

#define BRICKS_ROWS 8
#define BRICKS_COLUMNS 7 // dimensions of the matrix of bris

#define BRICKS_IMAGES 5 // I have 5 different brick images which can represent different powers
#define LIVES 8 // Maximum lives you can have
#define GAME_LEVELS 4 // Let's start with 4 levels

#define NORMAL_BRICK 1
#define METAL_BRICK 2 // Metal bricks cannot be killed. You will bounce off sharply

#define SUPER_BRICKS 3 // Any brick ID >=3 is a 'special' brick
#define LIFE_BRICK 3 // This one gives you a new life (if you are not at max life)
#define MISSILE_BRICK 4 // This one gives you 5 missiles with each hit

#define HACK_HITCOUNT 4 // What's a game without a hack? If hack mode is on, you get to next level
// after 4 hits

@interface BricksViewController : UIViewController <UIAccelerometerDelegate>
{

NSTimer *gameTimer; // used for the primary game logic (update ball, check hits etc)
NSTimer *backgroundTimer; // used to animate backround sprites - cloud and missile movement
NSTimer *harderTimer; // after MAKE_IT_HARDER seconds, this will be called so we can step up the game difficulty

IBOutlet UIImageView *ball; // will hold the ball as it bounces around
IBOutlet UIImageView *paddle; // will hold the paddle
IBOutlet UIImageView *cloud; // well, obviously, the cloud in the background
IBOutlet UILabel *labelScore; // holds the latest score shown on top right
IBOutlet UILabel *labelGameOver; // hidden by default, will showup in center as text when game is over
IBOutlet UILabel *labelPause; // text to display when paused
IBOutlet UIImageView *explodeView; // will hold explosion images
IBOutlet UIImageView *backgroundImageView; // holds the game background wallpaper
IBOutlet UILabel *labelCurrentLevel; // Text to display level on screen
IBOutlet UIImageView *haveMissileView; // Will show a missile at lower right when you have missiles
IBOutlet UIImageView *hackView; // Will show an icon at lower left when hack mode is on
IBOutlet UIImageView *volumeView; // swaps between volume on and off image - lower center
IBOutlet UIImageView *infoView; // displays the info button
IBOutlet UIImageView *helpView; // displays the help screen when you tap the info button

// various sound events depending on what event occurs.

SystemSoundID boingSound;
SystemSoundID clapSound;
SystemSoundID missSound;
SystemSoundID hitSound;
SystemSoundID explodeSound;
SystemSoundID booSound;
SystemSoundID holycowSound;
SystemSoundID gotlifeSound;
SystemSoundID missileSound;

CGPoint ballSpeed; // holds the speed at which the ball will move
CGPoint paddleSpeed; // holds the speed at which the paddle will move
int score; // holds latest score - this is used by labelScore to display
float touch;
int livesleft; // if this goes to 0, you are dead.
int gameLevel; // your current game level

UIImageView *bricks[BRICKS_ROWS][BRICKS_COLUMNS]; // will hold the X*Y array of brick images
int brick_description[BRICKS_ROWS][BRICKS_COLUMNS]; // will hold the brick format and powers

UIImageView *lives[LIVES]; // holds the display of lives on top left
UIImageView *missileView; // hold the missile Image
NSString *backgroundArray[GAME_LEVELS]; // holds different background images for levels
NSString *brickImages[BRICKS_IMAGES]; // holds the different brick images
NSMutableArray *explodeImages; // holds the sequence of images for an explosion
NSMutableArray *rainDrops; // holds the rain drops that are displayed on the screen
GBMusicTrack *song; //background music

int tBallSpeedX ; // used temporarily for one bounce
int tBallSpeedY ; // used temporarily for one bounce
int kBallSpeedX ;
int kBallSpeedY ;
int kMakeItHarder; // Time to make things harder in the game
int kGamePause; // if 1 then game freezes
int kHackHitCount; // HACK MODE: if 1, then we can skip levels just after 4 hits
int kMissileFiring; // 1 if a missile has launched. We only allow 1 missile at a time
int kMissilesLeft; // when 0, your missile power is done
int kVolumeIsOn; // toggles volume on and off

}

@property (nonatomic, retain) UIImageView *ball;
@property (nonatomic, retain) UIImageView *paddle;
@property (nonatomic, retain) UIImageView *cloud;
@property (nonatomic, retain) UIImageView *explodeView;
@property (nonatomic, retain) UIImageView *backgroundImageView;
@property (nonatomic, retain) UIImageView *missileView;
@property (nonatomic, retain) UIImageView *haveMissileView;
@property (nonatomic, retain) UIImageView *hackView;
@property (nonatomic, retain) UIImageView *volumeView;
@property (nonatomic, retain) UIImageView *infoView;
@property (nonatomic, retain) UIImageView *helpView;

@property (nonatomic, retain) UILabel *labelScore;
@property (nonatomic, retain) UILabel *labelCurrentLevel;
@property (nonatomic, retain) UILabel *labelGameOver;
@property (nonatomic, retain) UILabel *labelPause;
@property (nonatomic) SystemSoundID hitSound;
@property (nonatomic) SystemSoundID missSound;
@property (nonatomic) SystemSoundID clapSound;
@property (nonatomic) SystemSoundID explodeSound;
@property (nonatomic) SystemSoundID booSound;
@property (nonatomic) SystemSoundID holycowSound;
@property (nonatomic) SystemSoundID boingSound;
@property (nonatomic) SystemSoundID metalSound;
@property (nonatomic) SystemSoundID gotlifeSound;
@property (nonatomic) SystemSoundID missileSound;

@property (nonatomic, retain) NSTimer *gameTimer;
@property (nonatomic, retain) NSTimer *backgroundTimer;
@property (nonatomic, retain) NSTimer *harderTimer;

@property (nonatomic, retain) NSMutableArray *rainDrops;

- (void) initTimer;
- (void) playGame:(NSTimer *)timer;
- (void) adjustBackground:(NSTimer *)timer;
- (void) makeItHarder:(NSTimer *)timer;

- (void) initBricks;
- (void) initLives;
- (void) initRain;
- (void) moveRain;
- (void) hideRain;
- (void) initExplosion;
- (void) initAudioStreams: (SystemSoundID *)soundId: (NSString *)soundFile: (NSString *) type;
-(void) playAudio: (SystemSoundID) soundId;
- (void) resetAlphasforLives:(int) livesVal forBricks:(int) bricksVal ;
-(void) explodeBrick: (int) y : (int) x;
- (void) initBrickLayout;
- (void) launchMissile;
- (void) saveState;

@end
[/objc]

Let's break it down


[objc]
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#import "GBMusicTrack.h" // Using GBMusicTrack to play background MP3 (does NOT work in simulator)

#define BRICKS_ROWS 8
#define BRICKS_COLUMNS 7 // dimensions of the matrix of bricks

#define BRICKS_IMAGES 5 // I have 5 different brick images which can represent different powers
#define LIVES 8 // Maximum lives you can have
#define GAME_LEVELS 4 // Let's start with 4 levels

#define NORMAL_BRICK 1
#define METAL_BRICK 2 // Metal bricks cannot be killed. You will bounce off sharply

#define SUPER_BRICKS 3 // Any brick ID >=3 is a 'special' brick
#define LIFE_BRICK 3 // This one gives you a new life (if you are not at max life)
#define MISSILE_BRICK 4 // This one gives you 5 missiles with each hit

#define HACK_HITCOUNT 4 // What's a game without a hack? If hack mode is on, you get to next level
// after 4 hits
[/objc]



We first import "AudioToolbox.h". You need this file to play the audio files. We also import GBMusicTrack.h which is Jake's class to play a background MP3.  Next follows some key #defines. While for the most part, the comments are self-explanatory, some commentary is due:

  • The bricks matrix you see at each level is essentially a 2D array. BRICKS_ROWS and BRICKS_COLUMNS specify its dimensions

  • While the code currently uses 4 brick images to show different powers, I have 5 (1 for future use :)

  • Then, I use different values to depict which brick is 'normal' and which brick is 'super'. Why do I need this? You will see later, that for each level, I design a 2D matrix of bricks and fill in the values 1-4 so that when a ball or a missile hits that brick my game knows what to do (just explode, give you missiles, give you a life etc.)

  • Finally, I've added a 'developer mode'.If you triple tap the lower left corner of the screen, you get a 'pac-man on fire' icon that tells you that you don't need to shoot/hit all the bricks to get to the next level. HACK_HITCOUNT defines the number of bricks that need to be killed before you progress to the next level.

[objc]

@interface BricksViewController : UIViewController <UIAccelerometerDelegate>
{

NSTimer *gameTimer; // used for the primary game logic (update ball, check hits etc)
NSTimer *backgroundTimer; // used to animate backround sprites - cloud and missile movement
NSTimer *harderTimer; // after MAKE_IT_HARDER seconds, this will be called so we can step up the game difficulty

IBOutlet UIImageView *ball; // will hold the ball as it bounces around
IBOutlet UIImageView *paddle; // will hold the paddle
IBOutlet UIImageView *cloud; // well, obviously, the cloud in the background
IBOutlet UILabel *labelScore; // holds the latest score shown on top right
IBOutlet UILabel *labelGameOver; // hidden by default, will showup in center as text when game is over
IBOutlet UILabel *labelPause; // text to display when paused
IBOutlet UIImageView *explodeView; // will hold explosion images
IBOutlet UIImageView *backgroundImageView; // holds the game background wallpaper
IBOutlet UILabel *labelCurrentLevel; // Text to display level on screen
IBOutlet UIImageView *haveMissileView; // Will show a missile at lower right when you have missiles
IBOutlet UIImageView *hackView; // Will show an icon at lower left when hack mode is on
IBOutlet UIImageView *volumeView; // swaps between volume on and off image - lower center
IBOutlet UIImageView *infoView; // displays the info button
IBOutlet UIImageView *helpView; // displays the help screen when you tap the info button

[/objc]

  1. First, you will notice that my class derives from UIViewController (which is what Xcode generates when you select a View based application. But in addition, since I want to also be able to detect accelerometer movement (to move the paddle), I need to tell iPhone that this class will also implement the mechanics required to receive accelerometer events which is what achieves. You can read up on protocols, delegates and the general iphone architecture model if you don't know what this means. Google for these words.

  2. Next up, we declare 3 timers. these timers will be triggered for different purposes. gameTimer is triggered 30 times a second to determine state of the game (collisions, hits, etc). backgroundTimer will be called 30 times a second as well to animate the game background as well as move a missile when fired (more on this later)

  3. harderTimer is called once in 60 seconds to 'step up' the difficulty of a level (right now, it will increase the ball speed)

  4. Next up, we define a whole bunch of UIImageView related variables that will point to various objects on the screen. I've used Interface Builder to create the initial screen for almost all of the images, with the exception of the bricks themselves that are dynamically created according to the level in code. Pretty much everything else is created in IB.

[objc]

// various sound events depending on what event occurs.

SystemSoundID boingSound;
SystemSoundID clapSound;
SystemSoundID missSound;
SystemSoundID hitSound;
SystemSoundID explodeSound;
SystemSoundID booSound;
SystemSoundID holycowSound;
SystemSoundID gotlifeSound;
SystemSoundID missileSound;
[/objc]

  1. Next up, we have various handles to sound files that will be played when an event occurs in the game. Each sound is a WAV that these variables will point to. boing is when the ball bounces off the edges of the screen; clap is when you complete a level; miss is when your paddle misses the ball; hit is when it, er, hits; explode is when a missile or the ball hits a brick;  boo is when all your lives finish; holycow is when 'harderTimer' is called (its an indication that the level just got faster); gotlife is when you hit a brick that gives you a life; missile is when you launch a missile. Whew! this was tough explanation...

[objc]

CGPoint ballSpeed; // holds the speed at which the ball will move
CGPoint paddleSpeed; // holds the speed at which the paddle will move
int score; // holds latest score - this is used by labelScore to display
float touch;
int livesleft; // if this goes to 0, you are dead.
int gameLevel; // your current game level
[/objc]

  1. Comments are self-explanatory. Basically, paddleSpeed controls the ball movement. Depending on what the ball hits, its X and Y co-ordinates will be manipulated and later the ball will be moved relative to its current position based on the X,Y values of paddleSpeed

  2. I'm sure you have figured out the rest

[objc]
UIImageView *bricks[BRICKS_ROWS][BRICKS_COLUMNS]; // will hold the X*Y array of brick images
int brick_description[BRICKS_ROWS][BRICKS_COLUMNS]; // will hold the brick format and powers
[/objc]

  1. These two arrays are the heart of how bricks are displayed and controlled.

  2. bricks is a 2D array that holds the actual brick images for a level (hence it is an array of UIImageView - each brick is an ImageView layer)

  3. brick_description in a 2D array of the same size and holds integral values that define the 'brick power'

  4. You will see later that to draw the bricks, we look a nested for loop, and for each row/column, we will first read the brick_description_value (no brick, normal brick, steel brick, life brick, missile brick) and then display the appropriate image

  5. In other words, by simply changing the brick description array, we can create a new layout for every level with the same rendering code

[objc]

UIImageView *lives[LIVES]; // holds the display of lives on top left
UIImageView *missileView; // hold the missile Image
NSString *backgroundArray[GAME_LEVELS]; // holds different background images for levels
NSString *brickImages[BRICKS_IMAGES]; // holds the different brick images
NSMutableArray *explodeImages; // holds the sequence of images for an explosion
NSMutableArray *rainDrops; // holds the rain drops that are displayed on the screen
GBMusicTrack *song; //background music

int tBallSpeedX ; // used temporarily for one bounce
int tBallSpeedY ; // used temporarily for one bounce
int kBallSpeedX ;
int kBallSpeedY ;
int kMakeItHarder; // Time to make things harder in the game
int kGamePause; // if 1 then game freezes
int kHackHitCount; // HACK MODE: if 1, then we can skip levels just after 4 hits
int kMissileFiring; // 1 if a missile has launched. We only allow 1 missile at a time
int kMissilesLeft; // when 0, your missile power is done
int kVolumeIsOn; // toggles volume on and off

}
[/objc]

  1. Some commentary here incase comments are not clear enough: as I mentioned, we have different background images per level, so backgroundArray will hold the names of those images

  2. the explodeImages array will hold the 34 odd explosion sprites that we need to animate on top of a brick that is hit

  3. rainDrops is basically an array of around 50 rain drops that we will animate and move on the screen for some levels

  4. song will hold a pointer to the mp3 file that will play in the background

  5. tBallSpeedX and Y and values that we fill in when you hit a steel brick. Basically, when we compute the next ball position, we take the current position+ball speed+tBallSpeed. In effect what that means is that the ball will bounce faster when you hit a steel brick. Then, when the ball bounces off the screen, we make tBallSpeedX and Y zero. Effectively implying that the ball will shoot out if you hit a steel brick and then reset back to normal speed after it hits a screen edge.

  6. kMakeItHarder holds the time in seconds after which the ball speed will be bumped up (in other words, harderTimer is invoked kMakeItHarder seconds later)

  7. kMissileFiring - will be set to 1 when you launch a missile. When 1, we will not allow another missile to be fired. When the missile hits a brick, or, goes off screen, then this value is reset, so we can fire again

  8. kMissilesLeft - when you hit a missile brick, you get 5 missiles. When you shoot a missile, this variable keeps decreasing by one.

[objc]
@property (nonatomic, retain) UIImageView *ball;
@property (nonatomic, retain) UIImageView *paddle;
@property (nonatomic, retain) UIImageView *cloud;
@property (nonatomic, retain) UIImageView *explodeView;
@property (nonatomic, retain) UIImageView *backgroundImageView;
@property (nonatomic, retain) UIImageView *missileView;
@property (nonatomic, retain) UIImageView *haveMissileView;
@property (nonatomic, retain) UIImageView *hackView;
@property (nonatomic, retain) UIImageView *volumeView;
@property (nonatomic, retain) UIImageView *infoView;
@property (nonatomic, retain) UIImageView *helpView;

@property (nonatomic, retain) UILabel *labelScore;
@property (nonatomic, retain) UILabel *labelCurrentLevel;
@property (nonatomic, retain) UILabel *labelGameOver;
@property (nonatomic, retain) UILabel *labelPause;
@property (nonatomic) SystemSoundID hitSound;
@property (nonatomic) SystemSoundID missSound;
@property (nonatomic) SystemSoundID clapSound;
@property (nonatomic) SystemSoundID explodeSound;
@property (nonatomic) SystemSoundID booSound;
@property (nonatomic) SystemSoundID holycowSound;
@property (nonatomic) SystemSoundID boingSound;
@property (nonatomic) SystemSoundID metalSound;
@property (nonatomic) SystemSoundID gotlifeSound;
@property (nonatomic) SystemSoundID missileSound;

@property (nonatomic, retain) NSTimer *gameTimer;
@property (nonatomic, retain) NSTimer *backgroundTimer;
@property (nonatomic, retain) NSTimer *harderTimer;

@property (nonatomic, retain) NSMutableArray *rainDrops;
[/objc]

  1. Standard stuff. I sort of copy-pasted here. Likely the @property settings need a relook.

[objc]

- (void) initTimer;
- (void) playGame:(NSTimer *)timer;
- (void) adjustBackground:(NSTimer *)timer;
- (void) makeItHarder:(NSTimer *)timer;

- (void) initBricks;
- (void) initLives;
- (void) initRain;
- (void) moveRain;
- (void) hideRain;
- (void) initExplosion;
- (void) initAudioStreams: (SystemSoundID *)soundId: (NSString *)soundFile: (NSString *) type;
-(void) playAudio: (SystemSoundID) soundId;
- (void) resetAlphasforLives:(int) livesVal forBricks:(int) bricksVal ;
-(void) explodeBrick: (int) y : (int) x;
- (void) initBrickLayout;
- (void) launchMissile;
- (void) saveState;

@end
[/objc]

  1. Finally, we declare some of the internal functions of the game class. I'll explain them all later in the implementation file.

End of Part I


Well, that's it for now. I hope you are getting a good sense of the 'implementation direction' by going through the .h. In the next part of the tutorial, I will dissect the implementation of each function as well as post a ZIP file for you to download the project and files.

In the meantime...


If you are a pro, or a better beginner than me, feel free to leave comments here on what mistakes you may have already spotted. Thanks.

On to Part II - the Implementation


Click here.

16 comments:

  1. [...] Part I, we discussed the approach to implement a professional looking Bricks game for the iphone. We also [...]

    ReplyDelete
  2. [...] Cocos2D has made immortal. I have just started learning Cocos2D as a platform for game development. After my earlier effort of building Bricks using UIKit, I discovered Cocos2D and this is my first venture into [...]

    ReplyDelete
  3. Amazing tutorial about iPhone game programming!!!! I am an iPhone application developer. I’ll try your code.

    ReplyDelete
  4. how can i make a pause button ?

    ReplyDelete
  5. If you are using UIKit, doing a pause is the same as not updating your logic/screens in the timer - so you could just keep a variable toggled which you can check inside your main game timer. If its on, you are in pause state (and you display a tappable pause button). If its off, you keep going.

    ReplyDelete
  6. The code suggested had to be tried. As a iphone app developer, I would attempt to use it. If it gives better result, I will use it forever.
    Mobile App Developer

    ReplyDelete
  7. Great post! I am actually getting ready to go across, this post is very informative. By the way, Get Happy fathers day

    ReplyDelete
  8. Thanks for Sharing great article. It solve my few errors which I am getting in programming for creating App.
    Thanks
    iPhone App development

    ReplyDelete
  9. I simply intend to inform you you that I am new to having a blog and totally adored your write-up. Very possible I am probably to store your blog post .
    Dentist in Dubai
    Veneers in Dubai
    Dental Clinic in Dubai
    Dental center in Dubai

    ReplyDelete