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

2013/5/27

HELP - Accessing boolean from another class

1
2
Brunito Brunito

2013/5/27

#
Hello everyone, I am trying to create a Pacman for my school project and I am having some trouble with my game. The fact is that I want give my Pacman the ability to eat the other Ghosts in the world when he ate one "bonus food". Here is the code in my Ghost Class : /** * This method is used whenever the Pacman eats a "bonusFood". If he does, the ghosts will be changed into "Ghosts_e" which are edible by the Pacman. */ public void changeGhost() { int Xi = getX(); int Yi = getY(); if(Pacman.bonusEaten) { getWorld().removeObject(this); getWorld().addObject(new Ghost_e(), Xi, Yi); } } And here is the code in my Pacman class : public void lookForFood() { if ( canSee(Food.class) ) { eat(Food.class); Greenfoot.playSound("pacman_chomp.wav"); foodEaten = foodEaten + 1; } if ( canSee(BonusFood.class)) { eat(BonusFood.class); bonusEaten = true; Greenfoot.playSound("pacman_eatfruit.wav"); Greenfoot.playSound("pacman_intermission.wav"); Greenfoot.playSound("pacman_intermission.wav"); //Method used to wait 10 sec (duration of 2x intermission.wav) //bonusEaten=false; } if (foodEaten >= 135) { Greenfoot.playSound("pacman_beginning.wav"); Greenfoot.stop(); } if(bonusEaten && canSee(Ghost_e.class)) { eat(Ghost_e.class); Greenfoot.playSound("pacman_eatghost.wav"); } } } The problem is that I can't access the boolean "bonusEaten" from my Ghost class. I already tried to follow this tutorial : http://www.greenfoot.org/doc/howto-1. But I wasn't able to fix my problem. Everytime I try to compile my game I have this error : "non static variable bonusEaten cannot be referenced from a static context". Thanks ahead for your help!
danpost danpost

2013/5/27

#
An easier way to code what you are trying to do, would be to use a 'static boolean' class field in the Ghost class. Use it to control the state and behavior of the ghosts (instead of removing one type and adding another). 'static' fields in a class have one value that belongs to the class itself (not individual values for each object of that class and not belonging to any one object of that class). Objects of that class have immediate access to that value. Like 'non-static' fields, they can be 'public' or 'private' and 'get' and 'set' methods can be created for external access from the class. The 'get' and 'set' methods for 'static' fields must also be declared as 'static'. When pacman eats a 'bonusFood' object, just use 'Ghost.setVulnerable();' to call the following 'static' method in the Ghost class:
// with these static fields
private static boolean vulnerable;
private static vulnerableTimer;

public static void setVulnerable()
{
    vulnerable = true;
    vulnerableTimer = 600;
}

// called by pacman class to get vulnerability of ghosts
// called with 'Ghost.getVulnerable()'
public static boolean getVulnerable()
{
    return vulnerable;
}

public static void runVulnerableTimer()
{
    if (vulnerable)
    {
        vulnerableTimer--;
        if (vulnerableTimer == 0) vulnerable = false;
    }
}

In the world class 'act' method, add the following:
[code]Ghost.runVulnerableTimer();
Brunito Brunito

2013/5/28

#
danpost wrote...
An easier way to code what you are trying to do, would be to use a 'static boolean' class field in the Ghost class. Use it to control the state and behavior of the ghosts (instead of removing one type and adding another). 'static' fields in a class have one value that belongs to the class itself (not individual values for each object of that class and not belonging to any one object of that class). Objects of that class have immediate access to that value. Like 'non-static' fields, they can be 'public' or 'private' and 'get' and 'set' methods can be created for external access from the class. The 'get' and 'set' methods for 'static' fields must also be declared as 'static'. When pacman eats a 'bonusFood' object, just use 'Ghost.setVulnerable();' to call the following 'static' method in the Ghost class:
// with these static fields
private static boolean vulnerable;
private static vulnerableTimer;

public static void setVulnerable()
{
    vulnerable = true;
    vulnerableTimer = 600;
}

// called by pacman class to get vulnerability of ghosts
// called with 'Ghost.getVulnerable()'
public static boolean getVulnerable()
{
    return vulnerable;
}

public static void runVulnerableTimer()
{
    if (vulnerable)
    {
        vulnerableTimer--;
        if (vulnerableTimer == 0) vulnerable = false;
    }
}

In the world class 'act' method, add the following:
[code]Ghost.runVulnerableTimer();
Wow! Thank you so much danpost! It helped me a lot. It is functionning perfectly well! I was wondering if I could use this thread if I have other questions for my project or If I should make another thread everytime I have a question?
danpost danpost

2013/5/28

#
It is usually better to start a different discussion thread for different issues. Sometimes, however, if the discussion was specifically created for a particular project, you may have several different topics included in it. Using the same thread is not too problematic, as long as it is a current thread (re-activating an old thread is discouraged).
Brunito Brunito

2013/5/28

#
Ok thank you then I will use this thread for the questions related to my school project. (Is there a way to change the title maybe?) I could use some help for the code of movement of my Ghosts. Actually, they are moving randomly from 1 cell if there is no wall in the selected direction. To do so I use this code :
 
    public void move()
    {
       int x = Greenfoot.getRandomNumber(4);
        if (x==0 && upFree){
          setLocation(getX(), getY() - 1);
       }
       else if (x==1 && downFree){
          setLocation(getX(), getY() +1);
       }
       else if (x==2 && leftFree){
          setLocation(getX()-1, getY());
       }
       else if (x==3 && rightFree){
          setLocation(getX()+1, getY());
       }
    }
Here is the code of the boolean upFree, rightFree,...
  public void upFreeBoolean()
    {
        Actor upWall = getOneObjectAtOffset(0,-1, Mur.class);
        if(upWall != null){
            upFree=false;
        }
        else{
            upFree=true;
        }
    }
    

    public void downFreeBoolean()
    {
        Actor downWall = getOneObjectAtOffset(0, 1, Mur.class);
        if(downWall != null){
            downFree=false;
        }
        else{
            downFree=true;
        }
    }
    
    public void leftFreeBoolean()
    {
        Actor leftWall = getOneObjectAtOffset(-1, 0, Mur.class);
        if(leftWall != null){
            leftFree=false;
        }
        else{
            leftFree=true;
        }
    }
    
    public void rightFreeBoolean()
    {
        Actor rightWall = getOneObjectAtOffset(1, 0, Mur.class);
        if(rightWall != null){
            rightFree=false;
        }
        else{
            rightFree=true;
        }
    }
The problem is that the Ghosts haven't a real movement. I mean that they are only moving one cell by one and sometimes they go to the same cell they were previously (means no movement)... I would like to make a code to set my Ghosts to go into one direction until they encounter a wall. Have you any idea of how I could do that?
danpost danpost

2013/5/28

#
Brunito wrote...
I would like to make a code to set my Ghosts to go into one direction until they encounter a wall.
I really do not think that is what you want. If your ghosts were to act in that manner, then there will most probably be some pathways that they will never get to traverse (meaning there will some safe zones for pacman). They should continue in that direction until there is a choice to proceed (other than backward). Then, that choice should be randomly made. You can call the following method before your movement code to set the direction to move. You only need the one given collision checking method ('canMove') and no usage of booleans fields to determine direction.
public void setDirection()
{
    // count possible ways to proceed (not including backward)
    dirs = 0;
    turn(-90); if (canMove()) dirs++; // checks left
    turn(90); if (canMove()) dirs++; // checks front
    turn(90); if (canMove()) dirs++; // checks right
    turn(-90); // resets initial rotation
    if (dirs == 0) // if nowhere to proceed
    { // face backward and exit method
        turn(180);
        return;
    }
    // can proceed somewhere
    int choice = Greenfoot.getRandomNumber(dirs); // eeni-meeni-minee-mo
    turn(-180); // face backward
    // count down open paths while turning to them
    while (choice>=0)
    {
        turn(90); // first left, then front, then, right
        if (canMove()) choice--;
    }
}

private boolean canMove()
{
    move(1);
    Actor mur = getOneIntersectingObject(Mur.class);
    move(-1);
    return mur == null;
}
In your 'act' method, you would simply use the following for the movement code:
setDirection();
move(1);
danpost danpost

2013/5/28

#
The 'setDirection' method can be simplified a little:
public void setDirection()
{
    // count possible ways to proceed (not including backward)
    dirs = 0;
    turn(-90); 
    for (i=0; i<3; i++)
    {
        if (canMove()) dirs++;
        turn(90);
    } // comes out facing backward
    if (dirs == 0) return; // if nowhere to proceed, exit facing backward
    // can proceed somewhere
    int choice = Greenfoot.getRandomNumber(dirs); // eeni-meeni-minee-mo
    // count down open paths while turning to them
    while (choice>=0) // started already facing backward
    {
        turn(90); // first left, then front, then right
        if (canMove()) choice--;
    }
}
danpost danpost

2013/5/28

#
I know with this your ghosts will be turned upside-down and sideways. You can add an instance int field called 'direction' to the ghost class to hold the direction of movement (in degrees). Then, as the first line in 'setDirection', add 'turn(direction);' and as the last line in that method, add 'direction = getRotation();', and then after 'move(1);' in the 'act' method add 'setRotation(0);'.
Brunito Brunito

2013/5/29

#
First of all, thank you for your help. I appreciate it a lot! I have some trouble with the code you are giving me. The Ghosts are actually moving correctly, but they are going throw walls. Maybe there is a problem with the "canMove()" method?
danpost danpost

2013/5/29

#
I have tested the code I gave and all appears to be working properly. The problem is probably caused by something somewhere else in your code. Do you have any code in the Mur class? if so, what? if not, post the current Ghost class code. EDIT: working properly, except for if you have any dead ends (which you would have already complained about if you did have some in your map). Solving that issue involved moving the statement we inserted as the last statement in the setDirection method to the act method after the call to setDirection.
danpost danpost

2013/5/29

#
When testing, I was using a gridded world (8x8 cellsize) which worked well. When using a non-gridded world (1x1 cellsize), I adjusted the image of the ghost to barely fit within the pathways between the walls and changed all 'move(1)'/'move(-1)' to 'move(2)'/move(-2)'. I worked well that way, also. In neither case were the ghosts going through walls!
Brunito Brunito

2013/5/30

#
Well.. I have no idea why it isn't working in my game... I uploaded my code to let you see better what's my situation : Pacman Project Do you have any idea where is the problem?
danpost danpost

2013/5/30

#
Yeah, you still had your old movement methods and stuff messing with the new movement code. I cleaned up the code for the class, added the movement code to the end of the 'setDirection' method and renamed the method to 'move'. Also, you probably tried to 'fix' the code of the 'setDirection' method without success and did not precisely follow my direction on placing certain lines in the code. The entire class code follows:
import greenfoot.*;

public class Ghost extends Personnages
{
    private static boolean vulnerable;
    private static int vulnerableTimer;

    private GreenfootImage image_e; 
    private GreenfootImage image_n;
    private int direction;
    
    public Ghost()
    {
        image_n = new GreenfootImage("ghost.png");
        image_e = new GreenfootImage("ghost_e.png");
    }

    public void act() 
    {
        eatPacman();
        changeGhost();
        move();
    }
    
    private void eatPacman()
    {
        if (canSee(Pacman.class) && vulnerable == false ) 
        {
            eat(Pacman.class);
            Greenfoot.playSound("pacman_death.wav");
            Greenfoot.stop();
        }
    }

    private void changeGhost()
    {
        if(vulnerable) {
            setImage(image_e);
        }
        else {
            setImage(image_n);
        }
    }

    private void move()  
    {
        setRotation(direction);
        int dirs = 0;
        turn(-90);
        for (int i=0; i<3; i++) {   
            if (canMove()) dirs++;
            turn(90);
        }
        if (dirs == 0) return;
        int choice = Greenfoot.getRandomNumber(dirs);
        while (choice>=0) {  
            turn(90);  
            if (canMove()) choice--;  
        }  
        direction = getRotation();
        move(1);
        setRotation(0);
    } 

    private boolean canMove()  
    {  
        move(1);  
        Actor mur = getOneIntersectingObject(Mur.class);  
        move(-1);  
        return mur == null;  
    }  

    public static void setVulnerable()
    {
        vulnerable = true;
        vulnerableTimer = 20;
    }

    public static boolean getVulnerable()
    {
        return vulnerable;
    }

    public static void runVulnerableTimer()
    {
        if (vulnerable) {
            vulnerableTimer--;
            if (vulnerableTimer == 0) {
                vulnerable = false;
            }
        }
    }
}
Brunito Brunito

2013/5/31

#
Ok. Sorry for the "fixing", I didn't want to just copy your code without understanding it so I tried to rewrite it after reading yours. However, it seems that there is still a little glitch with this code : Each time a Ghost goes into a corner (example : where the cherries stands), the Ghost stop moving. Do you have any idea where is the problem? I think that's because we aren't checking if the Ghost can go backward so that when there is only this possibility left... They don't do anything. But I have no idea how to fix this in the code. Could you help me?
danpost danpost

2013/5/31

#
Yeah. Sorry. The problem arose when I combined the 'setDirection' code with the movement code to create a single 'move' method. Replace the 'move' method with the following:
private void move()  
{
    setRotation(direction);
    int dirs = 0;
    turn(-90);
    for (int i=0; i<3; i++) {   
        if (canMove()) dirs++;
        turn(90);
    }
    if (dirs > 0) {
        int choice = Greenfoot.getRandomNumber(dirs);
        while (choice>=0) {  
            turn(90);  
            if (canMove()) choice--;  
        }
    }
    direction = getRotation();
    move(1);
    setRotation(0);
}
There are more replies on the next page.
1
2