Week 7 – Midterm

Here we are, after Fall-ish break also known as Midterms Week:

Back to the Spelling Game

After a lot of planning, and not much sleep, I managed to achieve the general idea of my game, with a few bugs and missing elements. Although I would have loved to have it as I imagined, I think with the amount of time + midterms that I had, this is a cool result!

Additionally, if you still didn’t notice, I always try my best to avoid making games for our assignments and often opt for the artwork option. The thought of coding a game often scares me, especially when I think of moving between screens and checking for correct moves. So, this was a great challenge for me! And while I feel like I’m a bit more familiar with game states and other elements, I still think I can work on my game-making skills, and will probably end up looking at your codes for help 🙂

what planning looks like for me

List of Classes: 

  • Animals: this is where I load and display the visual for my animal
  • Buttons: where I create the start and replay buttons
  • Letter: Where I create letter blocks for a keypad grid and check for player clicks.

 

 

Steps

  • Make a start button, start screen, and then switch to the gameplay screen that is linked with an animal.

 

  • Make a keypad for each possible animal. This keypad must contain the letters of the animal name in random order, and it must not repeat letters within the alphabet list:

For this bit, I created two functions

  1. WordCharsinKeypad(): fills the characters from the animal name into the keypad randomly (the letters won’t appear next to each other).
  2. fillRemainingKeys(): checks for remaining empty spots in the keypad and fills them with a random letter from the alphabet without repeating letters from that alphabet array.
  • Display the game playing screen, make the keypad interactive, and give feedback to the user by printing on the screen the letters they get correctly:

I initially aimed to provide two types of feedback. One, which is evident in my program, is that the animal is gradually spelled out on the screen and a letter is added when the player picks the correct letter.

The other, however, I struggled with, which is showing a “try again” message when the player presses the wrong letter. For now, the program just doesn’t respond to a wrong letter.

When I tried to apply the second feedback this is what I got:

  • Finally, I wanted to switch between screens, as you can see above, move from the start screen to the gameplay screen, to the replay screen:

For the start and replay, I relied on buttons from my button class, however, for moving from gameplay to replay screen, it only requires the player to guess the complete word. A small issue I have here is that the last letter does not display before moving to the replay screen. I tried to resolve it with delay()  and altering the if condition in the code, but I still haven’t figured it out.

Some Design Choices

  • I was truly excited to design my own animals, I thought it would be a great chance to work on my Adobe Illustrator skills. However, I placed that as my last priority and unfortunately did not have time for that. So I used free PNGs from open source websites.
  • My game is missing sound, this is something that I will work on and practice as I still feel a bit unfamiliar with it
  • I tried to use soft colors with great contrast to appeal to the child’s eye
  • Keeping accessibility in mind, I made sure to use a font that is legible for most kids. This typeface is OpenDyslexic and it is specifically designed to make it easier for anyone with dyslexia to read a text.

Example of a Game Run

Future Developments

For a more developed version of this game, it would probably incorporate the sounds I mentioned in my progress post, my own designs, and levels rather than one run.

Here’s my code!

Main Function

// to load OpenDyslexic Font
PFont f; 
//for final screen
PImage confetti; 
boolean wrongLetter = false;
//startScreen
int screenNumber = 0;
//a string array to pick a random animal each time start is pressed:
String[] animalNames = {"CAT", "OWL", "FROG", "FISH", "PANDA", "MONKEY", "TURTLE", "CHAMELEON"}; 
// string where the random animal picked from array is stored:
String word; 
//character array of all letters in the alphabet:
char alphabet[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; 
//initializing a letter object array for a keypad:
Letter[] keypad = new Letter[12]; 
//initializing the animal object for the animal displayed in the run:
Animals animal4Run; 
//columns for keypad grid display
int cols = 3;
//rows for keypad grid display
int rows =4; 
// a variable that checks the players progress of selecting the correct letters -- e.g. if they have "CA" out of "CAT" it will equal 1 
int playerPosition = 0; 
//initializing a button object for start button
Buttons startButton;
// initializing a button object for replay button
Buttons replayButton; 
//an empty string variable. It will be used to reflect the player's progress in choosing the correct letter
String wordInProg; 

void setup() {
  size(960, 540);
  confetti = loadImage("CONFETTI.png");
  confetti.resize(960, 540);
  //using OpenDyslexic so the font could be readable for most
  f = createFont("OpenDyslexic-Bold.otf", 20);  
  textFont(f);
  //creating the start button object
  startButton = new Buttons(width/2, height/2+100, 100, 70, "Start"); //creating the start button object
  //creating the replay button object
  replayButton = new Buttons(width/2, height/2+200, 100, 70, "Replay"); 
  //setup the word in progress as an empty string, it will fill gradually as the player picks the correct letters.
  wordInProg = "";
  //generates a random index to pick a random animal each time run is clicked
  int indexForRun = (int)random(0, animalNames.length); 
  //sets the word variable using the generated random index
  word = animalNames[indexForRun];
  //creates an animal object using the word
  animal4Run = new Animals(word); 
  //index variable to go through all objects in the keypad array
  int index = 0; 
  for (int c = 0; c < cols; c++) {
    for (int r = 0; r < rows; r++) {
      //using columns and rows for a grid display
      keypad[index] = new Letter('x', c, r); 
      index += 1;
    }
  }

  //function that fills the characters from the animal name into the keypad in random positions
  wordCharsInKeypad(); 
  //function that fills the remaining empty keypad spaces
  fillRemainingKeys();
}

void draw() {
  background(227, 181, 164);
  //switch function to move between game screens
  switch(screenNumber) { 
  // case 0 is the start screen
  case 0:
  //calls setup to randomize a new animal everytime start is pressed
    setup(); 
    fill(232, 95, 92);
    textSize(60);
    text("Spell the Animal Name Game!", width/2, height/2 - 100);
    //display function for start button
    startButton.buttonDisplay();
    //checks if player clicks the start button and moves on to the next game screen
    if (mousePressed && mouseX >= startButton.xLoc - startButton.buttonW/2 && mouseX <= startButton.xLoc + startButton.buttonW/2 && mouseY >= startButton.yLoc - startButton.buttonH/2 && mouseY <= startButton.yLoc + startButton.buttonH/2) {
      screenNumber = 1; 
    }
    break;
  // playing screen
  case 1: 
    fill(156, 255, 250);
    textSize(50);
    text("What is this animal called?", width/2, height/2 - 200);
     //displays the player's progress in choosing the correct letters on the screen
    text(wordInProg, width/2-50, height/2 + 200);
    for (int i = 0; i < keypad.length; i ++) {
      //displays all letter objects in the keypad
      keypad[i].display(); 
      //displays the image of the animal in question
      animal4Run.display(); 
      //loops through all letters to check if 1. they are clicked , 2. if they are the correct letter 
      for (int j = 0; j < keypad.length; j++ ) { 
        textSize(20);
        //calls a function that checks whether the letter is clicked 
        keypad[j].letterIsClicked(); 
        if (keypad[j].letterClicked == true) {
          keypad[j].letterClicked = false;
          //println(">>>", keypad[j].letter, cat.animalName.charAt(playerPosition));
          if (keypad[j].letter != animal4Run.animalName.charAt(playerPosition)) {
            text("try again", width/2 - 300, height/2);} //?????
          //checks if the character clicked in the keypad matches the character that is at the player's position in the animal name
          if (keypad[j].letter == animal4Run.animalName.charAt(playerPosition)) {
            //this condition ensures that it adds the correct letters only for as long as the word in progress is the same length as the animal name, otherwise you would get "CATTTTTTTTTT" 
            if (wordInProg.length() < animal4Run.animalName.length()) {
              //keeps adding to reflect the player's progress
              wordInProg = wordInProg + animal4Run.animalName.charAt(playerPosition);
              //println(wordInProg);
              //println(keypad[j].letter + " " + cat.animalName.charAt(playerPosition));
              //condition: as long as the player position is still less than the length of the animal name, keep adding as the name is not complete yet
              if (playerPosition < animal4Run.animalName.length() -1) {
                playerPosition+= 1;
               //checks if the word is complete to switch to end screen that reflects success and gives replay button
              } else if (playerPosition == animal4Run.animalName.length()-1) {
                screenNumber = 2;
                break;
              }
            }
          }
        }
      }
    }
    break;
   //end screen
  case 2:
  //resets player position for next iteration of the game
    playerPosition = 0;
    for (int k = 0; k < keypad.length; k++ ) {
      //resets any letters clicked
      keypad[k].letterClicked = false; 
    }
    background(227, 181, 164);
    imageMode(CORNER);
    //tint(255);
    //loads confetti image for celebration :)
    image(confetti, 0, 0);
    fill(232, 95, 92);
    textSize(60);
    text("What a Spelling Champ!", width/2, height/2 - 100);
    fill(156, 255, 250);
    text("Press Replay to Spell Again!", width/2, height/2);
    //displaying replay button
    replayButton.buttonDisplay();
    //checks if pressed to go back to start screen
    if (mousePressed && mouseX >= replayButton.xLoc - replayButton.buttonW/2 && mouseX <= replayButton.xLoc + replayButton.buttonW/2 && mouseY >= replayButton.yLoc - replayButton.buttonH/2 && mouseY <= replayButton.yLoc + replayButton.buttonH/2) {
      screenNumber = 0;
    }
  }
}


//function that inputs the characters of the animal name in the keypad
void wordCharsInKeypad() {
  //a boolean to check if all the characters have been input
  boolean complete = false;
  //i variable to loop through all letters in the animal name
  int i = 0;
  while (complete == false) { 
    //generating a random index so letters don't appear in correct order in the keypad
    int randomIndex = (int) random(keypad.length - 1);  
    // condition: if the key is empty, signified by 'x', fill it with this letter, and then move to the next character (to avoid overwriting keys)
    if (keypad[randomIndex].letter == 'x') { 
    
      keypad[randomIndex].letter = animal4Run.animalName.charAt(i); 
      i += 1;
    }
    //if all the letters from the animal name are in the keypad, exit the while loop
    if (i == animal4Run.animalName.length()) { 
      complete = true;
    }
  }
}

//function to fill the rest of the keypad
void fillRemainingKeys() {
 //same boolean and variable concept as before
  boolean complete = false; 
  int j = 0;
  while (complete == false) {
    //this boolean is to check if the chosen letter already exists in the keypad
    boolean duplicated = false;
    //generates a random index to input a random letter from the alphabet
    int randomIndex = (int) random(alphabet.length -1);
    // println(j, keypad[j].letter, alphabet[randomIndex], word.indexOf(alphabet[randomIndex]));
    //if this position in the keypad is empty AND the chosen character is not in the animal name (as that wouldve been input in the prev function, fill it in the keypad)
    if (keypad[j].letter == 'x' && animal4Run.animalName.indexOf(alphabet[randomIndex]) == -1) {
      //for loop that checks if the letter that we are about to input already exists in the keypad to avoid repetition
      for (int k = 0; k < keypad.length; k++) {
        if (keypad[k].letter == alphabet[randomIndex] ) {
          duplicated = true;
          //if it is a duplicate it breaks out of this for loop and restarts to generate a new letter
          break;
        }
      }
      //to continue trying to generate
      if (duplicated) {
        continue;
      }
      // if it isn't a duplicate it inputs it into the keypad
      keypad[j].letter = alphabet[randomIndex];
    }
    //if the letter is in the word, meaning it is already in the keypad, also continue to generate something else
    if (word.indexOf(alphabet[randomIndex]) != -1) {
      continue;
    }
    j+= 1;
    //condition to exit the while loop when the keypad is fully formed
    if (j == keypad.length) {
      complete = true;
    }
  }

  //for (int k = 0; k < keypad.length; k++) {
  //println(k, keypad[k].letter);
  // }
}

Animals Class

class Animals {
  //two vars for animal name and to load the suitable image
  String animalName;
  PImage animalImage;
  
  
  Animals(String tempAnimalName){
    animalName = tempAnimalName;
    //using animal name to load the image
    animalImage = loadImage(animalName+".png");
    animalImage.resize(300,300);
  }
  
  
  void display(){
   fill(0,255,0);
   imageMode(CENTER);
   image(animalImage,width/2-50,height/2);
   //rect(width/2,height/2,100,100);
   //fill(0);
   //textAlign(CENTER,CENTER);
   //textSize(15);
   //text("I am a" + " " + animalName, width/2,height/2);
  }
}

Buttons Class:

  class Buttons {
    int xLoc, yLoc, buttonW, buttonH; 
    String buttonTitle;
    //
    
    
  
    Buttons(int xLocTemp, int yLocTemp, int buttonWTemp, int buttonHTemp, String buttonTitleTemp) {
      xLoc = xLocTemp;
      yLoc = yLocTemp;
      buttonW = buttonWTemp;
      buttonH = buttonHTemp; 
      buttonTitle = buttonTitleTemp;
      
      
    }
  
  
  

  
  
    void buttonDisplay() {
      rectMode(CENTER);
       noStroke();
       fill(200);
       rect(xLoc, yLoc, buttonW, buttonH);
       fill(0);
       textSize(25);
       textAlign(CENTER,CENTER);
       text(buttonTitle, xLoc, yLoc);
      }
  }

Letter Class:

class Letter {
  char letter; 
  int xLoc, yLoc; 
  int blockW = 70;
  int blockH = 70;
  int colNo;
  int rowNo;
  //booleans to check during the game
  boolean letterClicked;
  boolean letterCorrect;


  Letter(char letterTemp, int tempColNo, int tempRowNo) {
    letter = letterTemp;
    colNo = tempColNo;
    rowNo = tempRowNo;
  }


  void display() {
    //as it is a grid object, col and row number are used for x and y coordinates
    rectMode(CORNER);
    fill(0);
    stroke(255);
    rect(700+colNo*70, 150+rowNo*70, blockW, blockH);
    fill(255);
    textSize(20);
    textAlign(CENTER, CENTER);
    text(letter, 735+colNo*70, 185+rowNo*70);
  }
  
  
//the function that checks if the letter is clicked
 void letterIsClicked() {
    if (mousePressed && mouseX >=  700+(colNo)*70  && mouseX <= 700+(colNo)*70 + blockW && mouseY >= 150+(rowNo)*70 && mouseY <= 150+(rowNo)*70+blockH) {
     // println("mouseY: ", mouseY, " - 200+(rowNo-1)*70: ", 200+(rowNo-1)*70, " - 200+(rowNo-1)*70+blockH: ", 200+(rowNo-1)*70+blockH);

      letterClicked = true;
      //println(letter, " Clicked");
    }
  }
  
}

Zip: midtermm_Game

Leave a Reply