Core engine roundup time

31 May 2014

Over the last 2 weeks I logged quite a bit of development time, about 12 hours in total, which went into many small features and behind-the-scenes improvements related to the core functionality of the game engine. I really want to work up to the point where all core gameplay features are either implemented or have all their supporting infrastructure in place, so I can move on to one of the things I enjoy most about game programming: the graphics ;-)

The list of minor features and improvements is pretty long, so I won’t bore potential readers (god knows if there are any ;-) with all the details. Instead, I’ll summarize my checkins over the last few weeks along with some short commentary, in the order I implemented them:

  1. Implement ‘command inputs’ and use them for shooting

    Previously, the input handler class only supported on/off toggle inputs, for thrust and to enable the tractor beam. To support event-based inputs such as shooting, I added a ‘command input’ class, which represents a discrete event triggered by an input action. Command inputs are queued up in the K14Inputs class and can be peeked by the game logic update methods. At the end of each game update, the command input queue is emptied. The K14Ship entity now uses this to launch a projectile for every command input labeled as a ‘shoot’ action.

  2. Fix projectile self-collision using a Box2D contact filter

    When an entity launched a projectile, the projectile sometimes spawned inside the bounding rectangle of the entity, causing a self-collision. Especially when the shooting entity was moving (like the player ship), this resulted in projectiles killing the originating entity. The solution was to use a Box2D collision filter class, which gets called before collisions are propagated, and can reject them based on some condition. In this case, the condition was to filter out all collisions between a projectile and its originating entity.

  3. Fix projectile physics when firing from a moving entity

    When shooting while flying fast, the player ship would ‘overtake’ the projectile or otherwise launch it in a direction completely different from where the ship was facing. The fix was to add the ship velocity to the initial projectile velocity after launching it

  4. Add classes and API support to represent, create and break joints

    Instead of direct Box2D calls from the K14Ship step method to create a joint between the ship and the orb when it is lifted, there is now a class named K14Joint with a specialized subclass K14DistanceJoint, that represent a joint between 2 entities. The only joint type currently supported is a distance joint, which is created using a method K14Entity joinToEntityUsingDistanceJoint, which takes the entity to join, and the maximum joint length. Whenever the K14Joint instance is destroyed (e.g. when the player respawns), the backing Box2D joint is automatically removed from the physics simulation. Additionally, if an entity has a joined entity (accessible through a new property joinedEntity), both entities will be automatically wrapped around at the same time when either one crosses the wraparound point.

  5. Implement ‘dead entities’

    When an entity collides with a projectile, or when the player ship hits another entity or the planet surface, it is now marked as ‘dead’, and will be removed from the game world.

  6. Reactor game logic

    The K14Reactor entity now has a hit count, and if it exceeds a preset maximum, it will start a countdown timer. Eventually, this timer should trigger a planet meltdown that kills the player, but I didn’t implement this behavior yet.

  7. Refactor K14Ship and K14Orb creation

    Previously, the planet setup code had to explicitly create the entities representing the player ship and the orb, and position them somewhere on the planet. I didn’t like how this allowed creating an incomplete planet, and how much of the game logic only worked under the implicit assumption that exactly one K14Ship and one K14Orb entity were present. Having to create the ship and orb through K14Planet createEntity also resulted in a chicken-and-egg problem when I tried to add a respawn location property for the orb: it wasn’t possible to know beforehand the exact location and angle of the orb entity because it is usually placed at a calculated location along a surface edge, which meant I had to create the K14Orb instance, position it at its respawn location, get the resulting coordinates, and store them with the parent K14Game responsible for respawning the player and orb :-/. The solution I chose is to implicitly create the K14Ship and K14Orb entities on planet construction, and capture their location when starting the game (see below). The K14Planet class now has direct references to the ship and the orb, which means it is not necessary to look them up by iterating the list of planet entities anymore when they are required inside a step method, for instance.

  8. Game loop control

    After creating a new game, the game loop now has to be started explicitly using a new selector K14Game start. Only after the game is started, view controller callbacks result in game updates. In the future, I will also add pause, resume and finish selectors and corresponding state enumeration values to K14Game.

  9. Respawn the player and the orb when the player ship crashed or was hit

    Adding up all of the above, implementing player and orb respawning was pretty straightforward. Whenever the player is hit or crashes, or when the orb collides with something while it is being lifted, both entities are reset to their respawn locations, as captured when the game was started. Additionally their velocities (linear and angular) are set to zero and the joint between the ship and the orb is destroyed. There are no win/lose conditions yet, and the player life count is not used yet, but that’s mainly because it’s not that interesting to implement yet.

In addition to the things on the list above, I did some collateral cleanup and refactoring. Most of it barely warrants mention, such as Objective-C style fixes to satisfy my OCD. There’s a few things that deserve a few words though.

For instance, one thing I ran into after I implemented dead entities, was that after removing them from the game world, their K14Entity instance wasn’t properly deallocated, which in turn resulted in their backing Box2D body sticking around to haunt the planet. These entities were not rendered and did not receive any game logic updates anymore, because they were not officially part of the K14Planet set of ‘live entities’. Their Box2D body was still alive and kicking though, and being updated by the physics engine. The reason for this was that the data model contained some ARC cycles, strong references from K14Planet to K14Entity and back for example, or from K14Entity to K14Joint, and from there back to K14Entity. These cycles prevented dead K14Entity instances from being deallocated, and with the Box2D body cleanup in the K14Entity dealloc selector, they never left the physics simulation. The fix was to change all ‘back references’ in the data model to weak references that don’t add to ARC reference counts. Visualizing the data model as a tree with K14Game at the root, only references that go ‘down’ in the data model are now strong references. All references that go ‘up’ were changed to weak references.

Another refactoring step was to deprecate the K14Actor and K14StaticEntity classes that sat between K14Entity and concrete entity subclasses. This intermediate level of abstraction did not have any significant benefits, and only added unnecessary complexity, requiring protected scoping of K14Entity properties that needed to be modified by K14Actor for example, or downcasting from K14Entity to K14Actor. I consider these kinds of things ‘code smells’, indicating an incorrect level of abstraction, so I removed them. Instead, K14Entity now has a simple enumeration type K14EntityType to indicate the kind of entity. This enumeration has values such as K14EntityTypePlayer, K14EntityTypeEnemy, K14EntityTypeStatic, K14EntityTypeEnemyProjectile, etc, allowing much finer grained entity type-specific checks and operations. Right now, these are only used by the K14Planet method to organize live entities in disjunct dictionaries, but they will undoubtedly prove useful for other purposes later, for example to implement certain entity game logic.

Updated data model

All the changes I talked about in the previous sections had their effect on the data model, so I thought this would be a good time to post an updated version. Interestingly, even though many small features were added, the data model itself got simpler, which I obviously don’t regret at all ;-)

Video

To conclude this post, here’s the obligatory video showing off the new features added to the game engine. This video shows almost all features of the game engine: player ship controls, shooting, dead turrets, the reactor taking hits, fuel pickup, lifting the orb, and crashing and respawning:

Next steps

With most of the core engine features in place and seemingly working well, I’m going to work on the game graphics a bit. I’ll start with planet rendering first, then rendering game entities using sprites.

Development scoreboard

Total development went up by ~12 hours, to a total of ~44 hours. SLOC count went up to 889. Probably half of the added lines of code were a direct result of the Objective-C style fixes I did, and the dynamic properties added to get access to Box2D state I hadn’t needed before.