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.

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!
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();
}
}

Great job Amina! You can tell you put in extra time and it paid off.