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

2019/4/20

Rugged Movement

AdiBak AdiBak

2019/4/20

#
Hello, Can someone please help me on how to make an actor move in a jagged fashion? I want it to move horizontally with a constant dx, but its y-position should fluctuate a little. Thank you. Here's the code I'm working on:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Dino here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Dino extends Actor
{
    /**
     * Act - do whatever the Dino wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        // Add your action code here.
        int dx = 3;
        int dy = Greenfoot.getRandomNumber(1) - 3;
        setLocation(getX() + dx, getY() + dy);
    }    
}
Super_Hippo Super_Hippo

2019/4/20

#
Greenfoot.getRandomNumber(1)
This gives you a random number between 0 and (1-1=) 0. So it will always be 0. dy is always -3. If you want dy to be in a range of for example -3 to +3, then you do it like this:
int dy = -3 + Greenfoot.getRandomNumber(7);
If you want your character to move up for some time and then back down or up/down around some middle instead of this randomness, the code has to be different though.
AdiBak AdiBak

2019/4/20

#
Thanks, it worked!
AdiBak AdiBak

2019/4/20

#
Hi, What I want to do is that when I click on that actor, it goes back to a starting position and moves (similar to the "Duck Hunt" game). I intend to display an Accuracy text to show the player their accuracy, which is the number of hits on the actor (increased by 1 when actor is clicked on) divided by the number of attempts to hit that actor (incremented when actor is clicked on or not clicked on). But when I run the scenario I receive an Arithmetic Exception / by zero. I think it complains about the fact that both numHits and numTries variables start off as zero, but I'm not sure how to fix this. Can someone please help? Thank you. Here's the exception: java.lang.ArithmeticException: / by zero at Dino.checkMouseClick(Dino.java:33) at Dino.act(Dino.java:27) at greenfoot.core.Simulation.actActor(Simulation.java:567) at greenfoot.core.Simulation.runOneLoop(Simulation.java:530) at greenfoot.core.Simulation.runContent(Simulation.java:193) at greenfoot.core.Simulation.run(Simulation.java:183) Here's the code for Dino class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
/**
 * Write a description of class Dino here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Dino extends Actor
{

    /**
     * Act - do whatever the Dino wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        // Add your action code here.
        int dx = 3;
        int dy = -3 + Greenfoot.getRandomNumber(7);
        setLocation(getX() + dx, getY() + dy);

        if (getX() - getImage().getWidth()/2 > getWorld().getWidth()){
            setLocation(-getImage().getWidth()/2, Greenfoot.getRandomNumber(getWorld().getHeight() - getImage().getHeight()/2));

        }
        checkMouseClick();
    }    

    public void checkMouseClick(){
        MouseInfo m = Greenfoot.getMouseInfo();
        MyWorld wor = (MyWorld)getWorld();
        int accuracy = (wor.getHits() / wor.getTries()) * 100;
        if (Greenfoot.mouseClicked(this) == true){
            setLocation(-getImage().getWidth()/2, Greenfoot.getRandomNumber(getWorld().getHeight() - getImage().getHeight()/2));
            
            Score scTxt = wor.getObjects(Score.class).get(0);
            Accuracy acc = wor.getObjects(Accuracy.class).get(0);
            wor.setScore(wor.getScore() + 100);
            wor.setTries(wor.getTries() + 1);
            wor.setHits(wor.getHits() + 1);
            
            acc.setText("Accuracy: " + accuracy + "%");
            scTxt.setText("Score: " + wor.getScore());
        } else if (Greenfoot.mouseClicked(this) == false){
            wor.setTries(wor.getTries() + 1);
        } 
    }
}
Here's the MyWorld class code:
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
{
    public static int grid = 30;
    private int points = 0;
    private int numHits = 0;
    private int numTries = 0;
    /**
     * 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, false); 
        prepare();
    }
    public void prepare(){
        Score sc = new Score();
        sc.setSize(grid);
        addObject(sc, sc.getImage().getWidth()/(10/9), sc.getImage().getHeight()/2);
        
        Accuracy ac = new Accuracy();
        ac.setSize(grid);
        addObject(ac, getWidth() * 3/4, ac.getImage().getHeight()/2);
        
        Dino di = new Dino();
        addObject(di, -di.getImage().getWidth()/2, Greenfoot.getRandomNumber(getHeight() - di.getImage().getHeight()/2));
        
    }
    
    public int getScore(){
        return points;
    }
    
    public void setScore(int ami){
        points = ami;
    }
    
    public int getHits(){
        return numHits;
    }
    
    public void setHits(int mam){
        numHits = mam;
    }
    
    public int getTries(){
        return numTries;
    }
    
    public void setTries(int qer){
        numTries = qer;
    }
}
Super_Hippo Super_Hippo

2019/4/20

#
You can create a method in the world to handle that. It obviously depends on what you want to have displayed when nothing was done so far:
public int getAccuracy()
{
    if (numHits==0) returns 0; //or 100
    return 100*numHits/numTries;
}
Your checking is also not correct. Greenfoot.mouseClicked(this) will be false when nothing is clicked, not only if something else was clicked.
public void checkMouseClick()
{
    if (Greenfoot.mouseClicked(null)) //also check out mousePressed if you didn't do it yet
    {
        MyWorld wor = (MyWorld)getWorld();
        wor.addNumTries(1);
        if (Greenfoot.mouseClicked(this)) //see comment above
        {
            wor.addScore(100);
            wor.addHits(1);
        }
        wor.updateCounters();
    }
}
//in MyWorld
private Score sc = new Score();
private Accuracy ac = new Accuracy();

//remove lines 26 and 30


public void addNumHits(int amount) {numHits += amount;}
public void addNumTries(int amount) {numTries += amount;}
public void addScore(int amount) {points += amount;}
public void updateCounter()
{
    sc.setText("Score: " + points);
    ac.setText("Accuracy: " + getAccuracy + "%");
}
As long as the score is always 100 times the number of hits, it only needs one variable. You could also only keep the score/accuracy in the Counter class and remove it from the MyWorld class completely. You also don't need separate classes for Score and Accuracy.
AdiBak AdiBak

2019/4/20

#
Thank you, it works!
AdiBak AdiBak

2019/4/21

#
Hi, When I tried to publish this scenario, it took around 20-30 minutes for the publishing bar to become full, then it responded with a 500 error. Can someone please help? Thank you.
You need to login to post a reply.