Skip to content

mihaidanaila11/MatrixProject

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RETRO DRIVER

Backstory

This project is an Arduino-based LED matrix game developed using PlatformIO and C++. I created this project to explore the fascinating world of hardware programming and interactive LED displays. The game was inspired by classic arcade games and the desire to bring nostalgic gaming experiences to a compact, handmade device.

Game Description

RETRO DRIVER is an interactive game displayed on an LED matrix, controlled through Arduino. The game features dynamic graphics rendered on the LED display, providing a retro gaming experience. Players navigate through the game using physical controls, with real-time visual feedback displayed on the matrix.

The game leverages the power of C++ for efficient memory management and fast execution, ensuring smooth gameplay despite the hardware limitations of microcontroller platforms.

Game Features

Procedural Map generation

The map generation process divides the map into chunks. Each chunk generates a start, stop, and control point to shape the road. The start point (initially 0) inherits the end position of the previous curve. The stop point is set to the maximum possible height for that chunk. A control point is then placed randomly between them with a variable X-coordinate, which dictates how sharp or tight the curve will be.

Bezier Curves 1

The 3 point curve used for the map generation is named Quadratic Bezier Curve. A set of discrete "control points" defines a smooth, continuous curve by means of a formula. The formula for a point in a Quadratic Bezier Curve at a given moment of time is the following:

$B(t) = (1-t)^2P_0 + 2(1-t)tP_1 + t^2P_2$ Where $t \in [0,1].$

2 Quadratic Bezier Curvez. The round points represent the start/end points. The cross point represents the controll point.

Bezier Curves Implementation in map generation

The map generation method is implemented in the GameModel.h header.

The method takes chunks as argument, representing the number of chunks the map will be divided in.

void  generateRoad(const  int  &chunks)

Take note that the algorithm is working only with the left side of the road. The right side will be symmetric.

For every chunk we define the 3 points that will give us the road curve.

// startPoint will be last curve ending point.
// (mapWidth / 2 - roadwidth / 2 , 0) if its the first curve.
const  Point  startPoint(currentRoadX,  currentRoadY); 

The computing of the end point position depends on the turn direction of the curve (determined random)

const  int  turnDirection  =  random(0,  2); // 0 = left, 1 = right
int  finalPointX;
if (turnDirection  ==  0)
{
	// Left Turn
	...
}
else
{
	// Right Turn
	...
}

In order to have a left turn, the X coordinate has to be between 0 (the left edge of the map) and the last curve X end point (i.e. to the left of the last X end point). This coordinate will be capped, for safety, at the map width.

if (turnDirection  ==  0)
{
	// Left Turn
	const  int  minX  =  0;
	finalPointX  =  min(random(minX,  currentRoadX  +  1),  width  -  1);
	finalPoint  =  Point(finalPointX,  currentChunkEndY);
}

The same logic applies to the right turn. In order to fit the road correctly on the map, the max X coordinate for the end point can not be greater than mapWidth - (last curve's X coordinate + roadWidth).

// Right Turn
	const  int  maxX  =  width  - (currentRoadX  +  roadWidth);
	finalPointX  =  min(random(currentRoadX, maxX),  width  -  1);
	finalPoint  =  Point(finalPointX,  currentChunkEndY);

Finnaly the control point.

const  Point  controlPoint(
// X can be anywhere (random) between the road walls, being capped at the map width.
min(random(currentRoadX,  currentRoadX  +  roadWidth  +  1),  width  -  1),
// Y can be anywhere in within the chunk height, being capped at the map height.
min(random(currentRoadY, currentChunkEndY),  height  -  1));

The last step is to use the mathematic formula of the Quadratic Bezier Curve to get the points that will represent the road walls. The algorithm iterates through time moments starting from 0 and ending at 1, with a step of 0.05. Pluging in the t monent in the Quadratic Bezier Curve Formula will result in the point on the bezier curve at that moment. We have to cast that point's coordinates to integers, because the project uses a LED matrix as display.

const  float  precision  =  0.05f;
for (float  t  =  0.0f;  t  <=  1.0f;  t  +=  precision)
{
	Point  p  =  quadraticBezier(t,  startPoint,  controlPoint,  finalPoint);
	// The left side of the road.
	map[(int)(p.y  +  0.5f) *  width  + (int)(p.x  +  0.5f)] =  MapTile::createWall();
	// The right side of the road, symmetric.
	map[(int)(p.y  +  0.5f) *  width  + (int)(p.x  +  0.5f) +  roadWidth  -  1] =  MapTile::createWall();
}

How to Play

Setup

  1. Clone this repository

  2. Install PlatformIO IDE or extension for VS Code

  3. Open the project in PlatformIO

  4. Connect your Arduino board with the LED matrix

  5. Build and upload the code to your Arduino board

Controls

  • Tilt the breadboard to swerve.

  • Use the joystick to navigate the menus

Used Components

  • Arduino board (compatible with PlatformIO configuration)

  • LED Matrix display

  • 1x Joystick

  • 1x IMU Sensor

  • 1x 8x8 LED Matrix

  • 1x Buzzer

  • 1x Potentiometer

Video Demo

[Main Demo] (https://youtube.com/shorts/YNjJnX5iOYQ)

[Gameplay Demo] (https://youtube.com/shorts/36kC38s7uOg)

Pictures

Footnotes

  1. https://en.wikipedia.org/wiki/B%C3%A9zier_curve

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages