
Look at that face...I don't think Keeda is as excited about this endeavour as I am.
I have been chipping away at Box2D for what feels like forever. In reality it’s been almost 3 weeks since my last Box2D/JS related blog post. I’ve been huddled away juggling paid work, this, and X-Files, trying to figure this thing out. A few things contributes to the hindrance of progress in my efforts:
- I’m using a JavaScript Box2D port that’s been ported again for the Impact engine to be turned into a plugin. Syntax has changed, not everything matches the other Box2D versions 100%, and there’s next to no documentation
- My JavaScript skills are still average at best. I have never worked with Box2D or physics before (except for what rudimentary physics come with the Impact engine)
Challenge 1: Box2D installed, need to recode all movement
Box2D completely overwrites Impact movement and collisions. This meant that when I installed the Box2D plugin I had to recode everything using Box2D movement and scrap any existing collision and movement code.
Challenge 2: Box2D version discrepancies
I soon learned that the plugin I was using was an older version of Box2D. I upgraded to a newer version. Unfortunately this broke several things, including the debug drawer and my rule to check if the player is standing on the ground. This rule was being used in my jump trigger. As a result I’ve disabled jump completely until I can figure out how to rewrite the standing check to work with the new version.
The debug drawer took ages to fix, but I finally found a useful post on the Impact forum that explained how to rectify the prolem.
Challenge 3: Box2D cannot resize bodies
This was the start of the big problem. In Impact resizing bodies on the fly is easy. You simply change the size.x and size.y values. Box2D, it turns out, cannot resize bodies on the fly. Even something as small as implementing crouch suddenly became a problem. What I originally intended to do was destroy the player body and recreate it with different dimensions when the player presses crouch, then destroy that body and recreate it with the original dimensions when the player uncrouches.
Rob, thankfully, came to the rescue with an email explaining a better way to do this. Instead of destroying and recreating bodies he suggested creating two bodies for the player – one for the top half and the other for the bottom half. Then when the player presses crouch I could disable/filter out collision on the top half of the body (at the same time changing the animation to the crouched version of the player’s character). All the player would see is the crouching animation, but in the background what would really be happening is the top body collision being toggled on and off.
So emailing back and forth with Rob, who gave me awesome and detailed advice, I finally got the two bodies working. At first I was going blind due to the debug drawer issue above, which made checking body positions difficult. Finally when the debug drawer was fixed I could see exactly where the invisible bodies were and adjusted them as necessary to be in the correct position, connected by a distance joint (as well as modifying the damping and such to make them sit on top of each other correctly).
Challenge 4: Collision filtering
I knew the theory behind how collision filtering works in Box2D (on a somewhat rudimentary level). In practice, I couldn’t find much documentation for JavaScript specific syntax. No matter what I tried, I kept running into errors. Finally a person much more knowledgeable than myself in these matters – E – sat down with me at lunch to look at the problem. And totally saved the day. He helped me figure out how to create filters and set them for individual shapes.
When I got home tonight I sat down to review what I’d learned and actually implement the collision filtering for crouch. And voila! We have working crouch using two bodies connected with a distance joint and collision filtering toggle on the top body.
The code looks like this. Keep in mind that this is still kind of thrown together and messy. This may not be the best way to write this, but it (technically) works for now (but not completely. See issues below the code):
In my controller class I created a new function that defines two (so far) collision filters:
|
|
setCollisionFilters: function() {
// Default collision
this.collideDefault = new b2.FilterData();
this.collideDefault.categoryBits = 1;
this.collideDefault.maskBits = 65535;
// Collide with nothing
this.collideNone = new b2.FilterData();
this.collideNone.categoryBits = 2;
this.collideNone.maskBits = 65534;
} |
In box2d/entity.js I have an if statement that creates the two bodies and a shape for each of those bodies if the entity being initiated is the player entity:
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
|
createPlayerBody: function() {
var bottomBodyDef = new b2.BodyDef();
bottomBodyDef.position.Set(
(this.pos.x + this.size.x / 2) * b2.SCALE,
(this.pos.y + this.size.y / 2) * b2.SCALE
);
bottomBodyDef.type = b2.Body.b2_dynamicBody;
this.bottomBody = ig.world.CreateBody(bottomBodyDef);
var topBodyDef = new b2.BodyDef();
topBodyDef.position.Set(
(this.pos.x + this.size.x / 2) * b2.SCALE,
(this.pos.y + this.size.y / 2) * b2.SCALE - 4.5
);
topBodyDef.type = b2.Body.b2_dynamicBody;
this.topBody = ig.world.CreateBody(topBodyDef);
var bottomShapeDef = new b2.PolygonShape();
bottomShapeDef.SetAsBox(
45 / 2 * b2.SCALE,
45 / 2 * b2.SCALE
);
var topShapeDef = new b2.PolygonShape();
topShapeDef.SetAsBox(
45 / 2 * b2.SCALE,
45 / 2 * b2.SCALE
);
this.bottomBody.CreateFixture2(bottomShapeDef, 1);
this.topShape = this.topBody.CreateFixture2(topShapeDef, 1);
// Create distance joint
var jointDef = new b2.DistanceJointDef();
jointDef.Initialize(this.topBody, this.bottomBody, topBodyDef.position, topBodyDef.position);
jointDef.collideConnected = true;
jointDef.frequencyHz = 100;
jointDef.dampingRatio = 1;
var joint = ig.world.CreateJoint(jointDef);
}, |
Then in entities/player.js I set the collision filter for the top body when the player is crouching:
|
|
// Crouch
if (ig.input.state('crouch')) {
this.offset.y = 0;
this.currentAnim = this.anims.defaultCrouchIdle;
this.topShape.SetFilterData(ig.game.playerController.collideNone);
}
// Uncrouch
else if (!ig.input.state('crouch')) {
this.offset.y = 45;
this.maxVel.x = 300;
this.topShape.SetFilterData(ig.game.playerController.collideDefault);
} |
So now

When not pressing "S" to crouch, the player can't get under the ledge.

Pressing "S" to crouch. Top box collision filter is changed to 'collideNone', allowing top body to pass under the ledge body. The animation behind the debug view is updated to crouched state (which you can't properly see here behind the debug stuff)

Problem! This is what happens when you uncrouch under the ledge. BAD.
As you can see, there are still things to work out. For example, when I release the crouch key under a ledge the player should remain crouched until they emerge from under that ledge. I also still have to figure out standing, which will be related to figuring out the ledge detection thing. So next is being able to tell when the bottom of the player is colliding with the ground and the top of the player is colliding with another body. Tough, but getting there.
UPDATE: I’ve now set the rotation of the two shapes to fixed, which stops the above from happening and allows the player to keep moving through under the ledge. However, this is still dodgy and behaves weirdly sometimes. I think the final and “proper” solution will be to keep the player in a crouched state if they’re still under a ledge.
Thanks a lot to Rob and E for all the awesome advice. I’d probably still be stuck here ripping my hair out if it wasn’t for them. Did I mention how lucky I am to have friends who know what they’re doing and are willing to share a bit of their giant brains?
Posted on: April 26th, 2012 by Liza Shulyayeva
14 comments - in game dev, games
Tags: box2d, impactjs, javascript, js
I haven’t posted many any updates over the Easter break because I’ve been busy ripping my hair out with Box2D.
Basically, I realized that to properly implement the kinds of things I need to implement I need a better physics engine than what comes with Impact by default. Thankfully Impact has a Box2D plugin. That took about a day to implement what with sorting out bugs etc and getting the game to actually run with this thing.
The next challenge was changing how entities actually move. The syntax for setting things like velocity in Impact changes completely once you start using Box2D. Instead of saying this.vel.x = this.speed I now had to start using ApplyImpulse. I ended up scrapping all movement and animation code for my player entity and rewriting them. And…well…left, right, and jump worked. Now I’m stuck on crouching.
Destroy -> resize -> recreate
The problem is that Box2D doesn’t allow you to just resize bodies like Impact does. With Impact I could just say this.size.y = this.crouch (where this.crouch is the height of the crouching version of the player, which is in my case 45px). With Box2D, however (from what I understand) I have to first destroy the shape I’m working with, then resize it, then create a new shape of that size. So when the player presses the crouch key it will need to destroy the shape, resize, create a new shape. Then every time the player unpresses the crouch key it will, again, need to destroy the shape, resize back to full height, and recreate the shape.
And this is what I’m stuck on. I feel like I’m so close, but my main problem right now is having no fricking idea what to pass into the this.body.DestroyShape() function. In other words – I have no idea how to reference the current shape. And every body can have multiple shapes, so if I comment that line out and leave only my this.body.setShapeDef(); function a new shape gets created each time I press the crouch key (of the correct size). But the thing is that the full-sized version of the shape is still there. I feel like this is something obvious that I should already know how to do and it’s driving me insane.
So that’s my update for the weekend. This is more frustrating than working on the lighting was because at least with the lighting I was discovering something new and making progress each day until I found something that worked and polished it. With this I’m completely stuck and not moving anywhere. I mean sure, I can work on other things for now (which I will do), but this is so important that I’ll need to figure it out eventually anyway (I will need to resize bodies not just for crouch, but in other instances as well, so being able to do this is critical). Whether I’ll get it eventually or not isn’t the question – I will definitely get it. I just question the level of sanity I’ll be left with by the end.
Posted on: April 9th, 2012 by Liza Shulyayeva
2 comments - in game dev, games
Tags: box2d, destroyshape, impact, impactjs, javascript, physics
I am half asleep right now, but feel like quickly writing this down today instead of tomorrow. And holy crap I just realized it’s 3:40am right now, so I guess “tomorrow” would have technically been today regardless. Anyway, today (now yesterday) was productive. I not only did a lot of work on the game itself, but also worked on documentation. Even the process of compiling a document outlining the core functions being used in the different controllers gave me ideas as to how to clean up and improve the overall code structure (which I did…and which is still in progress).
What I don’t like at the moment is how many global variables I’m using. I am referring to five objects as globals at the moment throughout the code. I’ll be looking for ways around using so many globals this weekend.
Aside from the stuff I mentioned this morning and some other little things I focused on the following:
Placeholder audio
I put in some placeholder ambient sound in the first and second levels. This didn’t really seem all that useful as the actual implementation is a 10 second job and the track itself will end up changing down the line anyway, but the hour or so spent on finding free to use tracks and mixing them together into one, then actually putting them into the game were worth it. Hearing it just gives me an even better idea of the feel we’re working toward here and brings us a tiny bit closer to that feel. This in turn has started to give me more concrete ideas for things like environment art. It’s amazing how much difference sound can make when it comes to visualizing ideas and emotions.
Manually triggering object interaction
Up until today to interact with objects the player entity just had to collide with them. I’ve put in an “action” button that the player now has to use in order to interact with in-world items (right now this mostly just amounts to picking them up). This allows us and/or the player to do other stuff with the items on collision – things like pushing, pulling, jumping on, and even purposefully ignoring. I then also had to add things like proximity and other pickup rules.
Now I’m going to sleep for the 3 hours I have left before the alarm goes off. Tomorrow I want to modify camera movement slightly to allow the player to move a small amount on the X axis without triggering camera follow. This seems like such a small thing, but I think even though it’s so subtle it can make a big difference to the overall feel of the camera and game movement if implemented well.
Posted on: April 4th, 2012 by Liza Shulyayeva
No comments - in game dev, games
Tags: audio, camera, games, impactjs, javascript, sound
Last night I did no work on the game. Nothing. Nada. Zilch. Instead I had pizza, played some games, and then promptly fell asleep. I didn’t realize how tired I was after 4am-2am-whatever-am nights over this weekend, and really the past few weeks, until I passed out in front of my PC while ordering an artillery assault. I needed the one-night’s rest. As a result today I’m awake and ready to get back into it.
I’ve already started putting in level transition triggers on the train, but had some issues to work out regarding lighting not triggering in level 2 even though I’m calling the relevant functions. I’ve now figured it out, so “doorway” triggers are officially working! Some of this still feels quite messy, however, so I’ll be working on restructuring how it’s all actually done tonight. I’ve already done some rearranging, like removing an unnecessary extension and adding a controller class to keep all player states saved between levels (instead of cluttering up main.js).
Also this morning I started a spreadsheet outlining what art assets I think we’ll need (starting with character animations).
Someone asked me earlier how I don’t get exhausted by finishing paid work only to do this stuff every day – well, I think this might be how. And maybe I do. I figure you run yourself into the ground for a few days, or weeks, or months, and then take a break after you’ve achieved whatever it is you’ve been working toward – a feature, milestone, or just something that’s been driving you crazy. For me this time it was this lighting. I think maybe when it was in and working my brain decided that this was a good time to recuperate (aka get some sleep). Of course the fact that I have a whole another life of paid work out there that needs to be done on a daily basis also contributes to how much rest I can afford to give myself between that and personal projects (that is, not much). But I figure nobody else is going to push you to do what you want, so it just comes down to making it happen yourself.
On a related note: Easter Holidays this weekend! That’s four consecutive days of staying up as late as I want without worrying about work the next day. This is going to be awesome.
Posted on: April 3rd, 2012 by Liza Shulyayeva
2 comments - in game dev, games
Tags: impactjs, javascript, rest
Busy day yesterday! Got a lot done. Switching light source from one entity to another proved to be surprisingly quick and easy. I was done with my emitter attribute in no time.
Then it was time to finish implementing “states” for a couple of entities. So now when the player goes up to the light source in the first level and picks it up, the light source is killed and the player is switched from the default state to the withLightSource state, which not only changes it to now become the light source but also changes its animation.
Other progress included creating a title screen level, a pointer entity to handle clicking, the first in-game item (which when picked up influences the light), and some other stuff.
Getting up
One of the most interesting challenges yesterday was putting in a placeholder “Getting up” animation. When the player spawns in level 1 they get up from the ground before going into their regular idle animation. The trick was waiting for the getting up animation to finish playing completely before going into regular idle. I implemented this as follows:
- When the level is spawned, the player’s
state is set to “new”.
- The following code runs in the player’s
update() function:
|
|
// GET UP
if (this.state == 'new') {
this.currentAnim = this.anims.defaultGetUp;
if ( this.currentAnim == this.anims.defaultGetUp ){
if ( this.currentAnim.loopCount ) {
//Get up animation finished. Go to idle animation
this.state = 'default';
}
}
}
// ANIMATIONS IN DEFAULT STATE
else if (this.state === 'default') {
// Regular animations triggered here
} |
So as you can see when the get up animation has finished, the state is switched to “default”, which proceeds to trigger regular animations.
Got a dev blog? Link please.
A few people commented on a couple of blog posts like this one about how reading these entires has made them want to start their own blogs to record their progress (or even start coding again!), which is awesome. I love reading other people’s game related blogs/journals/whatever, so if you happen to have a public dev blog, Twitter feed, YouTube channel, or some other method of recording your game (or software in general) development progress, please leave a comment (or email me).
Posted on: April 2nd, 2012 by Liza Shulyayeva
5 comments - in game dev, games
Tags: animation, games, impactjs, javascript