Jario Update: Sounds and Semi-Passability!

Yes, thank you Chrome, only one of those is a word, and yet Jario now has both! Sounds were ridiculously easy to add through a generic SoundSystem with a handful of static sounds (courtesy of http://www.freesound.org/) and a static queue-push method, and then the single-line calls were peppered throughout the systems as required. The result is a game which is a lot more fun to play! Despite still being about 60 seconds long.

Go ahead, try it out!   Launch Java Web Start button

The issue of passability is a more technical one. Previously, all detected collisions were handled directly by each of the colliding entities. This is great for many cases, but there are some times when you don’t want to handle a collision, or when you want to not handle it under certain conditions, and for which adding in a bunch of conditional guards is ugly and inefficient.

My solution was to sneak an extra layer into my collision handling hierarchy (which I’ll talk more about when it’s a little more polished), right up the top, to manage collision persistence. In this context, persistence means that when two entities collide, all future collisions that are detected until they stop colliding can be grouped into a single collision, and handled only once at the beginning. This is important for a number of gameplay mechanics.

For example, the two cases I added just now were semi-passable platforms and improved handling of player recovery. Semi-passable platforms are those ones that you can jump through from below, as well as stand on top of. One way to get this behaviour is to say “if the collision is not from the top edge, do nothing, otherwise block the entity”. This may work, depending on your collision detection mechanism, but for the time being mine is very basic, and detects the edge of the collision based on the X and Y distance the two entities are overlapping by. The result is that if you jump through from the bottom, a bunch of collisions will occur for the handful of frames you’re passing through, and as you are about to exit from the top, one of those collisions will be detected as “top edge”, and the default behaviour is to place the player on top of the platform. The behaviour we want is for the player to keep jumping, eventually fall back down, and then be placed on the platform.

My solution is a little more complex than perhaps it needs to be, but it’s a good starting point. When a collision occurs, the handling systems can register the collision as a “passing through” case, after which future collisions will not be handled by the entity that is passing through (the ‘passer’) until the entities separate. However, the entity being passed through (the ‘passable’) will continue to receive handling calls in case the circumstances of its passability change. It can therefore also check whether the colliding entity has been previously registered as a passer. All of this handling is contained in PersistentEntityHandlingSystem class, which all current collision handlers extend.

In the case of the platforms, this is straightforward. On the first collision, if the player collides with a non-top edge of the platform, the platform registers the player as a passer, and the player continues unhindered. Once the player exits at the top, they are unregistered from the platform, and the next collision will be handled appropriately on the top edge.

Player recovery is a little trickier. By “recovery” I mean the period of invulnerability you get after being damaged with >1 health. During this time, you shouldn’t be able to stomp enemies from inside (i.e. walk into them from the left, then jump and kill them on the way out). So for this case, when the player collides with an enemy, he first checks whether he’s in recovery mode, and if so, if the enemy is not already registered as passing through, then the registration occurs. The enemy passing through the player means that the enemy is oblivious to the collisions (and so can’t die until the player leaves and comes back), but the player’s handler is still called each frame. Therefore when the test for recovery fails (i.e. recovery time has expired), then the enemy is unregistered as a passer, and the collision can be handled normally.

But wait, there’s more. It’s possible for recovery to expire while the player is standing right in the middle of the enemy, and if the position is right, it will register as a top-edge collision, and “handling normally” means the enemy will get stomped. This is not the desired behaviour – if the the player is standing inside the enemy when recovery expires, the player should get stomped instead. To work around this, I added a parallel map that records which passable-passer relationships should be unregistered in the next frame. This gives the player collision handler a chance to handle the collision manually and correctly (take damage) before unregistering. If the player manually takes damage AND unregisters in that frame, by the time the enemy handles the collision it will appear unregistered, and the potential top-edge problem persists. By delaying it one frame, the player’s damage will have been fully accounted for, and the enemy collision will not occur at all.

Problem solved! You can see all that in PlayerHandlingSystem if you like. Like I said, it’s quite complex and I’d like to simplify it a bit, but it’s a start. By experimenting with this approach, I’ve gained even more of an appreciation of the Artemis framework. You really can tackle your problems one at a time, in isolation. Even in the case of a two-entity collision, the collision handling of the two entities can be neatly decoupled. The future is looking bright!

Jario Update: Kinda Working!

I’ve just pushed an update to Jario with some pretty nice changes since I last mentioned it. As usual, you can check out the source if you’re interested or just Launch Java Web Start button!

I’ll be quick:

Features:

  • All the important items – coins, mushrooms, fire flowers and stars.
  • Goombas, Koopas and even empt shells, with the ‘proper’ graphics and animations.
  • Vastly improved input and collision handling.
  • Added a marginally more satisfying ending, though it still doesn’t do anything.
  • Fixed many, many bugs (but not the intermittent collision mesh one yet).

Architecture:

  • Cleaned up collision handling systems into a hierarchy of similar handlers for increasingly concrete entity types. I’ve found it to be very flexible and reusable so far, which is nice, since the logic of a game is little more than input and collisions.
  • Refactored image and animation spatials into a hierarchy of intermediate abstract classes, and added a SpatialComposer to group the different spatials of individual entity types and handle different states.
  • Inserted a hierarchy layer for spatial effect handling. Currently only processes changes in rendering alpha value, but does so quite nicely.
  • Played around with a TimerSystem to be used in conjunction with a Timer component, allowing systems to easily register callbacks with individual entities to be executed after a given delay. Makes it very easy to add temporary properties to entities. For instance, giving the player X seconds of invulnerability (hurt with >1 health, or press I) reduces to a single static function call. Still need to play with Artemis’ DelayedEntityProcessingSystem to see if that does a similar thing.

That’s all the significant bits so far. Still plenty more to go, though! Some of the above will need to change in order to support a complete level, which will be interesting. I also need some better game state transitions, though that’s nothing to do with Artemis. I’ll talk a little bit about some of the more interesting points soon, such as the collision handling and spatials, since those two are key to getting a game working smoothly.

Introducing: Jario

Jario logoYou saw Hario, and you revelled in its technical prowess. Now, the summer (winter) blockbuster of 2011 has arrived.

Jario is a port of Hario, and is similarly a very basic Mario clone, the quintessential platformer. From Hario’s C++ and HGE, Jario is running with Java and the Slick game library, as well as the brilliant Artemis entity-component framework, and it is an exploration of how to apply such a framework to a platformer-style game.

It’s currently in its very early stages after about a week of development from scratch, but it runs, and it already has more features than Hario. And although you may not believe it when you see it, it has superior graphics as well. There is no art more noble than that of a programmer.

It’s important to note that Jario is not a game so much as a proof of technology for the foundation of a game. As features are implemented it will become more game-like, and if I ever ‘finish’ it then it will perhaps be a game, but in my eyes it is just a body of code. The good news is that I can now refer to this code as I discuss Artemis and entity-component frameworks in general, which I certainly will get around to now. Jario is just the first step on the path to bigger and better things.

As usual, you can download the Web Start or run it in your browser. In addition, since it’s basically a piece of tech, I figured I should release the source code on Bitbucket to get some feedback from those with a little more Artemis experience. Finally, for this release there’s also a bonus feature: a pretty button for launching the Web Start! Behold:

Launch Java Web Start button

NOTE: Google Chrome users (such as myself) may find this button just downloading a JNLP file rather than launching anything tangible. To resolve this, click the little down arrow next to the downloaded file on the downloads shelf (the toolbar across the bottom) and select “Always open files of this type”. This will tell Chrome to launch JNLPs automatically (as well as downloading) rather than making the user do it, just like the other browsers.