The Outer Experience

Click  “The Outer Experience Here” to experience in fullscreen.

The central concept of this project was derived from galaxy features(rotation about a center point, rotation about an object’s axis, etc.).

The main goal is to achieve an experience for anyone to experience how space feels like. The project includes certain extraterrestrial bodies such as the sun, Jupiter and its moons, and other creative gas liked spherical structures.

How it Works

The project works by moving around using the mouse together with W,S,A,D  keys on the user front. Technically, this is achieved by implementing the cam feature in p5.js with sophisticated math only @ “morejpeg” on youtube could help me with.

The project also features Jupiter and its moons, the sun, and other spherical galaxy planet-liked structures. These implementations were made possible using “sphere,” “rotate,” “texture,” and “translate” keywords in p5.js. The technical achievement I am most proud of is randomly distributing star-liked structures in space.

Also, I think the decision to create a big sphere to house all the stars and other planetary bodies was a smart decision. The choice of music also makes the experience a calming one I believe.

Problems

Generally, working in 3D involves so much math and analysis, and that took an enormous amount of my time. Thus, the main problem I encountered was using math to implement the camera in 3D.

That aside, randomly distributing stars in the void was a challenging task because they constantly kept randomly rotating in the void. Finding the exact position to place a text for User control proved difficult because I simply couldn’t locate the default camera location in the void.

 

References

morejpeg, (2023, Jan)”Coding First Person Camera Controls in 10 Minutes.” Youtube:https://youtu.be/0b9WPrc0H2w

Week 7 – SURVIVE Midterm Project Completed

  • Describe the overall concept of your project (1-2 paragraphs)

For the midterm project, I’m continuing to develop the “SURVIVE” game I created in week 3. The game concept is based on many retro games such as space invaders. The goal of this interactive video game is to avoid oncoming RGB-colored missiles while the user controls a triangle at the cursor. The objective of the game’s endless mode is to live for as long as you can and obtain high scores. To go with the retro theme, I made the main menu also styled like an arcade game. The sound effects I chose were also intended to give off a retro vibe.  The soundtrack is energetic and upbeat which matches the type of feel I wanted the gameplay to have.  

 

 

  • Describe how your project works and what parts you’re proud of (e.g. good technical decisions, good game design) 2-3 paragraphs

The projectiles are all separate objects that have collision detection with the player. The timer counts up and the bullets’ speed increases the more time passes. To make the game easier to browse, I also incorporated a variety of menus. There is a main menu and a game-over menu included. I also added a Highscores menu that keeps track of the player’s scores locally (in the browser) and sorts them from highest to lowest. The gameplay has been enhanced by adding 3 new mechanics. Shield and Slowdown which are powerups and Clear which is an active ability. Picking up Shield allows the player to be able to take collide with an incoming projectile without losing any HP. Slowdown, when picked up makes the projectiles move in slow-motion for a short duration. Clear can be activated by pressing space or mouseclick, and it emits a blue circle around the player which neutralizes all incoming projectiles that collide within the circle.

Finding the right balance with regard to the power-up spawn frequency and clear cooldown is something that I found to be very interesting. For the game to have the right amount of challenge while not making it too easy is surprisingly a hard balance to find. This naturally took a lot of trial and error to find a frequency that forced the player to actually play the game and avoid the obstacles while also keeping them frequent enough to where the player gets to use the power-ups multiple times a playthrough. With Clear being an active ability the player can trigger it was vital to not make the cooldown time too short as it would make the game too easy, I settled on around 20 seconds. This amount of time makes the player heavily consider the opportunity cost of using the ability which makes the game more engaging.

I am also proud of how I structured the program to handle multiple menus. How organized or disorganized the code depends on the structure used. Each menu will be in its own if statement that tests the current “level,” as I chose to do. Currently, there are 4 different levels. These are the main menu, game over screen, high scores, and the actual game. The application can only retrieve information that is made available to the current level variable using this structure. As a result, developing game features is considerably simpler and easier. It also makes it so that the program does not have to go through every line of code as it is restricted to levels, this reduces the amount of processing power required.

  • Describe any problems you ran into (1-2 paragraphs)

I ran into problems with the Highscores function of the game. Initially I thought that it would be possible to write directly to an uploaded txt file in p5js. When I was researching online I saw that most people were using savestring() to do this. However, when I tried it, the file would just download onto my browser but not change the already uploaded txt file which I was reading from. I had tried a few more functions but to no success. So I opted for a local storage solution that used storeitem() and getitem(). These functions would store all the data locally on your browser and would stay after multiple sketch resets. The main drawback with this approach is that it is locally stored, meaning that players on other computers would not see the same high scores.

I also ran into a weird bug that I couldn’t figure out for a good while. When I was clicking on the return to main menu button it would take me to the high scores menu. This weird behavior did not make any sense when I looked at the code itself. But upon further investigation, I realized the problem stemmed from the mouseIsClicked variable I was using to interact with the buttons. The issue was that it would stay returning true as long as I held the mouse button down and I was within the range of the button. In addition to this, my return to the main menu button was in the exact same position as the high scores button in the main menu. So in reality the program was actually switching to the main menu, but in the split second in which I was holding down the mouse button, it would also activate the high score menu. I solved this problem but introducing a clicked boolean value and using the mouseClicked() function. This made it so that only one instance of true would be returned when I clicked on the mouse button.

 

Midterm Project – Final

Boy Who Cried Wolf: The Game

 To play the game click this link -> Boy Who Cried Wolf: The Game

Link to fully commented code -> Boy Who Cried Wolf: The Game (code)

૮꒰ ˶• ༝ •˶꒱ა. ૮꒰ ˶• ༝ •˶꒱ა  ૮꒰ ˶• ༝ •˶꒱ა. ૮꒰ ˶• ༝ •˶꒱ა. ૮꒰ ˶• ༝ •˶꒱ა

Process

Design

To start, I created a few pixel images that I would use for the game. I created three types of sheep, the shepherd, wolf and the trees. To create the wolf and the sheep, I took inspiration from the web (sheepwolf) but the boy and the trees are original creations. All of the images were created and animated using Piskel.

The boy is dressed in traditional Bosniak male clothing, the fes, vest (prsluk / džemadan), trousers (šalvare / shalwar or čakšire / çakşır), belt (bensilah) and shoes (opanci). The wolf looks very thin which represents his hunger

Using the images and Powerpoint (very handy program) , I created the start screen, as well as the winning and losing screens which are pictured below.

Implementation

The implementation process was quite straightforward, get the player to move the sheep in and around the pen. Unfortunately, the logic behind the game was not quite as straightforward. Having completed 90% of the game, I was stuck on the sheep and pen interaction for almost a whole day. Although that might not seem very bad, I was thinking of quite elaborate solutions that would calculate the depth of the interacting shapes which would translate into prohibiting the interaction. In the end, I went with the easiest solution and that is *drumroll* a lot of logical comparisons and arithmetic operations 🙁 . As a Computer Science student, I hate having my code look like a third grade maths notebook. However, running out of time forced me to take extreme measures and settle with the basic approach.

Other than the issues with object interactions, I was quite pleased with the flow of my programming. Although I really dislike working under pressure, working the code out was quite satisfying once I finalised the project.

Reflection

The project was very interesting to work on. Since I have made a simple game before, I knew my way around Object Oriented Programming, but what came as a surprise was that I am not yet capable of understanding the sizing of the canvas I am working on. The game is not at all scaleable. Although the variables such as number of sheep and their size are, the screen will not adapt to the change of values the way it should without going deep into the code and fixing it. In the future, I wish to make my games fully capable of resizing at anyone’s will. This may not be something that is done in re, but understanding the principles of canvas sizing will undoubtedly help me understand the greater scheme of things – responsive web design.

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.

Week 5: Midterm Progress Report

Concept

I am creating a game that I have named “Save the Ocean”. This game is inspired by the snakes game that I grew up playing. While I wanted to recreate that experience, I also wanted to add my own concept and content to the game. Therefore, I am using this game to create awareness about plastic pollution and how it affects our oceans and its wildlife.

In the game, the player will move from the start screen to the main screen after reading some instructions. When playing, the user will use arrow keys to move a character that cleans up plastic waste (just like a snake collects coins in the snake game). The more you clean, the more points you get.

Save ocean poster. Eco vector illustration about global save underwater nature from pollution, hand draw turtle in net with plastic bottles, concept cleanliness isolated on white background

To make it challenging, I have these ideas:

  1. Time limit: user has to collect all the garbage within a given time.
  2. Obstacles: user has to avoid obstacles

Depending on how challenging the concept is to implement, I will add more layers as needed to the project.

Game

Code

let segWidth = 30;
let step = 3;
let direction = 'start'
let gameState = 'start';
let begin = 'stop'
let startPlaying = false;
let img;
let song;
let cnv; 
function preload() {
  img = loadImage('images/1.png');
  song = loadSound('music.mp3');
}
class Segment {
  constructor(x, y){
    this.x = x;
    this.y = y;
    noStroke();
    fill('pink')
    ellipse(this.x, this.y, segWidth)
  }
  
   moveRight(){
    if (this.x > width){
       this.x = 0;
     }else {
    this.x += step;
     }
    ellipse(this.x, this.y,segWidth)
  }
   moveLeft(){
     if (this.x < 0){
       this.x = width;
     }
     else
    {
      this.x -= step;
    }
    ellipse(this.x, this.y,segWidth)
  }
   moveUp(){
     if (this.y < 0){
       this.y = height;
     }
     else{
       this.y -= step;
     }
    ellipse(this.x, this.y,segWidth);
  }
   moveDown(){
     if (this.y > height){
       this.y = 0;
     }
     else {
       this.y += step;
     }
    ellipse(this.x, this.y,segWidth)
  }
  updatePosition()
  {
    if (direction === 'right')
    {
     this.moveRight();
    }
  if (direction === 'left')
    {
      this.moveLeft();    
    }
  if (direction === 'up')
    {
      this.moveUp();
    }
  if (direction === 'down')
    {
      this.moveDown();
    }
  }
}

let segments = [];

function setup() {
  cnv = createCanvas(600, 600);
  song.play();
  append(segments,
  new Segment(width/2, height/2)
  )
}

function startPage(){
  image(img, 0, 0);
  noFill();
  if (mouseX< 580 && mouseX > 20 && mouseY < 580 && mouseY > 20) 
     {
      fill('lightblue');
      ellipse(width*4/5, height*5/6, 150,100);
      fill('rgb(246,237,237)');
      textFont('Helvetica');
      textSize(38);
      text('Start',440, 513);
      print("play option appears")
     } 
    if (mouseX < width*4/5+75 && mouseX > width*4/5-75 && mouseY < height*5/6 + 50 && mouseY > height*5/6-50)
    {
      fill('lightblue');
      ellipse(width*4/5, height*5/6, 150,100);
      if (mouseIsPressed)
          {
            gameState = 'play'
          }
    
    }
  fill(255, 60, 100);
  //text("(" + mouseX + ", " + mouseY + ")", mouseX, mouseY);
}

let currX = 300;
let currY = 300;

function draw() {
  
  if (gameState === 'start'){
    print('start');
    startPage();
  }
  else if (gameState === 'play'){
    print('play game')
    playGame();
  }

  
}

function keyPressed() {
  if (keyCode === RIGHT_ARROW) {
    direction = 'right';
    print('right')
  } else if (keyCode === LEFT_ARROW) {
    direction = 'left';
    print('left');
  } else if (keyCode === UP_ARROW) {
    direction = 'up';
    print('up')
  }
  else if (keyCode === DOWN_ARROW) {
    direction = 'down';
    print('down')
  }
}

function playGame(){
  smooth();
  background(220);
  showInstructions();
if (startPlaying === true){
    startPlayingGame();
  }

}
function showInstructions(){
  fill('lightblue')
  square(100,100,400);
  textSize(20);
  fill(0);
  text('This is where the instructions will go:', width/5, 200);
  text ('Up, down, left, and right arrows to move', width/5, 300);

  ellipse(width/2, height*2/3, 80);
  fill(255);
  text('GO', width/2-15,height*2/3+8)
  if (mouseIsPressed && mouseX > width/2-40  && mouseX < width/2+40)
    {
      print('start playing now')
      startPlaying = true;
    }
}

function startPlayingGame()
{
  background(220);
  text('Use arrow keys to start moving', width/4, height/3);
  fill('rgb(221,37,69)')
  ellipse(width/2, height/2, segWidth);
  if (direction === 'up' || direction === 'down' || direction === 'left' || direction === 'right' )
  {
   background(220);
   for (i = 0; i < segments.length; i++){
    segments[i].updatePosition(); 
  }
 }
}
function addSegment(){
  append(segments,new Segment(currX+step,currY+step))
}

I will be using object oriented programming structure and functions to design and organize the code. Text, shapes, and other elements used in class will be used.

Challenging Parts

What I find challenging at the moment is how to randomly generate obstacles and detect collisions. This is what I am figuring out now and then I will work on the design and aesthetics. Moreover, I want to check how to add video to the background or make the background move.

Midterm Game

Introduction: Inspiration
For this project, I wanted to build something simple but, at the same time, attractive to create. As children, my sister and I used to play this game called “Barbie bike stylin ride” so much that it was our favorite. So along with creating a game for my midterm project, I wanted to live those cute childhood memories and enjoy making this game.

Concept
This is a simple rescue game. So the game is called Romeo and Juliet. As the game suggestes the main character our Romeo has to pass through all the obstacles and reach his Julliet. The obstacle course is mainly a bike ride but I’m also thinking of implementing a flying mode as well.

Future implementations
For now the project is just in the initial phase and I have to implement the buttons for playing the game, and for the instructions. I am thinking of either having different levels or increasing the speed of the game as the time increases. So the score for the game will according to the highest time the player is able to stay in game.

Most Frightening part
The collision detection is the most difficult part so far according to me.