Exploring Game Structure

Max Novak
5 min readSep 20, 2023

--

For this game, I wanted to answer a different kind of question: How can you structure a game in PixiJS? While a game can just be a screen with a scene that just starts as soon as it loads (like everything I have made so far), if you want to build something more complex you need a bit more of a framework. So I decided for this game, rather than just build a game with more complex mechanics or rules I would build something more architecturally interesting.

First, I needed to figure out what core behaviors I wanted to architect. A menu with level select and the ability to pause seemed good things to build out. I could also add a system to manage game state like the player’s score or location in the game, which would get reset when changing levels. So, with my features of start , pause, & select a new level I had the base idea for my game. My next step was to do some research on different people’s approaches to scene management in Pixi. Most game engines come with scene management built into them. Because Pixi is a “rendering engine” instead of a game engine it is more of a system for interfacing with WebGL and Canvas, so scenes aren’t a part of its toolbox. After looking through a few implementations I found one I liked done in PixiJS Elementals (you might remember them from my first article).

After copying the gist of their code, I had a framework that would cache my assets in a loading scene and then switch to a scene with a little guy on it, who could move around. The little guy was a free sprite from ZeggyGames, which they use for prototyping and wanted to share out. If you’re not familiar with Itch.io I highly recommend taking a look for assets and just cool indie games that people put together.

Cute Lil’ Guy
Cute Lil’ Guy

Next, I had to put together a menu to let the player pause and select levels. This was my first time trying to structure text on the screen, so I decided to check out a Pixi library called PixiUI — I mostly picked it for the ability to make lists, but the other features looked cool too!

As I was putting together this menu, I realized something interesting. I had set up the players movement with Javascript EventListeners to listen for wasd or arrow keys. And when I was adding the menu scene I just added a new EventListener to exit the menu with esc. But when I opened the menu, I found that the character movement was still active (it was kinda fun to have the guy pop in and out behind the menu). So to add a pause behavior I needed to figure out how to stop his listeners, while the menu was open.

My first attempt was to add a stopImmediatePropagation() call to the menu, but that didn’t work! The guy would still move around when the menu was open. This led me to look a little deeper in the docs around EventListeners. A thing that I didn’t know was that EventListners always fire in the order that they are applied, so by creating my menu on top of the game scene I actually couldn’t have my menu stop other events.

This was a little frustrating, mostly because structurally I didn’t want to instantiate the menu first and just hide and show it. I came up with a simple solution of adding a setting to the manager, which would allow different scenes to check if the menu is open or not. I’m not a huge fan of this solution and I might revisit it next time I play around with menus, but it works well enough for now. So, now I have a small check in my game logic to stop movement if the menu is open:

if (Manager.menuOpen) {
this.playerVelocityY = 0;
this.playerVelocityX = 0;
if (this.isRunning) { // This is to switch to the idle animation
this.isRunning = false;
this.player.textures = Manager.playerSprites.animations.playerIdle;
this.player.play();
}
return;
}

Another weird hiccup I ran into in this project was around the sprite animation. To expand upon my sprite usage from last time, I wanted to use animated sprites. My idea was pretty simple to have the player stand in an idle animation that would become a run when you started moving. Pixi makes it easy to swap out the sprite textures between idle and run and then you just call play() to have them start animating. However, because I was swapping animations on an EventListener I was having the textures swap and replay constantly. This led to some very weird but funny behaviors like the player running a cycle and then just stopping with their leg in the air.

To get around this I did something similar as I did with checking the menu being open. I would only try to swap the animations once and then flip a flag to not try to swap it again. This meant I would only call play() once and Pixi wouldn’t get confused. I also added in a mirroring of the player if they pressed left or right so that they would look like they were moving in that direction. This was done using the .scale.x property on the texture and just setting it to -1 or 1 for the direction I wanted.

Game in action

Now, is this project a “game”? Yeah, of course! Is it something that will hold your attention for more than maybe a minute? Not at all! But that’s fine. I could definitely add more game like elements, like a gem that spawns around the screen for you to run and pick up in a time limit; levels having to be unlocked until you reach a certain score; etc. But that wasn’t really my goal with this game. Most of the games I want to build right now are more along the lines of prototypes to try out and learn new things. Through these learnings I mostly want to explore Pixi and game design. Those learns might help me find a super cool game I can build in Pixi, or they might show me that Pixi isn’t what I actually want to continue with and that switching to a game engine is my next step.

I’ve found that ’tis important to use the right tools for the right job, and a part of finding the right tools is to explore things and see what benefits and downsides they have. Coding is much more of a craft like woodworking or smithing where there are lots of ways to answer a question. And the goal of this series is to catalog my journey around adding new tools to my toolbelt. And maybe a cool game will come out of it in the end :)

Check out the game here and the code here and hopefully I’ll have some other small games to write about soon!

--

--

Max Novak

Software Engineer that likes to futz about with games