Wednesday, August 8, 2012

Moving with Box2D in Gladius

‹prev | My Chain | next›

I ran into quite the problem last night with Gladius and Box2D.js. I am trying to use Box2D.js for its collision detection capability. I think that I have that working. The problem is that, when I use Box2D.js, I can no longer move things. Collision detection without movement is less than useful.

Thanks to yet another tip from Alan Kligman (that guy is just awesome), I think I understand why. Since I am using a physics engine in my game, I need to use physics to move things. In retrospect, this seems pretty obvious, I admit.

So I update the "moveLeft" logic for my avatar states. Instead of setting a new position to the left of the current position, I give it a little push to the left:
        var avatarLogic = {
          "Update": function(event) {
            if (!this.owner.hasComponent("Controller")) return;
            // ...
            if (controller.states["moveLeft"]) {
              // position = [-space.clock.delta * 0.01, 0, 0];
              new engine.Event("LinearImpulse", {impulse: [-0.25,0]}).
                dispatch(this.owner);
            }
            // ...
          }
        };
I also have to add the Box2D body definition back to the avatar proper (I was flailing last night) so that the force will be applied to the right thing:
        var avatarBox2d = new box2d.Body({
          bodyDefinition: bodyDefinition,
          fixtureDefinition: fixtureDefinition
        });

        av = new engine.Entity("avatarx",
          [
            new engine.core.Transform([0,0,0], [Math.PI/2, 0, 0]),
            avatarBox2d,
            new cubicvr.Model(resources.cone_mesh, resources.red_material),
            new input.Controller( resources.avatar_controls ),
            new engine.logic.Actor( avatarLogic )
          ]
        );
        space.add(av);
With that, I start with my avatar body (just a cone for now) not colliding with the sphere/obstacle:


If I tell the avatar to "moveLeft" (I have controller logic from last night that maps the WASD keys to movement directions), then the avatar indeed moves left and, more importantly, I have a collision:


This is a light departure from last night: the obstacle starts grey and turns yellow when contact begins:
        var obstacleBox2d = new box2d.Body({
          bodyDefinition: bodyDefinition,
          fixtureDefinition: fixtureDefinition
        });

        obstacleBox2d.onContactBegin = function(event){
          console.log("Obstable contact begin");
         this.owner.findComponent( "Model").setMaterialDefinition(resources.yellow_material);
        };
        obstacleBox2d.onContactEnd = function(event){
          console.log("Obstable contact end");
         this.owner.findComponent( "Model").setMaterialDefinition(resources.grey_material);
        };
This seems more intuitive than starting yellow and greying on impact.

At any rate, this works, but...

I would prefer the obstacle be immovable. Instead it sticks to the avatar and both keep moving off the screen:


The other problem is that movement continues even if the input controller is no longer in the "moveLeft" state.

Both problems will have to wait for another day. For now, I simply get the remaining directions of motion working and call it a night:
        var avatarLogic = {
          "Update": function(event) {
            if (!this.owner.hasComponent("Controller")) return;

            var impulse;
            if (controller.states["moveLeft"]) {
              impulse = [-0.25, 0];
            }
            if (controller.states["moveRight"]) {
              impulse = [0.25, 0];
            }
            if (controller.states["moveForward"]) {
              impulse = [0, 0.25];
            }
            if (controller.states["moveBackward"]) {
              impulse = [0, -0.25];
            }

            if (impulse) {
              new engine.Event("SetLinearVelocity", {velocity: impulse}).
                dispatch(this.owner);
            }
          }
        };

Day #472

4 comments:

  1. You'll want to use a different body definition for the obstacle here. If you pass 'type: box2d.BodyDefinition.STATIC' then your obstacle should stay put when your avatar collides with it. I haven't tested this extensively, so there may be bugs :/

    ReplyDelete
    Replies
    1. Ah cool. I'll give that a try. If there are any bugs, I'll be sure to hit at least two of them :P

      Delete
  2. Also, this is a good read: http://www.iforce2d.net/b2dtut/constant-speed.

    ReplyDelete
    Replies
    1. Yah, I saw that. The LinearSpeed stuff looks nice, but I believe that it needs Box2D.b2Vec2 objects. I don't think those are exposed by the plugin currently. No matter, I stayed up late and think I came up with workaround: SetLinearDamping with a high value will stop the object as soon as there is no external force. That will probably be good enough for my purposes (though b2Vec2's are a nice-to-have in the future).

      Delete