Midterm Project: Space Navigator by Sihyun Kim

Final outcome:

Link to fullscreen:

https://editor.p5js.org/sihyunkim/full/o-b8ZVYnT

Concept of the Game

If someone asks me what my childhood favorite game was, I will say that my favorite game was Flappy Bird without any doubts. As a child, I found avoiding obstacles by controlling the bird up and down along with the increase in speed as the game progressed very intriguing and fun. Hence, for this midterm project, I wanted to create something working with the same logic but in a different style. So, inspired by my childhood favorite game- Flappy Bird, I created a game called “Space Navigator”. As its name suggests, the theme of the game is space exploration. The player is part of an astronaut team sent from Earth to explore Saturn. The mission of the player is simple. All the player has to do is avoid collision with the moving meteoroids on the way to Saturn and follow the path of the stars to arrive on Saturn.  

The images below are the concept image I drew while conceptualizing my project and the transparent images I utilized for my project. I wanted my midterm project to look cute and round. So, I searched for lots of images in the Canva. And ended up using the round-ish images below. Also, I wanted to give people the feeling of childish wonder. So, I intentionally chose a piece of music (video below) from a Nintendo game called Captain Toad: Treasure Tracker. I found this music to be a great fit to be  background music for my game as this music is not too loud but still not boring. Most importantly, this song gave me that feeling of “childish wonder”. So,  I decided to use this. 

Concept Image I drew for my project before working on it:

Images obtained from Canva that I have utilized for the game


The background music for the game:

How the game works: 

The game is quite straightforward. As mentioned above, all what player has to do is to avoid the meteoroids and follow the stars as much as he/ she can. Also, the player has to be careful to not touch the bottom and top boundaries to not lose track of the orbit.  And this is done by controlling the rocket. There are two modes in which the player could choose: Voice mode and key mode. As the modes’ names suggest, the voice mode enables the player to control his/her rocket using his/her voice volume. The voice volume is mapped to the adjustment of the velocity of the meteoroids. The higher the voice volume of the player is, the higher the rocket arises. The key mode is the same as the Voice Mode except that this mode involves controlling the rocket using the keyboard’s space bar instead of the player’s voice volume. The better the player plays the game, the faster the game goes. After “collecting” 15 stars, the game will end with the text that the player arrived at Saturn will appear. 

Explanation of codes for the game:

I have three essential components in my game: rocket, meteoroid, and stars. And I made  Meteoroids(), Rocket(), and Stars() classes for these components of the game. First of all, as the name suggests, the Meteoroids() class is responsible for making the moving meteoroids (obstacles) of the game and checking if they collide with the rocket. Inside this class, there are three functions: update(), show(), and checkCollision(). The update function is responsible to animate the meteoroid while the show function is responsible for depicting the meteoroid itself in the screen. Checkcollision is a function that does check Collision with the rocket. The logic behind the Checkcollision function follows the equation of the circle. Whenever collision with a rocket is detected, the flag named winningState changes to “lost”, indicating that the player lost. 

Next, the Rocket() class is responsible for properties related to the rocket that the player controls. In this class, there are four functions: gravity(), move(), update(), show(), and boundary check(). The gravity function stimulates gravity affecting the rocket. Meaning, that if the player does nothing, the gravity function will let the rocket move down. And move function is responsible for adjusting the velocity of the rocket based on the user’s voice volume or the space bar input. Using an if-else statement and a flag named “keycode”, I made sure that the rocket would only be controlled using the voice volume in voice mode and controlled by pressing the space bar in key mode. The update function is responsible for adding the adjustment from the move function to the y position of the rocket, resulting in the animation of a rocket being moved up or down. And show function is responsible for depicting the rocket in the function. The boundaryCheck() function checks if the rocket touched the top or bottom boundary by checking the position of the rocket and the coordinates of the boundaries. If the rocket touches the boundary, two flags, winningState and touchedBoundary, are changed. 

Thirdly, the Stars() class is the class responsible for generating the stats that will guide the rocket. Like the other two classes, the star function has show() and update() function which allows the stars to be animated and shown. One unique thing about the Stars class is that it has two collision check functions- one with the meteoroids and the other with the star. This is because I had to make sure that the stars did not overlap with the meteoroids and use collision detection with stars to know when to score the player. 

In the main sketch, codes related to ensuring the correct procedure of the game, global variables, and functions such as windowResized(), preload(), setup(), keyPressed(), and mousePressed() are located. Basically, windowResized() is responsible for resizing the game screen for the fullscreen mode, preload() is responsible for loading the images, fonts, and files for the game. In setup() function, I have put some properties of the game that should not be redrawn every time (e.g. background music).  The keyPressed() function is responsible for triggering the boost for the rocket in key mode when the space bar is pressed and letting fullscreen be activated/ deactivated when the “f” or “F” key is pressed. 

The mousePressed() is responsible for all conditions related to the mouse press. All the buttons in the work game work due to flags such as gameState being triggered in this mousePressed() function.  the draw() function handles the procedural aspects of the game, and the game’s state changes based on the value of the gameState variable. The use of if-else statements ensures that different screens are displayed depending on the current state of the game. I think this approach allows seamless transitions between various screens, guiding players through different gameplay stages.

Proud Things from the Project

The part which I am most proud of is also part of the star class. Particularly, I am proud of the code snippets attached below, which are responsible for generating stars. The first code snippet is the code of the checkCollision() method in the Stars class. As the first code snippet shows, the logic of a star’s detecting collision with the meteoroids involves the equation of the circle. It checks if the distance between the meteoroid and the star is greater than the sum of the size of the star and the radius of the meteoroid. The output of checkCollision() inside the star class is a boolean variable. It returns true if there was a collision detected and false if there was no collision. The second code snippet is the code snippet located in the main sketch, which simply ensures that the stars are making sure that stars are not being generated at the same position as the meteoroids. The logic of this code snippet using a while-loop is that it keeps generating new Star objects until the checkCollision() method of the Star object returns false. Then, we add the Star object into the array of the Star object. There will be only one object being pushed into an array at a time as we do not technically “save” the generated Star object in the while loop if it overlaps with the meteoroid object.

Code snippet of checkCollision() inside the Star class:

// method to check for collisions with meteoroids
checkCollision(meteoroids) {
  for (let i = 0; i < meteoroids.length; i++) {
    let distX = this.position.x - meteoroids[i].position.x;
    let distY = this.position.y - meteoroids[i].position.y;
    let distance = sqrt(distX * distX + distY * distY);
    if (distance < this.size + meteoroids[i].radius) {
      return true; // collision detected
    }
  }
  return false; // no collision detected
}
//method to check for collisions with the rocket
checkCollisionRocket(other,music) {
  let distX = this.position.x - other.position.x;
  let distY = this.position.y - other.position.y;
  let distance = sqrt(distX * distX + distY * distY);
  if (distance < this.radius + other.radius) {
    metRocket = true;
    music.play()
  }
}

The while-loop that ensures generated star doesn’t collide with meteoroids:

//checking for collision with stars
while (collision) {
  starX = windowWidth + 100;
  starY = random(windowWidth * 0.125, windowWidth * 0.875);
  newStar = new Stars(starX, starY); // Regenerate star
  collision = newStar.checkCollision(meteoroids);
}
//adding the created new Star object to the array if it does not collide with any meteoroids
stars.push(newStar);

I was just so proud of this part of my project because I felt like this was the hardest part of my project. I think that the collision check that the stars have is way more complicated than the collision check that the meteoroids have, because the stars have to consider where would the meteoroids be placed and make sure that stars are not being generated there. I thought using a while-loop that only exists when a star object does not collide with the meteoroid for this part of coding was a very simple but wise decision.  Visual-wise, I just find my output so cute and gives that sense of childish wonder. So, I am very proud of my intuitions(?) to choose the images and fonts  I have utilized. Also, I am proud of the little details I added to this project such as the sound effects when the buttons are clicked or when the mission failed/succeded. While they are very subtle, I think they altogether enhanced the quality of my work. So, I am very satisfied with my output. 

Areas of improvement and problems that you ran into: 

In the future, I think I can improve the game by adding more features. For instance, I could make the player have multiple “lives” per session of the game to enable the player to easily succeed in the mission. I could maybe also consider enabling a two-player key mode, where two players “race” to reach Saturn first. I think it will be also interesting if I allow the player to choose the level of difficulty in the first place or choose the types of obstacles that the player will encounter (e.g. aliens, meteoroids, or shooting stars).

Other than this, there weren’t lots of problems that I ran into, and I was able to resolve these as well.  One of the biggest problems I encountered was to ensure that stars were generated in a random place that didn’t overlap with the meteoroids. 

However, I was able to solve this problem by using a while loop (further explanation is explained above) and the solution to this problem became my proudest part of the project. Another problem I encountered was a very mysterious problem that I still don’t get why it was solved. I tried to load images but it didn’t work out well. I first thought that I perhaps made some spelling mistakes or syntax errors when writing the code. But, it turns out that I didn’t make one. After a few minutes of debugging, I just duplicated the project itself. The duplicated project just loaded the images properly when I did not do anything after duplicating it. I honestly still don’t get why the problem was caused and how it was resolved only through “duplicating” the project. 

Overall

As usual, I loved working on this project. This project was very fun to create and it improved my coding skills. I am very satisfied with the outcome, but I think it could have been improved by adding more modes or features as I have mentioned above. 

Thank you so much for reading my blog post 🙂 

 

Leave a Reply