Install Circle Chain on your iPhone for free and get the source code!! 645 downloads to go - last updated: April 21, 2012

Box2D collisions rendered in 3D with Away3D

Did you ever wonder what would be possible if you could merge a 2D physics engine with a 3D engine?

Roger Engelbert from Done With Computers, apart from having a blog with awesome posts (really! have a look!), tried to use Away3D to render Box2D collisions.

You will see the result by yourself.

« Here I’ll show you another way to build 3D collisions using 2D logic, by combining the Box2D engine with 3D rendering of elements. For this example, you must think of games where the 3D Y axis is not relevant (no change in altitude.)

In the game you can push the blue blocks, the larger one is harder to push around. And you cannot push the green cylinder. And when you shoot you a have nice recoil effect.

Here is the Box2D version of the “game”:

Use arrows to move, and space bar to shoot.

And here is the code for this version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
package  
{  
    import Box2D.Collision.Shapes.*;  
    import Box2D.Collision.b2AABB;  
    import Box2D.Common.Math.*;  
    import Box2D.Dynamics.*;  
 
    import flash.display.DisplayObjectContainer;  
    import flash.display.Sprite;  
    import flash.events.Event;  
    import flash.events.KeyboardEvent;  
    import flash.geom.*;  
    import flash.utils.Timer;  
 
    [SWF(width="800", height="600", backgroundColor="0x000000", frameRate="30")]  
    public class Box2Dto3D extends Sprite  
    {  
        private static const Y_DIR:int = 1;  
        private var _moveLeft:Boolean = false;  
        private var _moveRight:Boolean = false;  
        private var _moveUp:Boolean = false;  
        private var _moveDown:Boolean = false;  
 
        //box2D stuff  
        private var _world:b2World;  
        private var _player:b2Body;  
        private var _block1:b2Body;  
        private var _block2:b2Body;  
        private var speed:Number = 5;  
 
 
        private var player_rec:Rectangle = new Rectangle(0,0,50,50);  
        private var block1_rec:Rectangle = new Rectangle(-100,-100,80,80);  
        private var block2_rec:Rectangle = new Rectangle(-200,100,200,100);  
 
        private var shoot_timer:Timer = new Timer(500,1);  
        private var bullets:Vector.<b2body>;  
 
 
 
        public function Box2Dto3D()  
        {  
            x = 400;  
            y = 300;  
 
            bullets = new Vector.<b2body>();  
 
            createScene();  
 
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down, false, 0, true);  
            stage.addEventListener(KeyboardEvent.KEY_UP, onKey_Up, false, 0, true);  
            addEventListener(Event.ENTER_FRAME, onLoop, false, 0, true);  
        }  
 
        private function createScene ():void {  
 
            _world = new b2World(new b2Vec2(0,0),true);  
            var contactListener:BulletCollisionListener = new BulletCollisionListener();  
            _world.SetContactListener(contactListener);  
 
            //set up debug draw  
            var debugDraw:b2DebugDraw = new b2DebugDraw();  
            var container:Sprite = new Sprite();  
            addChild(container);  
            debugDraw.SetSprite(container);  
            debugDraw.SetDrawScale(30);  
            debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);  
            debugDraw.SetFillAlpha(0.5);  
 
 
            //create player  
            var bodyDef:b2BodyDef = createBoxDef(player_rec);  
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.allowSleep = false;  
            var bodyFixture:b2FixtureDef = createBoxFixture(player_rec);  
 
            _player = _world.CreateBody(bodyDef);  
            _player.CreateFixture(bodyFixture);  
 
            var data:Object = {};  
            data.type = "block";  
 
            //create obstacles  
            //block 1  
            bodyDef = createBoxDef(block1_rec);  
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.linearDamping = 20;  
            bodyFixture = createBoxFixture(block1_rec);  
            bodyFixture.density = 0.5;  
            bodyFixture.friction = 1;  
 
            _block1 = _world.CreateBody(bodyDef);  
            _block1.CreateFixture(bodyFixture);  
            _block1.SetUserData(data);  
 
            //block 2  
            bodyDef = createBoxDef(block2_rec);  
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.linearDamping = 20;  
            bodyFixture = createBoxFixture(block2_rec);  
            bodyFixture.density = 100;  
            bodyFixture.friction = 1;  
 
            _block2 = _world.CreateBody(bodyDef);  
            _block2.CreateFixture(bodyFixture);  
            _block2.SetUserData(data);  
 
            //fixed pillar  
            bodyDef = new b2BodyDef();  
            bodyDef.position.Set(p2m(100), p2m(40));  
            bodyDef.type = b2Body.b2_staticBody;  
            var bodyShape:b2CircleShape = new b2CircleShape();  
            bodyShape.SetRadius (p2m(20));  
            bodyFixture = new b2FixtureDef();  
            bodyFixture.shape = bodyShape;  
            bodyFixture.density = 1;  
 
            var pillar:b2Body = _world.CreateBody(bodyDef);  
            pillar.CreateFixture(bodyFixture);  
            pillar.SetUserData(data);  
 
 
            _world.SetDebugDraw(debugDraw);  
 
        }  
 
        private function shoot ():void {  
            if (shoot_timer.running) return;  
 
            //create particle  
            var bodyDef:b2BodyDef = new b2BodyDef();  
            var pPos:b2Vec2 = _player.GetPosition();  
            var angle:Number = _player.GetAngle()  + Y_DIR*Math.PI/2;  
            pPos.x -= p2m(10)*Math.cos(angle);  
            pPos.y -= p2m(10)*Math.sin(angle);  
 
            bodyDef.position.Set(pPos.x, pPos.y);  
 
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.angularDamping = 10;  
 
            var bodyShape:b2CircleShape = new b2CircleShape();  
            bodyShape.SetRadius (p2m(10));  
            var bodyFixture:b2FixtureDef = new b2FixtureDef();  
            bodyFixture.shape = bodyShape;  
            bodyFixture.density = 0;  
            bodyFixture.restitution = 0;  
 
            var bulletData:Object = {};  
            bulletData.type = "bullet";  
            bulletData.hit = false;  
 
            var bullet:b2Body = _world.CreateBody(bodyDef);  
            bullet.CreateFixture(bodyFixture);  
            bullet.SetUserData(bulletData);  
            bullet.SetLinearVelocity(new b2Vec2(-10*Math.cos(angle),-10*Math.sin(angle)));  
 
            bullets.push(bullet);  
 
            //shoot_timer.reset();  
            shoot_timer.start();  
        }  
 
        private function p2m(pixel:Number):Number {  
            return pixel/30;  
        }  
 
        private function m2p(m:Number):Number {  
            return m * 30;  
        }  
 
 
        private function updateBody ():void {  
 
            _player.SetLinearVelocity(new b2Vec2(0,0));  
 
 
            if (_moveLeft) _player.SetAngle( _player.GetAngle() - Y_DIR*0.1);  
            if (_moveRight) _player.SetAngle( _player.GetAngle() + Y_DIR*0.1);  
 
            var angle:Number = _player.GetAngle() + Math.PI/2;  
            var playerVelocity:b2Vec2 = _player.GetLinearVelocity();  
 
            if (_moveUp ) {  
                playerVelocity.x -= Y_DIR*speed*Math.cos(angle);  
                playerVelocity.y -= Y_DIR*speed*Math.sin(angle);  
 
            }  
            if (_moveDown ) {  
                playerVelocity.x += Y_DIR*speed*Math.cos(angle);  
                playerVelocity.y += Y_DIR*speed*Math.sin(angle);      
            }  
 
        }  
 
 
        ///////////////////////////// EVENTS ///////////////////////////////////////  
        private function onKey_Up (event:KeyboardEvent):void {  
 
            switch (event.keyCode) {  
                case 38:  
                    //UP KEY is up  
                    _moveUp = false;  
                    break;  
                case 39:  
                    //RIGHT KEY is up  
                    _moveRight = false;  
                    break;  
                case 37:  
                    //LEFT Key is up  
                    _moveLeft = false;  
                    break;  
                case 40:  
                    //DOWN KEY is up  
                    _moveDown = false;  
                    break;  
                case 32:  
                    //SPACE Bar is up  
                    shoot();  
                    break;  
            }  
        }  
        private function onKey_Down (event:KeyboardEvent):void {  
 
            switch (event.keyCode) {  
                case 38:  
                    //UP KEY is down  
                    _moveUp = true;   
                    break;  
                case 39:  
                    //RIGHT KEY is down  
                    _moveRight = true;  
 
                    break;  
                case 37:  
                    //LEFT Key is down  
                    _moveLeft = true;  
 
                    break;  
                case 40:  
                    //DOWN KEY is down  
                    _moveDown = true;  
                    break;  
                case 32:  
                    //SPACE BAR is down  
                    break;  
 
            }  
        }  
 
        private function onLoop (event:Event):void {  
            updateBody();  
 
            _world.Step(1/30,10,10);  
            _world.DrawDebugData();  
 
            for (var i:int = bullets.length-1; i >= 0; i--) {  
                if (bullets[i].GetUserData().hit == true) {  
                        _world.DestroyBody(bullets[i]);  
                        bullets.splice(i,1);  
                        break;  
                }  
            }  
        }  
 
        private function createBoxDef (rec:Rectangle):b2BodyDef {  
            var bodyDef:b2BodyDef = new b2BodyDef();  
            bodyDef.position.Set(p2m(rec.x + rec.width/2), p2m(rec.y + rec.height/2));  
            bodyDef.type = b2Body.b2_staticBody;  
            bodyDef.angularDamping = 10;  
            return bodyDef;  
        }  
 
 
        private function createBoxFixture (rec:Rectangle):b2FixtureDef {  
            var bodyShape:b2PolygonShape = new b2PolygonShape();  
            bodyShape.SetAsBox (p2m(rec.width/2), p2m(rec.height/2));  
            var bodyFixture:b2FixtureDef = new b2FixtureDef();  
            bodyFixture.shape = bodyShape;  
            bodyFixture.density = 1;  
            bodyFixture.restitution = 0;  
            return bodyFixture;  
        }  
 
    }  
}

And the collision object for the sake of completeness:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package {
	import Box2D.Dynamics.Contacts.b2Contact;
	import Box2D.Dynamics.b2ContactListener;
 
	public class BulletCollisionListener extends b2ContactListener {
		public function BulletCollisionListener() {
			super();
		}
 
		override public function BeginContact(contact:b2Contact):void {
 
			if (contact.GetFixtureA().GetBody().GetUserData()) {
				if (contact.GetFixtureA().GetBody().GetUserData().type == "bullet" &&  
				                        contact.GetFixtureB().GetBody().GetUserData().type == "block") {
					contact.GetFixtureA().GetBody().GetUserData().hit=true;
 
				}
			}
 
			if (contact.GetFixtureB().GetBody().GetUserData()) {
				if ( contact.GetFixtureB().GetBody().GetUserData().type == "bullet" &&  
				                        contact.GetFixtureA().GetBody().GetUserData().type == "block") {
 
					contact.GetFixtureB().GetBody().GetUserData().hit=true;
 
				}
			}
		}
	}
}

Now in 3D I use the same Box2D code but I add 3D primitives. Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
import away3d.cameras.*;  
    import away3d.containers.*;  
    import away3d.core.base.Object3D;  
    import away3d.lights.*;  
    import away3d.materials.*;  
    import away3d.primitives.*;  
 
    import flash.display.BitmapData;  
    import flash.display.DisplayObjectContainer;  
    import flash.display.Sprite;  
    import flash.events.Event;  
    import flash.events.KeyboardEvent;  
    import flash.geom.*;  
    import flash.utils.Timer;  
 
    [SWF(width="800", height="600", backgroundColor="0x444444", frameRate="30")]  
    public class Box3D extends Sprite {  
 
        //in case I need to adjust the change in Y direction  
        private static const Y_DIR:int = -1;  
        private var _moveLeft:Boolean = false;  
        private var _moveRight:Boolean = false;  
        private var _moveUp:Boolean = false;  
        private var _moveDown:Boolean = false;  
 
        //box2D stuff  
        private var _world:b2World;  
        private var _b2player:b2Body;  
        private var _b2block1:b2Body;  
        private var _b2block2:b2Body;  
        private var speed:Number = 5;  
 
        private var player_rec:Rectangle = new Rectangle(0,0,50,50);  
        private var block1_rec:Rectangle = new Rectangle(-100,100,80,80);  
        private var block2_rec:Rectangle = new Rectangle(-200,-200,200,100);  
 
        //away3D stuff  
        private var _view:View3D;  
        private var _player:Cube;  
        private var _block1:Cube;  
        private var _block2:Cube;  
        private var _container:ObjectContainer3D;  
        private var camera:TargetCamera3D;  
 
        private var shoot_timer:Timer = new Timer(500,1);  
        private var b2bullets:Vector.<b2body>;  
 
 
        public function Box3D() {  
            x = 400;  
            y = 300;  
            createScene();  
 
            b2bullets = new Vector.<b2body>();  
 
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey_Down, false, 0, true);  
            stage.addEventListener(KeyboardEvent.KEY_UP, onKey_Up, false, 0, true);  
            addEventListener(Event.ENTER_FRAME, onLoop, false, 0, true);  
        }  
 
        private function createScene ():void {  
            createBox2DWorld();  
            createAway3DView();  
        }  
 
        private function createBox2DWorld():void {  
 
            _world = new b2World(new b2Vec2(0,0),true);  
            var contactListener:BulletCollisionListener = new BulletCollisionListener();  
            _world.SetContactListener(contactListener);  
 
 
            //create player  
            var bodyDef:b2BodyDef = createBoxDef(player_rec);  
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.allowSleep = false;  
            var bodyFixture:b2FixtureDef = createBoxFixture(player_rec);  
 
            _b2player = _world.CreateBody(bodyDef);  
            _b2player.CreateFixture(bodyFixture);  
 
            var data:Object = {};  
            data.type = "block";  
 
            //create obstacles  
            //block 1  
            bodyDef = createBoxDef(block1_rec);  
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.linearDamping = 20;  
            bodyFixture = createBoxFixture(block1_rec);  
            bodyFixture.density = 0.5;  
            bodyFixture.friction = 1;  
 
            _b2block1 = _world.CreateBody(bodyDef);  
            _b2block1.CreateFixture(bodyFixture);  
            _b2block1.SetUserData(data);  
 
 
            //block 2  
            bodyDef = createBoxDef(block2_rec);  
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.linearDamping = 20;  
            bodyFixture = createBoxFixture(block2_rec);  
            bodyFixture.density = 10;  
            bodyFixture.friction = 1;  
 
            _b2block2 = _world.CreateBody(bodyDef);  
            _b2block2.CreateFixture(bodyFixture);  
            _b2block2.SetUserData(data);  
 
            //fixed pillar  
            bodyDef = new b2BodyDef();  
            bodyDef.position.Set(p2m(100), p2m(40));  
            bodyDef.type = b2Body.b2_staticBody;  
            var bodyShape:b2CircleShape = new b2CircleShape();  
            bodyShape.SetRadius (p2m(20));  
            bodyFixture = new b2FixtureDef();  
            bodyFixture.shape = bodyShape;  
            bodyFixture.density = 1;  
 
            var pillar:b2Body = _world.CreateBody(bodyDef);  
            pillar.CreateFixture(bodyFixture);  
            pillar.SetUserData(data);  
 
 
        }  
        private function createAway3DView ():void {  
            _container = new ObjectContainer3D();  
 
            var scene:Scene3D = new Scene3D();  
 
            camera = new TargetCamera3D();  
            camera.z = -1200;  
 
            _view = new View3D({scene:scene, camera:camera});  
            addChild(_view);  
 
            var light : PointLight3D = new PointLight3D();   
            light.position = new Vector3D(500,0,-500);  
            light.color = 0xFFFFFF;   
            light.diffuse = 0.7;  
            light.brightness = 2;  
            _view.scene.addLight(light);  
 
            //var material:WireColorMaterial = new WireColorMaterial(0xFF9900,{wireColor:0x000000});  
            var material:ShadingColorMaterial = new ShadingColorMaterial();   
            material.ambient = 0xFF9900;   
            material.diffuse = 0xFF9900;   
            material.specular = 0xFF9900;  
 
 
            var plane:Plane = new Plane({material:new WireColorMaterial(0x666666,{wireColor:0x666666}), width:1000,height:1000});  
            plane.bothsides = true;  
            plane.rotationX = 90;  
            plane.segmentsW = plane.segmentsH = 4;  
            plane.z = 200;  
            plane.y = 200;  
            plane.x = 30;  
            plane.ownCanvas = true;  
            _view.scene.addChild(plane);  
            _container.ownCanvas = true;  
 
            _player = new Cube({material:material, width:player_rec.width,height:player_rec.width,depth:player_rec.width});  
            _player.z = 25;  
            _player.x = player_rec.x;  
            _player.y = player_rec.y;  
            //create a 'face' for the cube, so player knows what is the front side  
            _player.cubeMaterials.bottom=new WireColorMaterial(0xFF3399,{wireColor:0x222222});  
            //use own canvas to help with z sorting       
            //_player.ownCanvas = true;  
            _container.addChild(_player);  
 
            material = new ShadingColorMaterial();   
            material.ambient = 0x0099FF;   
            material.diffuse = 0x0099FF;   
            material.specular = 0x0099FF;  
 
            _block1 = new Cube({material:material, width:block1_rec.width,height:block1_rec.width,depth:block1_rec.width});  
            _block1.z = 40;  
            _block1.x = block1_rec.x;  
            _block1.y = block1_rec.y;  
            _block1.segmentsD = 2;  
            _block1.segmentsH = 2;  
            _block1.segmentsW = 2;  
 
            _container.addChild(_block1);  
 
 
            _block2 = new Cube({material:material, width:block2_rec.width,height:block2_rec.height,depth:200});  
            _block2.z = 100;  
            _block2.x = block2_rec.x;  
            _block2.y = block2_rec.y;  
            _block2.segmentsD = 4;  
            _block2.segmentsH = 4;  
            _block2.segmentsW = 4;  
            _container.addChild(_block2);  
 
            material = new ShadingColorMaterial();   
            material.ambient = 0x66FF00;   
            material.diffuse = 0x66FF00;   
            material.specular = 0x66FF00;  
 
            var pillar:Cylinder = new Cylinder({material:material, radius:20, height: 60});  
            pillar.rotationX = 90;  
            /* 
            remember that the origin of an object is at its center: 
            so the z of every object is changed so that they are all "lying on the floor"  
            */  
            pillar.z = 30;  
            pillar.x = Y_DIR*100;  
            pillar.y = Y_DIR*40;  
            _container.addChild(pillar);  
 
 
            //rotate the view to add 3D feel and match the one from the 2D version   
            _container.rotationZ = -180;  
            _container.rotationX = -180;  
            _view.scene.rotationX = -45;  
 
            camera.target = _player;  
            _view.scene.addChild(_container);  
 
        }  
 
        private function shoot ():void {  
            if (shoot_timer.running) return;  
 
            //create particle in box2D  
            var bodyDef:b2BodyDef = new b2BodyDef();  
            var pPos:b2Vec2 = _b2player.GetPosition();  
            var angle:Number = _b2player.GetAngle() + Math.PI/2;  
            pPos.x -= p2m(10)*Math.cos(angle);  
            pPos.y -= p2m(10)*Math.sin(angle);  
 
            bodyDef.position.Set(pPos.x, pPos.y);  
 
            bodyDef.type = b2Body.b2_dynamicBody;  
            bodyDef.angularDamping = 10;  
 
            var bodyShape:b2CircleShape = new b2CircleShape();  
            bodyShape.SetRadius (p2m(10));  
            var bodyFixture:b2FixtureDef = new b2FixtureDef();  
            bodyFixture.shape = bodyShape;  
            bodyFixture.density = 0;  
            bodyFixture.restitution = 0;  
 
 
            var bullet:b2Body = _world.CreateBody(bodyDef);  
            bullet.CreateFixture(bodyFixture);  
            bullet.SetLinearVelocity(new b2Vec2(-10*Math.cos(angle),-10*Math.sin(angle)));  
 
 
            //create sprite3D  
            var sphere : Sphere = new Sphere({segmentsW:4,segmentsH:2, material:new WireColorMaterial(0xFF3399,{wireColor:0x222222}), radius:10 });  
            sphere.z = 35;  
            sphere.x = m2p(pPos.x);  
            sphere.y = m2p(pPos.y);  
            _container.addChild(sphere);  
 
            var bulletData:Object = {};  
            bulletData.type = "bullet";  
            bulletData.hit = false;  
            bulletData.sphere = sphere;  
            bullet.SetUserData(bulletData);  
 
            b2bullets.push(bullet);  
            shoot_timer.start();  
        }  
 
 
        private function p2m(pixel:Number):Number {  
            return pixel/30;  
        }  
 
        private function m2p(m:Number):Number {  
            return m * 30;  
        }  
 
        private function updateBody ():void {  
 
 
            _b2player.SetLinearVelocity(new b2Vec2(0,0));  
 
 
            if (_moveLeft) _b2player.SetAngle( _b2player.GetAngle() - 0.05);  
            if (_moveRight) _b2player.SetAngle( _b2player.GetAngle() + 0.05);  
 
            var angle:Number = _b2player.GetAngle() + Math.PI/2;  
            var playerVelocity:b2Vec2 = _b2player.GetLinearVelocity();  
 
            if (_moveUp ) {  
                playerVelocity.x -= speed*Math.cos(angle);  
                playerVelocity.y -= speed*Math.sin(angle);  
 
            }  
            if (_moveDown ) {  
                playerVelocity.x += speed*Math.cos(angle);  
                playerVelocity.y += speed*Math.sin(angle);    
            }  
 
        }  
        ///////////////////////////// EVENTS ///////////////////////////////////////  
        private function onKey_Up (event:KeyboardEvent):void {  
 
            switch (event.keyCode) {  
                case 38:  
                    //UP KEY is up  
                    _moveUp = false;  
                    break;  
                case 39:  
                    //RIGHT KEY is up  
                    _moveRight = false;  
                    break;  
                case 37:  
                    //LEFT Key is up  
                    _moveLeft = false;  
                    break;  
                case 40:  
                    //DOWN KEY is up  
                    _moveDown = false;  
                    break;  
                case 32:  
                    //SPACE Bar is up  
                    shoot();  
                    break;  
            }  
        }  
        private function onKey_Down (event:KeyboardEvent):void {  
 
            switch (event.keyCode) {  
                case 38:  
                    //UP KEY is down  
                    _moveUp = true;   
                    break;  
                case 39:  
                    //RIGHT KEY is down  
                    _moveRight = true;  
 
                    break;  
                case 37:  
                    //LEFT Key is down  
                    _moveLeft = true;  
 
                    break;  
                case 40:  
                    //DOWN KEY is down  
                    _moveDown = true;  
                    break;  
                case 32:  
                    //SPACE BAR is down  
                    break;  
 
            }  
        }  
 
        private function onLoop (event:Event):void {  
            updateBody();  
 
            _world.Step(1/30,10,10);  
 
            transformObject(_b2player, _player);  
            transformObject(_b2block1, _block1);  
            transformObject(_b2block2, _block2);  
 
            if (b2bullets) {  
                for (var i:int = b2bullets.length-1; i >= 0; i--) {  
                    transformObject(b2bullets[i], b2bullets[i].GetUserData().sphere);  
                    if (b2bullets[i].GetUserData().hit == true) {  
                        _container.removeChild(b2bullets[i].GetUserData().sphere);  
                        _world.DestroyBody(b2bullets[i]);  
                        b2bullets.splice(i,1);  
                        break;  
                    }  
                }  
            }  
 
            _view.render();  
 
        }  
        private function transformObject (original:b2Body, threeD:Object3D):void {  
            var position:b2Vec2 = original.GetPosition();  
            var angle:Number = original.GetAngle() * 180 / Math.PI ;  
 
            threeD.x = Y_DIR*m2p(position.x);  
            threeD.y = Y_DIR*m2p(position.y);  
            threeD.rotationZ = angle;  
        }  
 
        private function createBoxDef (rec:Rectangle):b2BodyDef {  
            var bodyDef:b2BodyDef = new b2BodyDef();  
            bodyDef.position.Set(p2m(rec.x + rec.width/2), p2m(rec.y + rec.height/2));  
            bodyDef.type = b2Body.b2_staticBody;  
            bodyDef.angularDamping = 10;  
            return bodyDef;  
        }  
 
 
        private function createBoxFixture (rec:Rectangle):b2FixtureDef {  
            var bodyShape:b2PolygonShape = new b2PolygonShape();  
            bodyShape.SetAsBox (p2m(rec.width/2), p2m(rec.height/2));  
            var bodyFixture:b2FixtureDef = new b2FixtureDef();  
            bodyFixture.shape = bodyShape;  
            bodyFixture.density = 1;  
            bodyFixture.restitution = 0;  
            return bodyFixture;  
        }         
 
    }  
}

And this is the result:

Use arrows to move, and space bar to shoot.

The code could be a lot cleaner and shorter if I’d used multiple classes, but I thought the example would be easier to understand if I used only one class.

One tip which I think is important would be to add some space between objects upon collision, in other words, make the collision area be slightly larger than the actual object. This will help with Z sorting. Sometimes in this example here, when you collide the player box with the blue boxes you can see the face segments get jagged and blink.

And the extra distance could be easily countered with a simple bump map in case it looks weird.

The problem of file size is however a big one. Box2D and Away3D are very heavy loads unfortunately. I’ll try to post the same code but with JigLib and see how that goes.

But I hope this helps with any ideas for 3D games you might have. I’ve seen race games using this engine, and third person shooters. They might seem very simple, but the number of fun games one could create with these simple ideas is amazing. And who says 3D has to be complicated!

Of course, uneven terrain in 3D can be a bitch…

Next I’ll do some line collision in 3D. »

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (24 votes, average: 4.96 out of 5)
Loading ... Loading ...
Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.
Be my fan on Facebook and follow me on Twitter! Exclusive content for my Facebook fans and Twitter followers

This post has 8 comments

  1. Patrick Mullady

    on March 15, 2011 at 8:45 pm

    Wow! This is a great example! Thanks for taking the time to put this out there.
    Exciting stuff.

  2. m1gu3l

    on March 15, 2011 at 9:40 pm

    http://m1gu3l.pl/demo/

  3. Chris Moeller

    on March 15, 2011 at 11:51 pm

    Very awesome, it’s inspiring!

    I can even see making a FPS with this idea – just have to handle ground collision in another way… But there also other engines tailored for that.

    Now I have about 4 new game ideas though! Thanks!

  4. Ze Ferreira

    on March 16, 2011 at 12:11 am

    nice demo m1gu3l

  5. MC

    on March 16, 2011 at 1:40 am

    I can see the potential… Thanx!

  6. Abmemar

    on March 16, 2011 at 10:57 am

    Please make the final step of Plants Vs Zombies !

  7. bieron

    on March 21, 2011 at 6:40 pm

    Another car game using box2d physic and away3d :
    http://www.yopsolo.fr/wp/2010/10/09/jeu-de-voiture/

  8. sonicoliver

    on July 1, 2011 at 7:51 pm

    If you use the correct z-sorting renderer in away3D it should sort out your z-rendering correctly…. woah… (@_@)