Sabbatical Log: November 9th

This blog series is running about a week behind my actual work, giving me time to clean things up.  The date the actual work was done is in the title, horizontal lines indicate when I stopped writing and started coding.

Before I move onto more complicated objects, I need to introduce a notion of “levels”. Right now every sprite is rendered on the same plane, which makes it basically impossible for things to occlude each other.

While I could introduce some explicit groupings of entities, I’m going to keep things simple and just add a level component and split things like the player and walls into multiple entities.

I’ve just finished decomposing the player into three separate parts, one for each “level”. I’m going with floor, mid, and top levels because that “makes sense” to me: attacks will occupy the mid or floor, and jumping will go through the top. It also map nicely to the moving parts of most things: feet, bodies, and heads.

I also had to introduce a PlayerControlSystem, now that the player isn’t represented by a single entity. I’m expecting this pattern to be very common, the smarts of enemies have to go somewhere after all. For the player all it’s doing is making sure the various body parts stay connected, and the player doesn’t leave the bounds of the room (other systems make sure the individual entities don’t, but that’s not quite correct for the whole player).

Collision detection has also become level aware, since two objects on different levels should not collide. It occurred to me that different levels can be checked in parallel, but I haven’t pursued that yet.

Visually not a lot has changed, but you can see the that the player’s body and head (but not their feet) are rendered above the rest of the objects now.

I’ve made some progress on implementing the next object, a tree. I chose a tree because it uses a lot of the new code, without being all that interactive.

To be precise, a tree:

  • Occupies multiple levels
  • Has collision
  • Is composed of multiple entities

To support a tree, I changed up my room object -> entity mapping code to support creating more than one entity. I also added a quick check to the collision system to check bounding boxes before doing the heavy math, a no-brainer optimization that I’d put off doing til I had to. Somewhat unexpectedly what forced my hand was not the time spent calculating collisions (CPU usage for the whole program is less than 2% right now), but rather that I put my test tree far away from every other collision aware entity and the large distances caused overflow errors in my fixed point implementation.

A new level was also needed (which I’m calling Ceiling) for objects that tower over the player, otherwise things like trees would be conceptually as tall as the player.


You might notice that collision detection isn’t actually on yet, and that’s because the collision map for a tree looks like this:

Which, as you can see, isn’t a convex polygon. Before I can flip on collisions for the tree, I need to implement a system for decomposing concave polygons into multiple convex ones. I’ll also need update code so that individual entities can have multiple hitmaps.

It looks like I haven’t mentioned the format of hit maps I’m using before, so let me quickly outline. You can juuuust barely see in the above that I’ve got points at each vertex. Those points are single pixels, and are each a different shade of gray. The hitmap is constructed by connecting each pixel to the next lighter one. I added the pink and green coloring to make it easier to see, the actual data just has the points – the rest of the canvas is transparent

As the day wraps up, I’ve got a working algorithm (and tests) for decomposing an arbitrary polygon into convex polygons. I still need to make the changes to the rest of the engine to deal with sets of polygons, but that’s a task for tomorrow.

In other news, these new tests have brought us up to 100 total. I’m honestly not all that pleased with the coverage of the systems, but the coverage of the actual math is pretty good (and has caught several regressions).

Continue onto November 10th