Danger Tank! is complete

The game in all it's glory

Danger Tank has been completed and is now with Apple being reviewed. It’s been a long time coming and has been a great learning experience for me, I’ve come to know and love Cocos2d for iPhone very much. I thought I’d share some of my biggest lessons learned while writing this game, so here they are as a handy bulleted list:

  1. Design your code – I’m a hacker (ethical) by trade and as such am used to cobbling together code in a quick-and-dirty manner to get different tasks done quickly. As my lecturers always used to say, a little design saves a lot of time. I can honestly say that if I’d even just scribbled down some rough classes in a diagram first, it would have helped.
  2. Whenever you have a problem, dip into Cocos2d’s documentation before you go about solving it yourself. There’s been quite a few helpful functions that I didn’t realise existed until I’d already re-written them, mostly for vector mathematics. ccpAdd, ccpSub, ccpMult, ccpDot, ccpCross etc. All of these are your friends.
  3. Don’t expect too much of yourself. Programming throws up difficult problems, sometimes in places that you don’t expect to find them. Don’t get upset if you end up spending an entire day trying to implement some tiny part of your game and don’t get anywhere. Take a break and refocus :-)
  4. Check out freesound.org for some free-to-use sound effects. Danger Tank!’s sound effects are all excellent and are sourced almost exclusively from there. Don’t forget to credit the original authors.
  5. If you’re gonna do your own graphics, get a drawing tablet. I have a Wacom Bamboo that I got for about £60 and it’s awesome. Also a decent drawing package will help. GIMP is good for free, but I use Serif’s Drawplus.
  6. Test your game a LOT. If you’re obsessive like me, this shouldn’t be a problem cos you’ll want to fiddle with it all the time anyway. All I can say is that how my girlfriend didn’t go mental from the continuous explosion sound effects I’ll never know. But testing is important, so give it to others to try and listen to their feedback. Danger Tank! had a few modifications due to suggestions from my testing team: Thanks to Ween, Al and Kirsty for their input.

So there you go, I hope that was both interesting and informative! Danger Tank’s fate is now in the hands of the Gods (and Apple, although I in no way want to link the two).

The Cat Sat On An Orange And Had Histerics

Writing games generally involves a fair bit of trigonometry. I never really liked it at school but it turns out I did remember one thing: a little phrase to aid one’s memory of equations for a right-angled triangle. In my current project I need to work out a coordinate position based on an angle and a distance – which relate to the angle and hypotenuse of said triangle. Now I realise this isn’t rocket science, but because I’m so generous I’m gonna share my function for returning the coordinates (from 0,0 origin) to a point at an angle and distance:

CGPoint translateAngleDistance(float angle, float distance)
{
CGPoint returnVal;
returnVal.x = cos(angle) * distance;
returnVal.y = sin(angle) * distance;
return returnVal;
}

Translating touch coordinates from screen to world using Cocos2d

EDIT: Danger Tank!’s camera feature no longer overrides visit(). Instead, it uses the main layer’s camera object and changes its coordinates to pan around the screen. Zoom is handled by scaling the main layer rather than changing the camera’s zEye value.

After hours of fiddling around and searching forums for a solution to this problem, I’ve worked it out and it’s fairly simple. What needs to be done is to calculate the touch’s screen coordinates as a proportion of the screen’s width and height, then apply that to the visible section of the world (between the horizontal and vertical clipping planes). My game at present does camera plane calculations manually by overriding the visit() function of the main layer and doing some magic with glOrthof(). The camera I use is actually just a dummy layer, using its position for the camera position and the scale property for zoom. Clip planes are then calculated as follows:

glOrthof(cameraLayer.position.x – SCREEN_WIDTH / (2 * cameraLayer.scale),                    cameraLayer.position.x + SCREEN_WIDTH / (2 * cameraLayer.scale),             cameraLayer.position.y – SCREEN_HEIGHT / (2 * cameraLayer.scale),             cameraLayer.position.y + SCREEN_HEIGHT / (2 * cameraLayer.scale),
-1000,
1000);

The following code will translate a touch to world coordinates using the method described above:

CGPoint touchRatios;
touchRatios.x = currentTouch.x / SCREEN_WIDTH;
touchRatios.y = currentTouch.y / SCREEN_HEIGHT;
currentTouch.x = (clipPlaneLeft + SCREEN_WIDTH / 2) + (clipPlaneRight – clipPlaneLeft) * touchRatios.x;
currentTouch.y = (clipPlaneTop + SCREEN_HEIGHT / 2) + (clipPlaneBottom – clipPlaneTop) * touchRatios.y;

The clipPlaneX values are calculated as shown in the glOrthof() call above, where they are shown in left, right, top then bottom order. -1000 and 1000 are the near and far planes, these seem to work fine for my needs.

Mmmmm, Clouds

Hi everyone, the terrain generation algorithms and parallax scrolling for the main game arenas are now pretty much done. Here’s an exciting screengrab from the simulator. For those who don’t know, parallax scrolling is a 2D technique to give the illusion of some depth by moving the background at a different rate to the foreground. My elegant solution is that whenever the camera moves, the background (sky and clouds) move at half the speed in the same direction. Adding further layers that move at different fractions of the front layer gives an even greater illusion of depth!

An early finished version of the main arena