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 🙂
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
- WordCharsinKeypad(): fills the characters from the animal name into the keypad randomly (the letters won’t appear next to each other).
- 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