NetMission Engine

And we’re back!

By popular demand today’s topic is PHYSICS! It also conveniently happens to be what I’m working on at the moment.


Making a game without a physics system is like making a game in PowerPoint. Objects just float there, and somehow you have to slide them around convincingly.

That said, physics systems come with their own complications. Objects just flail and bounce off each other, and somehow you have to slide them around convincingly.

Unfortunately object movement isn’t something I am ready talk about yet. After a full decade of off and on attempts, I still have not successfully finished putting a physics system into NetMission!

Despite that there is already way too much to discuss in one post. This is Part 1 of what will be a series of long-form posts on physics, and the goal by the end of the series is to finally, finally be sliding objects around convincingly. :sunglasses:

The Early History of Physics in NetMission

When I first took over the “Net Mission” game in 2006, I built a small arena in Game Maker 6 to test out some of the mechanisms.

Remember, Net Mission was originally going to be an online multiplayer mouse-controlled shooter. Maybe someday I’ll have a chance to revisit that idea!

Game Maker 6’s built-in physics lacked any substance, so I’d been studying this popular interactive N tutorial on the Separating Axis Theorem for boundary detection, in the hopes that I could spin my own system together. “Wow, real math!” I exclaimed with sparkling eyes. That sparkle disappeared once it turned out that Game Maker, at the time, was too slow to handle much scripted math. “But I need good physics!!” With no clue what I was getting myself into at age 14, I announced that I was switching from Game Maker to C++ on March 1, 2007. Thus began the “NetMission Engine” as we know it today.

In early 2008, I finally caved and decided to trust someone else’s physics code for once. It was Super Mario Galaxy of all things that convinced me I didn’t stand a chance on my own. I researched available 2D physics libraries and narrowed my options down to this highly promising one called Box2D which was still in the works. I tinkered and made some random experiments, like this bouncing red box:

(Pretend the red box is bouncing. The colorful space ship is unrelated)

Or this eye-burning demonstration, which played loud sounds for every bounce:

Or this destructible stack of blocks for guess-whom on guess-what-day:

By mid-2009 I managed to whip together a clunky Meta Ridley ragdoll: (click to play video)

That last example was the first time I had combined all my isolated bits of code into one single “engine” package, which was so exciting for me that naturally the next thing I did was remove Box2D from my engine and work on everything else instead.

Wait, what?

Game physics in general is an awfully intimidating and cumbersome topic, and I didn’t have the tools to make anything significant out of it. Moving my mouse through a picture point-by-point and typing coordinates into code was a grueling process. Awesome programs like R.U.B.E didn’t exist yet. I had no money, and I was in the mindset that someday I would make my own super-duper fancy NetMission Engine Editor all on my own. My attempts at that had been pretty limited and buggy…

So I gave up and didn’t bother with physics for 5 years. In that time Box2D developed into somewhat of an industry standard. It was picked up by Angry Birds (Dec 2009) followed by a ton of other games (even Shovel Knight (June 2014) which you’d never expect!), and Google expanded it into LiquidFun (Dec 2013). Legit game engines started integrating it natively, like Unity Engine under the name RigidBody2D (Nov 2013), and before that it was even built right into Game Maker (late 2012)!! Dang it! Guess I could’ve waited it out and saved myself writing a whole C++ game engine from scratch…

But in the summer of 2014, I decided it was time to give physics another go. I discovered the Tiled Map Editor and went nuts with integration and new features. Now I can draw the boundary lines around my scenes! I can draw complex shapes and load them in as objects! Surely that was the only thing I was missing before.

The Second Attempt at Physics

NetMission uses Lua scripts for its games, so I have to do what’s called “binding” or “wrapping” to enable access to Box2D’s C++ interface through Lua. Such bindings already exist, but they are more of a literal translation. My coding philosophy won’t let me inflict raw vanilla interfaces of any kind upon my Lua scripts, when I have this perfect opportunity to make things better and leverage Lua’s strengths!

The main technique I use when designing interfaces is the “Every time you X you also have to Y” pattern. There is probably a better name for it, but programmers constantly sniff around for that smelly phrase in our thought process. It’s our bread and butter. After all, that is precisely what computers are here to fix! If you X a lot, and the computer can automatically Y for you when you X, then we need to make it happen.

As you carry out your next day, see if you can notice the “Every time you X you also have to Y” pattern. It’s all over the place! Even something as simple as having to close out of a program before the newer version will continue installing, or always typing your name at the bottom of emails, or writing the same info here, here, and here on a form. It’s especially prevalent in the physical world, where automating something can imply an enormous engineering challenge or even an entire field of research. Maybe someday you’ll find yourself hooking up motion sensors and facial recognition components just to log into your phone faster! Wait a second…


With Box2D, here is one of the first obstacles I had to overcome. Check out this shape:

It’s a bit funky, but not unheard of to find something like this in a game. Maybe it’s a UFO on its side, or the end of a large weapon, or a cardboard cutout of a lizard monster wearing a shoe, and for whatever reason you need its collision to be this precise.

In NetMission, you would create this object like this:

body = createBody({position={x,y}})
shapes = body:AddShapes({SHAPE_POLYGON, 0,0, 40,40, 84,4, 44,12, 60,-24, 24,-8, 32,-32,
                                        52,-40, 16,-48, 14,-28, 12,-46.8, -4,-46},
                        {friction=0.5,restitution=0.2,density=1.0})

Those coordinates are specified in no particular direction. Looks like clockwise I guess.
Okay actually, more likely what you’d do is visually draw that shape in a TMX file, call it “funkyPolygon”, and grab it from there instead:

body = createBody({position={x,y}})
shapes = body:AddMapShapes(objLayer, "funkyPolygon", {})

Ah yes, this is how it should be. Draw it in an editor. You don’t even need to override the friction, restitution, or density settings anymore since you can specify those and other properties in the TMX file, too.

On the flip side, here is how you would create this object in Box2D:

b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
b2Body* body = world->CreateBody(&bodyDef);
b2FixtureDef fixtureDef;
fixtureDef.friction = 0.5f;
fixtureDef.restitution = 0.2f;
fixtureDef.density = 1.0f;
b2PolygonShape polygonShape;
fixtureDef.shape = &polygonShape;
b2Vec2 vertices[b2_maxPolygonVertices];
vertices[0].x = 8.4; vertices[0].y = 0.4;
vertices[1].x = 4; vertices[1].y = 4;
vertices[2].x = 4.4; vertices[2].y = 1.2;
polygonShape.Set(&vertices,3);
body->CreateFixture(fixtureDef);
vertices[0].x = 5.2; vertices[0].y = -4;
vertices[1].x = 3.2; vertices[1].y = -3.2;
vertices[2].x = 1.4; vertices[2].y = -2.8;
vertices[3].x = 1.6; vertices[3].y = -4.8;
polygonShape.Set(&vertices,4);
body->CreateFixture(fixtureDef);
vertices[0].x = 6; vertices[0].y = -2.4;
vertices[1].x = 4.4; vertices[1].y = 1.2;
vertices[2].x = 2.4; vertices[2].y = -0.8;
polygonShape.Set(&vertices,3);
body->CreateFixture(fixtureDef);
vertices[0].x = 4.4; vertices[0].y = 1.2;
vertices[1].x = 4; vertices[1].y = 4;
vertices[2].x = 0; vertices[2].y = 0;
vertices[3].x = 2.4; vertices[3].y = -0.8;
polygonShape.Set(&vertices,4);
body->CreateFixture(fixtureDef);
vertices[0].x = 3.2; vertices[0].y = -3.2;
vertices[1].x = 2.4; vertices[1].y = -0.8;
vertices[2].x = 1.4; vertices[2].y = -2.8;
polygonShape.Set(&vertices,3);
body->CreateFixture(fixtureDef);
vertices[0].x = 2.4; vertices[0].y = -0.8;
vertices[1].x = 0; vertices[1].y = 0;
vertices[2].x = -0.4; vertices[2].y = -4.6;
vertices[3].x = 1.4; vertices[3].y = -2.8;
polygonShape.Set(&vertices,4);
body->CreateFixture(fixtureDef);
vertices[0].x = 1.4; vertices[0].y = -2.8;
vertices[1].x = -0.4; vertices[1].y = -4.6;
vertices[2].x = 1.2; vertices[2].y = -4.68;
polygonShape.Set(&vertices,3);
body->CreateFixture(fixtureDef);

WHOHOHOH! What’s the deal? There are waaaay too many coordinates and fixtures in there! Isn’t this all just one shape?

Well, no. The deal is that polygons in Box2D must be convex (no dents), the vertices must be specified in counter-clockwise order (left on top), and there can be no more than 8 points by default. These limitations are wonderful from a low-level technical standpoint. It means that the calculations can be greatly simplified because they can make useful assumptions about the vertices, so your game can run faster with more things flying around. They can always combine into more complex shapes as needed. This image shows how our shape is actually stored internally, regardless of which above method you used:

Remember “Every time you X you also have to Y”? Here’s our first real example! Every time you create a polygon, you have to make sure you’ve broken it into well-mannered bite-size chunks. Seems like a missed opportunity there for a computer to do some work – NetMission to the rescue! To be fair, something as mundane as polygon partitioning is likely not within the scope of Box2D’s mission to provide a pure kernel of physics. But I do think that it’s a shame that every time a programmer wants to use arbitrary polygons in Box2D (X), they have to figure out how to solve this geometric problem first (Y).

NOTE: An observant eye may have noticed that the scale of coordinates is different, too. We have 4.6 in Box2D and 46 in NetMission, leading to the same location. When you’re designing a 2D game, you want to work and think in pixels, but physics calculations work best at a much smaller scale, such as meters (which are bigger, yes, but I mean there are fewer of them). NetMission automatically converts your units, so you can think in pixels or whatever unit you want.

The Third Attempt at Physics

Welp, that second attempt in 2014 didn’t last long. I patched up some of the immediate holes I could find, but soon enough my attention swayed over to more appealing things. Like… resource dependency resolution. And… input buffering.

So now we’re in 2018. Lack of physics is by far the biggest thing holding my engine back. I am working at it and making great strides, this time for real, and I’m excited to share all the clever ways I’ve been integrating physics into my engine. Two weeks ago I wrote a much different blog post, longer than this one, about all the work I had done, except I noticed something fishy when I was reading it back.

“NetMission now handles this for you, too!” I claimed in writing. Yes it does! I proudly thought, having already tested it several times.
Wait, unless you…

Okay but I can fix it really quick!
I couldn’t.

Creating and Destroying Things

Your player aims at an enemy. They shoot a beam of energy and land the target! KAPOW! The enemy takes damage, the blast is destroyed, some extra debris bounces away, and the game crashes.

NetMission is totally fine if all you want to do is destroy that beam. It secretly buffers objects being added or deleted into a command list, and executes those commands at the end of the frame, not even aware that this also helps Box2D out. But let’s say your beam is made of ice and you want it to stick onto the enemy for a second. The simple act of attaching the two together as soon as they collide is enough to crash Box2D, so every time you want to do this, you have to write down “I want these two objects to be attached at this point” and mail it to a later part of your code that isn’t inside a callback.

To me this is a serious design flaw. Every time you want to change the physics simulation during a collision (X), you have to store that action in a list and perform it later (Y). No matter how any of the underlying interfaces work, I want my engine to be as easy to use as possible. If you’re making a Snake clone, you should be able to type

function snakeBody:BeginCollide(other, contact)
    if (other.isFood) then
        self:attachToTail(NewTailPiece())
        other:teleportElsewhere()
    end
end

without worrying about crashing the entire program, because you forgot to mark for later that your Update() function is where the tail piece should be added, not here.

This turned out to be an intricately thorny issue. I scratched my head over all the possible ways to fix it for days. “Maybe PreSolve() can be renamed to ShouldSolve() so you aren’t tempted to make structural side effects?” I proposed. “Maybe I store all the callback data in a list and call them later? Or just every edited property of every possible new data structure?” I nauseated. “Maybe I edit Box2D’s object interface to allow Bodies, Shapes, and Joints to exist on their own before being added to the world?” I twitched.


There hasn’t been a picture for a while, so here is some abstract art in case you weren’t bored yet

I was going to make a case with the creators of Box2D that this (and many other things I haven’t mentioned) is an important next step, but then I found this post from 2009:

I think now is a good time to say that I have a lot of respect for Box2D, if that wasn’t already evident. First of all, it’s just plain cool, and always quite a spectacle to watch and play with. There is a significant degree of beauty and brilliance to its design, and good reasons why it became such an adopted standard. It was the first of its kind and remains the primary source of inspiration for its competitors. Its low-level workings are rock-solid and fully capable of whatever crazy physics scenes and behaviors you can imagine. It has been pristinely polished in so many aspects… except for user-friendliness.

It was a very sad day for me to come to the conclusion, but after a lot of careful research and prototyping, I began switching my physics code over to Chipmunk2D instead. This is going to be just as much of an uphill struggle as before, but there are some key differences in its interface design that make it possible to do what I want. My apologies to Box2D – we’ve known each other for so long… weve been through so much together… went so far… i didnt think it would have to end this way… :cry:

To see what happens next, stay tuned for Part 2 of this magical adventure

3 Likes