Midterm Project

Overview:

As mentioned before, for my midterm project, I was inspired by the mechanics of the Chrome Dino Runner game and tried to create a newer version with more features that I called “Knight Runner”. To avoid obstacles, the avatar can either jump over the fire, or jump/crouch when it’s a bird.

Process & Features:
Parallax:

To give the game a realistic aspect, I added a Parallax effect in which the far-away clouds and mountains seem to move more slowly than the closer ones, by changing each layer’s (6 layers) position by a different amount (between 1 and 5).

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Parallax effect
void update(){
x6--; x6_2--;
x5-=2; x5_2-=2;
x4-=3; x4_2-=3;
x3-=3; x3_2-=3;
x2-=4; x2_2-=4;
x1-=5; x1_2-=5;
}
// Parallax effect void update(){ x6--; x6_2--; x5-=2; x5_2-=2; x4-=3; x4_2-=3; x3-=3; x3_2-=3; x2-=4; x2_2-=4; x1-=5; x1_2-=5; }
// Parallax effect
void update(){
  x6--; x6_2--;
  x5-=2; x5_2-=2;
  x4-=3; x4_2-=3;
  x3-=3; x3_2-=3;
  x2-=4; x2_2-=4;
  x1-=5; x1_2-=5;
}
Infinite Side-scrolling:

Instead of making the character move inside the display window, I used an infinite side-scrolling in which the character is static whereas the background moves from the right to the left. To achieve that, I used two images placed next to each other that reappear on the right side once they get out of the display window.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Infinite scrolling
if (x6<=-width){x6=width;} if (x6_2<=-width){x6_2=width;}
if (x5<=-width){x5=width;} if (x5_2<=-width){x5_2=width;}
if (x4<=-width){x4=width;} if (x4_2<=-width){x4_2=width;}
if (x3<=-width){x3=width;} if (x3_2<=-width){x3_2=width;}
if (x2<=-width){x2=width;} if (x2_2<=-width){x2_2=width;}
if (x1<=-width){x1=width;} if (x1_2<=-width){x1_2=width;}
// Infinite scrolling if (x6<=-width){x6=width;} if (x6_2<=-width){x6_2=width;} if (x5<=-width){x5=width;} if (x5_2<=-width){x5_2=width;} if (x4<=-width){x4=width;} if (x4_2<=-width){x4_2=width;} if (x3<=-width){x3=width;} if (x3_2<=-width){x3_2=width;} if (x2<=-width){x2=width;} if (x2_2<=-width){x2_2=width;} if (x1<=-width){x1=width;} if (x1_2<=-width){x1_2=width;}
  // Infinite scrolling
  if (x6<=-width){x6=width;} if (x6_2<=-width){x6_2=width;}
  if (x5<=-width){x5=width;} if (x5_2<=-width){x5_2=width;}
  if (x4<=-width){x4=width;} if (x4_2<=-width){x4_2=width;}
  if (x3<=-width){x3=width;} if (x3_2<=-width){x3_2=width;}
  if (x2<=-width){x2=width;} if (x2_2<=-width){x2_2=width;}
  if (x1<=-width){x1=width;} if (x1_2<=-width){x1_2=width;}
Spritesheet:

To animate the character, I am using 3 sprite sheets stored in a 2D array (running, jumping, sliding, dying), each row has 10 images.

To animate the obstacles, I am using 2 other sprite sheets, one for fire (64 images), and the other for birds (9 images).

I am using frameCount to loop over the sprites

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Upload all the sprites
void loadsprites(){
// Running
for (int i=0; i<sprites.length;i++){
sprites[i][0]=loadImage("assets/run/run"+i+".png");
sprites[i][0].resize(53,74);
}
// Jumping
for (int i=0; i<sprites.length;i++){
sprites[i][1]=loadImage("assets/jump/jump"+i+".png");
sprites[i][1].resize(53,74);
}
// Sliding
for (int i=0; i<sprites.length;i++){
sprites[i][2]=loadImage("assets/slide/slide"+i+".png");
sprites[i][2].resize(53,57);
}
// Dying
for (int i=0; i<sprites.length;i++){
sprites[i][3]=loadImage("assets/dying/Dead__00"+i+".png");
sprites[i][3].resize(73,77);
}
// Fire
for (int i=0; i<firesprites.length;i++){
firesprites[i]=loadImage("assets/fire/tile0"+i+".png");
firesprites[i].resize(60,60);
}
// Bird
for (int i=0; i<birdsprites.length;i++){
birdsprites[i]=loadImage("assets/bird/tile00"+i+".png");
birdsprites[i].resize(80,80);
}
}
// Upload all the sprites void loadsprites(){ // Running for (int i=0; i<sprites.length;i++){ sprites[i][0]=loadImage("assets/run/run"+i+".png"); sprites[i][0].resize(53,74); } // Jumping for (int i=0; i<sprites.length;i++){ sprites[i][1]=loadImage("assets/jump/jump"+i+".png"); sprites[i][1].resize(53,74); } // Sliding for (int i=0; i<sprites.length;i++){ sprites[i][2]=loadImage("assets/slide/slide"+i+".png"); sprites[i][2].resize(53,57); } // Dying for (int i=0; i<sprites.length;i++){ sprites[i][3]=loadImage("assets/dying/Dead__00"+i+".png"); sprites[i][3].resize(73,77); } // Fire for (int i=0; i<firesprites.length;i++){ firesprites[i]=loadImage("assets/fire/tile0"+i+".png"); firesprites[i].resize(60,60); } // Bird for (int i=0; i<birdsprites.length;i++){ birdsprites[i]=loadImage("assets/bird/tile00"+i+".png"); birdsprites[i].resize(80,80); } }
// Upload all the sprites
void loadsprites(){
  // Running
  for (int i=0; i<sprites.length;i++){
    sprites[i][0]=loadImage("assets/run/run"+i+".png");
    sprites[i][0].resize(53,74);
  }
  // Jumping
  for (int i=0; i<sprites.length;i++){
    sprites[i][1]=loadImage("assets/jump/jump"+i+".png");
    sprites[i][1].resize(53,74);
  }
  // Sliding
  for (int i=0; i<sprites.length;i++){
    sprites[i][2]=loadImage("assets/slide/slide"+i+".png");
    sprites[i][2].resize(53,57);
  }
  // Dying
  for (int i=0; i<sprites.length;i++){
    sprites[i][3]=loadImage("assets/dying/Dead__00"+i+".png");
    sprites[i][3].resize(73,77);
  }
  // Fire
  for (int i=0; i<firesprites.length;i++){
    firesprites[i]=loadImage("assets/fire/tile0"+i+".png");
    firesprites[i].resize(60,60);
  }
  // Bird
  for (int i=0; i<birdsprites.length;i++){
    birdsprites[i]=loadImage("assets/bird/tile00"+i+".png");
    birdsprites[i].resize(80,80);
  }
}
Gravity:

I am using a gravity effect for both jumping and sliding, to give the animation a realistic aspect. When jumping, the speed is continuously decreased by the amount of gravity, however, when crouching, it gets increased.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
void move(){
ycoord -= speed;
// gravity if jumps
if (ycoord<425){
speed -= gravity;
}
// gravity if crouches
else if (ycoord>425){
ycoord += speed;
speed += gravity;
}
// remain same when running
else{
state=0;
speed=0;
ycoord=425;
}
}
void move(){ ycoord -= speed; // gravity if jumps if (ycoord<425){ speed -= gravity; } // gravity if crouches else if (ycoord>425){ ycoord += speed; speed += gravity; } // remain same when running else{ state=0; speed=0; ycoord=425; } }
void move(){
  ycoord -= speed;
  // gravity if jumps
  if (ycoord<425){
    speed -= gravity;
  }
  // gravity if crouches
  else if (ycoord>425){
    ycoord += speed;
    speed += gravity;
  }
  // remain same when running
  else{
    state=0;
    speed=0;
    ycoord=425;
  }
}
Jump and Crouch:

The user cannot jump and crouch at the same time. Both the jump and crouch are done using ycoord, speed and the gravity.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// jump
void jump(){
if (ycoord==425 && crouching==false){
state=1;
gravity=1;
speed= 16;
}
}
// crouch
void crouch(){
if (crouching==true && ycoord==425){
state=2;
ycoord=442;
gravity=1;
speed= -20;
}
}
// jump void jump(){ if (ycoord==425 && crouching==false){ state=1; gravity=1; speed= 16; } } // crouch void crouch(){ if (crouching==true && ycoord==425){ state=2; ycoord=442; gravity=1; speed= -20; } }
// jump
void jump(){
  if (ycoord==425 && crouching==false){
    state=1;
    gravity=1;
    speed= 16;
  }
}

// crouch
void crouch(){
  if (crouching==true && ycoord==425){
    state=2;
    ycoord=442;
    gravity=1;
    speed= -20;
  }
}
Generating obstacles:

To generate obstacles I am both using frameCount and two random functions, the first one is used to choose when to generate the obstacle, whereas the second one is used to choose what to generate (fire or bird). The obstacles are automatically stored in an array to keep track of their position and to display them continuously. If the obstacles disappear from the screen (go over the edge) they get immediately remove from the array.

The bird obstacles have a higher speed than fire because technically fire is static so it should have the same speed as the scrolling, whereas the bird is flying.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// add a new obstacle
void addObstacle(){
if (frameCount % 60 == 0 && random(1)<0.5){
// choose randomly if its fire or a bird
if (random(2)<1){
// add it to the list
firelist.add(new Fire());
}
else {
birdlist.add(new Bird());
}
}
}
// add a new obstacle void addObstacle(){ if (frameCount % 60 == 0 && random(1)<0.5){ // choose randomly if its fire or a bird if (random(2)<1){ // add it to the list firelist.add(new Fire()); } else { birdlist.add(new Bird()); } } }
// add a new obstacle
void addObstacle(){
  if (frameCount % 60 == 0 && random(1)<0.5){
    // choose randomly if its fire or a bird
    if (random(2)<1){
      // add it to the list
      firelist.add(new Fire());
    }
    else {
      birdlist.add(new Bird());
    }
  }
}
Collisions:

To flag when the avatar touches one of the obstacles, I first used a rectangle to limit the areas of both the obstacle and avatar, then checked if those areas overlapped. Meaning that the x and y coordinates of the avatar would be inside the obstacle area. The avatar should jump when there is fire, but can either jump or crouch when there is a bird, to avoid collisions with obstacles.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Bird
boolean checkfail(float ycoord){
// if crouching, avatar is safe
if (avatar.state==2){
return false;
}
// check if avatar touches the obstacle
return xcoord+25>=100 && xcoord+25<=150 && ycoord>=400 && ycoord<=400+30 || xcoord+40+25>=100 && xcoord+40+25<=150 && ycoord+70>=400 && ycoord<=400+30;
}
// fire
boolean checkfail(float ycoord){
// check if avatar touches the obstacle
return xcoord>=100 && xcoord<=150 && ycoord+70>=540-60-30 || xcoord+40>=100 && xcoord+40<=150 && ycoord+70>=540-60-30;
}
// Bird boolean checkfail(float ycoord){ // if crouching, avatar is safe if (avatar.state==2){ return false; } // check if avatar touches the obstacle return xcoord+25>=100 && xcoord+25<=150 && ycoord>=400 && ycoord<=400+30 || xcoord+40+25>=100 && xcoord+40+25<=150 && ycoord+70>=400 && ycoord<=400+30; } // fire boolean checkfail(float ycoord){ // check if avatar touches the obstacle return xcoord>=100 && xcoord<=150 && ycoord+70>=540-60-30 || xcoord+40>=100 && xcoord+40<=150 && ycoord+70>=540-60-30; }
// Bird
boolean checkfail(float ycoord){
  // if crouching, avatar is safe
 if (avatar.state==2){
      return false;
    }
    // check if avatar touches the obstacle
    return xcoord+25>=100 && xcoord+25<=150 && ycoord>=400 && ycoord<=400+30 || xcoord+40+25>=100 && xcoord+40+25<=150 && ycoord+70>=400 && ycoord<=400+30;
}
// fire
boolean checkfail(float ycoord){
  // check if avatar touches the obstacle
  return xcoord>=100 && xcoord<=150 && ycoord+70>=540-60-30 || xcoord+40>=100 && xcoord+40<=150 && ycoord+70>=540-60-30;
}
Menu: 

Similarly, to check which button the user clicked, I used mouseClicked(), mouseX, and mouseY and checked whether the x and y coordinates are inside the area of that specific button. The menu (lobby) is displayed first, then the user has a choice to either start the game, or read the instructions.

To switch between lobby, game, and instructions pages, I am overlapping backgrounds over each other.

draw():

Inside my draw() function, I mainly check the status of the game using boolean variables (avatar died, menu, reset, game ongoing…), then proceed with displaying the right images, and the right text.

Boolean variables:

Start: flags when the user clicks on the start button, if start is false, then the menu is displayed

Help: flags when the user clicks on the help button, the instructions are then displayed

Dead: flags when the avatar touches an obstacle, the game then ends, and the user is given a choice to replay

Reset: flags when the user chooses to replay, all the games settings are reset, and the arrays get cleared

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
void draw(){
// if instructions icon clicked
if (help){
// mute the music
back.amp(0);
image(main,0,0);
imageMode(CENTER);
image(instructmenu,width/2,height/2);
image(backmenu,width/2, height/2-200);
imageMode(CORNER);
textSize(20);
text("↑ : Jump",width/2,height/2-60);
text("↓ : Crouch",width/2,height/2-20);
text("Try to avoid all obstacles",width/2,height/2+20);
text("(Fire, birds)",width/2,height/2+60);
noFill();
rect(width/2-30,height/2-230,60,60);
}
else if (start){
// unmute the music if alive
if (dead==false) {back.amp(1);}
// mute the music if dead
else {back.amp(0);}
display(); // display the background images
update(); // parallax effect and infinite scrolling
rect(100,425,50,70);
avatar.show(); // display the avatar
addObstacle(); // add an obstacle
imageMode(CENTER);
// Display the score
image(scoremenu, width/2, 50);
imageMode(CORNER);
textSize(20);
textAlign(CENTER);
text("score: " + round(score),width/2,55);
// Display the obstacles
for (int i=0; i<firelist.size(); i++){
firelist.get(i).show();
firelist.get(i).move();
// check if avatar touches an obstacle
if (firelist.get(i).checkfail(avatar.ycoord)){
dead=true;
}
// remove the obstacles that are not displayed
if (firelist.get(i).xcoord <-70){
firelist.remove(i);
}
}
// Display the obstacles
for (int i=0; i<birdlist.size(); i++){
birdlist.get(i).show();
birdlist.get(i).move();
// check if avatar touches an obstacle
if (birdlist.get(i).checkfail(avatar.ycoord)){
dead=true;
}
// remove the obstacles that are not displayed
if (birdlist.get(i).xcoord <-70){
birdlist.remove(i);
}
}
// If replay button is clicked, reset the game
if (reset==true){
back.amp(1); // unmute the music
dead=false;
start=true;
reset=false;
score=0; // reset the score
// reset the obstacles list
firelist = new ArrayList<Fire>();
birdlist = new ArrayList<Bird>();
}
if (dead==true){
// stop the parallax
x6++; x6_2++;
x5+=2; x5_2+=2;
x4+=3; x4_2+=3;
x3+=3; x3_2+=3;
x2+=4; x2_2+=4;
x1+=5; x1_2+=5;
// stop the obstacles animation
for (int i=0; i<firelist.size(); i++){
firelist.get(i).xcoord +=5;
}
for (int i=0; i<birdlist.size(); i++){
birdlist.get(i).xcoord +=10;
}
// enable the dying animation
avatar.state=3;
// display the replay button
imageMode(CENTER);
image(startmenu,width/2, height/2-20);
text("REPLAY",width/2,height/2+7-20);
imageMode(CORNER);
}
}
// display the lobby menu
else if (start==false){
// mute the music
back.amp(0);
menu();
image(main,0,0);
imageMode(CENTER);
textAlign(CENTER);
textSize(30);
// display the ui
image(startmenu,width/2, height/2-20);
text("PLAY",width/2,height/2+7-20);
image(helpmenu,width/2, height/2+100-20);
text("HELP",width/2,height/2+100+7-20);
image(title,width/2, 100);
noFill();
rect(width/2-75,height/2-55,150,70);
rect(width/2-90,height/2+40,180,80);
imageMode(CORNER);
}
}
void draw(){ // if instructions icon clicked if (help){ // mute the music back.amp(0); image(main,0,0); imageMode(CENTER); image(instructmenu,width/2,height/2); image(backmenu,width/2, height/2-200); imageMode(CORNER); textSize(20); text("↑ : Jump",width/2,height/2-60); text("↓ : Crouch",width/2,height/2-20); text("Try to avoid all obstacles",width/2,height/2+20); text("(Fire, birds)",width/2,height/2+60); noFill(); rect(width/2-30,height/2-230,60,60); } else if (start){ // unmute the music if alive if (dead==false) {back.amp(1);} // mute the music if dead else {back.amp(0);} display(); // display the background images update(); // parallax effect and infinite scrolling rect(100,425,50,70); avatar.show(); // display the avatar addObstacle(); // add an obstacle imageMode(CENTER); // Display the score image(scoremenu, width/2, 50); imageMode(CORNER); textSize(20); textAlign(CENTER); text("score: " + round(score),width/2,55); // Display the obstacles for (int i=0; i<firelist.size(); i++){ firelist.get(i).show(); firelist.get(i).move(); // check if avatar touches an obstacle if (firelist.get(i).checkfail(avatar.ycoord)){ dead=true; } // remove the obstacles that are not displayed if (firelist.get(i).xcoord <-70){ firelist.remove(i); } } // Display the obstacles for (int i=0; i<birdlist.size(); i++){ birdlist.get(i).show(); birdlist.get(i).move(); // check if avatar touches an obstacle if (birdlist.get(i).checkfail(avatar.ycoord)){ dead=true; } // remove the obstacles that are not displayed if (birdlist.get(i).xcoord <-70){ birdlist.remove(i); } } // If replay button is clicked, reset the game if (reset==true){ back.amp(1); // unmute the music dead=false; start=true; reset=false; score=0; // reset the score // reset the obstacles list firelist = new ArrayList<Fire>(); birdlist = new ArrayList<Bird>(); } if (dead==true){ // stop the parallax x6++; x6_2++; x5+=2; x5_2+=2; x4+=3; x4_2+=3; x3+=3; x3_2+=3; x2+=4; x2_2+=4; x1+=5; x1_2+=5; // stop the obstacles animation for (int i=0; i<firelist.size(); i++){ firelist.get(i).xcoord +=5; } for (int i=0; i<birdlist.size(); i++){ birdlist.get(i).xcoord +=10; } // enable the dying animation avatar.state=3; // display the replay button imageMode(CENTER); image(startmenu,width/2, height/2-20); text("REPLAY",width/2,height/2+7-20); imageMode(CORNER); } } // display the lobby menu else if (start==false){ // mute the music back.amp(0); menu(); image(main,0,0); imageMode(CENTER); textAlign(CENTER); textSize(30); // display the ui image(startmenu,width/2, height/2-20); text("PLAY",width/2,height/2+7-20); image(helpmenu,width/2, height/2+100-20); text("HELP",width/2,height/2+100+7-20); image(title,width/2, 100); noFill(); rect(width/2-75,height/2-55,150,70); rect(width/2-90,height/2+40,180,80); imageMode(CORNER); } }
void draw(){
   
  // if instructions icon clicked
  if (help){
    // mute the music
    back.amp(0);
    image(main,0,0);
    imageMode(CENTER);
    image(instructmenu,width/2,height/2);
    image(backmenu,width/2, height/2-200);
    imageMode(CORNER);
    textSize(20);
    text("↑ : Jump",width/2,height/2-60);
    text("↓ : Crouch",width/2,height/2-20);
    text("Try to avoid all obstacles",width/2,height/2+20);
    text("(Fire, birds)",width/2,height/2+60);
    noFill();
    rect(width/2-30,height/2-230,60,60);  
  }
  
  else if (start){
    // unmute the music if alive
    if (dead==false) {back.amp(1);}
    // mute the music if dead
    else {back.amp(0);}
    display(); // display the background images
    update(); // parallax effect and infinite scrolling
    rect(100,425,50,70);
    avatar.show(); // display the avatar
    addObstacle(); // add an obstacle
    imageMode(CENTER);
    // Display the score
    image(scoremenu, width/2, 50); 
    imageMode(CORNER);
    textSize(20);
    textAlign(CENTER);
    text("score:  " + round(score),width/2,55);
    
    // Display the obstacles
    for (int i=0; i<firelist.size(); i++){
      firelist.get(i).show();
      firelist.get(i).move();
      
      // check if avatar touches an obstacle
      if (firelist.get(i).checkfail(avatar.ycoord)){
        dead=true;
      }
      
      // remove the obstacles that are not displayed
      if (firelist.get(i).xcoord <-70){
        firelist.remove(i);
      }
    }
    
    // Display the obstacles
    for (int i=0; i<birdlist.size(); i++){
      birdlist.get(i).show();
      birdlist.get(i).move();
      
      // check if avatar touches an obstacle
      if (birdlist.get(i).checkfail(avatar.ycoord)){
        dead=true;
      }
      
      // remove the obstacles that are not displayed
      if (birdlist.get(i).xcoord <-70){
        birdlist.remove(i);
      }
    }
    
    // If replay button is clicked, reset the game
    if (reset==true){
     back.amp(1); // unmute the music
     dead=false;
     start=true;
     reset=false;
     score=0; // reset the score
     // reset the obstacles list
     firelist = new ArrayList<Fire>();
     birdlist = new ArrayList<Bird>();
    }
   
    if (dead==true){
      // stop the parallax
      x6++; x6_2++;
      x5+=2; x5_2+=2;
      x4+=3; x4_2+=3;
      x3+=3; x3_2+=3;
      x2+=4; x2_2+=4;
      x1+=5; x1_2+=5;
      
      // stop the obstacles animation
      for (int i=0; i<firelist.size(); i++){
        firelist.get(i).xcoord +=5;
      }
      for (int i=0; i<birdlist.size(); i++){
        birdlist.get(i).xcoord +=10;
      }
      // enable the dying animation
      avatar.state=3;
      // display the replay button
      imageMode(CENTER);
      image(startmenu,width/2, height/2-20);
      text("REPLAY",width/2,height/2+7-20);
      imageMode(CORNER);
   }
 }
 
 // display the lobby menu
 else if (start==false){
   // mute the music
   back.amp(0);
   menu();
   image(main,0,0);
   imageMode(CENTER);
   textAlign(CENTER);
   textSize(30);
   // display the ui
   image(startmenu,width/2, height/2-20);
   text("PLAY",width/2,height/2+7-20);
   image(helpmenu,width/2, height/2+100-20);
   text("HELP",width/2,height/2+100+7-20);
   image(title,width/2, 100);
   noFill();
   rect(width/2-75,height/2-55,150,70);
   rect(width/2-90,height/2+40,180,80);
   imageMode(CORNER);
 }
 
}
Shapes:

I have used 4 blinking rectangles to add some aesthetics to the title.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
noStroke();
if (frameCount%15==0){
noFill();}
else{ fill(0);}
rect(width/2+220, 85,10,30,PI);
rect(width/2+240, 90,10,20,PI);
rect(width/2-225, 85,10,30,PI);
rect(width/2-245, 90,10,20,PI);
fill(255);
noStroke(); if (frameCount%15==0){ noFill();} else{ fill(0);} rect(width/2+220, 85,10,30,PI); rect(width/2+240, 90,10,20,PI); rect(width/2-225, 85,10,30,PI); rect(width/2-245, 90,10,20,PI); fill(255);
noStroke();
if (frameCount%15==0){
  noFill();}
 else{ fill(0);}
rect(width/2+220, 85,10,30,PI);
rect(width/2+240, 90,10,20,PI);
rect(width/2-225, 85,10,30,PI);
rect(width/2-245, 90,10,20,PI);
fill(255);
User Input:

To detect when the user clicks on a key, I used both keyPressed() and keyReleased() functions for keyboard, and mouseClicked.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
void mouseClicked(){
// if player clicks on start
if ((mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
start=true;
menu.play();
}
// if player clicks on help
if ((start==false) && (mouseX>width/2-90) && (mouseX<width/2+90) && (mouseY>height/2+40) && (mouseY<height/2+120)){
help=true;
menu.play();
}
// if player clicks on back
else if ((help==true) && (mouseX>width/2-30) && (mouseX<width/2+30) && (mouseY>height/2-230) && (mouseY<height-170)){
help=false;
menu.play();
}
// if player clicks on replay
else if ((dead==true) && (mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
reset=true;
menu.play();
}
}
void keyPressed(){
// Jump
if (keyCode==UP && dead==false){
avatar.jump();
}
// Crouch
if (keyCode==DOWN && dead==false){
avatar.crouching=true;
avatar.crouch();
}
}
void keyReleased(){
// stop crouching
if (keyCode==DOWN && dead==false){
avatar.crouching=false;
}
}
void mouseClicked(){ // if player clicks on start if ((mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){ start=true; menu.play(); } // if player clicks on help if ((start==false) && (mouseX>width/2-90) && (mouseX<width/2+90) && (mouseY>height/2+40) && (mouseY<height/2+120)){ help=true; menu.play(); } // if player clicks on back else if ((help==true) && (mouseX>width/2-30) && (mouseX<width/2+30) && (mouseY>height/2-230) && (mouseY<height-170)){ help=false; menu.play(); } // if player clicks on replay else if ((dead==true) && (mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){ reset=true; menu.play(); } } void keyPressed(){ // Jump if (keyCode==UP && dead==false){ avatar.jump(); } // Crouch if (keyCode==DOWN && dead==false){ avatar.crouching=true; avatar.crouch(); } } void keyReleased(){ // stop crouching if (keyCode==DOWN && dead==false){ avatar.crouching=false; } }
void mouseClicked(){
// if player clicks on start
if ((mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
start=true;
menu.play();
}
// if player clicks on help
if ((start==false) && (mouseX>width/2-90) && (mouseX<width/2+90) && (mouseY>height/2+40) && (mouseY<height/2+120)){
help=true;
menu.play();
}
// if player clicks on back
else if ((help==true) && (mouseX>width/2-30) && (mouseX<width/2+30) && (mouseY>height/2-230) && (mouseY<height-170)){
help=false;
menu.play();
}
// if player clicks on replay
else if ((dead==true) && (mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
reset=true;
menu.play();
}
}
void keyPressed(){
  // Jump
  if (keyCode==UP && dead==false){
    avatar.jump();
  }
  // Crouch
  if (keyCode==DOWN && dead==false){
    avatar.crouching=true;
    avatar.crouch();
  }
}

void keyReleased(){
  // stop crouching
  if (keyCode==DOWN && dead==false){
    avatar.crouching=false;
  }
}
SFX:

Concerning the sound effects, I have only used two main ones (the background music, and the click sound effect). Instead of stopping the music, I mute it, then unmute it when the game starts.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
SoundFile menu; // Click sound effect
SoundFile back; // background music
// Load the sound effects
menu = new SoundFile(this, "assets/menu.wav");
back = new SoundFile(this, "assets/back.mp3");
// Play the background music
back.play();
// Loop the background music
back.loop();
// unmute the music if alive
if (dead==false) {back.amp(1);}
// mute the music if dead
else {back.amp(0);}
SoundFile menu; // Click sound effect SoundFile back; // background music // Load the sound effects menu = new SoundFile(this, "assets/menu.wav"); back = new SoundFile(this, "assets/back.mp3"); // Play the background music back.play(); // Loop the background music back.loop(); // unmute the music if alive if (dead==false) {back.amp(1);} // mute the music if dead else {back.amp(0);}
SoundFile menu; // Click sound effect
SoundFile back; // background music 

// Load the sound effects
menu = new SoundFile(this, "assets/menu.wav");
back = new SoundFile(this, "assets/back.mp3");
// Play the background music
back.play();
// Loop the background music
back.loop();

// unmute the music if alive
if (dead==false) {back.amp(1);}
// mute the music if dead
else {back.amp(0);}
Score:

The score gets incremented when the avatar is moving by O.O5 per frame and is displayed on the top-center of the display window. It gets reset when the game restarts.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// increment the score
if (!dead) {score+=0.05;}
// increment the score if (!dead) {score+=0.05;}
// increment the score
if (!dead) {score+=0.05;}
End of the game:

When the avatar touches an obstacle, the dying animation is enabled and freezes at the last sprite, and all the other animations/motions are stopped. The score is displayed on top, and the replay button appears.

 

FULL CODE:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import processing.sound.*;
PImage bg1, bg2, bg3, bg4, bg5, bg6, bg7, platform, main, startmenu, helpmenu, title, instructmenu, scoremenu; // Background images
PImage backmenu;
int x1=0, x1_2=960, x2=0, x2_2=960, x3=0, x3_2=960; // X-coordinates of the images
int x4=0, x4_2=960, x5=0, x5_2=960, x6=0, x6_2=960; // X-coordinates of the images
PImage[][] sprites = new PImage[10][4]; // Store the sprites for the avatar
PImage [] firesprites = new PImage[64]; // Store the sprites for the fire
PImage [] birdsprites = new PImage[9]; // Store the sprites for the birds
ArrayList<Fire> firelist = new ArrayList<Fire>(); // Store all the fire objects
ArrayList<Bird> birdlist = new ArrayList<Bird>(); // store all the bird objects
boolean start=false;
boolean dead= false;
boolean help= false;
boolean reset= false;
float score=0; // Keep track of the score
SoundFile menu; // Click sound effect
SoundFile back; // background music
// Create a new avatar
Avatar avatar = new Avatar(0,425);
// Upload all the sprites
void loadsprites(){
// Running
for (int i=0; i<sprites.length;i++){
sprites[i][0]=loadImage("assets/run/run"+i+".png");
sprites[i][0].resize(53,74);
}
// Jumping
for (int i=0; i<sprites.length;i++){
sprites[i][1]=loadImage("assets/jump/jump"+i+".png");
sprites[i][1].resize(53,74);
}
// Sliding
for (int i=0; i<sprites.length;i++){
sprites[i][2]=loadImage("assets/slide/slide"+i+".png");
sprites[i][2].resize(53,57);
}
// Dying
for (int i=0; i<sprites.length;i++){
sprites[i][3]=loadImage("assets/dying/Dead__00"+i+".png");
sprites[i][3].resize(73,77);
}
// Fire
for (int i=0; i<firesprites.length;i++){
firesprites[i]=loadImage("assets/fire/tile0"+i+".png");
firesprites[i].resize(60,60);
}
// Bird
for (int i=0; i<birdsprites.length;i++){
birdsprites[i]=loadImage("assets/bird/tile00"+i+".png");
birdsprites[i].resize(80,80);
}
}
// Load the background images
void load(){
bg7 = loadImage("assets/bg.png");
// Resize the images
bg7.resize(960,540);
bg6 = loadImage("assets/bg6.png");
bg6.resize(960,540);
bg5 = loadImage("assets/bg5.png");
bg5.resize(960,540);
bg4 = loadImage("assets/bg2.png");
bg4.resize(960,540);
bg3 = loadImage("assets/bg4.png");
bg3.resize(960,540);
bg2 = loadImage("assets/bg1.png");
bg2.resize(960,540);
bg1 = loadImage("assets/bg3.png");
bg1.resize(960,540);
platform = loadImage("assets/platform.png");
platform.resize(960,610);
}
// menu loading
void menu(){
// load ui images
startmenu = loadImage("assets/b_3.png");
helpmenu = loadImage("assets/b_4.png");
// resize the images
startmenu.resize(150,70);
helpmenu.resize(180,80);
title = loadImage("assets/title.png");
instructmenu = loadImage("assets/b_5.png");
scoremenu = loadImage("assets/bar_1.png");
scoremenu.resize(250,40);
instructmenu.resize(350,300);
backmenu = loadImage("assets/b_6.png");
backmenu.resize(60,60);
}
// Display the background
void display(){
image(bg7,0,0);
image(bg6,x6,0);
image(bg6,x6_2,0);
image(bg5,x5,0);
image(bg5,x5_2,0);
image(bg4,x4,0);
image(bg4,x4_2,0);
image(bg3,x3,0);
image(bg3,x3_2,0);
image(bg2,x2,0);
image(bg2,x2_2,0);
image(bg1,x1,0);
image(bg1,x1_2,0);
// Add a tint to match the background
tint(#7cdfd2);
image(platform,x1,0);
image(platform,x1_2,0);
noTint();
}
// Parallax effect
void update(){
x6--; x6_2--;
x5-=2; x5_2-=2;
x4-=3; x4_2-=3;
x3-=3; x3_2-=3;
x2-=4; x2_2-=4;
x1-=5; x1_2-=5;
// Infinite scrolling
if (x6<=-width){x6=width;} if (x6_2<=-width){x6_2=width;}
if (x5<=-width){x5=width;} if (x5_2<=-width){x5_2=width;}
if (x4<=-width){x4=width;} if (x4_2<=-width){x4_2=width;}
if (x3<=-width){x3=width;} if (x3_2<=-width){x3_2=width;}
if (x2<=-width){x2=width;} if (x2_2<=-width){x2_2=width;}
if (x1<=-width){x1=width;} if (x1_2<=-width){x1_2=width;}
}
// add a new obstacle
void addObstacle(){
if (frameCount % 60 == 0 && random(1)<0.5){
// choose randomly if its fire or a bird
if (random(2)<1){
// add it to the list
firelist.add(new Fire());
}
else {
birdlist.add(new Bird());
}
}
}
void setup(){
size(960,540);
load(); // load the background images
loadsprites(); // load the sprites
main = loadImage("assets/main.png");
main.resize(960,540);
// Load the sound effects
menu = new SoundFile(this, "assets/menu.wav");
back = new SoundFile(this, "assets/back.mp3");
// Play the background music
back.play();
// Loop the background music
back.loop();
}
void draw(){
// if instructions icon clicked
if (help){
// mute the music
back.amp(0);
image(main,0,0);
imageMode(CENTER);
image(instructmenu,width/2,height/2);
image(backmenu,width/2, height/2-200);
imageMode(CORNER);
textSize(20);
text("↑ : Jump",width/2,height/2-60);
text("↓ : Crouch",width/2,height/2-20);
text("Try to avoid all obstacles",width/2,height/2+20);
text("(Fire, birds)",width/2,height/2+60);
noFill();
//rect(width/2-30,height/2-230,60,60);
}
else if (start){
// unmute the music if alive
if (dead==false) {back.amp(1);}
// mute the music if dead
else {back.amp(0);}
display(); // display the background images
update(); // parallax effect and infinite scrolling
//rect(100,425,50,70);
avatar.show(); // display the avatar
addObstacle(); // add an obstacle
imageMode(CENTER);
// Display the score
image(scoremenu, width/2, 50);
imageMode(CORNER);
textSize(20);
textAlign(CENTER);
text("score: " + round(score),width/2,55);
// Display the obstacles
for (int i=0; i<firelist.size(); i++){
firelist.get(i).show();
firelist.get(i).move();
// check if avatar touches an obstacle
if (firelist.get(i).checkfail(avatar.ycoord)){
dead=true;
}
// remove the obstacles that are not displayed
if (firelist.get(i).xcoord <-70){
firelist.remove(i);
}
}
// Display the obstacles
for (int i=0; i<birdlist.size(); i++){
birdlist.get(i).show();
birdlist.get(i).move();
// check if avatar touches an obstacle
if (birdlist.get(i).checkfail(avatar.ycoord)){
dead=true;
}
// remove the obstacles that are not displayed
if (birdlist.get(i).xcoord <-70){
birdlist.remove(i);
}
}
// If replay button is clicked, reset the game
if (reset==true){
back.amp(1); // unmute the music
dead=false;
start=true;
reset=false;
score=0; // reset the score
// reset the obstacles list
firelist = new ArrayList<Fire>();
birdlist = new ArrayList<Bird>();
}
if (dead==true){
// stop the parallax
x6++; x6_2++;
x5+=2; x5_2+=2;
x4+=3; x4_2+=3;
x3+=3; x3_2+=3;
x2+=4; x2_2+=4;
x1+=5; x1_2+=5;
// stop the obstacles animation
for (int i=0; i<firelist.size(); i++){
firelist.get(i).xcoord +=5;
}
for (int i=0; i<birdlist.size(); i++){
birdlist.get(i).xcoord +=10;
}
// enable the dying animation
avatar.state=3;
// display the replay button
imageMode(CENTER);
image(startmenu,width/2, height/2-20);
text("REPLAY",width/2,height/2+7-20);
imageMode(CORNER);
}
}
// display the lobby menu
else if (start==false){
// mute the music
back.amp(0);
menu();
image(main,0,0);
imageMode(CENTER);
textAlign(CENTER);
textSize(30);
// display the ui
image(startmenu,width/2, height/2-20);
text("PLAY",width/2,height/2+7-20);
image(helpmenu,width/2, height/2+100-20);
text("HELP",width/2,height/2+100+7-20);
image(title,width/2, 100);
noFill();
//rect(width/2-75,height/2-55,150,70);
//rect(width/2-90,height/2+40,180,80);
imageMode(CORNER);
noStroke();
if (frameCount%15==0){
noFill();}
else{ fill(0);}
rect(width/2+220, 85,10,30,PI);
rect(width/2+240, 90,10,20,PI);
rect(width/2-225, 85,10,30,PI);
rect(width/2-245, 90,10,20,PI);
fill(255);
}
}
void mouseClicked(){
// if player clicks on start
if ((mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
start=true;
menu.play();
}
// if player clicks on help
if ((start==false) && (mouseX>width/2-90) && (mouseX<width/2+90) && (mouseY>height/2+40) && (mouseY<height/2+120)){
help=true;
menu.play();
}
// if player clicks on back
else if ((help==true) && (mouseX>width/2-30) && (mouseX<width/2+30) && (mouseY>height/2-230) && (mouseY<height-170)){
help=false;
menu.play();
}
// if player clicks on replay
else if ((dead==true) && (mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
reset=true;
menu.play();
}
}
void keyPressed(){
// Jump
if (keyCode==UP && dead==false){
avatar.jump();
}
// Crouch
if (keyCode==DOWN && dead==false){
avatar.crouching=true;
avatar.crouch();
}
}
void keyReleased(){
// stop crouching
if (keyCode==DOWN && dead==false){
avatar.crouching=false;
}
}
class Bird{
//bird's x-coordinate
float xcoord;
Bird(){
// generate the bird outside the screen
xcoord = 40 + 960;
}
// display the bird
void show(){
// stop the animation
if (dead){image(birdsprites[6],xcoord,380);}
else{
// play the animation
image(birdsprites[frameCount/2%birdsprites.length],xcoord,380);}
}
// move the bird
void move(){
xcoord -= 10;
noFill();
//rect(xcoord+25, 400, 48,30);
}
boolean checkfail(float ycoord){
// if crouching, avatar is safe
if (avatar.state==2){
return false;
}
// check if avatar touches the obstacle
return xcoord+25>=100 && xcoord+25<=150 && ycoord>=400 && ycoord<=400+30 || xcoord+40+25>=100 && xcoord+40+25<=150 && ycoord+70>=400 && ycoord<=400+30;
}
}
class Fire{
//fire's x-coordinate
float xcoord;
Fire(){
// generate the fire outside the screen
xcoord = 40 + 960;
}
// display the fire
void show(){
// stop the animation
if (dead){image(firesprites[10],xcoord,435);}
else{
// play the animation
image(firesprites[frameCount/2%firesprites.length],xcoord,435);}
}
// move the fire
void move(){
xcoord -= 5;
}
boolean checkfail(float ycoord){
// check if avatar touches the obstacle
return xcoord>=100 && xcoord<=150 && ycoord+70>=540-60-30 || xcoord+40>=100 && xcoord+40<=150 && ycoord+70>=540-60-30;
}
}
class Avatar{
float xcoord=100; // xcoordinate of avatar
float ycoord; // ycoordinate of avatar
float gravity=1; // gravity of avatar
float speed= 0; // speed of avatar
int state=0; // state of avatar (jumping, crouchin, dying)
boolean crouching =false; // flag if crouching
// used for dying animation
int k=0;
int cnt;
// constructor
Avatar(int state, float ycoord){
this.state= state;
this.ycoord= ycoord;
}
void show(){
// play the dying animation
if (state==3 && cnt<9){
// freeze at last sprite
ycoord=427;
image(sprites[k*frameCount/2%sprites.length][state],xcoord,ycoord);
k=1;
cnt++;
}
// display animation
else if (state==1 || state==2 || state==0){
image(sprites[frameCount/2%sprites.length][state],xcoord,ycoord);
}
else {
// freeze at last sprite
ycoord=427;
image(sprites[9][state],xcoord,ycoord);
}
move();
}
// move the player
void move(){
// increment the score
if (!dead) {score+=0.05;}
ycoord -= speed;
// gravity if jumps
if (ycoord<425){
speed -= gravity;
}
// gravity if crouches
else if (ycoord>425){
ycoord += speed;
speed += gravity;
}
// remain same when running
else{
state=0;
speed=0;
ycoord=425;
}
}
// jump
void jump(){
if (ycoord==425 && crouching==false){
state=1;
gravity=1;
speed= 16;
}
}
// crouch
void crouch(){
if (crouching==true && ycoord==425){
state=2;
ycoord=442;
gravity=1;
speed= -20;
}
}
}
import processing.sound.*; PImage bg1, bg2, bg3, bg4, bg5, bg6, bg7, platform, main, startmenu, helpmenu, title, instructmenu, scoremenu; // Background images PImage backmenu; int x1=0, x1_2=960, x2=0, x2_2=960, x3=0, x3_2=960; // X-coordinates of the images int x4=0, x4_2=960, x5=0, x5_2=960, x6=0, x6_2=960; // X-coordinates of the images PImage[][] sprites = new PImage[10][4]; // Store the sprites for the avatar PImage [] firesprites = new PImage[64]; // Store the sprites for the fire PImage [] birdsprites = new PImage[9]; // Store the sprites for the birds ArrayList<Fire> firelist = new ArrayList<Fire>(); // Store all the fire objects ArrayList<Bird> birdlist = new ArrayList<Bird>(); // store all the bird objects boolean start=false; boolean dead= false; boolean help= false; boolean reset= false; float score=0; // Keep track of the score SoundFile menu; // Click sound effect SoundFile back; // background music // Create a new avatar Avatar avatar = new Avatar(0,425); // Upload all the sprites void loadsprites(){ // Running for (int i=0; i<sprites.length;i++){ sprites[i][0]=loadImage("assets/run/run"+i+".png"); sprites[i][0].resize(53,74); } // Jumping for (int i=0; i<sprites.length;i++){ sprites[i][1]=loadImage("assets/jump/jump"+i+".png"); sprites[i][1].resize(53,74); } // Sliding for (int i=0; i<sprites.length;i++){ sprites[i][2]=loadImage("assets/slide/slide"+i+".png"); sprites[i][2].resize(53,57); } // Dying for (int i=0; i<sprites.length;i++){ sprites[i][3]=loadImage("assets/dying/Dead__00"+i+".png"); sprites[i][3].resize(73,77); } // Fire for (int i=0; i<firesprites.length;i++){ firesprites[i]=loadImage("assets/fire/tile0"+i+".png"); firesprites[i].resize(60,60); } // Bird for (int i=0; i<birdsprites.length;i++){ birdsprites[i]=loadImage("assets/bird/tile00"+i+".png"); birdsprites[i].resize(80,80); } } // Load the background images void load(){ bg7 = loadImage("assets/bg.png"); // Resize the images bg7.resize(960,540); bg6 = loadImage("assets/bg6.png"); bg6.resize(960,540); bg5 = loadImage("assets/bg5.png"); bg5.resize(960,540); bg4 = loadImage("assets/bg2.png"); bg4.resize(960,540); bg3 = loadImage("assets/bg4.png"); bg3.resize(960,540); bg2 = loadImage("assets/bg1.png"); bg2.resize(960,540); bg1 = loadImage("assets/bg3.png"); bg1.resize(960,540); platform = loadImage("assets/platform.png"); platform.resize(960,610); } // menu loading void menu(){ // load ui images startmenu = loadImage("assets/b_3.png"); helpmenu = loadImage("assets/b_4.png"); // resize the images startmenu.resize(150,70); helpmenu.resize(180,80); title = loadImage("assets/title.png"); instructmenu = loadImage("assets/b_5.png"); scoremenu = loadImage("assets/bar_1.png"); scoremenu.resize(250,40); instructmenu.resize(350,300); backmenu = loadImage("assets/b_6.png"); backmenu.resize(60,60); } // Display the background void display(){ image(bg7,0,0); image(bg6,x6,0); image(bg6,x6_2,0); image(bg5,x5,0); image(bg5,x5_2,0); image(bg4,x4,0); image(bg4,x4_2,0); image(bg3,x3,0); image(bg3,x3_2,0); image(bg2,x2,0); image(bg2,x2_2,0); image(bg1,x1,0); image(bg1,x1_2,0); // Add a tint to match the background tint(#7cdfd2); image(platform,x1,0); image(platform,x1_2,0); noTint(); } // Parallax effect void update(){ x6--; x6_2--; x5-=2; x5_2-=2; x4-=3; x4_2-=3; x3-=3; x3_2-=3; x2-=4; x2_2-=4; x1-=5; x1_2-=5; // Infinite scrolling if (x6<=-width){x6=width;} if (x6_2<=-width){x6_2=width;} if (x5<=-width){x5=width;} if (x5_2<=-width){x5_2=width;} if (x4<=-width){x4=width;} if (x4_2<=-width){x4_2=width;} if (x3<=-width){x3=width;} if (x3_2<=-width){x3_2=width;} if (x2<=-width){x2=width;} if (x2_2<=-width){x2_2=width;} if (x1<=-width){x1=width;} if (x1_2<=-width){x1_2=width;} } // add a new obstacle void addObstacle(){ if (frameCount % 60 == 0 && random(1)<0.5){ // choose randomly if its fire or a bird if (random(2)<1){ // add it to the list firelist.add(new Fire()); } else { birdlist.add(new Bird()); } } } void setup(){ size(960,540); load(); // load the background images loadsprites(); // load the sprites main = loadImage("assets/main.png"); main.resize(960,540); // Load the sound effects menu = new SoundFile(this, "assets/menu.wav"); back = new SoundFile(this, "assets/back.mp3"); // Play the background music back.play(); // Loop the background music back.loop(); } void draw(){ // if instructions icon clicked if (help){ // mute the music back.amp(0); image(main,0,0); imageMode(CENTER); image(instructmenu,width/2,height/2); image(backmenu,width/2, height/2-200); imageMode(CORNER); textSize(20); text("↑ : Jump",width/2,height/2-60); text("↓ : Crouch",width/2,height/2-20); text("Try to avoid all obstacles",width/2,height/2+20); text("(Fire, birds)",width/2,height/2+60); noFill(); //rect(width/2-30,height/2-230,60,60); } else if (start){ // unmute the music if alive if (dead==false) {back.amp(1);} // mute the music if dead else {back.amp(0);} display(); // display the background images update(); // parallax effect and infinite scrolling //rect(100,425,50,70); avatar.show(); // display the avatar addObstacle(); // add an obstacle imageMode(CENTER); // Display the score image(scoremenu, width/2, 50); imageMode(CORNER); textSize(20); textAlign(CENTER); text("score: " + round(score),width/2,55); // Display the obstacles for (int i=0; i<firelist.size(); i++){ firelist.get(i).show(); firelist.get(i).move(); // check if avatar touches an obstacle if (firelist.get(i).checkfail(avatar.ycoord)){ dead=true; } // remove the obstacles that are not displayed if (firelist.get(i).xcoord <-70){ firelist.remove(i); } } // Display the obstacles for (int i=0; i<birdlist.size(); i++){ birdlist.get(i).show(); birdlist.get(i).move(); // check if avatar touches an obstacle if (birdlist.get(i).checkfail(avatar.ycoord)){ dead=true; } // remove the obstacles that are not displayed if (birdlist.get(i).xcoord <-70){ birdlist.remove(i); } } // If replay button is clicked, reset the game if (reset==true){ back.amp(1); // unmute the music dead=false; start=true; reset=false; score=0; // reset the score // reset the obstacles list firelist = new ArrayList<Fire>(); birdlist = new ArrayList<Bird>(); } if (dead==true){ // stop the parallax x6++; x6_2++; x5+=2; x5_2+=2; x4+=3; x4_2+=3; x3+=3; x3_2+=3; x2+=4; x2_2+=4; x1+=5; x1_2+=5; // stop the obstacles animation for (int i=0; i<firelist.size(); i++){ firelist.get(i).xcoord +=5; } for (int i=0; i<birdlist.size(); i++){ birdlist.get(i).xcoord +=10; } // enable the dying animation avatar.state=3; // display the replay button imageMode(CENTER); image(startmenu,width/2, height/2-20); text("REPLAY",width/2,height/2+7-20); imageMode(CORNER); } } // display the lobby menu else if (start==false){ // mute the music back.amp(0); menu(); image(main,0,0); imageMode(CENTER); textAlign(CENTER); textSize(30); // display the ui image(startmenu,width/2, height/2-20); text("PLAY",width/2,height/2+7-20); image(helpmenu,width/2, height/2+100-20); text("HELP",width/2,height/2+100+7-20); image(title,width/2, 100); noFill(); //rect(width/2-75,height/2-55,150,70); //rect(width/2-90,height/2+40,180,80); imageMode(CORNER); noStroke(); if (frameCount%15==0){ noFill();} else{ fill(0);} rect(width/2+220, 85,10,30,PI); rect(width/2+240, 90,10,20,PI); rect(width/2-225, 85,10,30,PI); rect(width/2-245, 90,10,20,PI); fill(255); } } void mouseClicked(){ // if player clicks on start if ((mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){ start=true; menu.play(); } // if player clicks on help if ((start==false) && (mouseX>width/2-90) && (mouseX<width/2+90) && (mouseY>height/2+40) && (mouseY<height/2+120)){ help=true; menu.play(); } // if player clicks on back else if ((help==true) && (mouseX>width/2-30) && (mouseX<width/2+30) && (mouseY>height/2-230) && (mouseY<height-170)){ help=false; menu.play(); } // if player clicks on replay else if ((dead==true) && (mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){ reset=true; menu.play(); } } void keyPressed(){ // Jump if (keyCode==UP && dead==false){ avatar.jump(); } // Crouch if (keyCode==DOWN && dead==false){ avatar.crouching=true; avatar.crouch(); } } void keyReleased(){ // stop crouching if (keyCode==DOWN && dead==false){ avatar.crouching=false; } } class Bird{ //bird's x-coordinate float xcoord; Bird(){ // generate the bird outside the screen xcoord = 40 + 960; } // display the bird void show(){ // stop the animation if (dead){image(birdsprites[6],xcoord,380);} else{ // play the animation image(birdsprites[frameCount/2%birdsprites.length],xcoord,380);} } // move the bird void move(){ xcoord -= 10; noFill(); //rect(xcoord+25, 400, 48,30); } boolean checkfail(float ycoord){ // if crouching, avatar is safe if (avatar.state==2){ return false; } // check if avatar touches the obstacle return xcoord+25>=100 && xcoord+25<=150 && ycoord>=400 && ycoord<=400+30 || xcoord+40+25>=100 && xcoord+40+25<=150 && ycoord+70>=400 && ycoord<=400+30; } } class Fire{ //fire's x-coordinate float xcoord; Fire(){ // generate the fire outside the screen xcoord = 40 + 960; } // display the fire void show(){ // stop the animation if (dead){image(firesprites[10],xcoord,435);} else{ // play the animation image(firesprites[frameCount/2%firesprites.length],xcoord,435);} } // move the fire void move(){ xcoord -= 5; } boolean checkfail(float ycoord){ // check if avatar touches the obstacle return xcoord>=100 && xcoord<=150 && ycoord+70>=540-60-30 || xcoord+40>=100 && xcoord+40<=150 && ycoord+70>=540-60-30; } } class Avatar{ float xcoord=100; // xcoordinate of avatar float ycoord; // ycoordinate of avatar float gravity=1; // gravity of avatar float speed= 0; // speed of avatar int state=0; // state of avatar (jumping, crouchin, dying) boolean crouching =false; // flag if crouching // used for dying animation int k=0; int cnt; // constructor Avatar(int state, float ycoord){ this.state= state; this.ycoord= ycoord; } void show(){ // play the dying animation if (state==3 && cnt<9){ // freeze at last sprite ycoord=427; image(sprites[k*frameCount/2%sprites.length][state],xcoord,ycoord); k=1; cnt++; } // display animation else if (state==1 || state==2 || state==0){ image(sprites[frameCount/2%sprites.length][state],xcoord,ycoord); } else { // freeze at last sprite ycoord=427; image(sprites[9][state],xcoord,ycoord); } move(); } // move the player void move(){ // increment the score if (!dead) {score+=0.05;} ycoord -= speed; // gravity if jumps if (ycoord<425){ speed -= gravity; } // gravity if crouches else if (ycoord>425){ ycoord += speed; speed += gravity; } // remain same when running else{ state=0; speed=0; ycoord=425; } } // jump void jump(){ if (ycoord==425 && crouching==false){ state=1; gravity=1; speed= 16; } } // crouch void crouch(){ if (crouching==true && ycoord==425){ state=2; ycoord=442; gravity=1; speed= -20; } } }
import processing.sound.*;
PImage bg1, bg2, bg3, bg4, bg5, bg6, bg7, platform, main, startmenu, helpmenu, title, instructmenu, scoremenu; // Background images
PImage backmenu;
int x1=0, x1_2=960, x2=0, x2_2=960, x3=0, x3_2=960; // X-coordinates of the images
int x4=0, x4_2=960, x5=0, x5_2=960, x6=0, x6_2=960; // X-coordinates of the images
PImage[][] sprites = new PImage[10][4]; // Store the sprites for the avatar
PImage [] firesprites = new PImage[64]; // Store the sprites for the fire
PImage [] birdsprites = new PImage[9]; // Store the sprites for the birds
ArrayList<Fire> firelist = new ArrayList<Fire>(); // Store all the fire objects
ArrayList<Bird> birdlist = new ArrayList<Bird>(); // store all the bird objects
boolean start=false;
boolean dead= false; 
boolean help= false;
boolean reset= false;
float score=0; // Keep track of the score
SoundFile menu; // Click sound effect
SoundFile back; // background music 

// Create a new avatar
Avatar avatar = new Avatar(0,425);

// Upload all the sprites
void loadsprites(){
  // Running
  for (int i=0; i<sprites.length;i++){
    sprites[i][0]=loadImage("assets/run/run"+i+".png");
    sprites[i][0].resize(53,74);
  }
  // Jumping
  for (int i=0; i<sprites.length;i++){
    sprites[i][1]=loadImage("assets/jump/jump"+i+".png");
    sprites[i][1].resize(53,74);
  }
  // Sliding
  for (int i=0; i<sprites.length;i++){
    sprites[i][2]=loadImage("assets/slide/slide"+i+".png");
    sprites[i][2].resize(53,57);
  }
  // Dying
  for (int i=0; i<sprites.length;i++){
    sprites[i][3]=loadImage("assets/dying/Dead__00"+i+".png");
    sprites[i][3].resize(73,77);
  }
  // Fire
  for (int i=0; i<firesprites.length;i++){
    firesprites[i]=loadImage("assets/fire/tile0"+i+".png");
    firesprites[i].resize(60,60);
  }
  // Bird
  for (int i=0; i<birdsprites.length;i++){
    birdsprites[i]=loadImage("assets/bird/tile00"+i+".png");
    birdsprites[i].resize(80,80);
  }
}

// Load the background images
void load(){
  bg7 = loadImage("assets/bg.png");
  // Resize the images
  bg7.resize(960,540);
  bg6 = loadImage("assets/bg6.png");
  bg6.resize(960,540);
  bg5 = loadImage("assets/bg5.png");
  bg5.resize(960,540);
  bg4 = loadImage("assets/bg2.png");
  bg4.resize(960,540);
  bg3 = loadImage("assets/bg4.png");
  bg3.resize(960,540);
  bg2 = loadImage("assets/bg1.png");
  bg2.resize(960,540);
  bg1 = loadImage("assets/bg3.png");
  bg1.resize(960,540);
  platform = loadImage("assets/platform.png");
  platform.resize(960,610);
}

// menu loading
void menu(){
  // load ui images
  startmenu = loadImage("assets/b_3.png");
  helpmenu = loadImage("assets/b_4.png");
  // resize the images
  startmenu.resize(150,70);
  helpmenu.resize(180,80);
  title = loadImage("assets/title.png");
  instructmenu = loadImage("assets/b_5.png");
  scoremenu = loadImage("assets/bar_1.png");
  scoremenu.resize(250,40);
  instructmenu.resize(350,300);
  backmenu = loadImage("assets/b_6.png");
  backmenu.resize(60,60);
}

// Display the background
void display(){
  image(bg7,0,0);
  image(bg6,x6,0);
  image(bg6,x6_2,0);
  image(bg5,x5,0);
  image(bg5,x5_2,0);
  image(bg4,x4,0);
  image(bg4,x4_2,0);
  image(bg3,x3,0);
  image(bg3,x3_2,0);
  image(bg2,x2,0);
  image(bg2,x2_2,0);
  image(bg1,x1,0);
  image(bg1,x1_2,0);
  // Add a tint to match the background
  tint(#7cdfd2);
  image(platform,x1,0);
  image(platform,x1_2,0);
  noTint();
}

// Parallax effect
void update(){
  x6--; x6_2--;
  x5-=2; x5_2-=2;
  x4-=3; x4_2-=3;
  x3-=3; x3_2-=3;
  x2-=4; x2_2-=4;
  x1-=5; x1_2-=5;
  
  // Infinite scrolling
  if (x6<=-width){x6=width;} if (x6_2<=-width){x6_2=width;}
  if (x5<=-width){x5=width;} if (x5_2<=-width){x5_2=width;}
  if (x4<=-width){x4=width;} if (x4_2<=-width){x4_2=width;}
  if (x3<=-width){x3=width;} if (x3_2<=-width){x3_2=width;}
  if (x2<=-width){x2=width;} if (x2_2<=-width){x2_2=width;}
  if (x1<=-width){x1=width;} if (x1_2<=-width){x1_2=width;} 
}

// add a new obstacle
void addObstacle(){
  if (frameCount % 60 == 0 && random(1)<0.5){
    // choose randomly if its fire or a bird
    if (random(2)<1){
      // add it to the list
      firelist.add(new Fire());
    }
    else {
      birdlist.add(new Bird());
    }
  }
}

void setup(){
  size(960,540);
  load(); // load the background images
  loadsprites(); // load the sprites
  main = loadImage("assets/main.png");
  main.resize(960,540);
  // Load the sound effects
  menu = new SoundFile(this, "assets/menu.wav");
  back = new SoundFile(this, "assets/back.mp3");
  // Play the background music
  back.play();
  // Loop the background music
  back.loop();
}

void draw(){
   
  // if instructions icon clicked
  if (help){
    // mute the music
    back.amp(0);
    image(main,0,0);
    imageMode(CENTER);
    image(instructmenu,width/2,height/2);
    image(backmenu,width/2, height/2-200);
    imageMode(CORNER);
    textSize(20);
    text("↑ : Jump",width/2,height/2-60);
    text("↓ : Crouch",width/2,height/2-20);
    text("Try to avoid all obstacles",width/2,height/2+20);
    text("(Fire, birds)",width/2,height/2+60);
    noFill();
    //rect(width/2-30,height/2-230,60,60);  
  }
  
  else if (start){
    // unmute the music if alive
    if (dead==false) {back.amp(1);}
    // mute the music if dead
    else {back.amp(0);}
    display(); // display the background images
    update(); // parallax effect and infinite scrolling
    //rect(100,425,50,70);
    avatar.show(); // display the avatar
    addObstacle(); // add an obstacle
    imageMode(CENTER);
    // Display the score
    image(scoremenu, width/2, 50); 
    imageMode(CORNER);
    textSize(20);
    textAlign(CENTER);
    text("score:  " + round(score),width/2,55);
    
    // Display the obstacles
    for (int i=0; i<firelist.size(); i++){
      firelist.get(i).show();
      firelist.get(i).move();
      
      // check if avatar touches an obstacle
      if (firelist.get(i).checkfail(avatar.ycoord)){
        dead=true;
      }
      
      // remove the obstacles that are not displayed
      if (firelist.get(i).xcoord <-70){
        firelist.remove(i);
      }
    }
    
    // Display the obstacles
    for (int i=0; i<birdlist.size(); i++){
      birdlist.get(i).show();
      birdlist.get(i).move();
      
      // check if avatar touches an obstacle
      if (birdlist.get(i).checkfail(avatar.ycoord)){
        dead=true;
      }
      
      // remove the obstacles that are not displayed
      if (birdlist.get(i).xcoord <-70){
        birdlist.remove(i);
      }
    }
    
    // If replay button is clicked, reset the game
    if (reset==true){
     back.amp(1); // unmute the music
     dead=false;
     start=true;
     reset=false;
     score=0; // reset the score
     // reset the obstacles list
     firelist = new ArrayList<Fire>();
     birdlist = new ArrayList<Bird>();
    }
   
    if (dead==true){
      // stop the parallax
      x6++; x6_2++;
      x5+=2; x5_2+=2;
      x4+=3; x4_2+=3;
      x3+=3; x3_2+=3;
      x2+=4; x2_2+=4;
      x1+=5; x1_2+=5;
      
      // stop the obstacles animation
      for (int i=0; i<firelist.size(); i++){
        firelist.get(i).xcoord +=5;
      }
      for (int i=0; i<birdlist.size(); i++){
        birdlist.get(i).xcoord +=10;
      }
      // enable the dying animation
      avatar.state=3;
      // display the replay button
      imageMode(CENTER);
      image(startmenu,width/2, height/2-20);
      text("REPLAY",width/2,height/2+7-20);
      imageMode(CORNER);
   }
 }
 
 // display the lobby menu
 else if (start==false){
   // mute the music
   back.amp(0);
   menu();
   image(main,0,0);
   imageMode(CENTER);
   textAlign(CENTER);
   textSize(30);
   // display the ui
   image(startmenu,width/2, height/2-20);
   text("PLAY",width/2,height/2+7-20);
   image(helpmenu,width/2, height/2+100-20);
   text("HELP",width/2,height/2+100+7-20);
   image(title,width/2, 100);
   noFill();
   //rect(width/2-75,height/2-55,150,70);
   //rect(width/2-90,height/2+40,180,80);
   imageMode(CORNER);
   noStroke();
   if (frameCount%15==0){
     noFill();}
    else{ fill(0);}
   rect(width/2+220, 85,10,30,PI);
   rect(width/2+240, 90,10,20,PI);
   rect(width/2-225, 85,10,30,PI);
   rect(width/2-245, 90,10,20,PI);
   fill(255);
 }
 
}

void mouseClicked(){
  // if player clicks on start
  if ((mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
    start=true;
    menu.play();
  }
  // if player clicks on help
  if ((start==false) && (mouseX>width/2-90) && (mouseX<width/2+90) && (mouseY>height/2+40) && (mouseY<height/2+120)){
     help=true;
     menu.play();
  }
  // if player clicks on back
  else if ((help==true) && (mouseX>width/2-30) && (mouseX<width/2+30) && (mouseY>height/2-230) && (mouseY<height-170)){
     help=false;
     menu.play();
  }
  // if player clicks on replay
  else if ((dead==true) && (mouseX>width/2-75) && (mouseX<width/2+75) && (mouseY>height/2-55) && (mouseY<height/2+15)){
    reset=true;
    menu.play();
  }
}

void keyPressed(){
  // Jump
  if (keyCode==UP && dead==false){
    avatar.jump();
  }
  // Crouch
  if (keyCode==DOWN && dead==false){
    avatar.crouching=true;
    avatar.crouch();
  }
}

void keyReleased(){
  // stop crouching
  if (keyCode==DOWN && dead==false){
    avatar.crouching=false;
  }
}

class Bird{
  //bird's x-coordinate
  float xcoord;
  
  Bird(){
    // generate the bird outside the screen
    xcoord = 40 + 960;
  }
  
  // display the bird
  void show(){
    // stop the animation
    if (dead){image(birdsprites[6],xcoord,380);}
    else{
    // play the animation
    image(birdsprites[frameCount/2%birdsprites.length],xcoord,380);}
  }
  
  // move the bird
  void move(){
    xcoord -= 10;
    noFill();
    //rect(xcoord+25, 400, 48,30);
  }
  
  boolean checkfail(float ycoord){
    // if crouching, avatar is safe
    if (avatar.state==2){
      return false;
    }
    // check if avatar touches the obstacle
    return xcoord+25>=100 && xcoord+25<=150 && ycoord>=400 && ycoord<=400+30 || xcoord+40+25>=100 && xcoord+40+25<=150 && ycoord+70>=400 && ycoord<=400+30;
  }
}

class Fire{
  //fire's x-coordinate
  float xcoord;
  
  Fire(){
    // generate the fire outside the screen
    xcoord = 40 + 960;
  }
  
  // display the fire
  void show(){
    // stop the animation
    if (dead){image(firesprites[10],xcoord,435);}
    else{
    // play the animation
    image(firesprites[frameCount/2%firesprites.length],xcoord,435);}
  }

  // move the fire
  void move(){
    xcoord -= 5;
  }
  
  boolean checkfail(float ycoord){
    // check if avatar touches the obstacle
    return xcoord>=100 && xcoord<=150 && ycoord+70>=540-60-30 || xcoord+40>=100 && xcoord+40<=150 && ycoord+70>=540-60-30;
  }
}

class Avatar{
  float xcoord=100; // xcoordinate of avatar
  float ycoord; // ycoordinate of avatar
  float gravity=1; // gravity of avatar
  float speed= 0; // speed of avatar
  int state=0; // state of avatar (jumping, crouchin, dying)
  boolean crouching =false; // flag if crouching
   // used for dying animation
  int k=0; 
  int cnt;
  
  // constructor
  Avatar(int state, float ycoord){
    this.state= state;
    this.ycoord= ycoord;
  }
  
  void show(){
    // play the dying animation
    if (state==3 && cnt<9){
      // freeze at last sprite
      ycoord=427;
      image(sprites[k*frameCount/2%sprites.length][state],xcoord,ycoord);
      k=1;
      cnt++;
    }
    // display animation
    else if (state==1 || state==2 || state==0){
      image(sprites[frameCount/2%sprites.length][state],xcoord,ycoord);
    }
    else {
      // freeze at last sprite
      ycoord=427;
      image(sprites[9][state],xcoord,ycoord);
    }
    move();
  }
  
  // move the player
  void move(){
    // increment the score
    if (!dead) {score+=0.05;}
    ycoord -= speed;
    // gravity if jumps
    if (ycoord<425){
      speed -= gravity;
    }
    // gravity if crouches
    else if (ycoord>425){
      ycoord += speed;
      speed += gravity;
    }
    // remain same when running
    else{
      state=0;
      speed=0;
      ycoord=425;
    }
  }
  
  // jump
  void jump(){
    if (ycoord==425 && crouching==false){
      state=1;
      gravity=1;
      speed= 16;
    }
  }
  
  // crouch
  void crouch(){
    if (crouching==true && ycoord==425){
      state=2;
      ycoord=442;
      gravity=1;
      speed= -20;
    }
  }
}

 

 

Leave a Reply