I tried to make a Mario game?

Prologue

Since the start of the class, I have been really struggling with practicing Processing consistently – I would usually start my homeworks 1-2 days in advance and not practice much outside of class hours. But this week is very special: I started working on the weekly assignment 4 days in advance and have even taken some time to practice geomerative* and come up with the midterm idea! 🥳 So here I am, typing this post on a Saturday afternoon (edit: publishing on Sunday though). Enjoy!

Introduction

Fascinated by last week’s spritesheet example, I could not resist using this idea for my assignment. General idea was to make a small game with a moving character catching objects – diamonds in this case. After browsing the web, I have downloaded this pixelated Mario (?) image and cropped it in Photoshop as it wasn’t a PNG.

Mario Spritesheet

Process

Milestone 0: learning how to use the spritesheet. I have re-visited the class example and have carefully studied it to understand what is going on behind the code. And especially this – confusing at first – part:

// loops through each step and returns to image 0 after reaching image 3
    if(frameCount%speed==0){
      step = (step+1)%col;
    }

Milestone 1: placing the diamond and building a collision detection function. It took me a good day (coding on and off) to figure out what is going on wrong with my collision detection function. Oh, I have repeated the same mistake as I did when building the OOP assignment! 😅 Good thing now I finally know how to detect collision between two rectangular objects:

// Mario right corner > diamond left AND Mario left corner < diamond right
  if ((posX + person.width/16) > diamondX && posX < (diamondX + diamond.width/4) && (posY+person.height/16) > diamondY && posY < (diamondY + diamond.height/4)){

Milestone 2: collision detection debugging  – spritesheet’s width and height. OK, the function was built, BUT it didn’t work out the way I wanted it to. I took all of the creative debugging ways I had in mind and just started printing out line by line what the function is doing…After a few coordinate manipulations, it FINALLY hit me that I am uploading my spritesheet in the original size and then I manually resize the image without providing the new size coordinates to my collision function. So, after fixing the sizes I thought that the problem was fixed…Not quite!

trying to detect the right coordinates

Milestone 3: The spritesheet’s dimensions aren’t perfect! 🤦‍♀️😅 After fixing the sizes in Processing I actually went to the original image to see what might be wrong – and there it was: there were a lot of blank spaces between spritesheet’s movements that counted towards the current image’s width and height. Yay, now I finally understand what is happening in my program!

Milestone 4: Beautifying the program. After the main logic of the program was done, I decided to add some functions, such as counting and displaying the score, checking for win, and checking borders for Mario’s movement around the screen.

Epilogue 

I actually never thought that building small games can be this fun and … actually simple? Definitely am proud for working consistently on this throughout the week and can also see some room for improvement (see milestone 3 and demo – there is a moment when Mario catches a diamond despite being a few pixels away from it xD)

Result

Code:

PImage diamond;
PImage person;
PImage[][] movement;
PImage background;
PFont font;

int direction = 1;
int step, score = 0;
int posX, posY;
int diamondX, diamondY;
int speed = 5;
int row = 4;
int col = 4;
int currentWidth, currentHeight;
String textScore = "Score: ";

void setup(){
  
  // output window
  size (600, 600);
  
  // define font
  font = createFont("VT323-Regular", 40);
  textFont(font);
  
  // get images
  diamond = loadImage("diamond.png");
  person = loadImage("person.png");
  background = loadImage("background.png");
  
  // place each direction in 2-dimensional array
  movement = new PImage[row][col];
  
  // divide each step according to each step's dimenstions
  currentWidth = person.width/row;
  currentHeight = person.height/col;
  
  // place each step into the right location
  for(int posY = 0; posY < 4; posY++){
    for(int posX = 0; posX < 4; posX++){
      movement[posY][posX] = person.get(posX*currentWidth, posY*currentHeight, currentWidth, currentHeight);
    }
  }
  
  // always start with these coordinates
  posX = 0;
  posY = height-person.width/8+50;
  
  // dimanod location
  diamondX = (int)random(width-diamond.width-100);
  diamondY = (int)random(height-diamond.height-100);
  
}

void draw(){
  
  background(255);
  image(background, 0, 0, width, height);
  
  // place the character onto the board
  image(movement[direction][step], posX, posY, width/4, height/4);
  
  // move the character
  movePerson();
  checkBorder();
  
  // place the diamond
  image(diamond, diamondX, diamondY, diamond.width/4, diamond.height/4);
  
  // check for collision
  detectDiamond();
  
  // display score:
  displayScore();
  
  // check for win
  checkWin();
}

// move the character
void movePerson(){
  
  // activate if key is pressed
  if(keyPressed){
    
    // move DOWN
    if(keyCode == DOWN){
      // select the corresponding row
      direction = 0;
      // animate the steps to go DOWN in the y-dir (increase)
      posY+=speed;
    }
    
    // move UP
    if(keyCode == UP){
      // select the corresponding row
      direction = 1;
      // animate the steps to go UP in the y-dir (decrease)
      posY-=speed;
    }
    
    // move LEFT
    if(keyCode == LEFT){
      // select the corresponding row
      direction = 2;
      // animate the steps to go LEFT in the x-dir (decrease)
      posX-=speed;
    }
    
    // move RIGHT
    if(keyCode == RIGHT){
      // select the corresponding row
      direction = 3;
      // animate the steps to go RIGHT in the x-dir (increase)
      posX+=speed;
    }
    
    // loops through each step and returns to image 0 after reaching image 3
    if(frameCount%speed==0){
      step = (step+1)%col;
    }
  }
}

// needs some bug fixing
void checkBorder() {
  
  // return from the left
  if (posX >= width) {
    posX = -currentWidth;
  }
  
  // return from the right
  if (posX+currentWidth < 0) {
    posX = width;
  }
  
  // return from the bottom
  if (posY+currentHeight < 0) {
    posY = height;
  }
  
  // return from the top
  if (posY > height) {
    posY = -currentHeight;
  }
}

// check for the image collision (diamond collection)
void detectDiamond(){
  
  // Mario right corner > diamond left AND Mario left corner < diamond right
  if ((posX + person.width/16) > diamondX && posX < (diamondX + diamond.width/4) && (posY+person.height/16) > diamondY && posY < (diamondY + diamond.height/4)){
 
    // increment the score
    score++;
    
    // replace diamond
    diamondX = (int)random(width-diamond.width-100);
    diamondY = (int)random(height-diamond.height-100);
  }
}


// display the score
void displayScore(){
  push();
    fill(0);
    text("Score: " + score, width-180, 40);
  pop();
}

void checkWin(){
  if (score == 5) {
    background(103, 212, 239);
    push();
      textAlign(CENTER);
      fill(random(255), random(255), random(255));
      textSize(100);
      text("You WON!", width/2, height/2);
    pop();
  }
}

 

One thought on “I tried to make a Mario game?”

Leave a Reply