Common game utilities + rollup config, suitable for a small game competition. Like JS13k! In TypeScript!
Examples:
- Signal Decay, JS13K-2020
- Health Alchemy (Incomplete), JS13K-2019
- Ghost High Fiver (Incomplete), JS13K-2018
- Night Shift Barisa, JS13K-2016
Includes:
- Component Entity System
- Stable Game Loop with interpolation and panic modes
- Scheduling, for game-time dependent time events
- JS13K-compatible zip creation + notice of how close you are to the limit:
yarn zip
- Rollup, so you still get to use modules and separate files.
- More? You should make a PR!
Rollup bundles JS using ES2015 modules, but does not leave any of the import/export syntax in the resulting bundle. It pulls everything into the same lexical scope, uniquely named. This makes it excellent for a size-based competition, because by its very nature it emits the smallest representation of code! Combined with UglifyJS this gets us very close to a nice base size.
Fork this repo, then add / change code in src/index.js as you see fit! There are dependencies included, but you can remove those. Rollup ensures that only code you import
is included!
- Static files can be configured for copying in rollup.config.js. Default is just
src/index.html
- Static files that are
import
ed are automatically copied into thedist/
folder by rollup. - Roadroller is ready! Check tools/zip.sh.
- PNG/ZIP optimizations are handled by Efficient-Compression-Tool (ect).
Run type checking, rollup, and a local http server in watch mode.
How close are you to the limit? Compiles in production mode, and creates a zip suitable for JS13K in /dist
!
Build a zip, then deploy the dist
folder to gh-pages
seamlessly! Best for testing your game on multiple devices.
Done automatically by yarn start
, but perhaps you just ran yarn zip
and want to run the actual compiled/mangled code.
MIT
TexturePacker removed animation support from their JSON output, so I decided to switch to Aseprite for now. But it's a benefit because Aseprite allows for trimming of the sprite sheet! It makes for more complex extraction, while gaining sprite atlas space savings.
Use pixels for drawing sprites
Got some entities in there and debug draw them! Keyboard control is working. Refactored systems into separate files.
Found a bug where the sprite sheet was drawing at the wrong (flipped) y, resulting in completely wrong results.
Aseprite has some missing behavior where frame tags are embedded in the atlas without any filename data. So the collection code needed to be rewritten to instead iterate through the frames and track how many times a specific tag had been encountered. Luckily the frame tags are still ordered!
Added an enemy that moves towards a target and the player. It's kite-able by the player!
Added a super basic "ability" that puts a dot on the field whenever you hit 1
.
An enemy is slowed down and can damage an obstacle! Eventually the obstacle becomes destroyed.
Brought in analog sticks again.
The player and defense targets can die.
The game will restart! There are levels, and the systems are initialized by the levels themselves rather than being global.
I think I'm going to call this "Paint a Picture of Death", and the goal will be to create a nice painting as you replace all the miasma with plants.
Took a few days diversion to look into spatial hashing (got a bit nerd sniped...). Found a cool series of videos and felt the need to investigate further. https://www.youtube.com/watch?v=oewDaISQpw0
Discovered that the author had used Map
wrong, so I made a PR. simondevyoutube/Tutorial_SpatialHashGrid_Optimized#1
Not even sure of the benchmark, tbh. After writing my own, and also doing basic benchmarks, I doubt that Set/Map are as slow as the simondev benchmarks imply.
Set
s seem incredibly fast:
Basic collision overlaps are working! The miasma is clumping.
Created a player abilities component to hold a future offensive ability.
Got a second player ability (grenade) almost complete!
Found a major bug in CES3, where a selection could accidentally include the completely unmatching entities! Unfortunate. Given three component kinds to select, if there was no intersection between kind[0] and kind[1] (e.g. the matching result should be empty, the results of kind[3] shouldn't matter), the selection algorithm was accidentally restarting and including all of kind[2]'s entities! This probably goes back several years...
Got player grenade destroying enemies! They explode outwards.
Tombstones when miasma dies are working.
Added like 10000 miasma to test the perf / limits. It's actually kind of fun to blow through all the miasma! But requires optimization. Might not even be possible to get 60fps.
Enemies have an "aggressiveness" value that determines how often they move.
Seems unlikely that I'll finish something by the deadline. So much polish is required to even have a complete game beyond a tech demo, and that's without consideration of actual gameplay / feel.
- Ability UI
- Health Display
- Player Sprites (kinda)
- Miasma Sprites
- Ability Sprites
- Start Screen
- Sharing / Export of the drawing
Health display is working, and added a safe zone.