Project type: Game

Date: 11-11-2024

Status: Finished

Software used: p5.js, Visual Studio Code, Tiled

Language used: Typescript, SQL

Role: Developer

Team size: 2 developers

About the project

For this project, I worked with another developer. The assignment was to create a platformer using p5.js.

The goal of the game is to reach the end of the level as quickly as possible. On your way to the finish line, you must first find a key to complete the level. The times are saved in a database, which makes it a fun and competitive speedrun game.

In this project I worked on the parts below.

Unity Structure

Since I’m familiar with Unity and found this to be an easy way to add structure, I recreated the Unity structure in TypeScript for p5.js.

To do this, I created elements such as GameObjects, a Vector2, and a SceneManager. The SceneManager is responsible for switching between scenes. The scenes themselves are responsible for all the GameObjects they contain and their lifecycle. To make things easier, I’ve also recreated search functions within a scene, such as FindObjectByType. Additionally, GameObjects can also be marked as DontDestroyOnLoad.

Physics System

For the physics system, I created a PhysicsManager and a Force class. The PhysicsManager is responsible for applying all forces to GameObjects, including gravity and custom forces.

The system includes familiar features from Unity, such as isKinematic, but also contains a useful extension of its own: the ForceGraph. This allows you to adjust the progression of a force using a graph. For example, a force can start out weak, be strong in the middle, and end weak again. Finally, this physics system works seamlessly with the collision system to handle collisions.

Collision System

I’ve created a collision system that incorporates features from Unity, such as a BoxCollider and Raycasts. With this system, you can check whether colliders overlap. This is done using an intersection calculation. GameObjects can also have multiple colliders. Additionally, there is an isTrigger setting. This ensures that forces do not stop upon a collision, but you can still detect the collision. This is useful, for example, for a jump pad, so you can simply walk through it if you don’t want to jump.

Tiled Map Parser

The Tiled Map Parser is designed to make it very easy to create and use maps. In Tiled, you can create grid-based worlds and set properties for sprites. For example, I can specify that a particular sprite is a gravity cloud and immediately assign it a collider.

Tiled then generates a JSON file that I load. Based on all the coordinates and properties in this file, I build the level in p5.js. I have clearly divided the responsibilities for this. The MapManager handles loading all JSON files. After that, the MapParser is responsible for converting this JSON into GameObjects and correctly setting the tile properties. Finally, the TilesManager extracts the rotation and properties and retrieves the correct tile sprite from the sprite map.

Highscore

At the end of a level, a player can choose to save their time by entering a name. The time is then saved in the database, after which everyone can see the top 10 times for each level. By adding this feature, the game truly becomes a competitive speedrun game, which works really well. In addition, the system also displays other statistics, such as the average time players take to complete the level and how many times a level has been played in total.

Heatmap

When a player fails, the database records the exact position in the level where this happened. The heatmap is a tool for seeing where players fail most often. This is indicated in the tool by red circles: the closer the circles are to each other, the more red the area becomes. As a developer, this is very useful information. This allows me to easily analyze where players are struggling and identify the truly challenging sections of a level.

For the players themselves, this information is displayed differently. As soon as they fail, a brief message appears above the player indicating exactly how many others have failed in that same area.