Midterm Project: Doodle Jump

Sketch links:

To play the game in fullscreen click this link -> Click Here to Play the Game

The project code -> Code

Overall Concept

Good day! I wanted to offer some information on a Doodle Jump game I made using p5.js. I truly adored playing this game as a kid. Trying to steer the avatar to leap on platforms and dodge obstacles was both thrilling and difficult. I can still recall how good it felt when I was able to jump higher and advance to new levels. However, playing solo was in a way boring, so I decided to make it two player game.

The objective of the game is to outperform your opponent. Both players control their Doodlers by using WASD keys and ARROWS keys. You compete against each other by getting up faster than your opponent. Whoever is left behind loses the game. On the way up you have obstacles such as monsters, UFOs, and black holes that can immediately kill you. Also, there are some pleasant surprises waiting on top such as boosters that speed up your way and make you invulnerable to the obstacles.

I’m pleased to inform you that I could effectively execute the game concept for my project. To improve the game’s realism and appeal, I included collision detection logic and gravity. Also, I took an effort to adjust the degree of difficulty such that it was demanding without being overly unpleasant.

Implementation and Design

How this project works

Welcome to Two Player Doodle Jump, the classic jumping game with a twist! In this game, you and a friend will control your own doodlers using WASD or ARROWS keys as you jump higher and higher.

But wait, there’s more! We have three different themes for you to choose from: Original, Ancient Egypt, and Easter Egg. Each theme has its own unique obstacles and designs to keep you entertained.

But beware, the journey to the top is filled with obstacles such as pesky monsters and UFOs trying to knock you off course. Don’t worry though, there are also boosters scattered throughout the game to help you on your way. Look out for jetpacks that will give you a temporary boost in height and trampolines that will launch you even higher.

As you climb higher, the obstacles become more difficult to avoid, making the game more challenging and exciting. With every jump, you and your friend will be on the edge of your seats, trying to reach the highest point possible.

So, gather your friends and get ready to jump into action in Two Player Doodle Jump. Can you make it to the top and become the ultimate jumping champion?

Technical Design/Good technical decisions

The game starts with an instructions screen where players will be able to learn how to play the game and select the theme they want to dive into. By clicking on any of the dancing Doodlers, the game will start with the appropriate mode(doodler skin, boosters, monsters).

After choosing the skin, players start competing in the main game.

One of the most impressive technical decisions in the game is its use of the p5.js library’s built-in functions for creating animations and graphics. The smooth animation of the doodlers jumping, the movement of the obstacles, and the booster effects all demonstrate the quality of the game’s technical design. Additionally, the use of different colors and themes for each level shows how I paid close attention to the visual design of the game.

Another notable technical decision is the game’s use of the keyboard as the primary control method for the doodlers. The use of WASD and ARROWS keys for the two players makes it easy to pick up and play the game without requiring any complicated controllers or devices. The control scheme is intuitive and responsive, which makes for a more enjoyable experience overall.

Furthermore, the game’s procedural generation of obstacles is a testament to the thought and effort put into the technical design of Two Player Doodle Jump. Each level presents new challenges with different patterns of obstacles and boosters, keeping the gameplay fresh and engaging. A lot of different computations were considered while working on the obstacle generation. You don’t want the user to get stuck in an impossible situation, otherwise, user will get angry and stop playing the game

The implementation of the game’s scoring system is also a well-executed technical decision. The scoring system is simple yet effective, with players earning points for each jump they make. The game’s technical design is also notable for its effective use of sound effects. The sound of the doodlers jumping, the obstacle collisions, and the booster pickups all enhance the overall experience of playing the game. The sounds are not random and actually resemble the physical world that people live in.

In conclusion, Two Player Doodle Jump is a well-designed game with excellent technical decisions that have contributed to its success. The use of the p5.js library’s built-in functions, the use of the keyboard as the primary control method, the procedural generation of obstacles, the scoring system, the effective use of sound effects, and responsive design are all examples of good technical design decisions.

Good Game Design

The availability of various characters to pick from increases the game’s originality and diversity is one of the things I’m most pleased about. I also included boosters that assist the player in making bigger jumps and scaling greater heights. In order to provide a personal touch, I left a particularly humorous message at the game’s conclusion. All the boosters are different depending on the doodler that is selected. That way the theme of the doodler stays the same. However, it was a bit tough to have all the pictures of the same dimensions(you can see in the game that some boosters are bigger than others). Nonetheless, even if it is not the same, it adds more of a personal touch to the game by being random and not symmetric(Who said that everything should be symmetric? xd)

After I let a few of my friends test the game, they gave me a few hints on what to improve/make clear. Apparently, it was not clear who is WASD player and who is ARROWS player, so instead, I named them player 1 and player 2 at the beginning of the game and at the game over screen. This made it clear to the players who won, so they didn’t have to map the keys and numbers themselves

In addition to that, a few of my friends pointed out a case where the game was breaking if one of the doodlers picked up the jetpack and the second one didn’t. I found the flaw in the code and was able to fix it straight away. I learned that even though I thought of myself as an expert there is a still possibility of an error that I could not catch. Hence, user testing is a perfect solution to make sure the game works as intended.

Potential Improvements and Challenges

I did, however, have certain difficulties in the course of the work. Implementing the collision detection mechanism correctly took me some time since it was so challenging. In the below code, I had to iterate in a reverse manner in order to check if the doodler was on a specific platform. According to the platforms the direction of the doodler may change and the game ground level changes so that game shifts up.

for (let p of [...game.platforms].reverse()) {
        // checking if doodler on the platform then change it to the ground, this.r/3 needed to cut the nose of the doodler and not count it
        if (
          this.y + this.r <= p.y &&
          this.x + this.r / 3 >= p.x &&
          this.x - this.r <= p.x + p.w &&
          this.dir == 1
        ) {
          this.g = p.y;
          break;
        } else if (
          this.y + this.r <= p.y &&
          this.x + this.r >= p.x &&
          this.x - this.r / 3 <= p.x + p.w &&
          this.dir == 0
        ) {
          this.g = p.y;
          break;
        } else {
          // ground is the under the screen
          this.g = game.g;
        }
      }

I also had to make sure that the game mechanisms were balanced to provide the gamer with a demanding experience without making it too difficult. The toughest part was to make update the amount and type of platforms depending on the score of the game. I created 3 thresholds for simplicity that represent 3 levels of difficulty. The higher you go the less easy-green platforms spawn, fewer platforms in general spawn, and more white types of platforms that disappear once you jumped on them. This way, the game keeps being interesting without looking to easy for the players.

// last level of platforms
if (game.score > 100000) {
  
  // maintaining playable game logic
  while (game.platforms.length <= 7) {
    
    // randoming y position but making it possible to jump
    this.tmp_y =
      game.platforms[game.platforms.length - 1].y - int(random(100, 150));
    if (this.tmp_y > 70) {
      this.tmp_y =
        game.platforms[game.platforms.length - 1].y - int(random(50, 70));
    }
    this.tmp_x = int(random(0, WIDTH - this.w + 1));
    
    // counting the number of white platforms
    let count = 0;
    for (let p of game.platforms) {
      if (p.c == "white") {
        count += 1;
      }
    }
    
    // if their number is less than 2 then add them and call the monster method
    if (count < 2) {
      game.platforms.push(
        new Platform(this.tmp_x, this.tmp_y, 100, 20, "white")
      );
      this.monster();
    }
    
    // based on random add either darkblue or green platform and call the booster method
    else if (int(random(0, 10)) > 7) {
      if (int(random(0, 2)) == 0) {
        game.platforms.push(
          new Platform(this.tmp_x, this.tmp_y, 100, 20, "darkblue")
        );
      } else {
        game.platforms.push(
          new Platform(this.tmp_x, this.tmp_y, 100, 20, "green")
        );
        this.booster();
      }
    } else {
      game.platforms.push(
        new Platform(this.tmp_x, this.tmp_y, 100, 20, "blue")
      );
    }
  }
}

// second level of platforms
else if (game.score > 50000) {
  if (game.platforms.length <= 10) {
    // randoming y position but making it possible to jump
    this.tmp_y =
      game.platforms[game.platforms.length - 1].y - int(random(20, 100));
    if (this.tmp_y > 70) {
      this.tmp_y =
        game.platforms[game.platforms.length - 1].y - int(random(40, 70));
    }
    this.tmp_x = int(random(0, WIDTH - this.w));
    
    // counting the number of brown and blue platforms
    let count = 0;
    for (let p of game.platforms) {
      if (p.c == "blue") {
        count += 1;
      }
    }
    
    // if their number is less than 2 then add them and call the monster method
    if (count < 2) {
      game.platforms.push(
        new Platform(
          this.tmp_x,
          this.tmp_y - int(random(20, 50)),
          100,
          20,
          "blue"
        )
      );
      this.monster();
    } else {
      game.platforms.push(
        new Platform(this.tmp_x, this.tmp_y, 100, 20, "green")
      );
      this.booster();
    }
  }
}

// first level of platforms
else {
  if (game.platforms.length <= 12) {
    // randoming y position but making it possible to jump
    this.tmp_y =
      game.platforms[game.platforms.length - 1].y - int(random(30, 60));
    if (this.tmp_y > 70) {
      this.tmp_y =
        game.platforms[game.platforms.length - 1].y - int(random(20, 70));
    }
    this.tmp_x = int(random(0, WIDTH) - this.w);
    
    // based on random green platforms and call booster method
    if (int(random(0, 11)) > 9) {
      game.platforms.push(
        new Platform(
          int(random(0, WIDTH - this.w)),
          this.tmp_y - int(random(20, 50)),
          100,
          20,
          "green"
        )
      );
    } else {
      game.platforms.push(
        new Platform(this.tmp_x, this.tmp_y, 100, 20, "green")
      );
      this.booster();
    }
  }
}

Overall, building a Two Player Doodle Jump game using p5.js was rewarding, and I hope that others will find it as entertaining as I did as a youngster.

Author: Akhat Suleimenov

I am 22 years old. Alumni of 42 Software Engineering School in Silicon Valley. Born and raised in Astana, Kazakhstan. As hobbies, I workout, travel, and play volleyball, and chess.

Leave a Reply