Create a Flash game like Roly Poly with Box2D

Read all posts about "" game

One of the first Nitrome games was Roly Poly.

It was a nice game based loosely based on physics, it was early 2006 and developers did not have that much physics engines to rely on.

Luckily in late 2012 we have Box2D which will help us to build our version of Roly Poly, even better than the original, cute graphics excluded.

Starting with some concepts about level design, I have to say you can reproduce most of the original levels using a tile based approach, and the aim of this first part is to create a level template using Box2D and a set of tiles.

This is what you’ll get at the end of the script:

Look at what we have: the circumference and a set of tiles ready to be activated or deactivated in order to generate a level.

And this is the script which generates it:

package {
import flash.display.Sprite;
import flash.events.Event;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
public class Main extends Sprite {
private var world:b2World=new b2World(new b2Vec2(0,10),true);
private var worldScale:Number=30;
private var rolyCenter:b2Vec2=new b2Vec2(320,240);
private var rolyRadius:Number=230;
private var rolyPieces:Number=24;
private var tileSize:Number=32;
public function Main() {
var centerAngle:Number=2*Math.PI/rolyPieces;
var rolySide:Number=rolyRadius*Math.tan(centerAngle/2)/worldScale;
rolyCenter.Multiply(1/worldScale);
debugDraw();
var bodyDef:b2BodyDef=new b2BodyDef();
bodyDef.position=rolyCenter;
var rolyLevel:b2Body=world.CreateBody(bodyDef);
var polygonShape:b2PolygonShape=new b2PolygonShape();
var fixtureDef:b2FixtureDef=new b2FixtureDef();
fixtureDef.shape=polygonShape;
fixtureDef.restitution=0;
fixtureDef.friction=1;
for (var i:Number=0; i<rolyPieces; i++) {
var angle:Number=2*Math.PI/rolyPieces*i;
polygonShape.SetAsOrientedBox(0.1,rolySide,new b2Vec2(rolyRadius/worldScale*Math.cos(angle),rolyRadius/worldScale*Math.sin(angle)),angle);
rolyLevel.CreateFixture(fixtureDef);
}
var numberOfTiles:Number=Math.ceil(rolyRadius*2/tileSize);
if (numberOfTiles%2==0) {
numberOfTiles++;
}
var tileSizePX:Number=tileSize/worldScale;
for (i=0; i<numberOfTiles; i++) {
for (var j:Number=0; j<numberOfTiles; j++) {
polygonShape.SetAsOrientedBox(tileSizePX/2,tileSizePX/2,new b2Vec2(tileSizePX*(numberOfTiles/2-i)-tileSizePX/2,tileSizePX*(numberOfTiles/2-j)-tileSizePX/2),0);
rolyLevel.CreateFixture(fixtureDef);
}
}
addEventListener(Event.ENTER_FRAME,updateWorld);
}
private function debugDraw():void {
var debugDraw:b2DebugDraw=new b2DebugDraw();
var debugSprite:Sprite=new Sprite();
addChild(debugSprite);
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(worldScale);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);
debugDraw.SetFillAlpha(0.5);
world.SetDebugDraw(debugDraw);
}
private function updateWorld(e:Event):void {
world.Step(1/30,10,10);
world.ClearForces();
world.DrawDebugData();
}
}
}

Let me explain the most interesting lines:

Line 11: rolyCenter is a b2Vec2 variable storing the center of the rolling maze. As you can see I am using pixel units to make level design easier, I will convert it to Box2D meters later on.

Line 12: rolyRadius is the radius of the rolling maze, in pixels.

Line 13: rolyPieces is the number of segments which will be used to approximate a circumference. Box2D does not allow us to create hollow circles, so rolling maze borders will be defined by a set of rectangles. I found 24 or 32 fit our needs, anyway feel free to experiment.

Line 14: tileSize represents the size of the tiles, in pixels.

Line 16: assuming I am dividing a circumference in rolyPieces slices, centerAngle is the angle represented by each slice.

Line 17: knowing the angle and the radius of the circle, I am able to determine the length of each segment which will approximate the circumference thanks to trigonometry.

Line 18: this is where I convert rolyCenter variable declared at line 11 from pixels to meters.

Lines 20-27: Creating a body along with its shape and fixture as seen a million times in this blog.

Lines 28-32: Placing all the boxes which will approximate the circumference as a compound object. For more information about compound objects refer to this post.

Line 33: Determining the number of tiles to be placed inside the circle, according to circle radius and tile size.

Lines 34-36: I don’t want to have an even number of tiles because I always want a tile to be placed exactly at the center of the circle.

Line 37: Temporary variable just to conver the tile size in meters

Lines 38-43: Placing all tiles, as part of the same compound object started with the circumference.

And that’s all for today, net time I’ll show you how to create and animate a real level.

Download the source code.

</rolypieces;>

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers