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

3 days ago

boolean not changing

1
2
bonyay bonyay

3 days ago

#
I'm thinking that my issue is when you switch worlds back to the Dock world after purchasing the next level in the Shop world, the boolean values reset? I tried changing it and put them in the shop world instead, but had the same issue, and then I tried putting it into the "FishShad" actor. I have tried other solutions, but that would make for a lengthy list. Apologies for the lack of comments in my code, but it should be straightforward enough to understand. I can explain what it's meant to do if needed. I mostly cut all the irrelevant bits of it, and I also reverted it to the state it was before I tried any fixes.
public class RodOneBuy extends BuyButtons
{
    /**
     * Act - do whatever the RodOneBuy wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        purchase();
    }
    public void purchase()
    {
        if(Dock.moneyVar >= 25 && Greenfoot.mouseClicked(this) && Dock.rodNo==true && Dock.rodLow==false)
        {
            Dock.moneyVar -= 25;
            Dock.rodLow=true;
            Dock.rodNo=false;
        }
    }
}
public class Dock extends World
{
    public static int moneyVar=0;
    public static int energyVar=100;

    public int timer=0;
    
    public static boolean baitNo=true;
    public static boolean rodNo=true;
    public static boolean baitLow=false;
    public static boolean rodLow=false;
    public static boolean baitMed=false;
    public static boolean rodMed=false;
    public static boolean baitHigh=false;
    public static boolean rodHigh=false;
    /**
     * Constructor for objects of class Dock.
     * 
     */
    public Dock()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1); 
        setBackground(new GreenfootImage("dockbg.png"));
        prepare();
        
        Greenfoot.start();
        
    }
public class FishShad extends Actor
{
    /**
     * Act - do whatever the FishShad wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        swim();
        escape();
        caught();
    }
    public void caught()
    {
        if(Greenfoot.mouseClicked(this) && Dock.rodNo==true && Dock.baitNo==true && Dock.energyVar>0)
        {
            Can can = new Can();
            getWorld().addObject(can, 300, 200);
            Dock.energyVar-=5;
            getWorld().removeObject(this);
            return;
        }
        else if(Greenfoot.mouseClicked(this) && Dock.rodLow==true && Dock.baitNo==true && Dock.energyVar>0)
        {
            Can can = new Can();
            getWorld().addObject(can, 297, 200);
            getWorld().addObject(can, 303, 198);
            Dock.energyVar-=5;
            getWorld().removeObject(this);
            return;
        }
    }
danpost danpost

3 days ago

#
bonyay wrote...
boolean not changing
static variables only reset when the scenario is recompiled. Between one compiling to the next, it does not matter how many Dock objects you create or when you create them, the static variables will not reset. As well, the static variables are shared among those Dock objects created. Basically, all those static variables in your Dock class codes should not be static at all. I know it is easier to access them from other classes, but there are ways around that when not using static variables. For example, all "Dock." instances in your FishShad class codes can be changed to "((Dock)getWorld())." to access them without them being static.
bonyay bonyay

2 days ago

#
danpost wrote...
For example, all "Dock." instances in your FishShad class codes can be changed to "((Dock)getWorld())." to access them without them being static.
Thank you so much for your help so far, I'm sure I'm much further along than I was before but I am still having some problems. (I knew nothing about non-static booleans before today) Luckily i solved errors with the help of reading past threads, but I am back to my original problem being that the "catch" code that relies on rodLow being true is not executing, and only the one with rodNo=true is. This time I added some comments to try and make more sense as to what I intend each thing to do. The solution is probably very simple and I'm just too uneducated in code to see it...However this is a final project due in 2 days so I don't think I have the time to learn everything!! ;(( I tried to take advice from some posts you made in the past about making an intermediate class and putting the worlds underneath it, then using the intermediate class in the code requiring a world to use but perhaps I misunderstood? (My code is also a bit scrambled right now, as I've been trying different solutions. Right now, all the public booleans other than rodLow, rodNo, and baitNo are irrelevant because I'm only testing the upgrade from rodNo to rodLow.) By the way, I had to do this due to an error about something to do with ClassCatching Edit: Had to add, I've been searching for the solution myself obviously, but I can't really get past the whole idea of "there is the original boolean and its value, and a copy is sent to the method and the method changes the copy but not the original" and i cant find the solution to make it change the original too. I saw someone use something like "return true;" but clearly I don't know where or how to implement that into my existing code.
public class Intermed extends World
{
    public boolean baitNo=true; 
    public boolean rodNo=true;
    
    public boolean baitLow=false;
    public boolean rodLow=false;
    /**
     * Constructor for objects of class Intermed.
     * 
     */
    public Intermed()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1); 
    }
}
public class RodOneBuy extends BuyButtons
{
    /**
     * Act - do whatever the RodOneBuy wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        purchase();
    }
    public void purchase()
    {
        if(Dock.moneyVar >= 25 && Greenfoot.mouseClicked(this) && ((Intermed)getWorld()).rodLow==false && ((Intermed)getWorld()).rodNo==true)
        {
            Dock.moneyVar -= 25;  //the price of the rod upgrade
            ((Intermed)getWorld()).rodLow=true; //upgrades the rod so that better catches (2 cans instead of 1) are enabled
            ((Intermed)getWorld()).rodNo=false;  //disables the catches (only 1 can) attached to the non-upgraded rod
            return;
        }
    }
}
public class FishShad extends Actor
{
    /**
     * Act - do whatever the FishShad wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        swim();
        escape();
        caught();
    }
    public void caught()
    {
        if(Greenfoot.mouseClicked(this) && ((Intermed)getWorld()).rodNo==true && ((Intermed)getWorld()).baitNo==true && Dock.energyVar>0)
        {
            Can can = new Can();   
            getWorld().addObject(can, 300, 200);  //adds a can into the Dock world for the player to sell
            Dock.energyVar-=5;  
            getWorld().removeObject(this);  //removes the fish shadow (actor FishShad) from the water (Dock world)
            return;   //to prevent error when FishShad is removed from the world using this method
        }
        else if(Greenfoot.mouseClicked(this) && ((Intermed)getWorld()).rodLow==true && ((Intermed)getWorld()).baitNo==true && Dock.energyVar>0)
        {
            Can can = new Can();
            getWorld().addObject(can, 297, 200);  
            getWorld().addObject(can, 303, 198);  //should add a second can into the Dock world
            Dock.energyVar-=5;
            getWorld().removeObject(this);
            return;
        }
    }
danpost danpost

yesterday

#
bonyay wrote...
my original problem being that the "catch" code that relies on rodLow being true is not executing, and only the one with rodNo=true is.
You have coded your FishShad actor to be only in the Intermed world. If it is the only world it is to be in, then fine. If not, you need to check the type of world before casting to any type world:
if (getWorld().instanceof(Intermed) && // etc.
If the different worlds have their specifically set boolean values, then those values are not even needed. Just a simple check to see which world it is in would be enough (again with the same check as above).
danpost danpost

yesterday

#
If your Intermed class had a reference to the Dock object:
public Dock dock;
(somewhere having an object assigned to it, of course, probably in the Intermed constructor) then, your actor classes can use:
Dock dock = ((Intermed)getWorld()).dock;
to reference it. Your boolean values can be changed in a similar manner from other classes:
((Intermed)getWorld()).baitNo = true;
(as an example) As far as classes go, non-static members, methods and variables, give behaviors and states of objects created from the class (repectively). Imagine having two or more objects created from the class (even if you only use one at a time), If a values of the variables can be different among those objects created, then those variables need to be non-static. Non-static variables are assigned individually to each object created from the class. If the value is the same, all the time, for all objects created from the class, only then can static be used. A static variable is not duplicated for each object created from the class.
bonyay bonyay

yesterday

#
danpost wrote...
You have coded your FishShad actor to be only in the Intermed world. If it is the only world it is to be in, then fine. If the different worlds have their specifically set boolean values, then those values are not even needed. Just a simple check to see which world it is in would be enough (again with the same check as above).
Yes, FishShad only needs to be in Intermed or Dock (which i have set as a subclass of Intermed). It shouldn't be in any other worlds (which that part of the code works as expected). I have all my currently relevant boolean values in Intermed, but I want them to be able to be changed, which would make that way of checking stop working after some upgrades, wouldn't it? (I have more than the one upgrade- you should be able to buy a new rod 3 times, each increasing your quantity of catches). Or are you saying that your example would be a better way of checking them in the if statements? Sorry if I'm not understanding, you may need to dumb things down, I've only been introduced to anything even related to real coding a couple months ago.
danpost wrote...
Your boolean values can be changed in a similar manner from other classes:
((Intermed)getWorld()).baitNo = true;
(as an example)
Perhaps I am also misunderstanding what you mean here, because I used those exact lines in my RodOneBuy code, yet they seem to have not changed the boolean value once it goes to the caught method in FishShad? Should I give more of my code to see if you spot anything else that could be the issue?
bonyay bonyay

yesterday

#
danpost wrote...
As far as classes go, non-static members, methods and variables, give behaviors and states of objects created from the class (repectively). Imagine having two or more objects created from the class (even if you only use one at a time), If a values of the variables can be different among those objects created, then those variables need to be non-static. Non-static variables are assigned individually to each object created from the class. If the value is the same, all the time, for all objects created from the class, only then can static be used. A static variable is not duplicated for each object created from the class.
I think I understand better now, thank you. Teaching myself using exclusively the Internet is difficult...everyone in my class but me has coding experience, so my instructor doesn't explain things to us T_T Before you suggest it, I unfortunately I cannot ask them for help because of social issues.
danpost danpost

yesterday

#
bonyay wrote...
I have all my currently relevant boolean values in Intermed, but I want them to be able to be changed, which would make that way of checking stop working after some upgrades, wouldn't it? (I have more than the one upgrade- you should be able to buy a new rod 3 times, each increasing your quantity of catches). Or are you saying that your example would be a better way of checking them in the if statements. << Code Omitted >>
For either checking or changing their values, that is the preferred way. Maybe, if I could see the methods used where you change between the Dock and Shop worlds, and maybe the main parts of the Shop world (variables and constructor(s), at least). I am hoping that you do not leave the Dock world, to enter the Shop world and then return to a new Dock world.
bonyay bonyay

yesterday

#
danpost wrote...
Maybe, if I could see the methods used where you change between the Dock and Shop worlds, and maybe the main parts of the Shop world (variables and constructor(s), at least). I am hoping that you do not leave the Dock world, to enter the Shop world and then return to a new Dock world.
You were correct, omg...I completely overlooked that, thank you so much. I don't know any other way to code it, though. Im sorry!! Hopefully this is the last thing I need. Edit: Ive been searching for the past hour and can't seem to find a solution that I could use. So, uh, yeah, you might need to overexplain yourself unless it's super duper simple.
public class DockButton extends Buttons
{
    /**
     * Act - do whatever the DockButton wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        change();
    }
    public void change()
    {
        if(Greenfoot.mouseClicked(this))
        {
            Greenfoot.setWorld(new Dock());
        }
    }
}
public class ShopButton extends Buttons
{
    /**
     * Act - do whatever the ShopButton wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        change();
    }
    public void change()
    {
        if(Greenfoot.mouseClicked(this))
        {
            Greenfoot.setWorld(new Shop());
        }
    }
}
public class Shop extends Intermed
{
    
    /**
     * Constructor for objects of class Shop.
     * 
     */
    public Shop()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        
        setBackground(new GreenfootImage("shopbg.png"));
        prepare();
        
    }
    
    private void prepare()
    {
        Money money = new Money();
        addObject(money,68,50);
        Energy energy = new Energy();
        addObject(energy, 532, 50);
        ShopButton shopButton = new ShopButton();
        addObject(shopButton,35,365);
        RoomButton roomButton = new RoomButton();
        addObject(roomButton,34,305);
        DockButton dockButton = new DockButton();
        addObject(dockButton,100,365);
        
        BaitOneBuy baitOneBuy = new BaitOneBuy();
        addObject(baitOneBuy,157,353);
        
        BaitTwoBuy baitTwoBuy = new BaitTwoBuy();
        addObject(baitTwoBuy,300,353);

        BaitThreeBuy baitThreeBuy = new BaitThreeBuy();
        addObject(baitThreeBuy,458,353);
        
        RodOneBuy rodOneBuy = new RodOneBuy();
        addObject(rodOneBuy,148,181);
        
        RodTwoBuy rodTwoBuy = new RodTwoBuy();
        addObject(rodTwoBuy,300,181);
        
        RodThreeBuy rodThreeBuy = new RodThreeBuy();
        addObject(rodThreeBuy,454,183);
        
       
    }
}
danpost danpost

yesterday

#
bonyay wrote...
You were correct, omg...I completely overlooked that, thank you so much. I don't know any other way to code it, though. Im sorry!! Hopefully this is the last thing I need. Edit: Ive been searching for the past hour and can't seem to find a solution that I could use. So, uh, yeah, you might need to overexplain yourself unless it's super duper simple. << Code Omitted >>
When creating an object (specifically, Dock, in your case) it is given memory storage for each non-static variable for its own use. So, when you execute, say, line 15 of the ShopButton class, the new Dock object will have its non-static variable set to their initial values. To regress back to the Dock object that lead to the Shop world, use the following:
/**  going to Shop world  (from some actor class)  */
Greenfoot.setWorld(new Shop(getWorld()));

/**  variable in Shop  */
private World returnToWorld;

/**  beginning of constructor in Shop  */
public Shop(World world) {
    super();
    returnToWorld = world;
    // etc.

/**  return to previous (Dock) world (from actor) */
Greenfoot.setWorld(((Shop)getWorld()).returnToWorld);
bonyay bonyay

yesterday

#
danpost wrote...
/** return to previous (Dock) world (from actor) */ Greenfoot.setWorld(((Shop)getWorld()).returnToWorld);
The thing is, if it routes to the previous world then I can't go to the third world. Perhaps it would just be easier if I uploaded it as a scenario so you had access to all my code? Or sent it to you? It's due tomorrow, and I just don't know what to do anymore. I have finals for all my classes due tomorrow that I dont even know how to begin and this has been taking up all my time. Edit: I uploaded it as a scenario. I hope I'm not asking too much. I'm really trying not to just give up here.
danpost danpost

yesterday

#
bonyay wrote...
I uploaded it as a scenario. I hope I'm not asking too much. I'm really trying not to just give up here.
Remove Intermed class -- move codes to Dock class and change to extend World. In Dock class, add reference for Shop and Room objects and, in Dock constructor, assign objects to them. If Dock object reference is passed among the different world, all worlds would be accessible via that Dock object. ***** In your FishShad class, in second part of the caught method, you only create one Can object; so, no second Can object is added into the world. Better is:
Can can = new Can();
getWorld().addObject(can, 297, 200); 
Can can2 = new Can();
getWorld().addObject(can2, 303, 198);
or, more simply:
getWorld().addObject(new Can(), 297, 200);
getWorld().addObject(new Can(), 303, 198);
bonyay bonyay

yesterday

#
danpost wrote...
In Dock class, add reference for Shop and Room objects and, in Dock constructor, assign objects to them. If Dock object reference is passed among the different world, all worlds would be accessible via that Dock object.
Alright, I've done the other parts, and I'm onto this. Maybe a stupid question, but are you saying like I should do
ShopButton shopbutton = new ShopButton();
? I am so sorry if this is aggravating, once again I am very new with rather limited guidance. I do best with specific examples, especially since I'm new to this terminology. (my brain is also a little fried from it being 1 AM with no sleep in 2 days combined with a lovely sprinkle of stress)
danpost danpost

yesterday

#
With the following, no reference is kept:
addObject(new Player(), 100, 365);
which is almost equivalent to, or short for:
Player player = new Player();
addObject(player, 100, 365);
The only difference between these two is that you can do something to player somewhere later within the method currently being executed with the two-liner (since there is a local reference to the player in that method). In the first case, you would have to go through all actors in the world and find the instance that is a Player object to get the reference. On the other hand, if a field reference is kept:
public Player player;

public Dock() {
    super(600, 400, 1);
    player = new Player();  // retains reference
    addObject(player, 300, 200); // wherever
    // etc.
then, the reference is readily available to any actor in the world and any other object that gains a reference to this world. With the following, all worlds will be accessible provided the current world (or an actor within it) maintains a reference to the Dock world:
public Shop shop;
public Room room;

public Dock() {
    super(600, 400, 1);
    shop = new Shop();
    room = new Room();
    prepare();
}
The codes of "new Shop()" and "new Room()" should not be used anywhere else in your project. Nor should "shop =" and "room =" be found anywhere else.
danpost danpost

23 hours ago

#
You still have two static variables in your Dock class. I am thinking that maybe energyVar is a state of the Player object and should probably be in the Player class. The other variable, moneyVar, seems to be a Player state as well and should probably be moved, as well (although, it might be more questionable).
There are more replies on the next page.
1
2