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

2023/3/8

I want an actor to apply a "rooted" status condition when it touches another actor

KCee KCee

2023/3/8

#
I have an actor called "RootedCorpse" and I want it to apply a rooted condition that halves the speed of any actor it touches in the "Pedestrian" class. However, when i try to apply the root status, instead of halving the actors speed, it ends up just stopping the actor completely, or sets its speed to 0. Heres my pedestrian code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * A Pedestrian that tries to walk across the street
 */
public abstract class Pedestrian extends SuperSmoothMover
{
    protected double speed;
    protected double maxSpeed;
    protected int direction; // direction is always -1 or 1, for moving down or up, respectively
    protected boolean awake;
    public Pedestrian()
    {
        this(1);
    }
    
    public Pedestrian(int direction) {
        // choose a random speed
        maxSpeed = Math.random() * 2 + 1;
        speed = maxSpeed;
        // start as awake 
        awake = true;
        this.direction = direction;
    }

    /**
     * Act - do whatever the Pedestrian wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void move()
    {
        // If there is a v
        if (awake){
            if (getOneObjectAtOffset(0, (int)(direction * getImage().getHeight()/2 + (int)(direction * speed)), Vehicle.class) == null){
                setLocation (getX(), getY() + (int)(speed*direction));
            }
            if (direction == -1 && getY() < 100){
                getWorld().removeObject(this);
            } else if (direction == 1 && getY() > 550){
                getWorld().removeObject(this);
            }
        }
    }
    
    /**
     * Method to cause this Pedestrian to become knocked down - stop moving, turn onto side
     */
    public void knockDown () {
        speed = 0;
        setRotation (90);
        awake = false;
    }
    
    public void rooted ()
    {
        speed = maxSpeed/2;
    }
    
    /**
     * Method to allow a downed Pedestrian to be healed
     */
    public void healMe () {
        speed = maxSpeed;
        setRotation (0);
        awake = true;
    }
    
    public boolean isAwake () {
        return awake;
    }
}
And heres the code for my RootedCorpse:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class RootedCorpse here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class RootedCorpse extends Vehicle
{
    /**
     * Act - do whatever the RootedCorpse wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public RootedCorpse(VehicleSpawner origin) {
        super(origin); // call the superclass' constructor
        GreenfootImage image = getImage();
        image.scale(image.getWidth() - 70, image.getHeight() - 120);
        setImage(image);
        maxSpeed = 1.5 + ((Math.random() * 30)/5);
        speed = maxSpeed;
        yOffset = 0;
    }

    public void act()
    {
        drive(); 
        checkHitPedestrian();
        if (checkEdge()){
            getWorld().removeObject(this);
        }
    }
    
    /**
     * When a Car hit's a Pedestrian, it should knock it over
     */
    public boolean checkHitPedestrian () {
        Pedestrian p = (Pedestrian)getOneObjectAtOffset((int)speed + getImage().getWidth()/2, 0, Pedestrian.class);
        if (p != null){
            p.rooted();
            return true;
        }
        return false;
    }
}
Super_Hippo Super_Hippo

2023/3/8

#
In line 35 when setting the new location, you round the new position to a integer. If you move only 0.5 at a time, your character won’t move at all. You need to save the location as a more precise value. That’s what the SmoothMover class does (and probably also the SuperSmoothMover class you use). However, it can’t do that if it never receives the exact values.
KCee KCee

2023/3/18

#
Im not really sure how to give SmoothMover exact values i tried removing the "int" in line 35 like so:
    public void move()
    {
        // If there is a v
        if (awake){
            if (getOneObjectAtOffset(0, (int)(direction * getImage().getHeight()/2 + (int)(direction * speed)), Vehicle.class) == null){
                setLocation (getX(), getY() + (speed*direction));
            }
            if (direction == -1 && getY() < 100){
                getWorld().removeObject(this);
            } else if (direction == 1 && getY() > 550){
                getWorld().removeObject(this);
            }
        }
    }
but it hasnt fixed anything
danpost danpost

2023/3/18

#
No one is familiar with what the SuperSmoothMover class does. Kindly post its codes.
KCee KCee

2023/3/18

#
Here is the SuperSmoothMover class:
import greenfoot.*;  // (World, Actor, GreenfootImage, and Greenfoot)

/**
 * <p>A variation of an actor that maintains a precise location (using doubles for the co-ordinates
 * instead of ints).  This allows small precise movements (e.g. movements of 1 pixel or less)
 * that do not lose precision.</p>
 * 
 * <p>Modified by Jordan Cohen to include a precise rotation variable, as well as turn, setRotation 
 * and turnTowards methods.</p>
 * 
 * <p>To use this class, simply have all of the Actors that need to move smoothly inherit from this
 * class. This class adds new versions of move, turn and setLocation which take doubles. It also adds the
 * following methods to access the precise values:</p>
 * <ul>
 * <li><code>getPreciseX, getPreciseY -></code> Retrieves precise values</li>
 * <li><code>getPreciseRotation -></code> gets the precise angle</li>
 * <li><code>turnTowards (Actor) -></code> an added bonus - turn towards another Actor instead of an xy position</li>
 * </ul>
 * 
 * 
 * 
 * @author Poul Henriksen
 * @author Michael Kolling
 * @author Neil Brown
 * 
 * @version 3.0jc -- Modified by Jordan Cohen
 * 
 */
public abstract class SuperSmoothMover extends Actor
{
    private double exactX;
    private double exactY;
    private double rotation;

    /**
     * Move forward by the specified distance.
     * (Overrides the method in Actor).
     * 
     * @param distance  the distance to move in the current facing direction
     */
    @Override
    public void move(int distance)
    {
        move((double)distance);
    }

    /**
     * Move forward by the specified exact distance.
     * 
     * @param distance the precise distance to move in the current facing direction
     */
    public void move(double distance)
    {
        double radians = Math.toRadians(getRotation());
        double dx = Math.cos(radians) * distance;
        double dy = Math.sin(radians) * distance;
        setLocation(exactX + dx, exactY + dy);
    }

    /**
     * Set the internal rotation value to a new value.
     * 
     * @param rotation the precise new angle
     */
    public void setRotation (double rotation){
        this.rotation = rotation;
        super.setRotation ((int)(rotation + 0.5));
    }

    /**
     * Set the internal rotation value to a new value. This will override the method from Actor.
     * 
     * @param rotation the new angle
     */
    @Override
    public void setRotation (int rotation){
        this.rotation = rotation;
        super.setRotation(rotation);
    }

    /**
     * Set the internal rotation to face towards a given point. This will override the method from Actor.
     * 
     * @param x the x coordinate to face
     * @param y the y coordinate to face
     */
    @Override
    public void turnTowards (int x, int y){
        setRotation( Math.toDegrees(Math.atan2(y - getY() , x - getX())));
    }

    /**
     * A short-cut method that I (Jordan Cohen) always thought Greenfoot should have - use the
     * tuntToward method above to face another Actor instead of just a point. Keeps calling code
     * cleaner. 
     * 
     * @param a     The Actor to turn towards. 
     */
    public void turnTowards (Actor a){
        turnTowards (a.getX(), a.getY());
    }

    /**
     * Turn a specified number of degrees.
     * 
     * @param angle     the number of degrees to turn.
     */
    @Override
    public void turn (int angle){
        rotation += angle;
    }

    /**
     * Turn a specified number of degrees with precision.
     * 
     * @param angle     the precise number of degrees to turn
     */
    public void turn (double angle){
        rotation += angle;
    }

    /**
     * Set the location using exact coordinates.
     * 
     * @param x the new x location
     * @param y the new y location
     */
    public void setLocation(double x, double y) 
    {
        exactX = x;
        exactY = y;
        super.setLocation((int) (x + 0.5), (int) (y + 0.5));
    }

    /**
     * Set the location using integer coordinates.
     * (Overrides the method in Actor.)    
     * 
     * @param x the new x location
     * @param y the new y location
     */
    @Override
    public void setLocation(int x, int y) 
    {
        exactX = x;
        exactY = y;
        super.setLocation(x, y);
    }

    /**
     * Return the exact x-coordinate (as a double).
     * 
     * @return double   the exact x coordinate, as a double
     */
    public double getPreciseX() 
    {
        return exactX;
    }

    /**
     * Return the exact y-coordinate (as a double).
     * 
     * @return double   the exact x coordinate, as a double
     */
    public double getPreciseY() 
    {
        return exactY;
    }
    
    public double getPreciseRotation (){
        return rotation;
    }
}
danpost danpost

2023/3/18

#
KCee wrote...
Here is the SuperSmoothMover class: << Code Omitted >>
Okay. Try the following for line 35:
setLocation(getPreciseX(), getPreciseY()+speed*direction);
You need to login to post a reply.