
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 Nicholas, Worms, 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 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.
- 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).
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.
// 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 Miners gameplay video below










Very awesome share. Very appreciated!!
Thanks!
Thanks!
Amazing! It goes right to the top of my “must read articles”
Congrats for your game
Thank you for sharing your code with the community. Just bought a copy of micro miners but hope others reward your gesture of sharing your code by buying your excellent game.
Amazing post, this class looks really great. I’m sure I’ll be using it in the near future.
And your game is great fun by the way.
Thanks a lot.
Amazing, I always wonder how the “pixel destructible” engines works.
Very sweet indeed!
My Goodness!! so can we say thats how Where’s my water works !!!!
@Rakshak , I don’t think that the destructible ground in “Where’s my water?” is pixel based. Look at this example on cocos2d forums by Birkemose, its done with Chipmunk and it’s called a deformable terrain. I think it’s probably more this kind of engine they used for “Where’s my water?”.
http://www.cocos2d-iphone.org/forum/topic/29216