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
| package {
/*
* Tony Lukasavage - SavageLook.com - 8/18/2010
* Box2DFlashAS3 2.1a HelloWorld example, minus the need for an accompanying FLA
*
* This the basic Box2DFlashAS3 HelloWorld.as file from the source distribution
* with some adjustments made so that you do not need an FLA file to compile and
* run the code. A simple bonus for us pure AS3 guys. Also a few minor modifications
* are made to account for changes between version 2.0 and 2.1, like adding a type
* for body definitions. Finally, I threw in an click handler to toggle between
* normal and debug drawing.
*
*/
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.*;
import __AS3__.vec.Vector;
import com.adobe.viewsource.ViewSource;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFormat;
[SWF(width="800", height="600", frameRate="30")]
public class box2d extends Sprite
{
private var _world:b2World;
private var _velocityIterations:int = 10;
private var _positionIterations:int = 10;
private var _timeStep:Number = 1.0 / 30.0;
private var _showDebug:Boolean = true;
private var _debugSprite:Sprite;
private var _bodySprites:Vector. = new Vector.();
// Box2D uses meters for measurement, AS3 uses pixels. 1 meter = 30 pixels
public var _worldRatio:int = 30;
public function box2d()
{
// Add event for main loop
addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
stage.addEventListener(MouseEvent.CLICK, onClick );
// add background gradient
var bg:Sprite = new Sprite();
var matrix:Matrix = new Matrix();
matrix.createGradientBox(stage.stageWidth, stage.stageHeight, Math.PI/2, 0, 0);
bg.graphics.beginGradientFill("linear", [0x9999ff, 0xffffff], [1, 1], [0, 255], matrix);
bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
bg.graphics.endFill();
addChild(bg);
// Define the gravity vector
var gravity:b2Vec2 = new b2Vec2(0.0, 10.0);
// Allow bodies to sleep
var doSleep:Boolean = true;
// Construct a world object
_world = new b2World(gravity, doSleep);
// set debug draw
var debugDraw:b2DebugDraw = new b2DebugDraw();
_debugSprite = new Sprite();
addChild(_debugSprite);
debugDraw.SetSprite(_debugSprite);
debugDraw.SetDrawScale(_worldRatio);
debugDraw.SetFillAlpha(0.5);
debugDraw.SetLineThickness(2);
debugDraw.SetAlpha(1);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
_world.SetDebugDraw(debugDraw);
// Vars used to create bodies
var body:b2Body;
var bodyDef:b2BodyDef;
var boxShape:b2PolygonShape;
var circleShape:b2CircleShape;
// Adding sprite variable for dynamically creating body userData
var sprite:Sprite;
var groundHeight:int = 60;
sprite = new Sprite();
sprite.graphics.lineStyle(1);
sprite.graphics.beginFill(0x444444);
sprite.graphics.drawRect(-stage.stageWidth/2, -groundHeight/2, stage.stageWidth, groundHeight);
sprite.graphics.endFill();
bodyDef = new b2BodyDef();
bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.Set(stage.stageWidth / _worldRatio / 2, (stage.stageHeight - sprite.height/2) / _worldRatio);
bodyDef.userData = sprite;
addChild(bodyDef.userData);
boxShape = new b2PolygonShape();
boxShape.SetAsBox(sprite.width/_worldRatio/2, sprite.height/_worldRatio/2);
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = boxShape;
fixtureDef.friction = 0.3;
fixtureDef.density = 0; // static bodies require zero density
body = _world.CreateBody(bodyDef);
body.CreateFixture(fixtureDef);
// Add some objects
for (var i:int = 1; i < 20; i++) {
// create generic body definition
bodyDef = new b2BodyDef();
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.x = Math.random() * 15 + 5;
bodyDef.position.y = Math.random() * 10;
var rX:Number = Math.random() + 0.5;
var rY:Number = Math.random() + 1;
var spriteX:Number = rX * 30 * 2;
var spriteY:Number = rY * 30 * 2;
// Box
if (Math.random() < 0.5) {
sprite = new Sprite();
sprite.graphics.lineStyle(1);
sprite.graphics.beginFill(0xff6666);
sprite.graphics.drawRect(-spriteX/2, -spriteY/2, spriteX, spriteY);
sprite.graphics.endFill();
bodyDef.userData = sprite;
boxShape = new b2PolygonShape();
boxShape.SetAsBox(rX, rY);
fixtureDef.shape = boxShape;
fixtureDef.density = 1.0;
fixtureDef.friction = 0.5;
fixtureDef.restitution = 0.2;
body = _world.CreateBody(bodyDef);
body.CreateFixture(fixtureDef);
}
// Circle
else {
sprite = new Sprite();
sprite.graphics.lineStyle(1);
sprite.graphics.beginFill(0x44ff44);
sprite.graphics.drawCircle(0, 0, spriteX/2);
sprite.graphics.endFill();
bodyDef.userData = sprite;
circleShape = new b2CircleShape(rX);
fixtureDef.shape = circleShape;
fixtureDef.density = 1.0;
fixtureDef.friction = 0.5;
fixtureDef.restitution = 0.2;
body = _world.CreateBody(bodyDef);
body.CreateFixture(fixtureDef);
}
_bodySprites.push(bodyDef.userData as Sprite);
addChild(bodyDef.userData);
}
// enable view source
ViewSource.addMenuItem(this, "srcview/index.html");
var text:TextField = new TextField();
text.text = "Right click to view source";
text.setTextFormat(new TextFormat("arial", 14, 0, true));
text.x = 20;
text.y = 20;
text.width = 200;
addChild(text);
}
public function onClick(e:MouseEvent):void {
_showDebug = !_showDebug;
if (!_showDebug) {
_debugSprite.graphics.clear();
}
for each (var sprite:Sprite in _bodySprites) {
sprite.visible = !_showDebug;
}
}
public function Update(e:Event):void{
_world.Step(_timeStep, _velocityIterations, _positionIterations);
if (_showDebug) {
_world.DrawDebugData();
}
// Go through body list and update sprite positions/rotations
for (var bb:b2Body = _world.GetBodyList(); bb; bb = bb.GetNext()){
if (bb.GetUserData() is Sprite){
var sprite:Sprite = bb.GetUserData() as Sprite;
sprite.x = bb.GetPosition().x * 30;
sprite.y = bb.GetPosition().y * 30;
sprite.rotation = bb.GetAngle() * (180/Math.PI);
}
}
}
}
}
|