Search code examples
javascriptclassobjectvariablesprocessing

Mini Game using Custom Classes and Objects Errors


I have a project where we are supposed to use classes and objects to create a mini game of sorts. I have the main structure of my game typed out, but I don't know if it is going to work or not. I've run into several errors while trying to make it run, but my brain is too tired to tell where the problems are. If you could take a look at my code and give me some feedback, I would greatly appreciate it.

void setup() {
  size(1090, 720); //canvas size
  //defining image variables
  helvetica = loadFont("Helvetica-20.vlw");
  startScreen = loadImage("Title Screen.png");
  playScreen = loadImage("Play Screen.png");
  endScreen = loadImage("End Screen.png");
  blindsOpen = loadImage("Open Blinds.png");
  blindsHalf = loadImage("Half Blinds.png");
  blindsClosed = loadImage("Closed Blinds.png");
  dryPot = loadImage("Pot Dry.png");
  wetPot = loadImage("Pot Wet.png");
  sprout = loadImage("Sprout.png");
  stem = loadImage("Stem.png");
  bud = loadImage("Bud.png");
  bloomRose = loadImage("Bloom Rose.png");
  bloomClemantis = loadImage("Bloom Clemantis.png");
  bloomAster = loadImage("Bloom Aster.png");
  //defininng sound variables
  blinds = new SoundFile(this, "Blinds.wav");
  dirt = new SoundFile(this, "Dirt_Sound.wav");
  water = new SoundFile(this, "Pouring_Water.wav");
  music = new SoundFile(this, "Gentle_Music.wav");
  //no loop to keep the sound from overlapping itself
  noLoop();
  //variables for the flower object
  int waterLevel;
  int lightLevel;
  int growthLevel;
  //initial values
  waterLevel = 0;
  lightLevel = 0;
  growthLevel = 0;
  //variables for the buttons
  int blueX, blueY;
  int greenX, greenY;
  int yellowX, yellowY;
  boolean blueOver = false;
  boolean greenOver = false;
  boolean yellowOver = false;
  int buttonSize = 100;
}

void draw() {
  //start screen image
  image(startScreen, 5, 0);
  music.loop(); //play gentle music for the entirety of the game
  fill(255);
  text("Click to start", 540, 540); //tell the user to click the screen
  //when mouse is clicked, switch to the main gameplay screen
  if (mousePressed) {
    gameplay();
  }
}

//gameplay function
void gamePlay() {
  //play screen image
  image(playScreen, 5, 0);
  //buttons for gameplay
  blueX = 100;
  blueY = 690;
  greenX = 540;
  greenY = 680;
  yellowX = 1000;
  yellowY = 680;
  fill(0, 0, 255);
  noStroke();
  smooth();
  circle(blueX, blueY, buttonSize);
  fill(0, 200, 0);
  circle(greenX, greenY, buttonSize);
  fill(220, 220, 0);
  circle(yellowX, yellowY, buttonSize);
  fill(255);
  text("Water", 77, 687);
  text("Seed", 520, 687);
  text("Light", 980, 687);
  update(mouseX, mouseY);
  OFlower o1 = new OFlower(5, 0);
  o1.update();
}

//flower class defined
class OFlower {
  int flowerX, flowerY;
  OFlower (int x, int y) {
    flowerX = x;
    flowerY = y;
  }
  void update() {
    if (waterLevel >= 5) {
      image(wetPot, 5, 0);
    } else {
      image(dryPot, 5, 0);
    }
    if (growthLevel == 5 && waterLevel >= 5 && lightLevel >= 5) {
      growthLevel = growthLevel+1;
    } else {
      growthLevel = growthLevel-1;
    }
    if (growthLevel <= 0) {
      gameOver();
    }
    if (growthLevel == 5) {
      image(sprout, 5, 0);
    } else if (growthLevel == 6) {
      image(stem, 5, 0);
    } else if (growthLevel == 7) {
      image(bud, 5, 0);
    } else if (growthLevel >= 8 && lightLevel <=7) {
      image(bloomClemantis, 5, 0);
    } else if (growthLevel >= 8 && lightLevel == 8) {
      image(bloomRose, 5, 0);
    } else if (growthLevel >= 8 && light Level >= 9) {
      image(bloomAster, 5, 0);
    }
  }
}

boolean overBlue(int x, int y, int diameter) {
  float disX = x - mouseX;
  float disY = y - mouseY;
  if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
    return true;
  } else {
    return false;
  }
}

boolean overGreen(int x, int y, int diameter) {
  float disX = x - mouseX;
  float disY = y - mouseY;
  if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
    return true;
  } else {
    return false;
  }
}

boolean overYellow(int x, int y, int diameter) {
  float disX = x - mouseX;
  float disY = y - mouseY;
  if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
    return true;
  } else {
    return false;
  }
}

void update(int x, int y) {
  if ( overBlue(blueX, blueY, buttonSize) ) {
    blueOver = true;
    greenOver = false;
    yellowOver = false;
  } else if (overGreen(greenX, greenY, buttonSize) ) {
    blueOver = false;
    greenOver = true;
    yellowOver = false;
  } else if (overYellow(yellowX, yellowY, buttonSize) ) {
    blueOver = false;
    greenOver = false;
    yellowOver = true;
  } else {
    blueOver = greenOver = yellowOver = false;
  }
}

void mousePressed() {
  if (blueOver) {
    water.play();
    waterLevel = waterLevel+10;
  }
  if (greenOver) {
    dirt.play();
    growthLevel = growthLevel+5;
  }
  if (yellowOver) {
    blinds.play();
    lightLevel = lightLevel+3;
    if (lightLevel <= 3) {
      image(blindsClosed, 5, 0);
    } else if (lightLevel <= 7) {
      image(blindsHalf, 5, 0);
    } else if (lightLevel >=10) {
      image(blindsOpen, 5, 0);
    }
  }
}

gameOver() {
  image(endScreen, 5, 0);
  fill(255);
  text("Oh no! Your flower died...", 540, 600);
}

PImage startScreen;
PImage playScreen;
PImage endScreen;
PImage blindsOpen;
PImage blindsHalf;
PImage blindsClosed;
PImage dryPot;
PImage wetPot;
PImage sprout;
PImage stem;
PImage bud;
PImage bloomRose;
PImage bloomClemantis;
PImage bloomAster;
PFont helvetica;

import processing.sound.*;

SoundFile blinds;
SoundFile dirt;
SoundFile water;
SoundFile music;

The way the game is supposed to work is sort of like a tamagatchi pet that has set variables that degrade over time. As I mentioned above, I have run into a lot of errors, but am unable to see them.


Solution

  • Ideally you would post a version that would isolate the issue (and exclude assets that we won't have access to in order to run your code/replicate the issue).

    I do understand it can be hard at the start. It looks like you've put a lot of work into this, but also fallen into a trap I found myself when getting started: adding more and more without testing. Ideally you'd write a tiny amount of functionality and test it immediately (e.g. load an image, place an image, load a sound, etc.). This way you would catch errors one at a time as they happen, rather than many at the same time which is harder to track down and fix.

    This shouldn't discourage you though. Here are a few gotchas I spotted so far:

    • gameplay() / gamePlay() typo. Processing is key sensitive: the name should match. (e.g. in draw() you call gameplay() which doesn't exist/probably should be gamePlay())
    • some variables (e.g. blueX, blueY, etc.) defined in setup() are local, but later referenced in draw() as if they were global. Perhaps you meant to move the definitions above setup so they are global ?
    • gameOver() is defined without the return type (e.g. void gameOver(){ ... })
    • noLoop() in setup() means a single frame will be rendered so interacting with the buttons will be impossible. Perhaps this was left there by mistake when debugging ? (On a similar note, perhaps music.loop(); should be in setup(), not in draw() if the intention was to start looping the music once rather than multiple times per second)
    • there may be more logic errors, but here are a few that stand out:
    • growthLevel is a global variable however it's locally in the OFlower class. If there were multiple instances all changing the same variable the behaviour might not be what you want
    • growthLevel starts at 0 wich results in an immediate game over
    • pressing any of the 3 buttons (water, seed, light) decreases the growthLevel value (Adding println(growthLevel); makes it easier to debug this issue). The logic needs to be fixed otherwise the game can't be won.

    Here's a tweaked version of code with some of the issues above addressed (but also commented sound to simplify testing):

    //variables for the flower object
    int waterLevel = 0;
    int lightLevel = 0;
    int growthLevel = 100;
    //variables for the buttons
    int blueX, blueY;
    int greenX, greenY;
    int yellowX, yellowY;
    boolean blueOver = false;
    boolean greenOver = false;
    boolean yellowOver = false;
    int buttonSize = 100;
    
    void setup() {
      size(1090, 720); //canvas size
      //defining image variables
      helvetica = loadFont("Helvetica-20.vlw");
      startScreen = loadImage("Title Screen.png");
      playScreen = loadImage("Play Screen.png");
      endScreen = loadImage("End Screen.png");
      blindsOpen = loadImage("Open Blinds.png");
      blindsHalf = loadImage("Half Blinds.png");
      blindsClosed = loadImage("Closed Blinds.png");
      dryPot = loadImage("Pot Dry.png");
      wetPot = loadImage("Pot Wet.png");
      sprout = loadImage("Sprout.png");
      stem = loadImage("Stem.png");
      bud = loadImage("Bud.png");
      bloomRose = loadImage("Bloom Rose.png");
      bloomClemantis = loadImage("Bloom Clemantis.png");
      bloomAster = loadImage("Bloom Aster.png");
      //defininng sound variables
      //blinds = new SoundFile(this, "Blinds.wav");
      //dirt = new SoundFile(this, "Dirt_Sound.wav");
      //water = new SoundFile(this, "Pouring_Water.wav");
      //music = new SoundFile(this, "Gentle_Music.wav");
      //no loop to keep the sound from overlapping itself
      //noLoop();
    }
    
    void draw() {
      //start screen image
      image(startScreen, 5, 0);
      //music.loop(); //play gentle music for the entirety of the game
      fill(255);
      text("Click to start", 540, 540); //tell the user to click the screen
      //when mouse is clicked, switch to the main gameplay screen
      if (mousePressed) {
        gamePlay();
      }
    }
    
    //gameplay function
    void gamePlay() {
      //play screen image
      image(playScreen, 5, 0);
      //buttons for gameplay
      blueX = 100;
      blueY = 690;
      greenX = 540;
      greenY = 680;
      yellowX = 1000;
      yellowY = 680;
      fill(0, 0, 255);
      noStroke();
      smooth();
      circle(blueX, blueY, buttonSize);
      fill(0, 200, 0);
      circle(greenX, greenY, buttonSize);
      fill(220, 220, 0);
      circle(yellowX, yellowY, buttonSize);
      fill(255);
      text("Water", 77, 687);
      text("Seed", 520, 687);
      text("Light", 980, 687);
      update(mouseX, mouseY);
      OFlower o1 = new OFlower(5, 0);
      o1.update();
      println(growthLevel);
    }
    
    //flower class defined
    class OFlower {
      int flowerX, flowerY;
      OFlower (int x, int y) {
        flowerX = x;
        flowerY = y;
      }
      void update() {
        if (waterLevel >= 5) {
          image(wetPot, 5, 0);
        } else {
          image(dryPot, 5, 0);
        }
        if (growthLevel == 5 && waterLevel >= 5 && lightLevel >= 5) {
          growthLevel = growthLevel+1;
        } else {
          growthLevel = growthLevel-1;
        }
        if (growthLevel <= 0) {
          gameOver();
        }
        if (growthLevel == 5) {
          image(sprout, 5, 0);
        } else if (growthLevel == 6) {
          image(stem, 5, 0);
        } else if (growthLevel == 7) {
          image(bud, 5, 0);
        } else if (growthLevel >= 8 && lightLevel <=7) {
          image(bloomClemantis, 5, 0);
        } else if (growthLevel >= 8 && lightLevel == 8) {
          image(bloomRose, 5, 0);
        } else if (growthLevel >= 8 && lightLevel >= 9) {
          image(bloomAster, 5, 0);
        }
      }
    }
    
    boolean overBlue(int x, int y, int diameter) {
      float disX = x - mouseX;
      float disY = y - mouseY;
      if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
        return true;
      } else {
        return false;
      }
    }
    
    boolean overGreen(int x, int y, int diameter) {
      float disX = x - mouseX;
      float disY = y - mouseY;
      if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
        return true;
      } else {
        return false;
      }
    }
    
    boolean overYellow(int x, int y, int diameter) {
      float disX = x - mouseX;
      float disY = y - mouseY;
      if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
        return true;
      } else {
        return false;
      }
    }
    
    void update(int x, int y) {
      if ( overBlue(blueX, blueY, buttonSize) ) {
        blueOver = true;
        greenOver = false;
        yellowOver = false;
      } else if (overGreen(greenX, greenY, buttonSize) ) {
        blueOver = false;
        greenOver = true;
        yellowOver = false;
      } else if (overYellow(yellowX, yellowY, buttonSize) ) {
        blueOver = false;
        greenOver = false;
        yellowOver = true;
      } else {
        blueOver = greenOver = yellowOver = false;
      }
    }
    
    void mousePressed() {
      if (blueOver) {
        //water.play();
        waterLevel = waterLevel+10;
      }
      if (greenOver) {
        //dirt.play();
        growthLevel = growthLevel+5;
      }
      if (yellowOver) {
        //blinds.play();
        lightLevel = lightLevel+3;
        if (lightLevel <= 3) {
          image(blindsClosed, 5, 0);
        } else if (lightLevel <= 7) {
          image(blindsHalf, 5, 0);
        } else if (lightLevel >=10) {
          image(blindsOpen, 5, 0);
        }
      }
    }
    
    void gameOver() {
      image(endScreen, 5, 0);
      fill(255);
      text("Oh no! Your flower died...", 540, 600);
    }
    
    PImage startScreen;
    PImage playScreen;
    PImage endScreen;
    PImage blindsOpen;
    PImage blindsHalf;
    PImage blindsClosed;
    PImage dryPot;
    PImage wetPot;
    PImage sprout;
    PImage stem;
    PImage bud;
    PImage bloomRose;
    PImage bloomClemantis;
    PImage bloomAster;
    PFont helvetica;
    
    //import processing.sound.*;
    
    //SoundFile blinds;
    //SoundFile dirt;
    //SoundFile water;
    //SoundFile music;
    

    Hopefully this is helpful in breaking down the big problems into smaller problems to solve them one at a time.