Making Code Happen

Super Aspen – Remake Jam

Super Aspen is a remake of my first game, a TI-82 skiing game that I made in high school. I remade it for #RemakeJam using HTML5/Javascript. This is my first game playable in browser, I really like being able to share without requiring a separate download. I wrote everything from scratch including a small game engine framework, art and music. Continue reading for more info and postmortem.

Play Super Aspen it in browser on itch.io. 

View post on imgur.com

Download

Postmortem

I’ve been hearing good things about HTML5 game engines like Phaser and Impact, but I’ve haven’t ever used HTML5 or Javascript before. So I wanted to start from scratch to learn the basics before jumping into a more powerful engine . I found a nice tutorial on how to make a simple HTML5 canvas game.  I liked this example because it contained only bare essentials and was easy to build on.

The theme of #RemakeJam was “Remake your first game with your new skills and aesthetics.” My first game worth mentioning is a skiing game I made for TI-82 about 20 years ago. TI-82 basic is usually really slow but this game was actually pretty fast because it used the automatic scrolling feature to advance the trees along. You can still download the original TI-82 game on ticalc.org! I don’t know why I named the original game Aspen Gold, I’ve never been to Aspen but I heard that was a place people ski.

Core Gameplay Mechanics

I started out by building a small game engine. Mostly everything inherits from the GameObject class that handles updating, rendering and collision detection. I also created a simple math library and some utility code. I used Brackets to edit my code, I loved the live preview option but wanted better debugging support and I had some difficulty with how tabs were handled. Here’s the simple GameObject class I wrote…

class GameObject {
 constructor(pos, image, size) {
     this.pos = pos? pos.copy() : new Vec2(0, 0);
     this.image = new Image();
     this.image.src = image;
     this.image.ready = false;
     this.image.onload = function () { this.ready = true; };
     this.size = size? size : new Vec2(32, 32);
     this.layer = 0;
     this.justAdded = true;
 }
 update(delta) { this.pos = this.pos.add(this.speed.multiply(delta)); }
 drawImage(image, pos, size) {ctx.drawImage(image, pos.x - size.x/2, pos.y - size.y/2, size.x, size.y); }
 render() { if (this.image.ready) this.drawImage(this.image, this.pos, this.size); }
 destroy() { gameObjectList.splice(gameObjectList.indexOf(this), 1); delete this; }
 isTouching(o) {
   if (o instanceof Vec2) return boxOverlap(this.pos, this.size, o, new Vec2(0,0));
   else return boxOverlap(this.pos, this.size, o.pos, o.size);
 }
}
Early screenshot

This is a simple game with one core mechanic: avoid trees, so I added that first. The trees are actually moving while the player is stationary. They spawn randomly just below the bottom and move upwards before getting removed after moving off the top. Their size is randomized to mix things up. The difficulty increases over time by modifying response to some random values. Simple box collision detection slows the player down after hitting a tree. The track generation changes between two modes, one with a mostly open lane you move down, and one where trees are just randomly placed.

I wanted the game to be somewhat forgiving if the player crashed because it is so random and unpredictable. So I added a snowball to represent your “health” by moving it close to the player when a tree is struck, it also increases in size over time scaled by difficulty. I had some trouble animating the snowball rolling and instead just varied the size by a small amount randomly.

Polish Features

I wanted to keep this game as simple as possible. To polish the game I just added a few more tree types and a rock to. I also created custom art for the player, all 32×32 pixel sprites. To make the “dead” version of the player I just flipped the sprite upside down and added some snow on top. The trails behind the player and snowball are just additional sprites rendered before anything else. I turned off imageSmoothingEnabled so the sprites don’t get blurry when scaled, though Firefox doesn’t seem to support that. There’s a total of only 10 sprites in the game. The background just is a simple gradient to give a little bit of texture.

I made the music with the iKaossilator app for iPhone. It’s a fun app to play around with and get a couple minutes of quick original music. I made the music slow down when the player gets hit to give more feedback. There are only two simple sound effects, created using BFXR.

A high score tracking was added to improve replayability. There is a single high score stored and a red line will indicate when the high score is reached. The high score is saved in a cookie so it will persist between sessions. I also added additional difficulty that gradually increases the maximum speed you can move. 

This was a really fun experiment, I definitely recommend making a small game in pure javascript. Being playable in browser lowers the bar for entry making it a great format for game jams. I ran onto some limitations on what I could do without a better engine. Also, the performance can be a bit jittery sometimes and I’m not sure that’s fixable. I found javascript a bit non-intuitive to work with and had some problems with how objects were being referenced instead of copied. Next time maybe I’ll take a look at some of the other HTML5 engines available.

What Went Right

  • Javascript was fast to prototype with
  • Playable in browser makes it easier to show people
  • Having the jam be a week long made it less stressful then 48 hour jams

What Went Wrong

  • Javascript has some confusing features
  • Need to find a better way to edit and debug javascript
  • Need a better engine and math library

Update

I have made a few improvements to the game after the original posting.

  • Speed Boost Power Ups (gives more speed, trees don’t slow you down)
  • Sprite Rotation – Allows player and snowball to rotate as they change direction.
  • More forgiving level generation

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.