Hi, guys. I posted a discussion about this simulation a while ago but I have a different problem now. I want the guy (Scavenger) to only collect the metal objects that are on the world (which is getX() > 400 since the width of my world is 800. but it isnt working right now. can you see how i would do that or any other errors i have? I will post all the classes just in case.
Scavenger (Collector) Class:
Metal Class:
World Class:
ScoreBar Class (for displaying number of metals collected):
TextButton Class (which is used by ScoreBar class):
Thanks for any help you can provide in advance. And if anyone's wondering, this code is to be used as part of a bigger war simulation. im just coding one portion of it for now.
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 Metal exists, move toward it
if (targetMetal != null && targetMetal.getWorld() != null)
{
moveTowardOrCollectMetal();
}
else if (getWorld().getObjects(Metal.class).size()==0)
this.setRotation(0);
// 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 && a.getX()>400)
{
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
getWorld().removeObject(targetMetal);
/*if (tryToCollect > 0)
* {
metalCollect += tryToCollect;
}*/
}
else
{
move (mySpeed);
}
}
private void randomMove()
{
if (Greenfoot.getRandomNumber (100) == 50)
{
turn (Greenfoot.getRandomNumber(360));
}
else
move (mySpeed);
}
}
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>();
public static int numMetals = 0;
/**
* 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);
}
}
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;
/**
* 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 boolean scoreShowing;
private int metalCount;
private int initialX;
private int initialY;
private ScoreBar scoreBar;
private TextButton metalButton;
private Scavenger g1;
/**
* Constructor for objects of class MyWorld.
*
*/
public MyWorld()
{
// Create a new world with 600x400 cells with a cell size of 1x1 pixels.
super(800, 600, 1);
GreenfootImage bg = new GreenfootImage("white back.png");
bg.scale(getWidth(), getHeight());
setBackground(bg);
Metal.numMetals = 0;
Metal m1 = new Metal();
addObject(m1,300,300);
Metal m2 = new Metal();
addObject(m2,350,350);
g1 = new Scavenger();
addObject(g1, Greenfoot.getRandomNumber(400), Greenfoot.getRandomNumber(480)+120);
initialX = g1.getX();
initialY = g1.getY();
ScoreBar scoreBar = new ScoreBar (800);
addObject(scoreBar, 400, 15);
scoreBar.update("Hi!");
// Add the spawn button to the world
metalButton = new TextButton (" -> Metals <- ", 24);
addObject (metalButton, 400, 550);
spawnMetal();
}
public void act()
{
actCounter++;
if (actCounter % 30 == 0)
{
//statUpdates();
//if (scoreShowing)
//{
//scoreBar.update(metals);
//}
}
if (Greenfoot.mouseClicked(metalButton))
{
spawnMetal();
}
returnHome();
}
/**
* Method to spawn a single bug at a random location
*/
private void spawnMetal ()
{
addObject (new Metal (), Greenfoot.getRandomNumber(800), Greenfoot.getRandomNumber(480)+120);
scoreShowing = true;
}
/**
* 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;
}
private void returnHome()
{
metalCount = getObjects(Metal.class).size();
if (metalCount == 0)
{
g1.setLocation(initialX, initialY);
}
}
}import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
// Need Color and Font for drawing ScoreBar
/**
* ScoreBar is a Greenfoot Actor that displays text.
* The text is white on a reddish brown
* background and designed to work in a scenario that is
* 800x600 pixels.
* <p>
* Display any String that fits, or send
* game info straight to customized method.
* @author Jordan Cohen
* @version April 2013
*/
public class ScoreBar extends Actor
{
// Declare Objects
private GreenfootImage scoreBoard;
private Color background;
private Color foreground;
private Font textFont;
private String text;
// Declare Variables:
private int width;
private int totalMetals = 0;
/**
* Construct a ScoreBar of the appropriate size.
*
* @param width width of the World where the
* ScoreBar will be placed
*/
public ScoreBar (int width)
{
scoreBoard = new GreenfootImage (width, 30);
background = new Color (175, 20, 23);
foreground = new Color (255, 255, 255);
textFont = new Font ("Courier", true, false, 24);
scoreBoard.setColor(background);
scoreBoard.fill();
this.setImage (scoreBoard);
scoreBoard.setFont(textFont);
this.width = width;
}
public void act()
{
update(totalMetals);
}
/**
* Updates this ScoreBar with game stats. This method should be
* re-written to work with your specific labels/values
*
* @param alive current number of living Bugs
* @param maxAlive largest number of bugs alive during game
* @param dead number of dead bugs
* @param averageLifespan
*/
public void update (int metalCollected)
{
// In order to make uniform sizes and preceding zeros:
String metalString;
// If there is only one digit
metalString = zeroAdder (metalCollected, 3);
text = "Metal pieces: " + Metal.numMetals;
// Now that we have built the text to output...
// this.update (String) calls the other version of update(), in this case
// update(String) - see below
this.update (text);
}
/**
* Takes a String and displays it centered to the screen.
*
* @param output Text for displaying.
*/
public void update (String output)
{
// Refill the background with background color
scoreBoard.setColor(background);
scoreBoard.fill();
// Write text over the solid background
scoreBoard.setColor(foreground);
// Smart piece of code that centers text
int centeredY = (width/2) - ((output.length() * 14)/2);
// Draw the text onto the image
scoreBoard.drawString(output, centeredY, 22);
}
/**
* Method that aids in the appearance of the scoreboard by generating
* Strings that fill in zeros before the score. For example:
*
* 27 ===> to 5 digits ===> 00027
*
* @param value integer value to use for score output
* @param digits number of zeros desired in the return String
* @return String built score, ready for display
*/
public static String zeroAdder (int value, int digits)
{
// Figure out how many digits the number is
int numDigits = digitCounter(value);
// If not extra digits are needed
if (numDigits >= digits)
return Integer.toString(value);
else // Build the number with zeroes for extra place values:
{
String zeroes = "";
for (int i = 0; i < (digits - numDigits); i++)
{
zeroes += "0";
}
return (zeroes + value);
}
}
/**
* Useful private method that counts the digit in any integer.
*
* @param number The number whose digits you want to count
* @return int The number of digits in the given number
*/
private static int digitCounter (int number)
{
if (number < 10) {
return 1;
}
int count = 0;
while (number > 0) {
number /= 10;
count++;
}
return count;
}
}
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
/**
* A Generic Button to display text that is clickable.
*
* This should be added to, and controlled by, a world.
*
* @author Jordan Cohen
* @version v0.1.5
*/
public class TextButton extends Actor
{
// Declare variables
private GreenfootImage myImage;
private GreenfootImage myAltImage;
private String buttonText;
private int textSize;
/**
* Construct a TextButton given only a String
* @param String String to be displayed
*/
public TextButton (String text)
{
this(text, 20);
}
/**
* Construct a TextButton given a String and a text size
* @param String String to be displayed
*/
public TextButton (String text, int textSize)
{
// Assign value to my internal String
buttonText = text;
this.textSize = textSize;
// Draw a button with centered text:
updateMe (text);
}
public void act ()
{
if (Greenfoot.mousePressed(this))
{
setImage (myAltImage);
}
else
{
setImage (myImage);
}
}
/**
* Update current TextButton text
*/
public void updateMe (String text)
{
buttonText = text;
GreenfootImage tempTextImage = new GreenfootImage (text, textSize, Color.RED, Color.WHITE);
myImage = new GreenfootImage (tempTextImage.getWidth() + 8, tempTextImage.getHeight() + 8);
myImage.setColor (Color.WHITE);
myImage.fill();
myImage.drawImage (tempTextImage, 4, 4);
myImage.setColor (Color.BLACK);
myImage.drawRect (0,0,tempTextImage.getWidth() + 7, tempTextImage.getHeight() + 7);
setImage(myImage);
tempTextImage = new GreenfootImage (text, textSize, Color.WHITE, Color.RED);
myAltImage = new GreenfootImage(tempTextImage.getWidth() + 8, tempTextImage.getHeight() + 8);
myAltImage.setColor (Color.WHITE);
myAltImage.fill();
myAltImage.drawImage (tempTextImage, 4, 4);
myAltImage.setColor (Color.BLACK);
myAltImage.drawRect (0,0,tempTextImage.getWidth() + 7, tempTextImage.getHeight() + 7);
}
}