Pixel based destructible ground with Cocos2d

Micro Miners iOS game

OMG a giant worm! Micro Miners iOS game.

 

Worms, Lemmings, Micro Miners…

A pixel based destructible ground is the kind of engine used in many popular games such as early appstore hit iShoot by Ethan NicholasWorms, or Lemmings. And also, since the 15th of November 2012, in my new iOS game Micro Miners. I started Micro Miners two years ago, after testing an amazing class called CCMutableTexture that was crafted and shared by the not less amazing Lam Pham. “2 years ago” means the source code provided here is based on cocos2d v1, but not too difficult to adapt to v2, I guess.

For this article, I’ve created a Xcode v4.5 + Cocos2d v1.01 project with a basic destructible ground engine. This is intended to be very simple starting point if you want to make your own game base on destructible grounds. But in any case this is a ready to use destructible ground engine.

I also recorded a short video of the project in action on the iPhone simulator. A quick way to see if this article could be of any interest to you.

Source code : https://github.com/jpsarda/Pixel-based-destructible-ground-with-Cocos2d-iPhone

1) GitHub project and video demo

Watch carefully the video below, it shows exactly what you get when you download, compile and run the demo project provided on GitHub.

2) The performance bottleneck

The engine is based on the CCMutableTexture class. Basically, a CCMutableTexture maintains an array of pixels value representing the texture. You can then quickly access and modify the pixels in this array. But once you’re done with the modifications, you have to apply them. The internal pixel array is then drawn on the actual texture. This step is the performance bottleneck of the destructible ground engine. Knowing this, all must be done to minimize the surface of the CCMutableTexture we draw on, and the number of times we call apply on the CCMutableTexture.

3) Minimizing the surface of the CCMutableTextures

This is achieved in 2 steps

  1. 1 pixel on the texture will be rendered as a 2×2 square on the screen. In other words the displayed CCSprite associated to the texture is scaled by a factor of 2. The look is more pixelated but it’s still acceptable. For example, instead for applying our changes on a 320×480 texture, we will apply them on a 160×240 texture. This is 4 times less pixels to draw when we call apply on the CCMutableTexture.
  2. If we use full screen textures, each time we move our finger on the screen to dig the ground, the full screen CCMutableTexture is modified and we must call apply on it. That’s a pity because only a small part of the screen is affected by our finger. To prevent this, the ground is splited in zones. In the project provided, we’ve splited the ground in 4 stripes (from top to bottom). When we dig the ground, only the affected zones are redrawn (you can see the affected grounds colorized in red while digging).

Destructible ground, 1 zone affected

Finger digging in the middle of a ground zone, only 1 zone affected.

Destructible grouns, 2 zones affected

Finger digging at the border of 2 zones, 2 zones affected.

4) Minimizing the calls to apply

ccTouchesMoved, which is the method invoked when the user moves his finger on the screen, can be called at very high frequency. We can’t afford to call apply on the textures on every move. We solve this problem by introducing a minimum delay (0.5 seconds) to pass before taking into account a move of the finger. Illustrated with this peace of code in ccTouchesMoved :

if (now-lastDigTime>0.05f) {
    // determine affected zones ...
    // draw lines ...
    // apply changes ...
    lastDigTime=now;
}


5) Digging and polygons

The awesome CCMutableTexture class was modified mainly to add polygon drawing capabilities.

Drawing a line with rounded extremities via convex polygon filling

Drawing a line with rounded extremities via convex polygon filling

// This method fills a convex polygon with a given color
-(void) fillConvexPolygon:(CGPoint*)p :(int)n withColor:(ccColor4B)c;
 
// This method draws a solid line (with line width parameter) by building a polygon to be used in fillConvexPolygon
-(void) drawLineFrom:(CGPoint)p0 to:(CGPoint)p1 withLineWidth:(float)w andColor:(ccColor4B) c;

So here is what happens when you move your finger on the screen to dig in the ground :

  • We call drawLineFrom:A to:B withLineWidth: andColor: , A and B being respectively the coordinates of the finger before the move and after the move.
  • The method build a 10 points polygon to draw a rounded line from A to B (4 points to draw the rectangle and 3 points for each rounded extremities)
  • We call fillConvexPolygon: : withColor: with the calculated polygon.
  • Before drawing, the points of the polygon are ordered from bottom to top.
  • The polygon is filled from bottom to top by drawing horizontal lines.
  • On each step of the drawing loop, we follow the left and right edges of the polygon to determine the coordinates of the horizontal line to be drawn.

6) Drawing on different zones

Most of the time, your finger on the screen will affect only one zone of ground. But when the finger cross a zones border, it hits 2 zones at the same time. When this happens, we draw the polygon on each textures. That means our polygon filling algorithm is run twice instead of once. That’s the price to pay for splitting the ground in zones, but it’s insignificant compared to the cost of not splitting the grouns in zones (see 2) and 3)).

7) Collisions

I’ve added some basic tiny miners in the demo project to show how to handle collisions. They will fall if you dig the ground under their feet.

For collision checking, we consider a miner to be 1 pixel. First we determine which ground zone contains the collision pixel. Then, by calling getPixelAt in the CCMutableTexture associated to the zone, we determine if the collision pixel is in a hole (alpha=0) or not.

8) Go further

  • Create a class to handle the multi-zone destructible ground, that will handle polygon drawing and zone detection.
  • Create a class to handle the characters (miners, lemmings, whatever…), make them walk, jump, …
  • Manage the scrolling of the ground, dynamically create new ground zones when needed.
  • Split the ground in smaller zones, vertical AND horizontal splitting managed with a 2-dimensional array. Necessary for large maps in both width and height.

Thank you for reading. Let’s keep in touch on twitter @jpsarda.

Micro MinersDownload Micro Miners on the AppStore : iTunes link.

Micro Miners gameplay video below

 

 

 

10 Responses to “Pixel based destructible ground with Cocos2d”


Leave a Reply




Social Widgets powered by AB-WebLog.com.