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

2017/4/4

Actor collecting something

ironphoenix20 ironphoenix20

2017/4/4

#
Ok, I have a simulation of a war and Im currently only working on one aspect of it. I want a Scavenger (person) actor to run to the other side of the world and grab metal pieces (they only appear when someone from that team dies but dont worry about that right now). i want to program it so the Scavenger actor goes to the other side, collects the metal (this increments the collected metals count) and comes back to the position they started at. How would I do this? I ll provide what I have so far. Just tell me if you spot any errors in my code. Scavenger Class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;

/**
 * Write a description of class Scavenger here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Scavenger extends Actor
{
    private Metal targetMetal;
    int numMetals;
    private ArrayList<Metal> metals;
    
    private int metalCollect = 0;
    private int mySpeed = 2;
    private int count = 0;
    
    private int offset;
    
    /**
     * Act - do whatever the Scavenger wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        {
            //hp -= DesertWorld.BUG_DEATH_RATE;
            if (count % 8 == 0) // Only run every 8 acts to avoid lag
            {
                targetClosestMetal ();
                //hpBar.update(hp);
            }
            // If my current target Flower exists, move toward it
            if (targetMetal != null && targetMetal.getWorld() != null)
            {
                moveTowardOrCollectMetal();
            }
            // If I can't find anything to eat, move in a random direction
            /*else
            {
                moveRandomly();
            }*/
        }
        count++;
        collectMetal();
    }
    
    //Constructor that initializes a new metal collector guy
    public Scavenger()
    {
        GreenfootImage guy = new GreenfootImage("scav guy.png");
        guy.scale(100,100);
        this.setImage(guy);
    }
    
    public void targetClosestMetal()
    {
        double closestTargetDistance = 0;
        double distanceToActor;numMetals = getWorld().getObjects(Metal.class).size();
        metals = (ArrayList)getWorld().getObjects(Metal.class);
        
        if (metals.size() > 0)
        {
            // set the first one as my target
            targetMetal = metals.get(0);
            // Use method to get distance to target. This will be used
            // to check if any other targets are closer
            closestTargetDistance = MyWorld.getDistance (this, targetMetal);

            // Loop through the objects in the ArrayList to find the closest target
            for (Metal o : metals)
            {
                // Cast for use in generic method
                Actor a = (Actor) o;
                // Measure distance from me
                distanceToActor = MyWorld.getDistance(this, a);
                // If I find a Flower closer than my current target, I will change
                // targets
                if (distanceToActor < closestTargetDistance)
                {
                    targetMetal = o;
                    closestTargetDistance = distanceToActor;
                }
            }
        }
    }
    
    /**
     * Private method, called by act(), that moves toward the target,
     * or eats it if within range.
     */
    private void moveTowardOrCollectMetal ()
    {
        turnTowards(targetMetal.getX(), targetMetal.getY());

                if (this.getNeighbours (30, true, Metal.class).size() > 0)
        {
            // If I was able to eat, increase by life by flower's nibble power
            int tryToCollect = 1;
            if (tryToCollect > 0)
            {
                metalCollect += tryToCollect;
            }
        }
        else
        {
            move (mySpeed);
        }
    }
    
    private void collectMetal()
    {
      offset = (this.getImage().getWidth() / 2) + 1;
      targetMetal = (Metal)getOneObjectAtOffset(offset, 0, Metal.class);
      if (targetMetal != null)
        {
            //System.out.println("got here");
            getWorld().removeObject(targetMetal);
            Metal.collectedMetals.add(1);
        }
    }
}
Metal (piece that scavenger collects) Class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;

/**
 * Write a description of class Metal here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Metal extends Actor
{
    //A list of all the metals that has been collected by a team
    public static ArrayList<Integer> collectedMetals = new ArrayList<Integer>();
    
    /**
     * Act - do whatever the Metal wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        
    }  
    
    public Metal()
    {
        GreenfootImage metal = new GreenfootImage("metal.png");
        metal.scale(100,100);
        this.setImage(metal);
    }
    
    public ArrayList<Integer> getMetals()
    {
        return collectedMetals;
    }
}
World Class (just in case you need it):
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class MyWorld here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class MyWorld extends World
{
    private int actCounter = 0;
   
    private ScoreBar scoreBar;
    /**
     * Constructor for objects of class MyWorld.
     * 
     */
    public MyWorld()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1); 
        GreenfootImage bg = new GreenfootImage("white back.png");
        bg.scale(getWidth(), getHeight());
        setBackground(bg);
        
        Metal m1 = new Metal();
        addObject(m1,300,300);
        
        Scavenger g1 = new Scavenger();
        addObject(g1, 200,200);
        
        ScoreBar scoreBar = new ScoreBar (800);
        addObject(scoreBar, 400, 15);
        scoreBar.update("Hi!");
    }
    
    public void act()
    {
        actCounter++;
        if (actCounter % 30 == 0)
        {
            //statUpdates();
            //if (scoreShowing)
            //{
                //scoreBar.update(metals);
            //}        
        }
    }
    
    /**
     * Static method that gets the distance between the x,y coordinates of two Actors
     * using Pythagorean Theorum.
     * 
     * @param a     First Actor
     * @param b     Second Actor
     * @return float
     */
    public static float getDistance (Actor a, Actor b)
    {
        double distance;
        double xLength = a.getX() - b.getX();
        double yLength = a.getY() - b.getY();
        distance = Math.sqrt(Math.pow(xLength, 2) + Math.pow(yLength, 2));
        return (float)distance;
    }
}
Super_Hippo Super_Hippo

2017/4/4

#
You need to save the "home position" where the Scavenger should return when he got a Metal. Add a boolean field to check if the Scavenger collected a Metal and if he does, he heads to the home position instead of checking for metals.
ironphoenix20 ironphoenix20

2017/4/6

#
OK. I made the home position code work, I think but now I'm getting a random null pointer error I'm not sure why and the guy stops after touching one metal piece instead of collecting it and going to collect the other ones. Can you see what the problem is?
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;

/**
 * Write a description of class Scavenger here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Scavenger extends Actor
{
    private Metal targetMetal;
    int numMetals;
    private ArrayList<Metal> metals;
    private int metalCount;
    
    private int metalCollect = 0;
    private int mySpeed = 2;
    private int count = 0;
    
    private int offset;
    //int initialX = this.getX();
    //int initialY = this.getY();
    
    /**
     * Act - do whatever the Scavenger wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        {
            //hp -= DesertWorld.BUG_DEATH_RATE;
            if (count % 8 == 0) // Only run every 8 acts to avoid lag
            {
                targetClosestMetal ();
                //hpBar.update(hp);
            }
            // If my current target Flower exists, move toward it
            if (getWorld().getObjects(Metal.class).size()!=0)
            {
                moveTowardOrCollectMetal();
            }
            else if (getWorld().getObjects(Metal.class).size()==0)
            randomMove();
            // If I can't find anything to eat, move in a random direction
            /*else
            {
                moveRandomly();
            }*/
        }
        count++;
        collectMetal();
    }
    
    //Constructor that initializes a new metal collector guy
    public Scavenger()
    {
        GreenfootImage guy = new GreenfootImage("scav guy.png");
        guy.scale(100,100);
        this.setImage(guy);
    }
    
    public void targetClosestMetal()
    {
        double closestTargetDistance = 0;
        double distanceToActor;
        numMetals = getWorld().getObjects(Metal.class).size();
        metals = (ArrayList)getWorld().getObjects(Metal.class);
        
        if (metals.size() > 0)
        {
            // set the first one as my target
            targetMetal = metals.get(0);
            // Use method to get distance to target. This will be used
            // to check if any other targets are closer
            closestTargetDistance = MyWorld.getDistance (this, targetMetal);

            // Loop through the objects in the ArrayList to find the closest target
            for (Metal o : metals)
            {
                // Cast for use in generic method
                Actor a = (Actor) o;
                // Measure distance from me
                distanceToActor = MyWorld.getDistance(this, a);
                // If I find a Flower closer than my current target, I will change
                // targets
                if (distanceToActor < closestTargetDistance)
                {
                    targetMetal = o;
                    closestTargetDistance = distanceToActor;
                }
            }
        }
    }
    
    /**
     * Private method, called by act(), that moves toward the target,
     * or eats it if within range.
     */
    private void moveTowardOrCollectMetal ()
    {
        if (targetMetal != null)
        {
            turnTowards(targetMetal.getX(), targetMetal.getY());
        }

        if (this.getNeighbours (30, true, Metal.class).size() > 0)
        {
            // If I was able to eat, increase by life by flower's nibble power
            int tryToCollect = 1;
            if (tryToCollect > 0)
            {
                metalCollect += tryToCollect;
            }
        }
        else
        {
            move (mySpeed);
        }
    }
    
    private void collectMetal()
    {
      offset = (this.getImage().getWidth() / 2) + 1;
      targetMetal = (Metal)getOneObjectAtOffset(offset, 0, Metal.class);
      if (targetMetal != null)
        {
            //System.out.println("got here");
            getWorld().removeObject(targetMetal);
            Metal.numMetals++;
        }
    }
    
    private void randomMove()
    {
        if (Greenfoot.getRandomNumber (100) == 50)
        {
            turn (Greenfoot.getRandomNumber(360));
        }
        else
            move (mySpeed);
    }
}
The error is on line 104.
ironphoenix20 ironphoenix20

2017/4/6

#
Also, I want the guy to collect only metal pieces that are in one half of the world. How would I do this?
ironphoenix20 ironphoenix20

2017/4/6

#
ok, i got that last part. i just check if the metal piece's x and y coordinates are in a certain range and then collect it if needed.
Super_Hippo Super_Hippo

2017/4/7

#
I really have no idea how you can get a NullPointer exception when you check if it is not null right before it =/
You need to login to post a reply.