Final Midterm Project: Street Crash: A Journey into the World of Retro Arcade Racing Games

Concept and Artistic Vision

I’ve always been captivated by the world of arcade games, especially those that revolve around cars and racing. My love for these games and my fascination with car races reached a peak this year when I watched the exhilarating “Gran Turismo” movie. When it came time to choose a topic for my midterm project, my passion for cars led me to one clear path: creating a car-related game.

Drawing from my experience in an “Introduction to Computer Science” course during my freshman year, where I had to create a game using Python’s Processing library, I decided to explore the world of programming languages more deeply. However, I quickly realized that working with JavaScript, especially in the context of p5.js, was a different ballgame altogether. My quest for inspiration led me to various online car racing codes, but none of them truly excited me. This realization prompted me to embark on a journey to create something truly unique and personal, drawing on my own ideas and designs. Below is an image of my old car game project using Python:

Coding Translation, Logic, and Planning

As I delved into writing the code for my car game, I drew on the knowledge I gained in my class. I leveraged concepts such as shapes, loops, functions, arrays, generative text, loading images, and audio, and even delved into computer vision using the webcam. The experience was a blend of creativity and coding, and I began by sketching my final draft to visualize each aspect of the game. Here’s a glimpse of my sketch:

To truly make my game unique, I decided to create my own designs for every element. I used a familiar tool, “Scratch,” which I had used during my high school years, to sketch my own cars, roads, titles, and more. Here are some of my sketches and how they look in the game:

With all the designs in place, I embedded them into the code and used arrays to store them efficiently. One feature I’m incredibly proud of is the ability to take a picture of the player and place it in the top left corner of the game. This concept was inspired by my experience with arcade games that would capture a photo of the player’s face and display it in the game, making it clear who was in control. This added an engaging and visually fascinating element to the game.

Gameplay and Features

The game starts with a set of basic instructions on how to play. Players use the arrow keys to control their car. The objective is to avoid collisions, as any contact with another object or car leads to a game over. Additionally, players must manage their fuel levels, as running out of fuel also results in a game over.

There are three exciting levels to the game, each offering a unique experience:

  1. Easy Mode: This is the regular mode where the game is a continuous loop, and it doesn’t end until the player loses.
  2. Hard Mode: In this mode, I’ve introduced a unique twist. The car moves backward, and the gameplay occurs in the dark, adding an extra layer of challenge and excitement.
  3. Race Mode: This is a newly added feature where players have a target to reach. It’s not an infinite or continuous loop; instead, the goal is to reach a score of 100 to win the game. It’s an engaging mode that introduces a winning target to the gameplay.

Here is my Final Project Embedded Sketch

Edit Link

Parts to be Proud Of and Overcoming Challenges

One element of my code that I’m particularly proud of is the intricate logic for bot generation, movement, and collision detection. The player’s car movement and its interactions with the street and gasoline collection also added a layer of excitement to the project. Here’s a snippet of the code that demonstrates this achievement:

//Cars
function bots() {
  // Set the initial position of the bot randomly within the canvas.
  this.pos = createVector(random(0, width), random(-size * 10, -size * 100));
  // Set the size of the bot (width and height).
  this.r = createVector(size * 5, size * 8.5);
  // Set the initial sprite for animation.
  this.sprite = 0;
  // Set a timer for sprite animation.
  this.time = 0;
  // Set a random color for the car.
  this.c = createVector(
    floor(random(0, 2) * 175),
    floor(random(0, 2) * 175),
    floor(random(0, 2) * 175)
  );

...

    // Check for collision with the player.
    if (
      p.pos.x - p.r.x / 2 < this.pos.x + this.r.x / 2 &&
      p.pos.x + p.r.x / 2 > this.pos.x - this.r.x / 2 &&
      p.pos.y - p.r.y / 2 < this.pos.y + this.r.y / 2 &&
      p.pos.y + p.r.y / 2 > this.pos.y - this.r.y / 2
    ) {
      // Play a sound when a collision occurs and set the screen to 2.

      songs[1].play();
      screen = 2;
    }
  };
}

...

// Gasoline object constructor function.
function Gas() {
  // Set the initial position of the gasoline randomly within the canvas.
  this.pos = createVector(random(0, width), random(-100, -2000));
  // Set the size of the gasoline (width and height).
  this.r = createVector(30, 40);

  // Render function for drawing the gasoline on the canvas.
  this.render = function () {
    push();
    translate(this.pos.x, this.pos.y);
    image(botsIMG[2], -this.r.x / 2, -this.r.y / 2, this.r.x, this.r.y);
    pop();
  };

  // Update function for updating the gasoline's position and behavior.
  this.update = function () {
    //Mode = 1
    if (mode == 1) {
      //Move
      this.pos.y -= vel / 100;
      if (this.pos.y + this.r.y / 2 < 0) {
        this.pos = createVector(
          random(0, width),
          random(width + 100, width + 2000)
        );
      }
    } else {
      //Mode = 0
      //Move
      this.pos.y += vel / 100;
    // Reset the gasoline's position if it goes off the screen vertically.
      if (this.pos.y - this.r.y / 2 > width) {
        this.pos = createVector(random(0, width), random(-100, -2000));
      }
    }

    // Check for collision with the player.
    if (
      p.pos.x - p.r.x / 2 < this.pos.x + this.r.x / 2 &&
      p.pos.x + p.r.x / 2 > this.pos.x - this.r.x / 2 &&
      p.pos.y - p.r.y / 2 < this.pos.y + this.r.y / 2 &&
      p.pos.y + p.r.y / 2 > this.pos.y - this.r.y / 2
    ) {
            // Play a sound, increase the gas, and reset the gasoline's position.

      songs[0].play();
      gas += 100;
      this.pos = createVector(random(0, width), random(-100, -2000));
    }

Another aspect that fills me with pride is the implementation of webcam computer vision. It elevates the gaming experience, making it more engaging and unique. Here’s a snippet of the code showcasing this feature:

// Declare global variables to hold video capture and image data
let video;
var img;

//Picture setup
function pictureSetup() {
  video = createCapture(VIDEO); // Create a video capture element and assign it to the 'video' variable

  video.size(size *40, size *40);
  video.hide();
}
// Capture a snapshot from the webcam and assign it to the 'img' variable
function picture() {
  //Set image webcam
  img = video.get();
}

Areas for Improvement and Future Work:

While I’m satisfied with the current state of my game, there are areas that I believe can be further enhanced. First, I’d like to experiment with colors and themes to make the game more visually engaging. Perhaps, as players progress through levels, the game’s theme could shift from daylight to nighttime, adding a dynamic element to the gameplay. Additionally, incorporating power-ups, introducing multiple levels, and improving the graphics could take the gaming experience to the next level.

References

Azimov, Bob. “LkvG5pT5g.” p5.js Web Editor, 2023, https://editor.p5js.org/azimovbob/sketches/LkvG5pT5g.

Carvalho, Kelly. “tDFpv6VLi.” p5.js Web Editor, 2023, https://editor.p5js.org/kellycarvalho2024/sketches/tDFpv6VLi.

Zohaib Naz. “CarRacing-p5.” GitHub, https://github.com/mzohaibnaz/CarRacing-p5.

 

Leave a Reply