404 Rhythm Not Found – js13k 2020

Js13kGames is a JavaScript coding competition for JavaScript Game Developers. The fun part of the compo is the file size limit set to 13 kilobytes. The competition started on 13th August and ended on 13th September 2020. The theme for 2020 was 404.

I managed to participate in the competition for the fourth time in a row, this year I teamed up with an elite team of game jammers and friends: agar3s, mapedorr and QuietGecko. We ended up creating a robot dancing game. You can play online here. Source code is here. There’s also a gameplay video.

The Story

This year I had two goals in mind: First off, I wanted to do something using a palette based sprite renderer, so that I could create a visually rich game under the size limit. The basic idea is, instead of drawing image files directly, have image data encoded to a more optimal (and lightweight) format and then using that data to manipulate what is displayed in the end (more details below).

The other thing I had clear was I was not going to jump on it alone; I had been talking with agar3s the months prior to the competition, entertaining the idea of joining forces for this year. Once the compo had begun we started brainstorming ideas and technical aspects and decided it would be nice to have a good pixel artist on board in order to make the best use of all the technical stuff we were doing under the hood, so we invited Mr. Mateo Robayo to join. He was a bit hesitant at first since it seems he didn’t enjoy his previous js13k participation a lot, but since this time he’d focus on the pixel art, he accepted to join.

As the first days passed, we considered doing some kind of action “roguelite” (ugh) with a robot exploring an abandoned factory looking for the correct URL, but as Mateo started coming up with art for the robots, and I implemented a basic “idle” animation with the parts we had, I thought it would be great to have a dancing game. We invited sound and music artist QuietGecko (with whom I’ve done a lot of work in NovaMundi and Emerald Woods), to create some cool tracks and SFX for the robots to dance.

In reality, I had a secret plan to have these 3 guys work back in a game together, but that’s not the kind of things you mention in a blog post.

I was able to do most of my contributions during the first week, luckily the guys were there to push through including the final days which required some big effort to close the scope, integrate everything and deliver an exceptional entry IMO.

The Sprite Renderer

There are many components on this entry, but my main contributions in the coding side I believe were aligned to what I was pursuing with my participation; I’ve always wanted to do a NES or GB emulator, this comes from back when I used to do some simple sprite ROM hacking, and reading about how graphics work in these kind of consoles. js13k seems like a perfect opportunity to use similar techniques for displaying visually rich content using as little storage as possible, and I bet I’m not the first one to think so, but I had never jumped into doing it.

So, with the fundamentals of the idea on my head, I jumped into it and together with agar3s we were able to put it together working great, this a summary of how it works (not that it’s something ground breaking, but I figure someone might find it interesting).

I aimed to support indexed 8 colors sprites, so we had each pixel take up 3 bits, and thus the entire pixel data (128×112 pixels) would fit about 5KB before any encoding or compression. We used a PNG file as the source of image data, thus allowing Mateo to work in whatever tool he wanted (I believe Aseprite is his weapon of choice); this file is then processed by a nodejs script which reads the image data into an array of bytes, encodes the array and exports it to a JS file used by the game.

Encoding the byte array was a bit tricky; my initial ideas worked but the string representations I was able to create ended up using special characters which wound up taking 2 bytes instead of one; as I thought on some workarounds for this, to restrict the symbols to safe 1 byte printable ASCII, we also did some research and ended up following xem’s latin-1 string trick.

On runtime, this data is decoded by the game, and then the renderer displays a sprite by crossing the data from a given palette of RGB values and the index defined in the sprite, thus allowing 24bit color depth display, without having to store the color data for each pixel.

In order for this to perform well, however, the pixels should be rendered “offscreen” using an image data buffer and writing to its pixel data directly, and then putting the entire image data on every frame.

Besides potential savings in storage space, this also allowed us to use palette animation effects (Mateo seems to have had a lot of fun with this) and to include variety in the game.

Ultimately, my contributions to this were mostly infrastructure work; the rest of the team did a great job extending and actually applying it into the game!

Soundworks

This being a dancing game, music and sound effects were bound to have an important part on it. As QuietGecko joined he struggled a lot first with the tools, trying out different trackers trying to make the JS conversion plugins work.

All I could do was recommending using Soundbox, the tool I used for my past two entries which worked great to me; however, everything changed when Keith Clark, the author of ZzFXM, released the beta version of ZzFXM Tracker. Everything worked perfectly from there, and as a plus, the code that was exported made a lot of sense and was much easier to work with.

I’m not sure what happened during the final hours, but in the end we had great SFX too. But you cannot expect less from the QuietGecko.

In his own words:

Having to convert .mod files to .js and translating synths was very difficult until Keith Clark released his tracker, although I experimented creating synths using his sfx creator and it ended up being very helpful. Also, having the issues with the instruments was a bit frustrating at first but it gave me a chance to try different trackers and strengthen the composing muscle which was useful when the time to rush came.

Additionally, having to use 64 note sequences seemed to be a bit too constraining, I wanted to test smaller sequences so we could have a procedural approach but it would be something to revisit next time.

I like that we ended up having a cohesive retro style sound even though I wished to have it more balanced mix wise. I really liked it. I would also have wanted to have a way to teach or suggest rhythm or patterns to players other than beat subdivision.

QuietGecko, September 2020

Discarded Gameplay Ideas

As I mentioned, I could not contribute a lot of code after the first week… besides being stuck with a lot of work in other projects, I also felt kind of stalled regarding the game. In spite of being the one who proposed we went that route, I had never made a rhythm game, and I didn’t think I could contribute a lot to the design so in a way I decided to see what the rest of the team could come up with.

However, one of the things I experimented with after seeing how the game was evolving, was making it so that instead of pressing sequences of random (but varied) letters, you had to do some patterns that would be translated into special moves into the game and give you bonus points. The idea was you would find out about these moves from your opponents, and would replicate them using your individual robot-part movements.

While it technically worked, it was pretty hard! almost impossible as the BPM went up. So we decided not to integrate it in the end, may be it could work for a different kind of robot dancing game.

What Went Right?

Teamwork worked great but this was no coincidence. We are no strangers to game jams and we have worked together in many projects, so everybody knew how to contribute and we also let the project evolve organically with all our ideas. Again, it was great to know the project was going to be completed because the guys were serious about taking it to the finish line.

Besides making the pixel art for the game, Mateo ended up coding a lot of the GUI, as well as the palette animations. I already mentioned QuietGecko’s contributions, and agar3s…. well, let’s say besides contributing a lot of build, tooling and engine infrastructure, he made sure everything worked together and extended the engine towards what we needed. I hope he manages to write down his experience so I can link it here.

What Went Wrong?

Now, if we evaluate the end result, maybe we didn’t really integrate the 404 theme a lot into the game; it ended up being a shallow aspect, when you miss a beat you get the 404, if you don’t find your rhythm, you fail.

Onboarding was also not great, I didn’t like the key layout a lot (D, F, J, K ?), but I was told that’s what people uses nowadays especially on laptops. How the bonus mechanics work inside the game is also not very explicit, but on the other hand it can be deduced after some game play so I don’t think it’s a big deal (as it was in Lost in Asterion).

Overall, one could think if we had a clearer vision of the game design from the beginning, we could have integrated the theme better, and polished the mechanics, but I actually feel the journey of exploring different gameplay ideas was a good experience, and was in a way more fun and exciting than just following a set plan.

The Future

This is one of these rare jam entries for which I don’t feel there needs to be any further development; not that it’s a perfect game, but I believe it’s just as good as it should be for a js13k entry (If anything, we could add support for mobile, and that would not be a big deal).

Backpack Monsters – js13k 2019

Js13kGames is a JavaScript coding competition for HTML5 Game Developers. The fun part of the compo is the file size limit set to 13 kilobytes. The competition started on 13th August and ended on 13th September 2019. The theme for 2019 was back.

I managed to participate in the competition for the third time in a row, this year I created a monster-catching game. You can play online here or here. Source code is here.

image (3)

The game itself is pretty simple, you walk around the map using the cardinal directions, and when you land on a spot you may find a monster and catch it. Both moving and attempting to catch a monster will consume your action points, which replenish automatically every 20 seconds to a maximum of 40. It works in both mobile and desktop browsers.

The organizers were encouraging the participants to integrate with coil.com and XRP tip bot to monetize their entries, I implemented a simple bonus for coil subscribers (they get a 25% bonus on the speed for action points to recover). So far I have received 1.08 XBR (That’s Ripple cryptocurrency,  converting to about 0.3 USD today)

The Story

What was my motivation this year? I was really hesitant to participate since I’ve been busy with other projects and just participating for the sake of it was not enough of a reason. Certainly, after last year’s results, I didn’t care much about “winning” the contest.

So, in the end my motivation ended up being merely to create an interesting procedural generator, to hone my procgen skills. I had just tried to participate in “Advanced Topics in Procedural Content Generation” online summer school provided by the IT University of Copenhagen and New York University, where I was able to watch some talks and gain some insights, but failed to participate in the course project.

The weeks before the challenge started I had an idea for a procedurally generated sports event (that thing has been in my head for some time now), but it was not very compatible with the theme they announced (“Back”). For most of the month, I couldn’t come up with something fun and interesting, that only managed to happen in the last week. So I started late and only managed to invest about 5 days on it, but the last days were super intense.

Being a pokemon fan (and a somewhat proud genwunner), I always wanted to create a monster-catching game (well, I kind of already did). Some years ago I was even working on a Pokemon Go-like game, but it never lifted off due to missing some original designs for them monsters.

So, I thought I could take another stab at a similar project, using procgen to fill the gap. I started by analyzing some pokemon anatomies and coming up with their structure and even used tracery.io to have an idea of how this “taxonomy” was looking (I had wanted to use it for something, for years :P). Sadly I didn’t include these descriptions in my final entry. (then again, I dunno how big the JS lib for tracery is)

js13k0

js13k1

Then, I started setting up the project, reusing the structure from my previous entries. In keeping my idea of NOT using pixel art on new projects, I thought of reusing the vector rendering routines I had used in these previous entries, however, the shapes I was planning to use were going to be more complex (I was initially thinking on trying to replicate the look of the original pokemon, like this one), so instead of just coding them by hand I used some online SVG editors and then manually translated the SVG instructions into my rendering routine.

However, as I needed to produce more complex shapes (mainly supporting bezier curves), I found out it would be more straightforward to generate SVG objects rather than extending the “vector script” I had in place, which by coincidence was pretty similar already to the SVG path definitions. This became more important as I looked for ways to get an artist to help me with content for the game since I would have had to translate SVG into my own script language, either manually or automatically.

So I ditched rendering paths and shapes into the canvas and instead started experimenting with generating SVG components from code and overlaying them using CSS.

js13k5

As the deadline drew closer, it became obvious that I would not be able to replicate the appearance of the reference I had for the monsters in a convincing way. I looked around a lot and finally found something in Etsy that I could use as a reference for my generator. (sadly, the store and the item itself seem to be gone now. Good timing for me tho!)

unnamed

These designs had several advantages:

  • They were portrayed as a symmetrical front view
  • They were more “symbolic”, without relying on individual poses for personality.
  • They were “inspired” by the original Pokemon designs, so not a direct knock-off.
  • They were already provided in SVG format.

I bought it, thinking I could at least cut and paste the different body parts and use them as individual SVGs, but my skills with both Illustrator and Inkscape proved not to be enough for it. Luckily, js13k colleague Rybar came to the rescue and helped me with the task, probably having to redo a lot of SVG work following the references.

Now with the individual SVG assets provided by Ryan, I could finally advance in the actual generator, having, at last, some progress to show.

The generator works by picking a random “anatomy” which determines the body parts slots the monster will have, and their location. then it proceeds to select a random type of body part for each slot and positions them together using some anchor points.

It also picks a random “pastel” color for the monster, I did some research and found out an easy way to generate them was using the HSL model, and having both Saturation and Lighting at 70%, and picking a random Hue. Luckily, CSS supports defining colors with the HSLA notation so this was pretty easy to include.

I also build a simple, syllable-swapping based name generator for the monsters. It generates names using two to three syllables, picking from a random list of consonants, vowels and a possible third consonant, for each syllable.

It’s also worth noting that this generator is seeded, which means the “races” of monsters that are generated are always the same, and all players will get the same set! For this, I reused the simple (on implementation!) but effective Park-Miller LCG

Now that I was finally generating some content, I focused on creating an actual game around the generator. I knew from the onset the game would not be deep, but there had to be a game!

I created a world represented by a 10×10 grid of locations and added a simple name generator for them (reusing the monster name generator but also adding some flavor with location types and colors). Also added the energy system to move around and catch the monsters, to serve as a barrier for content consumption.

In the world model, I placed lists of monsters for each location, considering their “rarity” so that very rare monsters can only be found in a single location, and so on. The idea being that players could share their findings, creating something of a social aspect to the game (Hey, what monster are you missing? I found Lesense in the Temple of Serkekol!).

I added a simple model to keep track of the monsters you had captured, and a view where you could see them.

I had managed to have a playable game one day before the deadline, so I could focus on enhancing the UX and testing. Needless to say, this ended up consuming a lot of energies but the end result was very good.

I managed to include a music track (thanks again to Rybar for creating it!) and even modified it in the tracker to make it longer (first time I make something useful using a tracker). We used SoundBox again (here‘s the final version of the track)

sb

I also made the game public and asked around for suggestions to improve it, one of them was adding more variations to make the monsters feel more unique. I fired Inkscape and drew a lot of horns, antenna, mouths and some tails, and also defined an additional anatomy with no “body” (just a head with things attached to it). The structure that was in place made it very easy to add new content.

Also, in order to add some “depth” into their appearance, I was suggested to do some shading into the bodies, which I managed to do with the help of Prinfexita, a fellow indie dev from Colombia. She drew the shadow shapes and I added support for them into the generator (including producing a darker version of the body color)

I also did a LOT of tweaks on the user interface, to make navigation easier for the players and provide a cleaner experience, especially in mobile.

What went right

  • I was able to create a finished, stable and polished experience
  • I learned a bit more about SVG
  • I created something technically different than last year entries.
  • The monsters look cute.
  • I was able to collaborate again with Ryan Malm, for the first time with graphics and for the second time with music.

Inadvertently, I think I managed to do just what I set to do from last year’s postmortem:

  • An easy game, rewarding players without requiring lots of skill.
  • Gorgeous visuals. (Maybe??? :))

What went wrong

Nothing really went wrong, however, there are some core things I wish I had managed to include to make my entry more fun:

  • A scrolling map view of the world, since right now it relies a lot on the player imagination
  • Deeper gameplay mechanics for catching the monsters, maybe collecting some items in the world that would help you lure them.
  • Allow trading monsters with other players.
  • More body parts, especially Wings and tails
  • Scaling variations for the monster’s appearances.

But all in all, I’m very happy with what I was able to create in the short time frame.

However, I got pretty sick and weak for two days after the deadline, I believe I pushed too hard. Would be better to avoid crunch by starting earlier.

The Future

I never intended the game to be more than just a collecting game, so things like a plotline or a combat system were willingly ignored.

Some other things that would have been nice to have, as possible points of expansion:

  • A more in-deep generation of the monster anatomies beyond randomly selecting and swapping parts.
  • Generate monster descriptions and stories.

 

 

 

Postmortem: ArcherFire Duet of Aces – js13k 2018

ArcherFire: Duet of Aces is a game I made for the js13k 2018 contest, you can check it out here! (and the source code is here)

I decided to write one final piece of text about my second participation on the contest. I already described my journey in detail here and here, and also did a dissection of the source code, but I wanted to record some lessons learned which may come in handy for other people or myself in the future.

afdoa

The story

Whenever I participate in a game jam or contest, I ask myself what is my motivation:

  • Learn a new language or tool
  • Create something cool
  • Win the contest prize

This was the second time I participated in the contest; results from last year had been a bit disappointing (regarding the ranking given by the jurors), and I knew my development time this year was going to be very limited. Still, I aimed to rank high into the lists.

The theme for this year was OFFLINE, as mentioned in my first blog post, I started off with a vague idea of a space… thing… where you could collaborate with other players offline to advance through the game.

20180913_210742

On the first day of dev, I created some foundations work looking forward to having some kind of space sandbox thing with arcade elements (Similar to this entry, which ended up being one of the contest winners). However, given the constraints I had, I decided to follow my own advice from last year’s postmortem and create:

  • An arcade game bringing full action from the first second of gameplay
  • Complete music track

And that’s precisely what I ended up doing! Interestingly, and maybe because of what I set to do and my experience from last year, I didn’t have any issues with the 13KB limit so I didn’t have to cut around any corners. I incorporated the OFFLINE theme by allowing 2 players hot-seat offline play.

However, the results were even less encouraging this year. Despite receiving good feedback from the jurors, the game didn’t even end up in the top 100. (Last year it ended up #40 overall and ranked well in the Community and Social lists). Since this was the first year where some constraints were put on the prizes model (only top 100 entries would get prizes) that meant that effectively I lost the contest. There was a total of 270 entries, and mine ended up ranked #105.

Screen Shot 2018-10-18 at 6.35.57 PM

Unlike last year, this time I don’t really have some big factors I think led to this result. I contented myself in thinking that the jurying process is not perfect, and there may have been very good entries this year. Still, here’s what I think worked and didn’t work.

What went right

  • Seeded Procedural Generation: Managed to create an infinite, increasingly harder, top-down shooter level which was the same every time you played (So, in theory, the more you play the game the more likely you are to memorize the hazards and get farther)
  • Pseudo 3D Effect: Everyone loved how cool the ships looked when soaring around.
  • Straightforward action-packed: The game is pretty responsive and quick, with lots of action on screen. No need to explain anyone how to play because it’s obvious!
  • 2 players hot-seat mode: I couldn’t test this much because I have no friends, but I saw some people have fun and yell at each other afterward.
  • A solid, finished entry: No bugs, no feeling of being an “incomplete game”, it is what it is and it doesn’t break.
  • Music: One of the game highlights, and I didn’t do it myself 😀 it was all thanks to Ryan Malm. I just gave him a reference and some ideas, and he came up with the track. Thanks again!

What went wrong

  • Floaty Controls: Since my foundational work on a simple physics engine had support for acceleration, I stuck to the end with the idea of the ships being “hard to control” as a “challenging aspect” for the player. I knew it was frustrating, but I waged on the players trying harder to learn how to control it. In the end, it ended up being too hard and too different to the standard. A model where the ships had less inertia would have been much more playable and enjoyable. Maybe I need to start making easier games!
  • Balancing: Some people reported the game was a bit too hard. In part, this may be closely related to the controls, but also could have lessened the hit points of the enemies or made the difficulty curve less step.
  • Lack of theme: Yet another space shooter, no plot, maybe went too much into the arcade direction? So that aspect was pretty uninteresting. There were also too few types of enemies, mainly because of the time constraints I had.
  • Graphics too simple: I am not an artist, and the game had high-resolution vector art. Unlike last year where I could go around that by using shadows in the darkness, this year I went for colors and maybe it didn’t look too nice. One thing that could have worked would have been using WebGL filters to post-process the bare graphics, which has worked great for other games in the past.

The Future

This is not the end of the story for Duet of Aces… I plan to make it evolve into a more complete game, keeping the core design but adding better art, sound effects, more music, a complete plot and more importantly, adapting it to social media mobile platforms. More info soon!

Also, some things I want to do next year:

  • An easy game, rewarding players without requiring lots of skill.
  • Gorgeous visuals.

ArcherFire: Duet of Aces, js13k 2018 source code dissection

JS13k 2018 has gone by! this is the third of a series of posts detailing my journey, as well as the structure of the game I built. You can play it online here!

afdoa

Links to the full series: part1, part2, postmortem

The full source code of the game (github repo), uncompressed and unminified, is 43136 bytes for the single javascript file, plus 349 bytes for the html file. This includes a lot of comments and code that could be written in a more optimal way, which reflects that my biggest restriction this year was not the size, but the time I could invest in the project.

Screen Shot 2018-09-21 at 10.02.50 AM

Following is a summary of the 43136 bytes, which of course could be laid out in a much better, modular way, but were thrown together in a huge file for the sake of reducing overload from webpack for having multiple modules.

So, why do I think this may be relevant? Well, I believe this may be a bare minimum setup to have an arcade game up and running; understanding how these components work together to create the game experience might be helpful to create a more organized structure, without falling on the mistake of over-engineering (start small and simple!).

Also, having them all in a monolithic block creates an implicit graph of dependencies, where the more general purpose components are (generally) defined first, then other code uses them. Here’s a first stab at translating that to a component / class / object diagram.

Screen Shot 2018-09-21 at 10.50.36 AM

With each segment of the source code, I’m including a short description which may give you an idea of the types of components in play for the game, here we go!

  • Soundbox player (11879 bytes): Pasted from here, this is the code that interprets the song “script” and transforms it into a WAV stream.
  • Theme song (5148 bytes): Created by Ryan Malm, it’s exported from Soundbox online player.
  • SFXR player lib (2637 bytes): Minified form of the original source code here, this code allows playing SFXs based on a list of settings
  • Initialization function (466 bytes): Creation of the music player and the WAV stream from the song script.
  • Sound data for SFXR (484 bytes): 5 different sound effects represented by SFXR instructions (Explosion, Bullet, Missile, Super Explosion, Start Game Beep)
  • SFX playback functions (359 bytes): Preload Audio objects from SFXR sound data and allows easy playback.
  • pRNG functions (719 bytes): Functions to generate random numbers, including the seedable pRNG.
  • Keyboard input routine (533 bytes): Some hooks around keypress and keydown to allow polling for the state of a key or add a listener function.
  • Shape renderer (1765 bytes): Given a canvas rendering context, a set of “shape instructions”, a position and a scale value, translate the simplified instructions into Canvas 2D API operations.
  • Mob class (887 bytes): Model the basic things moving around in the world, every Mob has an appearance, speed, and position in the x and y axis. This class also includes functions to update the mob, destroy it and check collisions with other mobs, as well as the creation of explosions.
  • RAF function (401 bytes): Function that allows hooking other functions into an animation frame, doing the fundamental calculations for the elapsed time between frames which are used to (try to) keep things running at a constant speed regardless of where they are run.
  • Collision functions (177 bytes): Simple collision checks based on the Manhattan distance between two mobs and their size.
  • Game Loop (1952 bytes): Keeps tracks of different list of mobs, used for both updating them on each animation frame, as well as rendering them on screen. It also keeps tracks of the animation-based Timers
  • LCD-like number rendering (805 bytes): Allows drawing any number as an LCD-like display.
  • UI Rendering (1371 bytes): Depending on the current state of the game, might draw the loading message, or the title screen, or the HUD including the scores and the current wave, or the Game Over message.
  • Enemy Factory (2318 bytes): Contains the stats for the different kind of enemies, as well as function to create groups of them in a given initial setup. For example you can request the factory to create 5 mines in horizontal formation at y = 200
  • Player Ship class (2356 bytes): Extends Mob, has special checks on its update function to simulate inertia as well as handle the practical “3d” effect when moving around and keeping the player ships on-screen. Of course, it also includes functions to control the movement of the ship using the keyboard (the actual keys that are used are received as a parameter, which means there could potentially be more than 2 players on screen). Also allows firing missiles, and keeps track of a player’s score.
  • Enemy class (1208 bytes): Extends Mob, has a simple “reaction” model which allows it to potentially fire a bullet at the player each x milliseconds. The speed of the bullet on each axis is calculated using the arc-tangent between the target and the enemy. The target is selected from the list of players (the closest one)
  • Star class (304 bytes): Extends Mob refining the destroy class so that a new star is created at the top when a star is destroyed.
  • Planet class (366 bytes): Extends Mob defining a special render function which draws a circle filled with a gradient based on the 2 colors and rotation of the planet.
  • Explosion class (928 bytes): This class is similar to Mob, but explosions have no speed (just a position). It’s designed to progressively draw an explosion on screen, based on the “run time” and “size” parameters, the size and color of the circle to be drawn are determined by the “progress” of the animation (a value growing from 0 to 100, based on the accumulated render time and the total run time). When fading, it substracts from the drawn circle creating a growing “hole” inside of it.
  • Shape definitions (2487 bytes): A dictionary of lists of drawing instructions to be interpreted by the Shape Renderer, all Mobs have a reference to a shape definition, used in the game loop
  • Game Start function (683 bytes): Plays the theme song, creates the player ships and starts a timer for wave generation. Called by the title screen and the enter key handler (for restarting the game)
  • Enemy Wave Generation (1947 bytes): Several functions containing the logic to create a new “wave” of enemies. Levels are made of waves generated every 3 seconds, this component decides what enemies will be spawned on each wave, and under what behavior. Makes extensive use of the seeded pRNG, as well as the Enemy Factory. Also creates the planets.
  • Enter key handler (320 bytes): Used to control the game state from the title screen and game over status, into the “in game” status.
  • Game state machine control functions (628 bytes): Transitions into the different game states (title, game over and “in game”)

Coming up next, final postmortem and future of the game!

 

ArcherFire: Duet of Aces – js13k 2018 – Part 2

JS13k 2018 has gone by! this is the second of a series of posts detailing my journey, as well as the structure of the game I built. You can play it online here!

Links to the full series: part1part3postmortem

Day 4

First thing I did was fixing the build scripts since I really needed to know how I was doing vs the 13KB limit (last year I spent a lot of time by the end of the time-frame, removing things). I figured out the build problems by checking the script for Lost of Asterion; I had to replace a dependency (gulp-uglify) with the ES6 ready version (gulp-uglify-es) since I was using ES6 features in my code (cannot live without arrow functions now). The zipped archive was 5.36KB, and I had 46 hours to go.

I created a list of priorities in Trello, as I said there was a game there already, so what was left was polishing some rough edges and add fancy stuff. The last missing core thing was making the levels consistent (that is, they should be the same every time the player plays). Of course, the trick because of the size restrictions is not having the levels hand-designed but rather using a seedable (and small) pRNG, I ended up using an implementation of  Park/Miller LCG based on this.

function LCG(s) {
  return function() {
    s = Math.imul(16807, s) | 0 % 2147483647;
    return (s & 2147483647) / 2147483648;
  }
}

I seeded it with 13312, and it’s used only for the enemy wave generation.

Another annoying thing I was pending fixing was replacing the temporary setTimeout based timers with something that relied on the game update cycle instead so that the game wouldn’t go bananas when the animation was paused (say because the game’s tab became inactive) but the timers kept running. I added a simple function to the RAF loop to keep track of a list of timers on every frame update, reducing a timeout value by the update delta, and executing a callback when it reached zero.

Next up was showing the “current wave” in the UI, so that players could have a sense of progress besides the score so they could brag about being able to reach wave X. This was also used to increase the difficulty of the waves, so the further the player is the harder the enemies and the shorter their reaction time (so they shoot more bullets)

There were some weird issues where mobs were being “killed” out of nowhere, I thought this may be due to the way they were being sliced out of the lists during the update phase which might cause the wrong mob to be deleted. I changed it so that when a mob’s update function deemed it necessary for the mob to be killed, it is marked and then all the marked mobs are deleted, instead of doing it on the spot. It seemed to work.

Also added some cosmetic changes on the explosion SFX, changing the colors so that it looked a bit darker and different when fizzling, and a scaling effect so the ships would look like they were “landing” on the game (but it didn’t look very good)

Finally, continuing with the idea of adding a music track, I asked on the js13k slack and was lucky to have Ryan Malm offer to create a track for the game, as long as I could set up SoundBox on it.  So I did that and added one of the sample tracks.

Screen Shot 2018-09-18 at 10.34.22 PM
SoundBox in action

Day 5

The final day of development was long, but not really too crazy compared to last year.

I proceeded to add more variation to the different enemy formations, adding the following:

  • Enemies coming from below
  • Horizontal row of mines
  • Vertical row of mines

I also did the best I could to enhance the appearance of the turret “platforms” and the mines.

20180913_210908
Designing the appearance for the enemies

Added some planets to the background, they are a circle filled with a gradient, their generation is tied to the wave generation so they serve as milestone markers to see how far you’ve gone (so far I have only been able to reach the second, purple planet, in my highest score)

Did some playtesting and balanced the difficulty a bit, then, since the game bootup was a bit crappy, I added a “loading” screen to cover the process of converting the soundbox script into a WAV stream, in turn, I also added a simple title screen with the name of the game, some credits, and instructions. This required adding some “mode” handling to the game and a simple state machine.

Was getting close to midnight when I got the theme song by Ryan, it was awesome! because of time constraints, it was a bit short (about 15 seconds long) but it did a great job at enhancing the atmosphere of the game.

It should be noted that this 15 seconds track, including the whole “library” to play it, is 2.5KB of compressed source code. Compared that to 361 KB for the OGG export. It’s really wonderful.

I did some work on the player bullets, changing them from red balls to missiles, using a different sound effect for them, and throttling the fire rate so it was more controlled and predictable. Also, since I still had plenty of space, added sounds for the explosion when a ship was destroyed, and a beep for starting the game.

Continued with small tweaks, removing the “ships landing” scaling effect which didn’t really look too good, changing the keybindings for the “down” key for player 2 to be “5” instead of “2”.

The game was almost ready to ship, I did some basic CSS styling for the containing page (black background, centered canvas), but more importantly scaling the canvas to 100% height so that it looked good on most horizontal display cases.

I hesitated a lot, but in the end, decided to jump into allowing the player to restart the game without having to refresh the page when dying. Anyone who has participated in a jam knows how tricky it can be to reset the game state, especially if you didn’t design for that in advance. But I went ahead and did it, and I think being able to restart quickly  became an important part of the game (and makes it look much more polished)

As part of the final playtesting, I added “shield” to the ships so the player can take 3 hits before dying instead of exploding instantly, and increased the acceleration so it’s easier to dodge bullets. I also fixed an issue with the Numpad not working in Safari and Firefox

afdoa

Next up, a view of the complete structure of the game, and then some final thoughts!

ArcherFire: Duet of Aces – js13k 2018 – Part 1

JS13k 2018 has gone by! this is the first of a series of posts detailing my journey, as well as the structure of the game I built. You can play it online here!

Links to the full series: part2part3postmortem

Before Coding

I wasn’t really sure what to do, I actually was wondering if I was going to be able to participate at all, but the weeks before coding I toyed in my head with several different ideas… one of them would be a mobile entry based on my Energy Radar project (which is inspired by Pokemon Go), running completely offline but allowing players to interact and capture monsters as a team. I decided against it because of it being maybe too big in scale.

20180913_210812

Another one would have been an offline life simulator, someone living on the forest, fishing, something more of an experience than a game since there would be little stress, this would have been more heavy on the graphical side so I abandoned it (more so as the deadline was getting closer)

20180913_210757

Finally, had an idea of a non-linear “Space shooter”, keeping some of the Energy Radar ideas on offline interactivity, players could fly from planet to planet; once in a planet, they would input a code from another player on the same planet, which would allow them to advance on the plot.

20180913_210742

Knowing that I may very well wound up doing something completely different, but I had to start somewhere, I went with this idea.

Day 1

At first, I tried to use source from Lost in Asterion (my js13k from 2017), but lost a lot of time. I went instead with a fresh copy of js13k boilerplate. I modified the example and was able to have a static starfield in little time.

Since this was going to be a non linear shooter, and I thought having a “lerping” camera effect would be cool, I invested a lot of time trying to make the “camera” work (again, based on Lost in Asterion). It worked, almost, since I wasn’t really tweening it but rather handling it as an object on-screen with acceleration and position, so it was hard to make it “stick” to the player once it reached him.

I also added simple keyboard input to move the “ship” around, and with the camera following it, it was a rudimentary space scene.

Screen Shot 2018-09-03 at 11.05.36 AM.png

Day 2

After giving it some thought in my head, and reading my postmortem from 2017, I decided to go on a different route. I would instead focus on making a simple arcade game, and use the 13K to add as much eye and ear candy as possible.

I ditched all the work that I had done in the camera since it was now going to be a linear game (and it wasn’t really working very well)

With a more clear vision of what the game was to be about, I implemented a lot of things,

  • Collisions between player and enemies.
  • Bullets killing enemies, increasing the player score.
  • Removing mobs when out of the screen (stars, enemies, bullets).
  • “Serial rendering” of mobs allowing potential complex representations.
  • Render score with LCD like display.

Since I needed something to test my “rendering” system, I decided to design the player ship, I based myself on the ship from the original ArcherFire made in QBasic in 2002.

Screen Shot 2018-09-13 at 9.30.34 PM
Original QBasic Archerfire, 2002

Doing vectorial art, however, is something I don’t have any experience with. I can do _some_ pixel art, but this is a different beast. Plus I had to manually input the sequence of commands to draw each shape. I did the best I could with the little time I had.

20180913_210847

In the end, this design is represented as follows in the code:

‘#eeeeee’,’p’,-2,2,-4,4,-6,0,-4,-1,-2,-4,0,-4,0,2,’f’,’o’,’#0000ff’,’p’,-3,3,-4,4,-6,4,-8,0,-6,-3,-4,-4,-5,-1,’f’,’o’,’#dddddd’,’v’,0,-6,2.2,2.2,’f’,’o’,’#888888′,’vh’,0,1,2.5,2,Math.PI,2*Math.PI,’f’,’o’,’#ff3333′,’p’,0,1,-2.5,1,-2.5,2,-1.5,3,0,3,’f’,’o’,’#000000′,’v’,0,-6,2,1.5,’f’,’o’,’#ff0000′,’vh’,0,-6,2,1.5,0.5,Math.PI-0.5,’f’,

(Note that this is meant to be only half of the ship, the other half is drawn mirrored)

Since I was already drawing a scaled version of it, I figured I’d try to include a practical 3d looking effect when turning the ship, it did look pretty good.

Tried to build the game by the end of the day to see how I was doing with the size but found out there was a problem with uglify which didn’t let me thru.

js13k2

Day 3

Since I was no longer going for the “offline social” component, I wondered how to incorporate the theme. One obvious option was to provide hotseat multiplayer, and I ended up adding that.

Made enemies being able to shoot at the nearest player, and added the infrastructure to be able to create enemies given a set of parameters. Also added enemies cruising from left to right of the screen, and platforms with 4 mounted turrets.

Added explosion effects, since I didn’t have any tweening library and the rendering was being done manually, had to implement the explosion animation by drawing an expanding circle which would them be “hollowed” when dissipating. Drawing a “hollow” circle in canvas context2d was not as easy as I thought! I ended up using a weird trick to compose the path to fill: Draw the outer circle clockwise and the inner one counter-clockwise. I still don’t understand how that worked.

For SFX, I included again the good old trusty jsfxr. It keeps being useful even after years of not being updated. I added sounds for the explosions and the firing of bullets.

I saw that I still had plenty of space left so I began wondering how to include music. I tried minimusic, set it up and made it work inside the game with a test melody, but was unable to come up with anything half decent (guess why, I’m not a musician!). I left it there, asking a friend to see if he could maybe device something out of it.

Also designed one of the enemy ships (again based on ArcherFire 2002). I tried to implement some way to “rotate” its rendering but after spending some time on it gave up.

Finally, I added one first version of the “wave generator”, that is the thing that puts up new enemies on the stage as the player goes thru. After putting that I found myself with a rudimentary but complete game that someone might even enjoy!

day3.5.gif

Journey onward to Day 4 and 5, and then a detailed rundown of the game’s structure and some conclusions and thoughts!

Postmortem: Lost in Asterion – js13k 2017

Lost in Asterion is a game I made for the js13k 2017 contest, you can check it out here!

I decided to write one final piece of text about my first participation on the contest. I already described my journey in detail through the 19 days of development here, here and here; but I wanted to record some things earned and some lessons learned which may come in handy for other people or myself in the future

lostInAsterion2

My Story

Whenever I participate into a game jam or contest, I try to ask myself what is my motivation:

  • Learn a new language or tool
  • Create something cool
  • Win the contest prize

This was the first time I participated on the contest so I started a bit clueless, knowing not what to focus on.

Later, I set my goal on trying to create a FULL game, something that you would not believe was contained within 13 kilobytes. I was inspired by Aquaria… could I create a similar experience within the boundaries of the contest? besides the size limit, there was also the time constraint: One month of work, with very limited availability due to some other more important personal projects (it was around the release date of a human being I created). But I jumped in.

In the end, I think I succeeded on that (which is great!) but I cannot deny the results from the judges, which put the game pretty down the list, were pretty disappointing for me at first.

Screen Shot 2017-09-30 at 10.52.14 PM

Later, after giving it some thought, I understood it made sense… there were many entries this year, some of them really good, and when I created my own I didn’t even consider the judging process that was going to take place: I didn’t really aim to make a good impression on the limited time the judges have to check the entries.

Giovanny Beltrán shared some tips, and my opinion in general terms is you need something that grabs the attention of the judges in the first 5 seconds: animations, music, an inviting environment or an intriguing setting.

What went right

A huge world

I managed to create a BIG world, thanks to a couple of things: The cavern level generator which used Voronoi diagramas and Celular Automata, and the compact map format for the 2 areas with fixed maps.

I’m glad one of the jurors got to experience EXACTLY what I was going after! I wanted the players to actually try to make a map of the world, in paper, somewhere. This is why I didn’t include an automap. I followed a similar design on Stygian Abyss, with less exciting results.

A full run through the game may take over 2 hours (may be even more) if you are playing for the first time.

Breaking the pixel art mold

I created another game without using pixel art (a personal goal I’m trying to go after), instead all graphics are vector based. Everything is represented using geometric shapes: the background, the player, the enemies, even the bubble particles.

wp-image-1750981584

Atmosphere and Feel

I managed to create a believable atmosphere using the symbolic vectorial art with a color palette which worked pretty well, as well as the limited sound effects and the textual messages that made up the plot.

Greatest Challenge: The 13k barrier

It hit me REALLY hard and I had to spent a lot of time doing both technical tricks as well as design choices of what to keep and what to take out. I didn’t really expect to have to battle this hard with it since I wasn’t using any image files just to make sure I could have as much space as possible to build the world and the story, but it happened.

The main causes for this were the inclusion of the Voronoi diagrams library (used for map generation and background graphics) and jsfxr (Used for the 2 sound effects in the game).

The first one was completely necessary (no way to remove it) and very hard to reduce size other than trying to optimize the module structure and playing around with the uglifier. I put a lot of work on it with minimal effects over the package size.

As for jsfxr, there was little that could be done other than deciding whether it was worth keeping it or not. Because of the goal I set myself, I decided it had to remain, and I was gonna try to make the most out of it. (In the end I’m not sure it was worth it, since I could only keep two sounds)

Since I couldn’t do much to reduce the size of these two dependencies, I had to start optimizing my code (which was fineΩ) and cutting content (which was painful!)

What went wrong

Removed critical content

I cut some critical training / instructions as well as some interesting plot. People had trouble understanding what the “Drill” was for (and of course instinctively tried to use it to cut the rocks), and the plot was a bit too light.

Looking back at it, I think a better choice would have been removing some type of enemies, or even one of the fixed map areas.

Use the arrows, Z to drill
That’s about all the instructions given to the player

Ran out of time

This is because I didn’t have a clear idea on what to do since the beginning.

However, I’m not sure I’d say that was something bad or it could have been avoided… I think sometimes it’s ok to start with a general idea (2D cavern exploration game, vector art) and then let it evolve.

In any case, I spent a lot of time working on something that didn’t end up in the final product: The “collisions” with slopes. That was educational but would have been better invested on playtesting.

No Playtesting

Due to how the time frame ended, there was no playtesting at all. I was lucky that the game was fairly stable and I only had to submit a single patch, however I missed some details which would have been very easy to correct and could have left a better impression:

  • Scaling to use the whole viewport / going full screen
  • Removing enemies from the starting area so players could read the instructions peacefully and building a better ambient

The Future

This is not the end of the story for Lost in Asterion… I plan to make it evolve into a more complete game, keeping the core design but adding better sound effects, music, a complete plot (based on the original one which was chopped up), cutscenes, boss battles and an infinite exploration mode. More info soon!

Also, some things I want to do next year:

  • An arcade game bringing full action from first second of gameplay
  • Complete music track

Lost – js13k 2017 (Update #2)

There’s about one week left for js13k 2017. As usual the jam has sequestered my mind, draining my processing power, thinking about it all day long how to push it further.

Here’s the story from last update, reconstructed from twitter + the git log. It’s been a fun journey so far.

August 19 – Added background stones using Voronoi. Keeping up with the goal of not using pixel art, got the idea from a shower curtain. May need some additional details to make them look like rocks without using textures.

Screen Shot 2017-09-02 at 11.25.29 AM
Walking around alien caverns

August 22 – Infinitely spawning maps, generated on the fly. This was tricky but needed in order to not be completely irresponsible with memory. One of my goals was to create a huge spawning world within the 13k limit, that of course was going to involve procedural generation (but I intend to keep the world fixed by seeding the pRNG properly). For this I’m dividing the map in 4 quadrants, and based on where the player is I clean the opposite sector and generate the closer ones.

August 23 – Implemented a CA module for Voronoi diagrams and used it on terrain and background to smooth them out. I used the output of the Voronoi library and post processed it adding the neighbor sectors. The CA module I made allow simple rules as in “For a cell of given type X, if there are (more/less) than N cells of type Y around, change its type to Z, P% of times”.

Also added a jetpack for easier exploration. I still didn’t have a clue on the theme of the game, was thinking it was may be going to be a space explorer ala Samus Aran.

August 27 – Added complete zoom support for the camera object (still thinking if it’ll be used in game, for now just using it for debugging purposes). All positions and dimensions are scaled based on the zoom factor, and then repositioned based on the camera position (which right now keeps synced with player, but may change that in the future)

August 29 – Worked hard trying to add support for smoothly walking on the slopes. I almost got it but there were some edge cases where the player would become stuck, or go through the slope and into the rock.

The way it worked was by tracing a line between the player’s hitbox center and an imaginary point below representing the gravity drag. Then I checked for the intersection of the polygon sides vs it to see what side was colliding with the player. Previously, I calculated the slope of all sides of the polygons. Then when the player was walking against the polygon, I changed his y position too, based on the slope.

One of the issues was faced was that when walking between stones the player may sometimes hit the wrong polygon side (one inside the rocks) .

August 30 – Figured out the issues with slopes were going to eat up all my time and I wouldn’t ship without them working perfectly. So decided to change theme to underwater caverns.

Tweaked the physics to allow the player to “float” (weaker gravity) as well as removing jumping since you can thrust upwards anytime now.  Initially made a “radial” movement schema where you could rotate and then thrust forward, but then decided to simplify it so you just move in the direction you press the key to. Also changed collisions so you’ll be stopped completely when colliding with anything (removed slope calculations), but they were still a bit buggy at this point.

Screen Shot 2017-09-02 at 11.31.59 AM
Floating in the caverns

August 31 – Up until now, the player had just been a colored squared so I decided to jump into changing it to what it was going to be in the final game. I considered several options from the beginning but since I was not going to use pixel art, adding humanoid characters with animation would have been quite painful, taking a lot of time and I wasn’t confident the end result would look good since I lack the skills. So, give that I had switched the theme to underwater, I decided to use a rigid body (a vehicle).

Did some research on deep exploration vehicles (Bathyscaphes) and in the end settled for a fantasy bathysphere. Also went ahead and added some “bubble” particles, generated from the sphere’s fans depending on the direction the vehicle was moving. Then as a last touch added a simple emulated head light, using a semitransparent white triangle.

September 1 – Started by doing some needed upgrades into the boilerplate project, mainly replacing using the uglify module with uglify-es in order to be able to use ES6 features in the source code.

Then I finally got into fixing the collisions, so right now I’m checking the intersection between the four sides of the player’s “future” hitbox vs the nearest stones, and calling it a collision in case there’s any intersection. I’m also keeping the case of projecting a line from the hitbox center to the future center and checking for intersections, to prevent cases of high y acceleration by gravity. It works pretty well now.

Did some cleanup using jshint and upgraded some parts to ES6 syntax, just for easier maintenance in the future and for the code to look better too 🙂

I got my hands into a more serious high level world layout generation, I designed the fixed world map which is composed by different sections, each section has a given type (which defines the parameters for the sector generator to build the map) as well as expected connections with neighbor sectors.

After the Voronoi diagram has been generated, the generator marks some of the sectors as special types: Unbreakable stones at the borders of the sector, and fixed open spaces representing the connections with its neighbors, these represent the constraints of the sector in order for it to fit the overall map, the CA rules don’t affect them.

I defined the parameters for some of the sector types: The Gate, Caverns, Open Areas, Farmlands and the Darkness Abyss (In which you can only see your headlight)

darkness
The Darkness Abyss

Then I added The Gate and the orbs needed to open it. In order to win the game you have to explore the depths, find the fours orbs and come back to open it, without getting lost in the process.

I also resized the viewport to 800×600 (was 400×400), and modified the physics a bit by generating a bit of “lift” with the vertical movement (akin to the sphere having some kind of “fins”, I guess)

lost
The Gate

Coming up

In order of relevance seeking to make a fun game

  • Enemies
  • Powerups
  • Parallax effect for background
  • Vegetation in the foreground
  • Enhance sector connection
  • Temple generator
  • City Ruins generator
  • Volcanic Ridge generator

 

Lost in the Underworld – Day 1, js13kgames

Alright, I decided to participate for the first time on js13kgames!

The plan is to create a cavern exploration game with a huge world and multiple paths on it, where the player has to find treasures and powerups. I also hope this series of blog posts is more informative and useful than usual.

The idea is to do terrain generation on the fly using Voronoi diagrams and Cellular Automata, also I won’t use pixel art but instead vector graphics (at least for the terrain).

After checking some of the options in the tools page, I decided to use Florent Cailhol’s JS13k Boilerplate. It is probably the simpler starter project there… it has some game loop logic, seedable RNG and gulp scripts for packing and minifying. It also comes with a sample simple implementation for physics.

I started adding keyboard support so you could jump and move around.

const pressed = {};

module.exports = {
	init: function(){
		window.onkeydown = function(e) {pressed[e.keyCode] = true};
		window.onkeyup = function(e) {pressed[e.keyCode] = false};
	},
	isDown: function(keyCode){
		return pressed[keyCode];
	}
}

Also did some foundations of the “physics” system based on the original, since the terrain will be irregular, what I’m doing for the collisions is checking if the future position of the player will be located inside one of the polygons. I used the “inside” function from James Halliday Point in Polygon repo, an implementation of the PNPOLY algorithm. There’s still a lot of potential optimizations to be done.

stones.forEach(function(s){
  if (e.dx != 0){
    if (e.dx > 0){
      if (inside([tx+e.w,ty+e.h/2], s.vs)){
        hCollision = true;
      }
    } else if (e.dx > 0){
      if (inside([tx,ty+e.h/2], s.vs)){
        hCollision = true;
      }
    }
  }
  if (inside([tx+e.w/2,ty+e.h], s.vs)){
    vCollision = true;
  }
}

Had to add a special case for high acceleration caused by gravity, which would make the player go though thing barriers because the updated position would just go through it. For this one I’m checking if the line traced from the current position to the future position intersects the polygon, based on a stack overflow response by Dan Fox.

if (e.dy > 100){
  //Prevent falling through thin borders at high acc
  if (polygonIntersects({
    a: {x: e.x+e.w/2, y: e.y+e.h},
    b: {x: tx+e.w/2, y: ty+e.h}},
    s.vs
  )){
   vCollision = true;
  }
}

Added simple camera support, centered on the player, for this I have a camera object whose position I affect along with the player’s. Then I substract that position from the world position of all objects when it’s time to draw them, to translate them to viewport coordinates.

js13k-2

Then I added super simple Voronoi map gen using Raymond Hill’s JavaScript Voronoi, it adds quite a bit of weight to the package but works pretty nice. I may have to slim it down for the final dist.

js13k-3.1

For now, I’m just randomly picking Voronoi cells, next up will use CA for the caverns to look less random.

var voronoi = new Voronoi();
var bbox = {xl: -300, xr: 1450, yt: 0, yb: 3550};
var sites = [];
for (var i = 0; i < 450; i++){
  sites.push({
    x: rand.range(bbox.xl, bbox.xr),
    y: rand.range(bbox.yt, bbox.yb)
  })
}
var diagram = voronoi.compute(sites, bbox);
const stones = [];
diagram.cells.forEach(function(cell){
  if (rand.bool())
    return;
  let vs = [];
  cell.halfedges.forEach(function (halfedge){
    vs.push([halfedge.getStartpoint().x, halfedge.getStartpoint().y]);
  });
  stones.push({vs: vs});
});

Navigating around the map made evident that my physics system still needs a lot of work. I will post it here once it’s more polished so it can be useful for someone.

I found out the core of the RNG module of the boilerplate isn’t working, so made it use Math.random instead for now. It also seems the current gulp tasks don’t work well with some ES6 syntax, I’ll take care of that later.

Current package size is: 7.13 KB