Box2D platform engine alternative
2009-10-18 00:00:00 栖坿��WEB蝕窟利At line 5 the script imports levels (just one in this example) coded in this way:
package Levels {
public class Level1 extends GameLevel {
public function Level1(k:keys) {
//// Always remember to call the superior constructor first!
super(k);
//// The player:
createPlayer(250, 50);
//// The moveable blocks:
addBox(110, 110, 50, 50);
addBox(190, 200, 30, 50);
addBox(100, 50, 120, 20);
// Small see-saw:
addBox(400, 250, 30, 30);
addBox(400, 220, 200, 10);
addBox(480, 200, 20, 20);
//// The ground block:
addStaticBox(550/2, 300, 550, 20);
}
}
}
At line 10 the script calls the most important class, GameLevel, that’s made this way:
package {
import flash.display.Sprite;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
// Main Game Level class definition
public class GameLevel extends Sprite {
// Player:
public var playerBody:b2Body;
public var player:Player;
// Jump trigger:
public var upDown:Boolean = false;
// Misc:
public var lastBody:b2Body;
// Vars used to create bodies
public var body:b2Body;
public var bodyDef:b2BodyDef;
public var boxDef:b2PolygonDef;
public var circleDef:b2CircleDef;
// Keyboard listener:
public var keyboard:keys;
public function GameLevel(k:keys) {
keyboard = k;
// World Setup:
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-100.0, -100.0);
worldAABB.upperBound.Set(100.0, 100.0);
// 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
m_world = new b2World(worldAABB, gravity, doSleep);
player = new Player();
}
public function Update() {
// Wake up the player body, if it falls asleep, the player cannot
// move anymore!
playerBody.WakeUp();
// Jump:
if(keyboard.is_up()){
// Cheesy way to check if the button was hit, instead of being held down:
if(upDown == false){
var b1:b2Body = GetBodyAtPoint(player.x, player.y + player.height/2, true);
var b2:b2Body = GetBodyAtPoint(player.x-7, player.y + player.height - 4, true);
var b3:b2Body = GetBodyAtPoint(player.x+7, player.y + player.height - 4, true);
if((b1 != playerBody && b2 != playerBody && b3 != playerBody) && b1 != null || b2 != null || b3 != null && playerBody.m_linearVelocity.y >= 0){
var DO = true;
if(DO){
playerBody.ApplyImpulse(new b2Vec2(0, -10), playerBody.GetPosition());//playerBody.m_linearVelocity.y = -10;
// If you want the underliying body to react according to Newton's
// second law of motion (it's pushed down), uncoment the following laws:
/*var bo = (b1 != null ? b1 : (b2 != null ? b2 : b3));
bo.ApplyImpulse(new b2Vec2(0, 10), playerBody.GetPosition());*/
}
}
upDown = true;
}
}else{
upDown = false;
}
// Side movements:
if(keyboard.is_right()){
playerBody.m_linearVelocity.x = 3;
}
if(keyboard.is_left()){
playerBody.m_linearVelocity.x = -3;
}
// Sted the world:
m_world.Step(m_timeStep, m_iterations);
// Go through body list and update sprite positions/rotations
for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next){
if (bb.m_userData is Sprite){
bb.m_userData.x = bb.GetPosition().x * 30;
bb.m_userData.y = bb.GetPosition().y * 30;
bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
}
}
}
// Create the player using this function, _x and _y are the coordinates to place
// the object:
public function createPlayer(_x, _y) : b2Body {
bodyDef = new b2BodyDef();
bodyDef.position.x = _x / 30;
bodyDef.position.y = _y / 30;
circleDef = new b2CircleDef();
circleDef.radius = 30 / 2 / 30;
circleDef.density = 1.0;
circleDef.friction = 1;
circleDef.restitution = 0.1;
var mass:b2MassData = new b2MassData;
mass.mass = 1;
bodyDef.userData = player;
player.x = _x;
player.y = _y;
addChild(player);
body = m_world.CreateDynamicBody(bodyDef);
body.SetMass(mass);
body.CreateShape(circleDef);
body.m_linearDamping = 1;
playerBody = body;
return playerBody;
}
// Using this function, you can create dynamic (moveable) blocks.
// The parameters are self-explanatory.
// The userData parameter is optional and it replaces the boring
// sprite used to represent the box.
public function addBox(x, y, wid, heig, userData:* = null) : b2Body {
bodyDef = new b2BodyDef();
bodyDef.position.x = x/30;
bodyDef.position.y = y/30;
boxDef = new b2PolygonDef();
boxDef.SetAsBox(wid/30/2, heig/30/2);
boxDef.density = 1.0;
boxDef.friction = 0.7;
boxDef.restitution = 0.2;
if(userData != null){
bodyDef.userData = userData;
}else{
bodyDef.userData = new PhysBox(wid, heig);
//bodyDef.userData.width = wid * 2;
//bodyDef.userData.height = heig * 2;
addChild(bodyDef.userData);
}
body = m_world.CreateDynamicBody(bodyDef);
body.CreateShape(boxDef);
body.SetMassFromShapes();
lastBody = body;
return body;
}
// Using this function, you can create static (non-moveable) blocks.
// The parameters are self-explanatory.
// The userData parameter is same as in addBox function.
public function addStaticBox(x, y, wid, heig, userData:* = null) : b2Body {
var bodyDef = new b2BodyDef();
bodyDef.position.x = x/30;
bodyDef.position.y = y/30;
boxDef = new b2PolygonDef();
boxDef.SetAsBox(wid/30/2, heig/30/2);
boxDef.density = 0.0;
boxDef.friction = 0.5;
boxDef.restitution = 0.2;
if(userData != null){
bodyDef.userData = userData;
}else{
bodyDef.userData = new PhysBox(wid, heig);
//bodyDef.userData.width = wid * 2;
//bodyDef.userData.height = heig * 2;
addChild(bodyDef.userData);
}
body = m_world.CreateStaticBody(bodyDef);
body.CreateShape(boxDef);
body.SetMassFromShapes();
lastBody = body;
return body;
}
// Really, dunno how this works, but it does. And that's what matters.
public function GetBodyAtPoint(px:Number, py:Number, includeStatic:Boolean = false) : b2Body {
// Make a small box.
var px2 = px/30;
var py2 = py/30;
var PointVec:b2Vec2 = new b2Vec2();
PointVec.Set(px2, py2);
var aabb:b2AABB = new b2AABB();
aabb.lowerBound.Set(px2 - 0.001, py2 - 0.001);
aabb.upperBound.Set(px2 + 0.001, py2 + 0.001);
// Query the world for overlapping shapes.
var k_maxCount:int = 10;
var shapes:Array = new Array();
var count:int = m_world.Query(aabb, shapes, k_maxCount);
var body:b2Body = null;
// The loop that seeks for the body:
for (var i:int = 0; i <count; ++i) {
if (shapes[i].m_body.IsStatic() == false || includeStatic) {
var tShape:b2Shape = shapes[i] as b2Shape;
var inside:Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), PointVec);
if (inside) {
body = tShape.m_body;
break;
}
}
}
return body;
}
// Physics world and definitions
public var m_world:b2World;
public var m_iterations:int = 20;
public var m_timeStep:Number = 1.0/25.0;
}
}
厚謹娼科
壘廁斌全俊
