Wednesday, April 8, 2009

First day of madness

The secret to getting things done is just to do them. Over the course of today, Josiah was able to make most of the graphics for the game, and I was able to get almost all of his graphics in, get animations in, add a couple more units, and help prettify movement.

We started today with the following: . (Anyone who plays game maker games may recognise the art in this game as being ripped from a game known as Medieval Clash ... this was done during the prototyping stage to enable me, a programmer who can't draw, from having to try and draw things. The game we are making is in fact inspired by Medieval Clash.)

By the end of today, the game looked like this: .

This can be compared with Josiahs latest mockup, and you can see that we are well on track.

You may notice in the above image that there are two buttons repeated, and that they still have the old graphics. This is because I have not yet got Josiahs button images in the game (they are already complete). Cocos does not have an Atlassed HUD Image, like I thought they did, so I'm either going to have to get the HUD split into a separate image for each button state (bad ... ) or figure out another solution.

Now, I'm going to end this blog post on a quick tutorial on what specifically you need to create an animation in cocos2D and have it play and repeat. There may be a better way; this was the best I could find today. Due to our development cycle, the quick and easy wins are what we are aiming for.

Step 1: Create an AtlasSpriteManager

Assuming that you have an image named img.png, make the following call:

AtlasSpriteManager* mgr = [AtlasSpriteManager spriteManagerWithFile:@"img.png"];

Once you have your mgr, add it to your Layer, Scene, or other Cocos2D node.

[self addChild:mgr z:GAME_DEPTH];

Step 2: Create an AtlasSprite and add it to your AtlasSpriteManager
CGRect rect = CGRectMake(0, 0, 50, 50) ;
AtlasSprite* sprite = [[AtlasSprite alloc] initWithRect:rect spriteManager:mgr];
[mgr addChild:sprite z:GAME_DEPTH];

Step 3: Create an animation
An animation in Cocos2D is represented using an AtlasAnimation. So create an atlas animation and supply it with the rectangles you want.

AtlasAnimation* animation = [AtlasAnimation animationWithName:@"anim" delay: 0.1f];

If your sprite sheets, like many that exist, are laid our horizontally, you can use a nice cheat to get your sprites lined out without having to hard code each value.

int numFrames = 4;
for(int i = 0; i < numFrames; i++)
int x = rect.origin.x + (i * rect.size.width);
[animation addFrameWithRect:CGRectMake(x, rect.origin.y, rect.size.width, rect.size.height)];

Turn your animation into an action

Next, you must create an Animation action and apply it to your sprite.

id action = [Animate actionWithAnimation:animation];
[sprite runAction:acion];

On Repeating
The above will actually only play your animation once - if you want your sprite to play repetitively, you must create another action from your initial reaction that repeats. This can be done as below:

id repeatAction = [Repeat actionWithAction:action times:100];
[self runAction:repeatAction];

As best as I could tell, there was no way to create an action that would repeat forever. Supplying an aribritrarily large number to times may work in some cases, but I'd recommend actually digging deeper and finding a real solution, or implementing one, in most cases. In the case of this game, because of the small time frame and because our objects are not on screen for longer than 10 seconds at a time, setting the action to repeat 100 times was a suitable solution.


Jack Nutting said...

Thanks for this explanation, I was pretty lost on how to do this myself, and yours was the only example I could find!

Me said...

Hi, appreciate the post. It got me up and running super quick. My little contribution: you can repeat forever by changing the following:
id repeatAction = [Repeat actionWithAction:action times:100];

to this:

id repeatAction = [RepeatForever actionWithAction:action];

Thanks again!