This site requires JavaScript, please enable it in your browser!
Greenfoot back
CalzoneCannon
CalzoneCannon wrote ...

2014/6/7

Can not longer place my units.

1
2
3
CalzoneCannon CalzoneCannon

2014/6/7

#
I am making a plants vs zombies project for my class, and I don't know what I changed in my code, but I can no longer place either my Sunflowers or my Wallnuts. I will paste the code for the world, abstract plant class, wallnut, and sunflower below: import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) /** * Write a description of class Lawn here. * * @author (your name) * @version (a version number or a date) */ public class Lawn extends World { private int PeaTimer; private int zombTimer; private Location grid; /** * Constructor for objects of class Lawn. * */ public Lawn() { // Create a new world with 600x400 cells with a cell size of 1x1 pixels. super(1050, 600, 1); grid = new Location; for(int r = 0; r < grid.length; r++) { for(int c = 0; c < grid.length; c++) { grid = new Location(215 + (c*80), 130 + (r*97)); } } Menu menu = new Menu(); addObject(menu, getWidth()/2, 38); menuLoad(); zombTimer=300; PeaTimer=0; } public void act() { if(!(StartScreen.checkChange())) { Greenfoot.setWorld(new StartScreen()); } zombSpawn(); if(Greenfoot.mousePressed(this)) { build(Greenfoot.getMouseInfo().getX(), Greenfoot.getMouseInfo().getY()); } PeaTimer++; } public void build(int x, int y) { String key = getKey(); for(int r=0; r < grid.length; r++) { for(int c = 0; c <grid.length; c++) { if( x + 40 >= grid.getX() && x - 40 <= grid.getX()) { if(y + 48 >= grid.getY() && y - 48 <= grid.getY()) { if(checkEmpty(grid.getX(), grid.getY()) && key != null) { spawn(grid.getX(), grid.getY(), key); } } } } } } public String getKey() { if(Greenfoot.isKeyDown("P")) { return "P"; } else if(Greenfoot.isKeyDown("S")) { return "S"; } else if(Greenfoot.isKeyDown("W")) { return "W"; } else if(Greenfoot.isKeyDown("M")) { return "M"; } else { return null; } } public void spawn(int x, int y, String str) { if(str.equals("P")) //&& SunScoreboard.getSun() >= PeaShooter.getCost()) { addObject(new PeaShooter(), x, y); SunScoreboard.changeSun((PeaShooter.getCost())*-1); } else if(str.equals("S")) //&& SunScoreboard.getSun() >= Sunflower.getCost()) { addObject(new Sunflower(), x, y); SunScoreboard.changeSun((Sunflower.getCost())*-1); } else if(str.equals("W")) { addObject(new Wallnut(), x, y); SunScoreboard.changeSun((Wallnut.getCost())*-1); } /* else if(str.equals("M")) { addObject(new PotatoMine(), x, y); SunScoreboard.changeSun((PotatoMine.getCost())*-1); } */ else; //addObject(new PeaShooter(), x, y); } public boolean checkEmpty(int x, int y) { if(getObjectsAt(x, y, Object.class) instanceof Plant) { return false; } else { return true; } } public void zombSpawn() { int zomb = (int)(Math.random()*2); if(zombTimer == 0) { if(zomb == 0) { addObject(new RegZombie(), getWidth() , 130 + ((int)(Math.random()*5)*97)); } else if(zomb == 1) { addObject(new BucketZombie(), getWidth(), 130 + ((int)(Math.random()*5)*97)); } zombTimer=300; } else { zombTimer--; } } public void menuLoad() { BuySunFlower buySun = new BuySunFlower(); addObject(buySun, 313, 38); BuyPeaShooter buyPea = new BuyPeaShooter(); addObject(buyPea, 407, 38); BuyWallnut buyWall = new BuyWallnut(); addObject(buyWall, 360, 38); } public static void gameOver() { Greenfoot.setWorld(new GameOver()); } } import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) /** * Write a description of class Plant here. * * @author (your name) * @version (a version number or a date) */ public abstract class Plant extends Actor { private int cost; private int health; private int hitCounter; /** * Act - do whatever the Plant wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { } public boolean checkDamage() { if(this.isTouching(Zombie.class) && hitCounter <= 0) { return true; } return false; } public void loseHP() { this.health--; hitCounter = 50; } public boolean checkDeath() { if(health <= 0) { return true; } return false; } public void die() { getWorld().removeObject(this); } } import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) /** * Write a description of class Wallnut here. * * @author (your name) * @version (a version number or a date) */ public class Wallnut extends Plant { private GifImage gif; private boolean changed1; private boolean changed2; private int health = 30; private static int cost = 50; private int hitCounter; public Wallnut() { gif = new GifImage("WallNut.gif"); hitCounter = 0; } /** * Act - do whatever the Wallnut wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { setImage(gif.getCurrentImage()); if(health <= 20 && health > 10) { medHealth(); } if(health <= 10) { lowHealth(); } if(checkDamage() && health > 0) { this.loseHP(); } else { this.hitCounter--; } if(checkDeath()) { die(); } } public boolean checkDamage() { return super.checkDamage(); } public void loseHP() { super.loseHP(); } public void medHealth() { if(changed1 == false) { gif = new GifImage("Wallnut_cracked1.gif"); changed1 = true; } } public void lowHealth() { if(changed2 == false) { gif = new GifImage("Wallnut_cracked2.gif"); changed2 = true; } } public boolean checkDeath() { return super.checkDeath(); } public void die() { super.die(); } public static int getCost() { return cost; } } import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) /** * Write a description of class Sunflower here. * * @author (your name) * @version (a version number or a date) */ public class Sunflower extends Plant { private static int placeTimer; private int health = 6; private int sunTimer=200; private static int cost = 50; private GreenfootImage images; private int currentImage = 0; private int tmp=15; private GifImage gif; private int hitCounter; public Sunflower() { gif = new GifImage("Sunflower.gif"); hitCounter = 0; } /** * Act - do whatever the Sunflower wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { sunSpawn(); setImage(gif.getCurrentImage()); if(checkDamage() && health > 0) { this.loseHP(); } else { this.hitCounter--; } if(checkDeath()) { die(); } } public boolean checkDamage() { return super.checkDamage(); } public void loseHP() { super.loseHP(); } public boolean checkDeath() { return super.checkDeath(); } public void die() { super.die(); } public void sunSpawn() { if(sunTimer<=0) { getWorld().addObject(new Sun(), this.getX() + 35, this.getY() - 25); sunTimer=400; } else { sunTimer--; } } public static int getCost() { return cost; } } The error is that I can no longer place Wallnuts or Sunflowers, if anyone could figure out why, I appreciate the help. Thanks, ~Calzone
danpost danpost

2014/6/8

#
First, the line after the world constructor super call -- 'grid = new Location;' should not compile. And as the Location class was not given, I cannot say what is needed there, if anything. Second thing spotted was in the 'checkEmpty' method. The if condition -- 'getObjectsAt(x, y, Object.class) instanceof Plant' will always be false (which is why nothing is being spawned). 'getObjectsAt' returns a List object (an instance of List) which is NOT a Plant object. You can determine if a Plant object is at that location by having 'getObjectsAt' search specifically for Plant object and then check to see if the returned list is empty or not
public boolean checkEmpty(int x, int y)
{
    return getObjectsAt(x, y, Plant.class).isEmpty();
}
Finally, you should not re-declare 'cost', 'health', and 'hitCounter' in your subclasses of Plant. Once you declare them in Plant, all instances of its subclasses will be given those fields to use. Also, the 'cost' field and 'getCost' methods should not be static and all common methods should be in the Plant class instead of in each of the subclasses. The different initial values of those fields can be assigned in the constructors of the subclasses. For methods that all subclasses do, but do differently, you can have an empty method with the same name in the Plant class so you do not need to know which subclass the object is of to run that method on it. I know that this is a lot to take in, but if you have problems, I will be here to help. You can also review (or study up) on this and other stuff within the Java tutorials. The section on inheritance explains my concern above. It might be good to look at how interfaces work also as it shows the mechanism that is referred to in my final statement above.
CalzoneCannon CalzoneCannon

2014/6/8

#
I get what you are saying, but I guess what confused me is the fact that my other two plant classes were placeable without any issues. I have all the plants placeable through the same method, and I tested to see if the methods were being called (which they were), yet nothing happened.
CalzoneCannon CalzoneCannon

2014/6/8

#
Also, I had cost and getCost static because I was calling them from the world (does that not matter?)
danpost danpost

2014/6/8

#
The way I see it, you would still have to figure out what subclass of Plant an object is to get the cost. By changing them to non-static, you only need to know that it is some type of Plant; but, you will not be required to know which one. If you have problems with calling them from the world, please do not hesitate to post your code (the method you are calling it from) for help.
danpost danpost

2014/6/8

#
If you get what I was saying, then you should, by now, have realized that methods like this:
public boolean checkDamage()
{
    return super.checkDamage();
}
are not needed in the subclasses. You are overriding methods with methods that call the overridden methods. You can simply remove these method without altering the execution.
danpost danpost

2014/6/8

#
danpost wrote...
The way I see it, you would still have to figure out what subclass of Plant an object is to get the cost. By changing them to non-static, you only need to know that it is some type of Plant; but, you will not be required to know which one. If you have problems with calling them from the world, please do not hesitate to post your code (the method you are calling it from) for help.
Strike the above. 'static' is the way to go with the 'cost' field. The 'getCost' method kind of through me. You can make the 'cost' field 'public static final int COST = 50;' and remove the 'getCost' method. Instead of 'Wallnut.getCost()', use 'Wallnut.COST'; and similar with the other cost fields for the other subclasses of Plant. Another thing that through me was 'private int cost;' in the Plant class, which should be removed.
danpost danpost

2014/6/8

#
I think that for any further help, I would need to see the Location class code.
CalzoneCannon CalzoneCannon

2014/6/8

#
Alright. My Location code is: public class Location { private int x, y; public Location(int x, int y) { this.x=x; this.y=y; } public int getX() { return x; } public int getY() { return y; } } I mean, I had all the units placing with no problem previously. I must have changed something to make them not work. The following classes place with no problem (I haven't changed the super class and stuff yet, I will get to those): import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) /** * Write a description of class PotatoMine here. * * @author (your name) * @version (a version number or a date) */ public class PotatoMine extends Plant { private static int cost = 25; private int health; private int hitCounter; private GifImage gif; private int armTimer; private boolean changed; public PotatoMine() { gif = new GifImage("PotatoMine.gif"); armTimer = 300; changed = false; } /** * Act - do whatever the PotatoMine wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { setImage(gif.getCurrentImage()); if(armTimer == 0) { arm(); } else { armTimer--; } } public boolean checkDamage() { return super.checkDamage(); } public void loseHP() { super.loseHP(); } public boolean checkDeath() { return super.checkDeath(); } public void die() { super.die(); } public static int getCost() { return cost; } public void arm() { if(changed == false) { gif = new GifImage("PotatoMineNotReady.gif"); changed = true; } } } import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) import java.util.*; /** * Write a description of class PeaShooter here. * * @author (your name) * @version (a version number or a date) */ public class PeaShooter extends Plant { private static int placeTimer; private int shootTime; private int maxHealth; private int button, mouseX, mouseY = 0; private static int cost = 100; private int health = 6; private GifImage gif; public PeaShooter() { gif = new GifImage("PeaShooter.gif"); shootTime=0; } public void act() { if(canShoot()) { shoot(); } else { shootTime--; } setImage(gif.getCurrentImage()); } public boolean canShoot() { if(shootTime <= 0) { for(int x = this.getX(); x < getWorld().getWidth(); x++) { List<Actor> actors = getWorld().getObjectsAt(x, this.getY(), Zombie.class); if(actors.size() > 0) { return true; } } } return false; } public void shoot() { getWorld().addObject(new Pea(), this.getX()+43, this.getY()-20); //getWorld().addObject(new Pea(), this.getX(), this.getY()); shootTime = 60; } public boolean placeable() { if(placeTimer==0) { MouseInfo mouse = Greenfoot.getMouseInfo(); if(mouse!=null) { button = mouse.getButton(); if(button==1 && Greenfoot.mouseClicked(getWorld()) && Greenfoot.isKeyDown("P")) { return true; } } } return false; } public void loseHP() { super.loseHP(); } public static int getCost() { return cost; } public boolean checkDamage() { return super.checkDamage(); } public boolean checkDeath() { return super.checkDeath(); } public void die() { super.die(); } } import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) import java.util.*; /** * Write a description of class Threepeater here. * * @author (your name) * @version (a version number or a date) */ public class Threepeater extends Plant { private int shootTime; private int maxHealth; private static int cost = 325; private int health = 6; private GifImage gif; public Threepeater() { gif = new GifImage("Threepeater.gif"); shootTime = 0; } /** * Act - do whatever the Threepeater wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { if(canShoot()) { shoot(); } else { shootTime--; } setImage(gif.getCurrentImage()); } public boolean canShoot() { if(shootTime <= 0) { for(int x = this.getX(); x < getWorld().getWidth(); x++) { List<Actor> actors = getWorld().getObjectsAt(x, this.getY(), Zombie.class); if(actors.size() > 0) { return true; } } } return false; } public void shoot() { getWorld().addObject(new Pea(), this.getX() + 43, this.getY() - 20); if(this.getY() > 130) { getWorld().addObject(new Pea(), this.getX() + 43, this.getY() - 117); } if(this.getY() < 518) { getWorld().addObject(new Pea(), this.getX() + 43, this.getY() + 77); } shootTime = 60; } public void loseHP() { super.loseHP(); } public static int getCost() { return cost; } public boolean checkDamage() { return super.checkDamage(); } public boolean checkDeath() { return super.checkDeath(); } public void die() { super.die(); } } I really don't understand why the wallnut and sunflower class just stopped working. I have all the spawning the same.
CalzoneCannon CalzoneCannon

2014/6/8

#
I did make a small discovery, although I can't make any sense of it. If I have certain methods in my act class for any subclasses, they become not placeable. Although, if I put those methods in the act method of my plant class, nothing happens. I am completely and utterly confused.
danpost danpost

2014/6/8

#
There is something that is bothering me in your Lawn class. You are using 'grid.length' both in the constructor and in the 'build' method; but, if 'grid' is a Location object, it does not have a 'length'. Exactly what value are you trying to use as the limit for the counters in the 'for' loops?
CalzoneCannon CalzoneCannon

2014/6/8

#
The grid.length is what I am using for my limit. What grid.length does is returns the length of the grid array, meaning the amount of slots. The grid.length is returning the length of the array in the specific slot of the first array. It's a little hard to explain, but it's like an array of arrays.
danpost danpost

2014/6/8

#
'grid' is not declared as any type of array. You are using 'private Location grid;' to declare the field. This means it will hold a single Location object.
danpost danpost

2014/6/8

#
danpost wrote...
'grid' is not declared as any type of array. You are using 'private Location grid;' to declare the field. This means it will hold a single Location object.
Wait a minute. Give me a second to check something out.
danpost danpost

2014/6/8

#
Ok. None of your square brackets were shown on your post (and none of the values or fields within them) because you did not use the 'code' tag below the input box to insert your code into your post. I now have a better idea of what you are doing (or trying to do). I would like to see what your Lawn class look like now (use the 'code' tag below the 'Post a reply' input box to insert your code into the post.
There are more replies on the next page.
1
2
3