As a for-fun side project, I've been working on a simple top-down pixel art game engine in vanilla TypeScript on-and-off over the past year. It's been a nice break to work on TypeScript code that is completely decoupled from any framework or library, and I've always been interested in game development. Some features I want to highlight in the game engine:

  1. Function- rather than Class-based code

    I see this as the trajectory that coding is moving towards, especially in web development. It takes some getting used to, and I could do a bit more structuring of the code. But I like how accessible all of my logic is.

  2. Fully animated using HTML5 Canvas and requestAnimationFrame

    I learned that I needed to couple game object states with realtime Date methods rather than frame renders. A variety of factors can affect the browser window's framerate, like the device's battery level and GPU usage. I don't want the game to feel like Neo's bullet-time in those conditions. So objects can change their animations in real time, but the actual frame of the animation that's drawn is tied to framerate through `requestAnimationFrame`.

  3. Color values that can be manipulated based on material and lighting data

    All the visuals of the game are stored as arrays of RGB values, rather than something like PNGs. Because of this I have full and immediate access to manipulate any color values of any visual element. If a character equips a helmet, or upgrades their weapon, I can modulate RGB values to display that change on the character. If a character is in a dark area and moves under a light source, I can change how shadows look on the character, and even adjust the colors based on the color of the light source. This lets the game display an enormous variety of visual states without having to manage a huge number of assets.

  4. Visual effects for wind and weather

    I can generate sine waves that help calculate the position and animation of certain objects like cloaks and capes. It's an easy and convincing way to animate something blowing in the wind. Wind values can adjust the amplitude, frequency, and radius of the sine waves. Wind values change based on randomly calculated large circles that move across the map. Objects within those circles will change their animation frames or sine wave parameters based on the strength of the circle's wind value. There is also a day/night cycle that adjusts global ambient light values. Global ambient light values can also trigger events at certain thresholds, like lanterns turning on or fireflys lighting up.

  5. Reusable menu systems for settings and inventory

    I can calculate how big I should draw a menu window based on the contents it will have. Menu and inventory options can be set up in various grids that the player can navigate using a keyboard or controller. I use the same code to render text for objects like interactive sign posts.

  6. Controller support

    I use the native browser gamepadconnected event, and the navigator.getGamepads method to access connected controllers. I can read the input state of a controller and map those inputs to various functions within the game.

The basic architecture of the project is vanilla TypeScript for the front-end game engine, ExpressJS backend for basic CRUD operations on game data, and a MongoDB database to store game data. I have not built anything that could be considered a real game with this yet. There's a lot that should be done still, like save data for players, drawing larger maps, and implementing web sockets. The work has been fun, and it's enjoyable to see it play out on screen. Someday I'd like to take all of this work and turn it into a real web-based game.

Here's the repo for the game engine:

https://github.com/jdillman1989/garden-quest

Here's an example of what the game can do currently:

https://garden-quest.jdillman.com