Mid-Term Project: Star Chaser ˗ˏˋ ★ ˎˊ˗ by Aysha AlMheiri

Link to Sketch (Please Press Space Bar for it to be in Full Screen): https://editor.p5js.org/am.almh/full/7XY6Q1OrX

Before actually developing my game, my initial idea was to create  a Mario-inspired pac man game, in which Mario and Luigi go around a maze to collect stars while being chased by ghosts. In my eyes, the game would be a perfect blend of two retro games, creating a very nostalgic experience for users, particularly those who played both games growing up. However, as I was attempting to implement such a game in p5, I realized that such a project would be too advanced for my skill level and given the time constraints, I would not be able to create a fleshed out version of the game. 

Initial Game Design

After countless hours of thinking of another idea, I came up with a simple, yet exciting, game in which the player chases stars across the sketch in order to win the game, which is why I called the game, Star Chaser. Ultimately, the focus shifted into a much simpler game centered around chasing stars and avoiding shells, still retaining the essence of retro Nintendo games that I was initially going for. It ensured that even with the changes to the game I was creating, the main concept of classic Nintendo games remained prominent. Thus, while the project may have evolved from its original idea, the concept of celebrating retro Nintendo games still remains. 

Final Game Design 

In my game, Star Chaser,  players are able to control a Mario character using the arrows on the keyboard in order to collect stars and avoid incoming shells. The objective of the game is to catch all the stars within the given time limit, 30 seconds, trying to preserve Mario’s lives. Each time Mario gets hit by a shell, he loses one of his two lives. To win the game, the player must avoid the shells and achieve the maximum score of 60 points. This is done by maneuvering Mario around the sketch to collect all the stars. 

Screen 1- Landing Page

Screen 2- Instructions Page

Screen 3- Game Page

Screen 4- Win Page

Screen 5- Lose Page

The aspect of my project I am particularly proud of is the actual game design. Initially, it was incredibly difficult for me to get things to move for the game, set up the lives and scores board, and even simply get the character to move. Although we did discuss some of these things in class, it was still quite difficult to do it myself given the fact that as I was attempting to put the game together, there were a lot of bugs and errors that kept occurring. Due to the fact that this was my first time creating a game, I had to sit for hours trying to figure out what kept causing the errors. However, after countless hours of attempting to understand the root cause of the problems, I was able to figure out that it was due to the order of the code and wrongly declaring variables. Although this was frustrating, I am proud that I was able to fix this issue and implement somewhat smooth controls for the game, which can be seen in the code below: 

// Function to display the game screen
function gameScreen(){
// Sets background color to Green
  background('#92CA5B');
  
// Displays grass images
  //Right Side
  image(grass, 0, 0, 1500, 1800);
  //Left Side
   image(grass, 780, 0, 1500, 1800);
  
 // Displays stars
  for (let i = 0; i < stars.length; i++) { // Loop through stars array
    stars[i].display();
  }
  
 // Displays shells and handle their movement
   for (let i = 0; i < shells.length; i++) { // Loop through shells array
    shells[i].move(); //Moves Shells
    shells[i].bounce(); //Helps Shells Bounce around Sketch
    shells[i].display(); //Helps Display Shells on Sketch
  }
  
//Draws a Rectangle for Information Boxes on Top of Sketch
  //Right Box
  fill('rgba(255,255,255,0.83)');
  stroke('rgba(255,255,255,0.83)')
  rect(40, 35 , 370, 70, 20);
  
  //Left Box
  fill('rgba(255,255,255,0.83)');
  stroke('rgba(255,255,255,0.83)')
  rect(1030, 35 , 370, 70, 20);
  

// Ensures in-game music is looping
  if (!inGameMusic.isPlaying()) {
    inGameMusic.loop(); 
  }
  
// Ensures in-game music is playing
   if (!inGameMusic.isPlaying()) {
        inGameMusic.play();
    }
  
// Displays the Player's Score
  textFont("Mina");
  fill('black');
  stroke('white');
  strokeWeight(3);
  textSize(30);
  text('Points:', 58, 80);
  text(score, 168, 80);
  
// Displays the Player's Remaining Lives
  textFont("Mina");
  fill('black');
  stroke('white');
  strokeWeight(4);
  textSize(30);
  text('Lives:', 280,80 );
  text(lives, 370, 80);
  
// Calculates and display the remaining time
  landingTime = landingTime;
  
//Calculates the Game Time by Subtracting the Landing Time from the Current Total Time to then Converting the Results to Seconds by Dividing by 1000 and rounding down using the int() function.
  gameTime = int((totalTime-landingTime)/1000);
  
// Displays text indicating time remaining
  textFont("Mina");
  fill('black');
  stroke('white');
  strokeWeight(3);
  textSize(30);
  text('Time Remaining:', 1070, 80);
  
//Displays the calculated remaining time
  text(timeLimit - gameTime, 1316, 80);
  
//Game Outcomes
//If the score reaches 60 (maximum number of points) then the game will stop and take you to the win screen
  if (score>=60){
    inGameMusic.stop();
    gameStage = 3;
    winSong.play();
  }
  
//If lives reach 0 then the game will stop and take you to the lose screen
  if (lives<=0){
    inGameMusic.stop();
    gameStage = 4;
    loseSong.play();
  }
  
//If time reaches 0 then the game will stop and take you to the lose screen
  if (gameTime>=timeLimit){
    inGameMusic.stop();
    gameStage = 4;
    loseSong.play();
  }

// Arrow keys pressed to move the player accordingly
//Left Arrow
if (keyIsDown(LEFT_ARROW)) {
  playerDirection = -1; // Set direction to left
  p1X -= 12; // Move left
//Right Arrow
} else if (keyIsDown(RIGHT_ARROW)) {
  playerDirection = 1; // Set direction to right
  p1X += 12; // Move right
}
  
//Up Arrow
if (keyIsDown(UP_ARROW)) {
  p1Y -= 12; // Move up
} 
//Down Arrow
else if (keyIsDown(DOWN_ARROW)) {
  p1Y += 12; // Move down
}

// Moves the player within canvas boundaries
  p1X = constrain(p1X, pWidth / 2, width - pWidth / 2); // Constrain x position
  p1Y = constrain(p1Y, 0, height - pHeight); // Constrain y position


// Draws the image based on player direction
if (playerDirection === -1) {
  // Flips the image horizontally when moving left
  scale(-1, 1); // Flips horizontally
  image(mario, -p1X, p1Y, pWidth, pHeight); // Draws image
  scale(-1, 1); // Resets scale
} else {
  // Otherwise, draws the image normally
  image(mario, p1X, p1Y, pWidth, pHeight); // Draw image 
}

// Check for collision between player and stars
    for (let i = 0; i < stars.length; i++) {
        if (stars[i].checkCollision(p1X, p1Y, pWidth, pHeight)) {
            // Remove the collided star from the array
            stars.splice(i, 1);
            // Increase the score by 5 points
            score += 5;
        }
    }
   
}

Another aspect that I am proud of is the visual and auditory elements of the game. I have incorporated hand drawn elements and sound effects from different Mario games in order to create a holistic experience for users and immerse them into the nostalgic game I created. 

Hand Drawn Title 

I believe doing this successfully captured the concept of Nintendo games I was trying to showcase to users and offers users an engaging experience. The code for this can be seen below: 

//Helps transition back to the landing page when the button is pressed
  if (mouseX >= 580 && mouseX <= 910 && mouseY >= 500 && mouseY <= 695 && mouseIsPressed == true){
  //Moves to gameStage 0, which is landing page page
  gameStage = 0;
    
  //When button is pressed mainButtonSound will play
  mainButtonSound.play();
}

Example of Where I Used Audio in my Game

In terms of improvements, I feel like I can incorporate more audio and visual elements to create a more immersive experience. I could potentially add a loading or waiting screen in between the game and instruction screens to make the game design more comprehensive. I also could have added some form of computer vision. I feel like it would make the design complex and creative, which can make it an engaging, unique, and enjoyable experience for users.

In regards to problems, I feel like my main issue, although quite silly, is the sprite sheet. I could not find any sprite sheet online that worked well with my game concept. Although that is the case, I tried finding anything just so I could get started with my game design. When I found one that could work as a placeholder, p5 would not load the image onto the sketch. I kept getting an error message from p5. I then tried to draw my own sprite sheets, which also did not work on p5. This problem was very frustrating because it was essentially the most important element of the game. Therefore, I had to stick to using a singular image to help move the character around. The image was of the character facing the right. Thus, I  made the character flip horizontally when the left arrow key was pressed to add more movement to the character and the game experience as a whole.

Initial Sprite Sheet

Final Character Design

Overall, this project pushed me to learn more about p5 programming and how I am able to manipulate code to create what I wanted. This project, although difficult, was one of the most rewarding thing I have ever done. I am proud of how far I have come with p5 and I genuinely believe that this project shows my progress thus far.

Leave a Reply