The Hullet Bells – Part 5 (Valuing your Input)

What is Input Handling, anyway?
Handling input is the process of taking the player’s key presses and converting them to actions in game. Pygame supports two methods for doing this:
1) Examining the state of the keyboard directly each frame, which I’ll refer to as the key state method.
2) Key events, where the game pumps an event queue that is populated only when keys are pressed and released.
Typically, we will attach a function to a key state or event and it will be called when the key is pressed or held.

For the key state approach, the part of your main loop that deals with input will look something like this:

...
  keystates = pygame.key.get_pressed()
  if keystates[pygame.K_UP]:
    moveUp()
  if keystates[pygame.K_DOWN]:
    moveDown()
... continues for each key tested ...

Meanwhile, if you take a key event approach, it will look more like this:

...
  events = pygame.event.get()
  for event in events:
    if event.type == pygame.KEYDOWN:
      if event.key == pygame.K_UP:
        startMovingUp()
      elif event.key == pygame.K_DOWN:
        ...
    elif event.type == pygame.KEYUP:
      if event.key == pygame.K_UP:
        stopMovingUp()
      elif event.key == pygame.K_DOWN:
        ...
...

The first obvious difference is that we won’t check the keys we’re watching for in the key event approach until someone actually presses a key to populate the events variable. The second is that we have a different idea about how movement should be handled: On key down, it starts and will likely continue every frame until key up. The key state approach typically moves players directly (I say typically, because we’ll see later on that it’s not always the case), while the key event approach modifies the player’s velocity, letting the game loop sort out actually moving the player. The former (direct movement) is frowned upon for a reason I’ll touch on later.

The Big Problem with Key Events

With that out of the way, I’d like to talk about one of the interesting challenges when implementing a multi-handler system. Suppose a player is moving their ship to the left when he pauses the game (switching the handler). If the player lets go of the left key and unpauses the game, what is their expectation? Is it:

  1. The ship comes to a standstill after unpausing, or…
  2. The ship continues moving to the left, with further movements to the left doubling the player’s speed, with right key presses causing the movement to stop while the key is held?

I have a pretty good idea myself about what I’d expect. The latter is a pretty serious bug, and it’s one I’ve encountered over and over again.

The above problems are caused when using key events for actions that require both the key down (begin movement) and key up (end movement) events to be caught in pairs. We have issues when beginning a movement, but then the corresponding end movement event is lost. In some implementations of key events, this can be achieved by losing application focus while the key is held, releasing the key, then giving the application focus again. The end result is that the game believes the key is still held down when it is not! Another example using our handler system: holding right and pausing the game will switch the current handler to the pause screen. Letting go of the key then sends the key up event to the pause screen handler, and not the game screen: The key up is lost. When we return to the game, we’ll see the dreaded behaviour above.

A brief aside to discuss the underlying method of moving a ship around the screen: Something you learn from a few game programming websites is that you should never directly modify a player’s position as a result of input. Instead, input should modify the player’s velocity. That way, because you’ve been a good programmer and decoupled the input and game logic, the game itself will be able to decide if the velocity applied will affect a movement. It shouldn’t if the player is at the bounds of the game area, for instance, but directly moving the player means you lose the information about how the player got out of bounds, so they may not be correctly placed back on the field. So directly modifying position is out. The idea that helps solve this: Key down means you affect the player’s velocity in some way, key up means you reverse that change.

This is a great piece of advice when implementing the movement stuff for your game. A common pattern I’ve seen on game tutorial sites is to add to the player’s velocity on key down events, and to subtract the same value on key up. This unfortunately causes the problems described above if a large number of precautions aren’t taken, including but not limited to:

  • Making sure a key up is ignored if we haven’t seen a key down from that key
  • Maintaining a list of all held keys when switching between handlers (can be rolled in to the above)
  • Making sure any paired events don’t let one half of the pair fire more than once (two key downs in a row, say)
  • When switching between handlers, checking every key in the new handler, seeing if it is waiting for an event, and firing it if the key state has changed (not ideal, because this means the player will have to repress the button after unpausing, say)

It’s a lot of messing about. I might add, it’s not wrong either (when you correctly code the safeguards). It can be a pain to code, and the edge cases extend beyond what I’ve outlined above. As a result, I attempt to keep things simple: we should never require an event pair in the first place. Instead, for movement functionality traditionally provided by events, I instead use the key state: A map of each key to a boolean value, either true for pressed or false for released. Every frame I check if the left or right key is pressed, I add to the velocity as normal. However, rather than subtract when the key is lifted, I reset the velocity at the end of the game logic for that frame. Suddenly, all of the above problems disappear: with no events to miss, we can’t get the velocity in a weird state, especially when it is reset at the end of every frame anyway.

This introduces something that some might be considered a bug: Suppose the game runs at 60 FPS and I’m moving to the right. That is to say, I am holding the right key. If I release the key after I’ve moved that frame and before the next frame hold the key again, it would be as though I never let go of the key in the first place. Given that we’re running at 60FPS, that gives you roughly 0.0167 seconds to push it. Most likely, you simply can’t release and re-press that fast. Even if you could, under most scenarios this is not a problem. Indeed, for movement this is the exact same behaviour you’d see with key events: On the second frame you would see a key up and a key down event, with the net result of no change in your velocity. There are conceivably scenarios where this is a problem. Consider you could charge a shot by holding space, and fire by releasing. If the player wants to fire a shot and then begin charging a new one, the key event approach would win out: Space bar comes up, space bar comes down, so you get both events on the queue and they’re processed on frame 2. Under the key state approach, we wouldn’t fire the shot. Again, this is a bug, but we would only see the problem if the player is really, really, really fast. I can’t stress how fast he would have to be! They would have to be faster than this dude. So we sacrifice a small bit of functionality in the case where the player is faster at pushing buttons than the world champion. It’s a sacrifice I’m willing to make.

In actual fact, key events will fall over here for movement too: If you tap the right key and get the key down/key up within 0.0167 seconds, the net result will be no movement, just like the key state approach. Maybe it’s not so bad after all! At least for movement. But what about performance? As it turns out, I did some number-crunching on my desktop computer and came up with the following: It takes one millionth of a second more to watch 10 key states than it does to wait for any number of key events (which takes no time, really, because the event loop isn’t populated until you actually press things). I think that’s acceptable! And even on a non-monster machine, it’s not going to take up a significant amount of time compared to the rendering or actual proper game logic. If you want to compare the approaches, here’s a gist of what I did. You’ll need pygame to run it, of course.

So, we’re trading a millionth of a second and a little bit of velocity resetting logic for the peace-of-mind of not having to deal with the edge cases of the key event approach for paired events. I’d call that a fair trade. Hullet Bells runs on a hybrid system: Key state-based function calls for movement (and later shooting), and key events for rarer events like using a special attack or pausing the game. In fact, the input handler presented in the gist is the same one used in Hullet Bells! Yes, it has some pretty gnarly named functions (what’s all this talk about callbacks? They’re just functions!), but it is basically the complete implementation of the system. One limitation is that I have no support for key combinations (say, calling a function if two keys are pressed, rather than just one), but for Hullet Bells (and many shooting games) this is an acceptable limitation.

The Hullet Bells InputHandler

The goal of the InputHandler was to allow isolation of the input logic between handlers, and to make programming input stuff as painless as possible. As long as you’ve defined the logic you want behind a key, actually attaching it is as easy as making the following calls:

# For key states
self.inputHandler.addPerFrameCallback(self._moveUp, pygame.K_UP)
# For key events
self.inputHandler.addPerFrameCallback(self._startMoveUp, pygame.K_UP, KEYDOWN)
self.inputHandler.addPerFrameCallback(self._stopMoveUp, pygame.K_UP, KEYUP)

These cause the event/key to be put in to lists that are evaluated every time inputHandler.update() is called:

  events = pygame.event.get()
  for event in events:
    if event.type == pygame.KEYDOWN:
      for keydownCallback in self.keydownCallbacks:
        if keydownCallback.key == event.key:
          keydownCallback.callback()
    elif event.type == pygame.KEYUP:
      for keyupCallback in self.keyupCallbacks:
        if keyupCallback.key == event.key:
          keyupCallback.callback()
...
  keystates = pygame.key.get_pressed()
  for perframeCallback in self.perframeCallbacks:
    if keystates[perframeCallback.key]:
      perframeCallback.callback()

For the key event stuff, it has just occurred to me that it would be nicer to store all KEYDOWN etc. events in a map of [event -> (key, callback)]. Also, for key states it might be nice to attempt to call all functions related to pressed keys regardless of whether a function exists or not, then we can eliminate the if statement too.. Anyway, those are actions for another time! As it stands, the input handler runs pretty well, so I’m not exactly looking to optimise yet. For the complete code, you can check out the Github or the above gist.

This was far too long, and didn’t really go anywhere. But that pretty much covers everything I wanted to talk about: Input handling in general, some of the problems you might have, and finally, my own implementation using the pygame library. I’d love to say the next post will be about the scripting system, but I’ll have to finish that before I can write about it. So if I want to write a post before then, I’ll talk about the game handler itself as it stands.

The Hullet Bells – Part 4 (Insert Title Here)

The title screen! At this point in game development, it’s probably a waste of time, especially if you’ve already decided to implement a handler system that will let you slot the title screen in at the end. But what’s done is done, so here it is!

The title screen!

They should have sent a poet.

Obviously a work of art. In this post, I’d like to talk a bit about the menu system and the Drawable class. The latter forms an important part of the game too, so it’s worth examining.

The menu system is fairly basic. The title screen handler has a collection of Buttons, with each Button containing a function that will be called when it is chosen. These buttons inherit from the TitleScreenElement class, which in turn inherits from the Drawable class.

class Drawable(object):
  def __init__(self, x, y):
    self.x = x
    self.y = y

  def setX(self, x):
    self.x = x

  def setY(self, y):
    self.y = y

...

class TitleScreenElement(drawable.Drawable):
  def __init__(self, x, y, text):
    super(TitleScreenHandler.TitleScreenElement, self).__init__(x, y)
    self.text = text
    font = pygame.font.Font(None, 24)
    self.renderText = font.render(text, 1, (255,255,255))
    self.textPos = self.renderText.get_rect(centerx=x, centery=y)

  def setFontSize(self, size):
    font = pygame.font.Font(None, size)
    self.renderText = font.render(self.text, 1, (255,255,255))
    self.textPos = self.renderText.get_rect(centerx=self.x, centery=self.y)

class Button(TitleScreenElement):
  def __init__(self, x, y, text, func):
    super(TitleScreenHandler.Button, self).__init__(x, y, text)
    self.text = text
    self.selected = False
    self.func = func

  def run(self):
    if self.func:
      self.func()
    else:
      print("No stuff!")

  def toggleSelect(self):
    self.selected = not self.selected
    if (self.selected):
      self.setFontSize(28)
    else:
      self.setFontSize(24)

The title itself is a TitleScreenElement, while the menu items are Buttons. As you may have noticed, each Button has a notion of being ‘selected’, which in turn affects how it appears on the screen. The title screen handler itself also contains a variable that tracks the index of the currently selected Button. It might be more accurate to call it the ‘hovered’ Button, as selection implies that it has been chosen. When a different menu item is chosen, the buttons toggle their selected status and change their font sizes.

Navigating the menu and activating a menu item is managed by an InputHandler (which we’ll discuss next time) and a number of functions. These functions adjust both the currently selected Button according to both the buttons and the title screen handler, as well as actually running the associated function. In the current version, one button will change the current handler to the Game handler, while the other terminates the game cleanly by ending the main loop.

... In the title screen handler ...
  self.buttons = [TitleScreenHandler.Button(self.game.xRes // 2, 300, "Start Game", self._startGame),
                  TitleScreenHandler.Button(self.game.xRes // 2, 400, "Quit", self._inputQuit)]
...
  def _inputQuit(self):
    self.running = False

  def _startGame(self):
    fadeToHandler(self.game.screen, 0.1, GameScreenHandler(self.game), self.game)

The logic for changing the selected button looks like this (without the corresponding _selectionDown function):

...
self.inputHandler.addEventCallback(self._selectionUp, pygame.K_UP, pygame.KEYDOWN)
...
def _selectionUp(self):
self.buttons[self.selected].toggleSelect()
self.selected -= 1
self.selected = (len(self.buttons) - 1) if (self.selected < 0) else self.selected self.buttons[self.selected].toggleSelect() print(self.selected) ... [/python] That covers the higher-level stuff for the title screen, so what about the Drawable base class we talked about earlier? Drawables are currently very simple: They contain an x and y coordinate, and nothing more. In the future, they will also contain Animations, the foundation for all displayed images. For Buttons, we currently create the text on the fly via the pygame.font library, but these will eventually be replaced by images if we're going to be making a seriously gorgeous title screen. Animations are only partially implemented, but will be heavily 'inspired' by the implementation in my platform game. An Animation is a set of one or more pygame surfaces, with the current image cycled every N frames. Animations may loop (not necessarily from the first frame). A Drawable will contain a collection of Animations, as well as an index to the current animation. It's a very simple system, and if we need to layer something more fancy on top of it later (particle effects, lighting..) it won't be too nightmarish. Next time we'll look at the input handling framework. The write-up is bit of a beast, but the actual logic is pretty simple! If you haven't already, you can see the list of all Hullet Bells articles here. There's even a link to the Github repo, if you can't wait for the play-by-play on this blog.

The Hullet Bells – Part 3 (Handling It)

Handling transitions between various screens was one of the problems my friends and I encountered when developing our shmup game at university. For instance, it was a pain getting the game flow moving from the title screen to the game screen, from game screen to loading screen, and so on.

Because of the way we initially structured the main loop, it was pretty awkward to shoehorn in these transitions. We ended up with this system where the title screen would come up, and part of its main loop would have a call to the game screen’s main loop. Effectively, we were two loops deep whenever we were running the game. It’s not exactly inefficient, but it’s not pretty. The answer I discovered during my internship, long after the project died, was relatively simple. Rather than treat these screens as different loops to jump between, I implemented a system which only uses one loop. This loop repeatedly calls the update function of the current handler. Handlers are the abstractions of each screen, containing their loop logic, assets and so forth. They derive from a common base class and override its update function. It’s quite a simple approach to arrive at, but when you’re just starting out you tend to prioritise the wrong things. Learning about this pattern in a professional environment was a definite boon. It was also probably covered at university (under the much more general polymorphism), but seeing the practical use cemented it in my mind. Later, I would use this approach when designing the platform game. It was so good, it was carried over to my current project.

Here’s the base class for handlers:

class Handler(object):
  # Handlers are the wrappers for the more separated parts of the game,
  # like the title screen, the main game screen, the game over screen..
  def __init__(self, game):
    self.game = game
    self.running = True

  def update(self):
    print("Default handler")
    return True

And here’s a snippet from the title screen handler:

class TitleScreenHandler(Handler):
  ...
  def _draw(self):
    self.game.screen.blit(self.background, (0,0))
    self._drawText()

  def _logic(self):
    for button in self.buttons:
      button.update()

  def _handleInput(self):
    self.inputHandler.update()

  def update(self):
    self._draw()
    self._logic()
    self._handleInput()
    return self.running

And of course, the part of the main loop responsible for calling the handlers in the first place:

def main():
  ...
  while True:
    # Cap the frame rate.
    clock.tick(60)

    # Run the game handler.
    if not game.handler.update():
      break

    # Show our hard work!
    pygame.display.flip()

As you may have noticed, the current handler is stored as part of a Game variable. The game class is meant to carry over cross-handler information. Normally we’d expect it to store some sort of game state, but most of the information is stored inside the handler. This Game object is passed in to the handler on creation, allowing a handler to transition to another by simply altering the current handler itself. Thanks to some behind-the-scenes Python magic, these self-orphaned handlers are cleaned up and not left hanging around.

Here’s an example of how we might transition (very quickly!) from the title screen handler to the game screen:

class TitleScreenHandler(Handler):
  ...
  def _startGame(self):
    self.game.handler = GameScreenHandler(self.game)
  ...

It’s pretty simple, right? We make sure the game state is passed on so further transitions can be performed. This system also allows us to do some clever things, such as allowing us to run handlers within handlers. For instance, if we wanted to create a loading handler such that the current handler continued running until some number of assets were ready, we could write something like:

class LoadingScreenHandler(Handler):
  ...
  def update(self):
    if (self.loading):
      self.currentHandler.update()
    else:
      self.game.handler = self.nextHandler
  ...

Here the loading handler runs its own handler before transferring control to a target handler after asset loading has finished (probably via a thread). Of course, this is getting ahead of ourselves: we have no assets! Indeed, we won’t for a good while yet. Rather, we now have the framework for implementing the many screens of the game. Next time, we’ll look at the title screen and input system in more detail.

The Hullet Bells – Part 2 (Getting Organised)

Recently I embarked upon a quest: a quest to produce a platform game, the likes of which the world had never known. However, I got bored of that, but not before exercising my Python chops. Although I failed, I discovered the wonderful pygame library. Pygame is a Python wrapper for the ever-popular C++ SDL library, which I had used before when working on a small game project with a group of university friends. Much like the project preceding this one, the university project died an untimely death, this time due to heavy college workloads.

Still, both experiences provided a great number of learning opportunities, and during university a six month placement at a video game company let me take a peek under the hood of some pretty heavy AAA title stuff. I took what I learned then and tried to apply it to the platform game, but a general lack of interest on my part meant the project had no chance of survival.

Thinking back, there’s only been two genres I’ve really ever fallen in love with: Platforming and shmups. Sure, I’ve had my flirts with RPGs, particularly JRPGs. As I’ve grown however, I just don’t find them nearly as charming as I used to. Recently, I went back to Final Fantasy 7 to give it a proper playthrough, this time around older and wiser. I figured I might be able to appreciate the combat and magic systems a bit more, because now I’m a more patient, understanding guy. Sadly, I also have a lot less time than I used to, and it turns out those systems never had any depth after all: It was all just grinding in the end, like pretty much every other RPG I’ve ever played.

So I’ve come to appreciate the platformers and shmups. With less time to spend on leisure than ever before, it’s important to me that I maximise the enjoyment I get from the limited time I spend on games. Don’t misunderstand, I do branch out occasionally with new releases outside my comfort zone! But when I need to relax, being able to pick up a platformer and speed through it means a lot. The average shmup won’t take more than an hour per playthrough, so you already know in advance how long you’re likely to spend on it (Side note: There are some insane examples of shmups with multiple ‘loops’, meaning you start back and play through again on an increased difficulty level. These can take several hours to fully beat, and must generally be done in one sitting!).

Why did my platforming game die? I’m not sure myself. I think there was a deadly combination of boredom and laziness. While I’d love to get in to the Procrastination Formula, that might be a topic for another time. The short of it is; I didn’t block time to get my teeth in to it, and when I did have time I wouldn’t develop the right features to bring it towards a minimum viable game. Rather, I spent time developing fluff features like ladders or tweaking values that could wait until later.

This time around, there is a system. I intend to spend at least 25 minutes a day focused on this shmup engine, more if I’m on a roll. I have also mapped out some of the key requirements for what will constitute a complete shmup. In a somewhat mock-Agile approach, these requirements take the form of one-line user stories grouped by screen (title screen, game screen, options screen, etc.).

Having once taken a half-day Agile course, I’m something of an expert on the topic. I can do away with that separation of product owner, scrum master and development team garbage because I am in fact all three! Indeed, this is why I call this shaky approach ‘mock-Agile’, because I’m making a mockery of it. That said, taking parts of Scrum seems to work even for a one-man dev team. Here’s an example of the embarrassing list of requirements I came up with:

Title Screen

  • I want to be able to navigate a menu at the start of the game
  • I want to be able to start the game via the menu
  • I want to be able to quit the game via the menu

It might look silly and insignificant, but this sort of thing keeps me on task and aware of what needs to be done. At this point, you may be wondering if I’ve even done any development yet, what with all the mocking and pondering. Well, take a look at this!

The white box is the player, the green box is a baddie, and the blue one is a bullet! This is cutting edge stuff, guys.

The white box is the player, the green box is a baddie, and the blue one is a bullet! This is cutting edge stuff, guys.

Prior to finally buckling down and properly organising myself, I did a bit of development on and off, tearing bits out of the platform engine and transplanting them in to the shmup. In all, I estimate that about four to five hours of actual work went in to the shmup over the course of a month. It’s time to buckle down and make something. Next post I will give you a sneak peak behind the scenes of how I’ve structured the game.

The Hullet Bells – Part 1 (A Primer on Shmups)

As a would-be hardcore gamer, for me shoot ’em ups, or ‘shmups’, are a fascinating intersection of complexity, fun and playability.

With humble roots in Space Invaders, shmups began with a simple premise: The player controls a ship (or perhaps a flying witch or android) and must defend themselves against wave after wave of enemy attacks. Typically, the player will shoot them, although some games reward dodging over destruction.

The genre split in to two distinct schools of design: fewer, often faster bullets, and denser, slower bullet clouds. The former emphasises reaction speed, the latter memorisation. For example, R-Type and Gradius fall in to the former category, while games such as ESP Ra. De and DoDonPachi epitomise the other.

ESP Ra. De, a bullet hell game
R-Type III, a more traditional game focused on environment

Towards the end of either type of game, the two styles begin to converge: Bullets can only get so fast or dense before they become impossible to dodge, so elements of the other style begin to creep in.

The mechanics of these games vary. Often in simple games, the only variations will be in the graphics and bullet patterns, while the mainstays of lives, power ups and bombs are changed only in token ways. Such games are not necessarily bad! I can revel in the simplicity of a game like Strikers or Raiden, so even with limited mechanics it is possible to construct entertaining games.

That isn’t to say that there isn’t innovation happening! Far from it. The arcade roots of shmups meant that you had to stand out in a sea of other shmups. Some games introduced alternate modes of fire, giving the player a choice between whether they mow down their enemies with scattered shots or concentrated blasts. Others capitalised on the nature of the competitive high score lists omnipresent in the arcade, implementing complicated scoring systems that would require months to master, but for huge score rewards.

More recently, games like Ikaruga have aimed to maintain the old school shmup elements while placing unique and innovative mechanics on top. In Ikaruga’s case, the inclusion of the polarity switch (each polarity allowed players to absorb one of two kinds of bullet) added an entirely new dimension of gameplay, requiring not only that players dodge bullets, but also take in to consideration whether they should be absorbed or not.
Ikargua is a challenging polarity-based shooting game
Generally speaking, once play begins the player will always be looking at the playfield, with the ship present on screen at all times. Plot is sacrificed for an uninterrupted game experience, due to the very nature of the arcade itself: players are here to play games and not take up time on the machine watching cutscenes! This was something of a missed opportunity. CAVE, the popular shmup creators, would be forced to explain the majority of the plot in a 15 second cutscene at the start of the game, with the remainder inferred from short boss dialogues and cryptic ending scenes (if any). With the advent of releasing shmups in both the arcade and then porting them to home console, games have begun to include a longer ‘story mode’ in addition to the ‘arcade mode’ they would normally experience.

This is a completely different story to the doujin and independent game scene. Doujin games are created with the intention of sold at Japanese conventions. Touhou is a popular doujin game shmup series. While the story is probably just as deep as any given fable, a huge fan community has sprung up to fill in the blanks for the world, creating a vibrant living setting with hundreds of different interpretations.

The independent game Sine Mora has a very strong plot with a moderately challenging game to go with it. Indeed, the plot is explained over the course of the game with haunting monologues between levels, and heated dialogue during the game itself. In a rare twist for the genre, control is occasionally taken from the player for plot purposes.

The world of shmups is hugely varied, despite the basic principles being the same between games. This thread that runs through them means skills learned are transferable, while the player can still experience something new and challenging. The best way to experience it is to get out there and try some of the linked games in this post! I can’t possibly describe the fun you’ll experience.

I have a deep enjoyment of these games. While I don’t have the artistic ability or level design experience, there is still one thing I can do to help this dying genre: I can write an easily extensible, open source engine for the creation of shooting games. Over the next few months, I hope to build a small demo game in this engine, graphics be damned! I will also have to write the engine, of course.

I will document this journey here, both to provide insight in to the development process and to keep myself motivated. Maybe one day you’ll even want to build a shmup yourself!