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

2020/9/22

Sharing a variable across actors

Randomgreenguy Randomgreenguy

2020/9/22

#
I just finished the tutorial and wanted to add more. I have named crabHealth that is added to if the crab eats worms. But i also wanted to have the health decrease if touched by the lobster and instantly killed. I have tried multiple methods but nothing seems to work.
Randomgreenguy Randomgreenguy

2020/9/22

#
crabHealth is an integer that I have declared in the Crab class and wanted to access in the Lobster class
RcCookie RcCookie

2020/9/23

#
There are multiple ways to do this:
//Access one intersecting object
Actor a = getOneIntersectingObject(Actor.class);

//Access all intersecting objects
List<Actor> a = getIntersectingObjects(Actor.class);
//Access one of the list
Actor ofList = a.get(0);

//Access one at a certain offset
Actor a = getOneObjectAtOffset(x, y, Actor.class);

//Access all at a certain point
List<Actor> a = getWorld().getObjectsAt(x, y, Actor.class);
danpost danpost

2020/9/23

#
RcCookie wrote...
There are multiple ways to do this:
//Access one intersecting object
Actor a = getOneIntersectingObject(Actor.class);
Immediately after this, you will need to check for a null reference:
if (a != null) // ...
//Access all intersecting objec[ts
List<Actor> a = getIntersectingObjects(Actor.class);
//Access one of the list
Actor ofList = a.get(0);
Line 4 must not be executed without first checking that the list is not empty. Also, the list object must be type cast to Actor before it can be assigned to the reference variable:
Actor ofList = null;
if ( ! a.isEmpty() )
{
    ofList = (Actor)a.get(0);
    // ...
//Access one at a certain offset
Actor a = getOneObjectAtOffset(x, y, Actor.class);
Similar to the first code set.
//Access all at a certain point
List<Actor> a = getWorld().getObjectsAt(x, y, Actor.class);
Similar to the second code set. ****************************************************** Once you have the actor referenced, you will need to type cast it as a Crab object before you can access the crabHealth field:
Crab crab = (Crab) a; // Actor a
Randomgreenguy Randomgreenguy

2020/9/23

#
Which class would i declare this in and i thought it would something similar to this totalCrabHealth = getWorld().getObjects(Crab.class).get(0).crabHealth;
Randomgreenguy Randomgreenguy

2020/9/23

#
I left my code here if that makes it easier to understand import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) import java.lang.Class; public class Crab extends Actor { int movementSpeed = 4; int turningSpeed = 4; public static int crabHealth = 69; public boolean crabHealthChanged = false; public boolean crabBreadBoost = false; /** * Act - do whatever the Crab wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { moveAndTurn(); eatWorm(); eatBread(); eliminateCrab(); //Every time a lobster damages a crab, it dies. crabNotOverHealth(); } public void moveAndTurn() { move(movementSpeed); if (Greenfoot.isKeyDown("left")) { turn(turningSpeed); } if (Greenfoot.isKeyDown("right")) { turn(-turningSpeed); } } public void eatWorm() { Actor worm; worm = getOneObjectAtOffset(0, 0, Worm.class); if (worm != null) { World world; world = getWorld(); world.removeObject(worm); Greenfoot.playSound("eating.wav"); crabHealth += 20; crabHealthChanged = true; } } public void eatBread() { Actor bread; bread = getOneObjectAtOffset(0, 0, Worm.class); int boostTimer = 0; if (bread != null) { World world; world = getWorld(); world.removeObject(bread); crabBreadBoost = true; } if (crabBreadBoost = true) { boostTimer ++; movementSpeed += 3; turningSpeed += 2; } if (boostTimer >= 10) { crabBreadBoost = false; boostTimer = 0; } if (crabBreadBoost = false) { movementSpeed = 4; turningSpeed = 4; } } public void eliminateCrab() { Actor lobster; lobster = getOneObjectAtOffset(0, 0, Lobster.class); if (lobster != null) { World world; world = getWorld(); world.removeObject(lobster); } } public void crabNotOverHealth() { if (crabHealth > 100) { crabHealth = 100; } if (crabHealth < 0) { crabHealth = 0; } if (crabHealthChanged = true) { getWorld().showText("Crab Health: " + crabHealth, 80, 10); crabHealthChanged = false; } } } crab Class import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) import java.lang.Class; /** * Write a description of class Lobster here. * * @author (your name) * @version (a version number or a date) */ public class Lobster extends Actor { public static int totalCrabHealth; public boolean lobsterDamagedCrab = false; int crabHealth = getOneObjectAtOffset(0, 0, Crab.class); /** * Act - do whatever the Lobster wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { damageCrabHealth(); moveAround(); } public void moveAround() { move(4); if (Greenfoot.getRandomNumber(100) < 10) { turn(Greenfoot.getRandomNumber(90) - 45); } if (getX() <= 5 || getX() >= getWorld().getWidth() - 5) { turn(180); } if (getY() <= 5 || getY() >= getWorld().getHeight() - 5) { turn(180); } } public void damageCrabHealth() { Actor crab; crab = getOneObjectAtOffset(0, 0, Crab.class); if (crab != null) { World world; world = getWorld(); totalCrabHealth -= 20; lobsterDamagedCrab = true; //world.removeObject(crab); } do { totalCrabHealth = getWorld().getObjects(Crab.class).get(0).crabHealth; lobsterDamagedCrab = getWorld().getObjects(Crab.class).get(0).crabHealthChanged; crab = null; } while(crab != null); } } Sorry I am new to greenfoot and very confused
danpost danpost

2020/9/23

#
So many issues, it is hard to decide where to start. Also, without line numbering, it would be difficult to explain what changes can be made. SO ... here we go: Given Crab class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.lang.Class;

public class Crab extends Actor
{
    int movementSpeed = 4;
    int turningSpeed = 4;
    public static int crabHealth = 69;
    public boolean crabHealthChanged = false;
    public boolean crabBreadBoost = false;
    
    /**
     * Act - do whatever the Crab wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    
    public void act() 
    {
        moveAndTurn();
        eatWorm();
        eatBread();
        eliminateCrab(); //Every time a lobster damages a crab, it dies.
        crabNotOverHealth();
    }
    
    public void moveAndTurn()
    {  
        move(movementSpeed);
        
        if (Greenfoot.isKeyDown("left"))
        {
        turn(turningSpeed);
        }
      
        if (Greenfoot.isKeyDown("right"))
        {
        turn(-turningSpeed);
        }
      
    }

    public void eatWorm()
    {
        Actor worm;
        worm = getOneObjectAtOffset(0, 0, Worm.class);
    
        if (worm != null)
       {
         World world;
         world = getWorld();
         world.removeObject(worm);
         Greenfoot.playSound("eating.wav");
         crabHealth += 20;
         crabHealthChanged = true;
       }
      
    }
    
    public void eatBread()
    {
        Actor bread;
        bread = getOneObjectAtOffset(0, 0, Worm.class);
        
        int boostTimer = 0;
        
        if (bread != null)
        {
            World world;
            world = getWorld();
            world.removeObject(bread);
            crabBreadBoost = true;
        }
        
        if (crabBreadBoost = true)
        {
                boostTimer ++;

                movementSpeed += 3;
                turningSpeed += 2;
        }
        
        if (boostTimer >= 10)
        {
            crabBreadBoost = false;
            boostTimer = 0;
        }
        
        if (crabBreadBoost = false)
        {
            movementSpeed = 4;
            turningSpeed = 4;
        }
    }
        
    public void eliminateCrab()
    {
        Actor lobster;
        lobster = getOneObjectAtOffset(0, 0, Lobster.class);
        
        if (lobster != null)
        {
            World world;
            world = getWorld();
            world.removeObject(lobster);
        }
    }
    
        public void crabNotOverHealth()
    {
        
        if (crabHealth > 100)
        {
           crabHealth = 100;
        }
        if (crabHealth < 0)
        {
            crabHealth = 0; 
        }
        
        if (crabHealthChanged = true)
        {
            getWorld().showText("Crab Health: " + crabHealth, 80, 10);
            crabHealthChanged = false;
        }
    }
}
Given Lobster class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.lang.Class;

/**
 * Write a description of class Lobster here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Lobster extends Actor
{
    public static int totalCrabHealth;
    public boolean lobsterDamagedCrab = false;
    int crabHealth = getOneObjectAtOffset(0, 0, Crab.class);
    
    /**
     * Act - do whatever the Lobster wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        damageCrabHealth(); 
        moveAround();
    }   
    
    public void moveAround()
    {
        move(4);
        if (Greenfoot.getRandomNumber(100) < 10)
        {
            turn(Greenfoot.getRandomNumber(90) - 45);
        }
        if (getX() <= 5 || getX() >= getWorld().getWidth() - 5)
        {
            turn(180);
        }
        if (getY() <= 5 || getY() >= getWorld().getHeight() - 5)
        {
            turn(180);
        }
    }

     public void damageCrabHealth()
    {      
        Actor crab;
        crab = getOneObjectAtOffset(0, 0, Crab.class);
   

        if (crab != null)
        {  
            World world;
            world = getWorld();
            totalCrabHealth -= 20;
            lobsterDamagedCrab = true;
            //world.removeObject(crab);
        }
        
        do 
        { 
          totalCrabHealth = getWorld().getObjects(Crab.class).get(0).crabHealth;
          lobsterDamagedCrab = getWorld().getObjects(Crab.class).get(0).crabHealthChanged;
          crab = null;
        } while(crab != null);
    }

}
danpost danpost

2020/9/24

#
Starting at the top: (1) Remove line 2 from both classes. It not a problem -- just not needed. The java.lang.* package is always automatically included in your projects. (2) Line 8 in Crab class should not be made static. crabHealth is (or is something that would be) specific to each instance of Crab (or, to each crab actor). In general, a class describes an object, its states (property values) in fields and its behavior (actions) in methods. The static modifier is used for other functions and class/global state properties. (3) Lines 9 and 10 in Crab class can be dispensed with. It would involve re-writes in codes elsewhere. However, the fewer fields you have to work with, the easier the coding and less apt you are to miss something. (4) This deals with one your main concerns as well as the mention of line 9 in (3) above. Look at lines 53 and 54 in Crab class. Note that not just there, but any time the health changes, you would want to update the displayed crab health value. Also, since you may want to change a crab's health via another actor (i.e. lobster), it would be helpful to make a method for changing the health value that also updates the display:
public void adjustHealth(int chgAmt)
{
    crabHealth += chgAmt;
    if (crabHealth > 100) crabHealth = 100;
    if (crabHealth < 0) crabHealth = 0;
    getWorld().showText("Crab Health: " + crabHealth, 80, 10);
}
With this, you can replace lines 53 & 54 with:
adjustHealth(20);
and remove line 23 and lines 108 thru 125. (5) Line 22 in the Crab class (or, rather, the eliminateCrab method) checks for a collision between crab and lobster, which is already being done in the Lobster class. Collision checking between two types should only be done by only one of the two types. not by both. Usually, it is best done by the more major actor -- Crab, in your case. That means you can remove all crab-related code from the Lobster class (lines 12, 13, 14, 22, and lines 43 thru 64). Now, rename the method (line 95) and the calling of it (line 22) to touchLobster, since that is what is being checked. The method can be simplified to the following:
public void touchLobster()
{
    if (isTouching(Lobster.class))
    {
        removeTouching(Lobster.class);
        adjustHealth(-20);
    }
}
You may want to add code at the end of the adjustHealth method in the Crab class to remove the crab from the world (and possibly play a sound) when health is zero.
Randomgreenguy Randomgreenguy

2020/9/24

#
Sorry for that, i kinda didn't know how to add lines. Anyways, my problem is solved and I just wanted to say thank you for your help. Also, just one more thing, I wanted my crab to gain a speed boost for 10 seconds after eating bread which randomly spawns.(still working on that) As you can see my code is not really displaying that.
Randomgreenguy Randomgreenguy

2020/9/24

#
what i'm trying to say is, i'm having trouble creating a timer.
danpost danpost

2020/9/24

#
Randomgreenguy wrote...
what i'm trying to say is, i'm having trouble creating a timer.
Line 64 is misplaced. Move it up to line 11. Otherwise (as it was), it is being initialized every frame. Then replace your eatBread method with the following:
public void eatBread()
{
    if (boostTimer > 0 && --boostTimer == 0)
    {
        movementSpeed = 4;
        turningSpeed = 4;
    }
    if (isTouching(Bread.class))
    {
        removeTouching(Bread.class);
        movementSpeed  += 3;
        turningSpeed += 2;
        boostTimer = 600;
    }
}
You can also remove line 10.
Randomgreenguy Randomgreenguy

2020/9/25

#
Thanks for the help, but can i just ask for one more thing. Sorry, but i wanted the game to end when crabHealth is 0, how would i do that. I'm guessing probably in the world class.
danpost danpost

2020/9/25

#
Randomgreenguy wrote...
Thanks for the help, but can i just ask for one more thing. Sorry, but i wanted the game to end when crabHealth is 0, how would i do that. I'm guessing probably in the world class.
I mentioned the following previously:
You may want to add code at the end of the adjustHealth method in the Crab class to remove the crab from the world (and possibly play a sound) when health is zero.
For finalizing, a world act method could be used to check on absence of crab and do a game over routine.
Randomgreenguy Randomgreenguy

2020/9/28

#
ok thank you for all the help, means a lot.
You need to login to post a reply.