Box2D Forums

It is currently Sat May 25, 2013 11:34 am

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Tue Jan 31, 2012 4:18 am 
Offline

Joined: Fri Jan 27, 2012 6:12 am
Posts: 1
Hi!
I'm new to box2d engine. Thus to learn it more I'm trying to create a platform game and I've encountered following problem:
after making a dynamic body moving with ApplyImpulse it moves for some distance, and then suddenly stops and doesn't react anymore to this metod.

That's the main class, that initiates all objects, gets keyboard states and has a mian loop
Code:
   public class Main extends Sprite
   {
      private const TILE_WIDTH:int = 32;
      private const TILE_HEIGHT:int = 32;
      private const PLAYER_JUMP_POWER:int = 40;
      private const PLAYER_SPEED:int = 3;
      
      private var physicsEngine:PhysicsEngine;
      private var keys:Keys;
   
      private var fpsText:TextField;
      private var fpsCounter:FpsCounter;
      
      private var controlledObjectId:int;
      
      public function Main():void {
         if (stage) init();
         else addEventListener(Event.ADDED_TO_STAGE, init);
      }
      
      private function init(e:Event = null):void {
         removeEventListener(Event.ADDED_TO_STAGE, init);
         
         initKeyboard();
         initPhysics();
         initStaticTiles();
         initHero();
         initFpsCounter();
         initLoop();
      }
      
      private function initKeyboard():void {
         keys = new Keys();
         keys.addKeysListeners(this.stage);
      }
      
      private function initPhysics():void {
         physicsEngine = new PhysicsEngine(new Point(0, 9.8));
         physicsEngine.setDebugContainer(this);
         physicsEngine.setDebugMode(true);
      }
      
      private function initStaticTiles():void {
         for (var i:int = 0;  i < Math.floor(this.stage.stageWidth / TILE_WIDTH); i++)
            physicsEngine.addObject(new Point(i * TILE_WIDTH, stage.stageHeight - TILE_HEIGHT), TILE_WIDTH, TILE_HEIGHT, false, 1, 7, 0);
      }
      
      private function initHero():void {
         controlledObjectId = physicsEngine.addObject(new Point(0, stage.stageHeight - 3 * TILE_HEIGHT), TILE_WIDTH, TILE_HEIGHT, true, 1, 8, 0);
      }
      
      private function initFpsCounter():void {
         fpsCounter = new FpsCounter();
         //nothing useful
      }
      
      private function initLoop():void {
         this.addEventListener(Event.ENTER_FRAME, update);
      }
      
      private function update(event:Event):void {
         physicsEngine.update();
         updateFrameRate();
         updateKeyboard();
      }
      
      private function updateFrameRate():void {
         //nothing useful
      }
      
      private function updateKeyboard():void {
         var speedVector:Point = new Point(0, 0);
         var keyWasPressed:Boolean = false;
         if (keys.isLeft()) {
            speedVector.x += -PLAYER_SPEED;
            keyWasPressed = true;
         }
         if (keys.isRight()) {
            speedVector.x += PLAYER_SPEED;
            keyWasPressed = true;
         }
         if (keys.isUp()) {
            speedVector.y += -PLAYER_JUMP_POWER;
            keyWasPressed = true;
         }
         if (keys.isDown()) {
            speedVector.y += PLAYER_JUMP_POWER;
            keyWasPressed = true;
         }
         if (keyWasPressed)
            physicsEngine.applyImpulse(speedVector, controlledObjectId);
      }
   }


The second class in PhysicsEngine, which implements all box2d logic:creates world, and manages all the objects
Code:
public class PhysicsEngine {
      private const METERS_TO_PIXELS:int = 32;
      private const PIXELS_TO_METERS:Number = 1 / METERS_TO_PIXELS;
      
      private var world:b2World;
      private var gravity:b2Vec2;
      private var timeStep:Number = 0.03;
      private var debugMode:Boolean = false;
      private var gravityVector:Point;
      private var bodies:Vector.<PhysicsObject>;
      private var dynamicBodies:Vector.<PhysicsObject>;
      
      public function PhysicsEngine(gravityVector:Point) {
         this.gravityVector = gravityVector;
         gravity = new b2Vec2(gravityVector.x, gravityVector.y);
         world = new b2World(this.gravity, true);
         world.SetContactListener(new CollisionListener());
         bodies = new Vector.<PhysicsObject>();
         dynamicBodies = new Vector.<PhysicsObject>();
      }
      
      public function setTimeStep(step:Number):void {
         timeStep = step;
      }
      
      public function setDebugMode(debug:Boolean):void {
         debugMode = debug;
      }
      
      public function setDebugContainer(debugContainer:Sprite):void {
         var debugDraw:b2DebugDraw = new b2DebugDraw();
         debugDraw.SetSprite(debugContainer);
         debugDraw.SetDrawScale(METERS_TO_PIXELS);
         debugDraw.SetAlpha(.3);
         debugDraw.SetLineThickness(1);
         debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);
            world.SetDebugDraw(debugDraw);
      }
      
      public function setGravity(gravityVector:Point):void {
         this.gravity.SetV(new b2Vec2(gravityVector.x, gravityVector.y));
         world.SetGravity(gravity);
      }
      
      public function update():void {
         world.Step(timeStep, 10, 10);
         if (debugMode)
            world.DrawDebugData();
      }
      
      public function addObject(position:Point, width:Number, height:Number, isDynamic:Boolean = false, friction:Number = 0, density:Number = 0, restitution:Number = 0):int {
         var object:PhysicsObject = new PhysicsObject(new Point(position.x * PIXELS_TO_METERS, position.y * PIXELS_TO_METERS), width * PIXELS_TO_METERS, height * PIXELS_TO_METERS);
         object.setDensity(density);
         object.setFriction(friction);
         object.setRestitution(restitution);
         object.setDynamic(isDynamic);
         object.addToWorld(world);
         if (isDynamic) dynamicBodies.push(object);
         else bodies.push(object);
         return object.getId();
      }
      
      public function removeObject(objectId:int):void {
         for (var i:int = bodies.length; i >= 0; i-- )
            if (bodies[i].getId() == objectId) {
               removeFromWorld(i);
               if (bodies[i].isDynamic())
                  removeDynamicObject(objectId);
               removeStaticObject(i);
               break;
            }
      }
      
      private function removeFromWorld(index:int):void {
         world.DestroyBody(bodies[index].getBody());
      }
      
      private function removeStaticObject(index:int):void {
         bodies.splice(index, 1);
      }
      
      private function removeDynamicObject(id:int):void {
         for (var i:int = dynamicBodies.length; i >= 0; i-- )
            if (id == dynamicBodies[i].getId()) {
               dynamicBodies.splice(i, 1);
               break;
            }
      }
      
      public function getDynamicObjetsNumber():int {
         return dynamicBodies.length;
      }
      
      public function getDynamicObjectPosition(index:int):Point {
         var pos:Point = new Point(dynamicBodies[index].getPosition().x * METERS_TO_PIXELS, dynamicBodies[index].getPosition().y * METERS_TO_PIXELS);
         return pos;
      }
      
      public function applyImpulse(force:Point, objectId:int):void {
         for (var i:int = 0; i < dynamicBodies.length; i++ )
            if (dynamicBodies[i].getId() == objectId) {
               dynamicBodies[i].applyImpulse(force);
               break;
            }
      }
   }


The last one is PhysicsObject that represents a body and all its properties.
Code:
public class PhysicsObject {
      
      private static var bodyCount:int = 0;
      private var id:int;
      private var position:Point;
      private var width:Number = 0;
      private var height:Number = 0;
      private var dynamic:Boolean = false;
      private var density:Number = 0;
      private var friction:Number = 0;
      private var restitution:Number = 0;
      private var maxVelocity:int = 5;
      private var body:b2Body;
      
      public function PhysicsObject(position:Point, width:Number, height:Number) {
         this.id = bodyCount++;
         this.position = position;
         this.width = width;
         this.height = height;
      }
      
      public function addToWorld(world:b2World):void {         
         var def:b2BodyDef = new b2BodyDef();
         if (dynamic) def.type = b2Body.b2_dynamicBody;
         def.position.Set(position.x + width / 2, position.y + height / 2);

         body = world.CreateBody(def);
         body.SetFixedRotation(true);
         
         var shape:b2PolygonShape = new b2PolygonShape();
         shape.SetAsBox(width / 2, height / 2);
         
         var mainFixtureDef:b2FixtureDef = new b2FixtureDef();
         mainFixtureDef.shape = shape;
         mainFixtureDef.density = density;
         mainFixtureDef.friction = friction;
         mainFixtureDef.restitution = restitution;
         var mainFixture:b2Fixture = body.CreateFixture(mainFixtureDef);
      }
      
      public function getId():int {
         return id;
      }
      
      public function getPosition():Point {
         position.x = body.GetPosition().x - width/2;
         position.y = body.GetPosition().y - height/2;
         return position;
      }
      
      public function getWidth():Number {
         return width;
      }
      
      public function getHeight():Number {
         return height;
      }
      
      public function setDynamic(isDynamic:Boolean):void {
         dynamic = isDynamic;
      }

      public function isDynamic():Boolean {
         return dynamic;
      }
      
      public function setDensity(density:Number):void {
         this.density = density;
      }
      
      public function getDensity():Number {
         return this.density;
      }
      
      public function setFriction(friction:Number):void {
         this.friction = friction;
      }
      
      public function getFriction():Number {
         return friction;
      }
      
      public function setRestitution(restitution:Number):void {
         this.restitution = restitution;
      }
      
      public function getRestitution():Number {
         return restitution;
      }
      
      public function getBody():b2Body {
         return body;
      }
      
      public function isMovingRight():Boolean {
         return (body.GetLinearVelocity().x > 0) ? true : false;
      }
      
      public function isMovingLeft():Boolean {
         return (body.GetLinearVelocity().x < 0) ? true : false;
      }
      
      public function isMovingUp():Boolean {
         return (body.GetLinearVelocity().y < 0) ? true : false;
      }
      
      public function isMovingDown():Boolean {
         return (body.GetLinearVelocity().y > 0) ? true : false;
      }
      
      public function applyImpulse(forceVector:Point):void {
         trace("linear speed x:" + body.GetLinearVelocity().x + " y:" + body.GetLinearVelocity().y);
         trace("impulse vector x:"+forceVector.x+" y:"+forceVector.y);
         var canMove:Boolean = canMakeAMove(forceVector.x);
         trace("can make a move " + canMove);
         if (canMove)
            applyHorizontalImpulse(forceVector.x);
         if (canMakeAJump())
            applyVerticalImpulse(forceVector.y);
      }
      
      private function canMakeAMove(impulse:Number):Boolean {
         //if wants to move right
         if (impulse > 0)
            return canMoveRight();
         //move left
         else if (impulse < 0)
            return canMoveLeft();
         else return true;
      }
      
      private function canMoveRight():Boolean {
         var velocity:Number = body.GetLinearVelocity().x;
         //and currently also is moving right
         if (isMovingRight()) {
            //check if max speed is reached
            if (Math.abs(velocity) < maxVelocity)
               return true;
            else return false;
         }      
         else
            return true;
      }
      
      private function canMoveLeft():Boolean {
         var velocity:Number = body.GetLinearVelocity().x;
         if (isMovingLeft()) {
            if (Math.abs(velocity) < maxVelocity)
               return true;
            else return false;
            }      
         else
            return true;
      }
      
      private function canMakeAJump():Boolean {
         return (body.GetLinearVelocity().y == 0) ? true : false;
      }
      
      private function applyHorizontalImpulse(impulse:Number):void {
         body.ApplyImpulse(new b2Vec2(impulse, 0), body.GetWorldCenter());
      }
      
      private function applyVerticalImpulse(impulse:Number):void {
         body.ApplyImpulse(new b2Vec2(0, impulse), body.GetWorldCenter());
      }
   }


Attachments:
File comment: Swf file
ErrortestSwf.rar [146.23 KiB]
Downloaded 97 times
File comment: Flash develop project
Error test.rar [184.79 KiB]
Downloaded 67 times
Top
 Profile  
 
PostPosted: Tue Jan 31, 2012 7:45 pm 
Offline

Joined: Sun Oct 25, 2009 3:28 am
Posts: 242
I think the combination of gravity, 1.0 friction, and your code is preventing the applyImpulse from working at certain places for whatever reason. I noticed that the body seems to stop completely when you land, which is the result of both the body and the ground having 1.0 friction, so the random stoppage when just moving left and right may be caused by the frictional force canceling the impulse. Try setting the controller body's friction something close to 1.0, but not exactly 1.0...something like 0.999 (and maybe the floor's as well).

If that doesn't help, try using applyForce (and keep the friction below 1.0) instead of applyImpulse. You may need to increase the magnitude of the force vector by a lot to get the thing moving.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: psbot [Picsearch] and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group