Light Cycles

For my first Ironhack project I built a snake-type browser game (hosted on GitHub Pages) using JavaScript, CSS and HTML5, including the canvas element. Working with this "vanilla" tech stack helped me to better understand various fundamentals like event listeners, classes (from ES6 aka ECMAScript 2015), callbacks, clean code and more. I'm glad to have worked on this foundation before moving on to using a library like React.
Inspired by the 1982 film Tron, the purpose of the game is to "derez" (destroy) the enemy "Light Cycle." Light Cycles move in straight lines and leave behind solid "jetwalls" in their wake. Players, represented by Light Cycles, race around a two-dimensional "Game Grid," using keys (up, down, left, right) to change direction. Players can also use fusion power to speed up their Light Cycle as well as shoot bullets.
The game is over when a player crashes into either the other player's or their own jetwall or bullet explosion.
Given that this was a learning project, I'm proud that the game is actually fun. I realized it wouldn't be interesting if players couldn't reach one another, so I added elements like acceleration and bullets (which can blow up walls) to improve the gameplay. Below find some links and highlights.
Links
- Light Cycles (play using a computer, not mobile / tablet)
- GitHub
- Trello
- Presentation
MVC design pattern
I followed a model-view-controller design pattern, with most of the JavaScript divided across three files:
- Lightcycle.js – the model where the Lightcycle class is defined, with a constructor that initializes the starting position, speed and other player configurations, and methods that allow the cycle to move forward, turn, speed up, burn fuel, stop, etc. Bullets are handled by a separate class since once a bullet is shot, it's an independent entity in the game. Finally, there's a class for the Fuel which appears randomly on the board and regenerates when picked up or shot. State is stored in arrays (e.g. row and column positions).
- Main.js – the view where the canvas and audio elements are set up, with a start button and event listener and game over messages. Clicking start will instantiate a new (singleton) instance of the Game class, defined in the controller.
- Game.js – a stateless controller where the Game class is defined, which in turns creates two Lightcycle instances and a Fuel instance. An update loop driven by requestAnimationFrame() cycles through methods that draw the jetwalls, check for crashes, generate fuel, check for fuel pickup, draw bullet paths, etc. Finally, event listeners set up here listen for keydown and keyup events.
I left the canvas paint instructions in the controller (rather than defining them in the view) since the logic is so simple, i.e. painting a jetwall requires one line of code to fill a rectangle:
Creating the logic for the various types of game collisions was among the most involved parts of the project. For instance, players can crash into their own jetwall or that of the other player:
Even with a simple game, with multiple moving objects the logic of potential intersections can quickly become complex, which gives me a better appreciation for how amazing even the Nintendo games I played as a kid were.