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

2012/4/13

Help please!

kiarocks kiarocks

2012/4/13

#
I am making a game and I need an arrow to point to the player when he is offscreen. However, rounding atan2 does not work and gets me stuck in an endless loop. Here is my current code:
public void ensurePos()
    {
        if(ActorHelp.actorInvalid(tip) || ActorHelp.actorInvalid(this))return;
        tip.setRotation(getRotation());
        tip.setRotation(getRotation(), getX(), getY());
        while(!ActorHelp.actorInBounds(getWorld(), tip))
        {
            tip.move(-1);
            move(-1);
        }
        double atan = Math.atan2(tip.getY()-getY(), tip.getX()-getX());
        while(atan != tipDist)
        {
            atan = Math.atan2(tip.getY()-getY(), tip.getX()-getX());
            tip.move(((int)atan) > tipDist ? -1 : 1);
        }
    }
ActorHelp is a custom class with common methods, and tip is just an object.
kiarocks kiarocks

2012/4/14

#
Help?
ttamasu ttamasu

2012/4/14

#
I would help but your code is not completely there to view. For example you need to provide how you define the setRotation method you created for the "tip" class (ie, setRotation (int, int,int) ) on line 5. Further it doesn't make sense what you are doing with the value for atan which is the angle in radians on line 11., if you wnat the arrow to point to the object that while statement form 12 through 16 is won't work you should replace that with tip.setRotation((int)Math.toDegrees(atan)) so all you really want is to have the arrow (I assume that is is the object "tip") point at the offscreen current object ,all you should need is replace lines 4 through 16 with ---- double atan = Math.atan2(tip.getY()-getY(), tip.getX()-getX()); //gets angle in radians from the tip to object atan = Math.toDegrees(atan); // convert it to degrees tip.setRotation( (int) atan); //rotate tip to the current object --- but like I said your snipet isn't too clear
nccb nccb

2012/4/14

#
Your snippet isn't clear, as ttamasu says. What's tipDist? Why are you comparing an angle (atan) to something that seems like a distance (tipDist)? Why are you moving in a loop rather than just moving straight to where you want to go (remember, all the moves in one act() call effectively happen together)?
kiarocks kiarocks

2012/4/14

#
Whoops, forgot that atan2 isn't distance. How do I get the distance? Rest of code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Pointer here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Pointer extends Rotator
{
    Actor pointAt;
    Point tip;
    int tipDist;
    public Pointer(Actor toPoint)
    {
        getImage().scale(50, 10);
        pointAt = toPoint;
        tipDist = getImage().getWidth()/2;
    }

    /**
     * Act - do whatever the Pointer wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        pointAt(pointAt);
        ensurePos();
    }    

    public void pointAt(Actor a)
    {
        double rotation = getRotation(a.getX(), a.getY());
        setRotation((int)rotation);
    }
    
    public void addTip(Point tip, int x, int y)
    {
        this.tip = tip;
        getWorld().addObject(tip, x, y);
    }

    public void ensurePos()
    {
        if(ActorHelp.actorInvalid(tip) || ActorHelp.actorInvalid(this))return;
        tip.setRotation(getRotation());
        tip.setRotation(getRotation(), getX(), getY());
        while(!ActorHelp.actorInBounds(getWorld(), tip))
        {
            tip.move(-1);
            move(-1);
        }
        double atan = Math.atan2(tip.getY()-getY(), tip.getX()-getX());
        while(atan != tipDist)
        {
            atan = Math.atan2(tip.getY()-getY(), tip.getX()-getX());
            tip.move(((int)atan) > tipDist ? -1 : 1);
        }
    }
}
import greenfoot.*;  // (World, Actor, GreenfootImage, and Greenfoot)

/**
 * Actors that inherit this class have methods available to them to rotate around any
 * given point in the world. They also maintain double precision for their co-ordinates.
 * 
 * <br><br>
 * 
 * Double precision code taken from Poul's SmoothMover class.
 * 
 * @author Michael Berry (mjrb4)
 * @author Poul Henriksen
 * @version 17/02/09
 */
public abstract class Rotator extends Actor
{
    
    private double x = 0;
    private double y = 0;
    
    /**
     * Get exactly where we are in the world
     * @return the x value of our position
     */
    public double getExactX()
    {
        return x;
    }
    
    /**
     * Get exactly where we are in the world
     * @return the y value of our position
     */
    public double getExactY()
    {
        return y;
    }
    
    /**
     * Providing 'setLocation' based on doubles. This will eventually call
     * the built-in 'setLocation' method in Actor.
     */
    public void setLocation(double x, double y) 
    {
        this.x = x;
        this.y = y;
        super.setLocation((int) x, (int) y);
    }
    
    /**
     * Override the default 'setLocation' method to keep our own coordinates
     * up-to-date.
     */
    public void setLocation(int x, int y) 
    {
        setLocation((double) x, (double) y);
    }
    
    /**
     * Get the rotation around a specific point in the world.
     * @param x the x co-ordinate of the point
     * @param y the y co-ordinate of the point
     * @return the rotation in degrees around the point
     * (0 degrees is to the left of the point)
     */
    public double getRotation(double x, double y)
    {
        double xDistance = getExactX()-x;
        double yDistance = getExactY()-y;
        double angle = Math.toDegrees(Math.atan2(yDistance, xDistance))+180;
        
        return angle;
    }

    /**
     * Set the rotation of this object to a value around 
     * a specific point.
     * @param degrees the degrees to set the rotation to
     * (0 degrees is to the left of the point)
     * @param x the x co-ordinate of the point
     * @param y the y co-ordinate of the point
     */
    public void setRotation(double degrees, double x, double y)
    {
        //Convert degrees to between 180 and -180
        degrees = ((degrees+180) % 360)-180;
        
        /*
         * We need to deal with 180 and -180 especially, but this is
         * pretty simple - just put the actor the other side of the 
         * point of rotation.
         * 
         * HACK: Until it deals with 180 properly, it'll just call the
         * method with 179.9. This works but isn't very nice, so I'll
         * update this at some point to work properly...
         */
        if(Math.abs(degrees)==180) {
            setRotation(179.9, x, y);
            return;
        }
        
        /*
         * Otherwise, we've got a bit more maths on our hands...
         * Fair bit of trig going on here, including the sine rule.
         */
        else {
            /*
             * Let's get the distance between this point and the
             * point we're rotating around.
             */
            double xDistance = getExactX()-x;
            double yDistance = getExactY()-y;
            double distance = Math.sqrt((xDistance*xDistance + yDistance*yDistance));
            
            /*
             * Bit of a hack, but first set the location to 0 
             * degrees around the point.
             * Then we can just work from there.
             */
            setLocation(x-distance, y);
    
            /*
             * Next is a bit trickier. Imagine a triangle formed 
             * from a line that starts at the point we're rotating
             * around at 0 degrees and another line at *degrees*
             * degrees. Both those lines are length *distance*, 
             * and the third line joins those two. The triangle is
             * therefore isocoles.
             * 
             * One angle is degrees, the other two (identical)
             * angles are theta.
             * 
             * c is the length of the side that isn't necessarily
             * the same length of distance. (Sine rule is needed
             * to calculate this.
             * 
             * Finally, imagine a second triangle formed by a 
             * vertical line drawn from the point in the triangle
             * furthest away in the y direction from the point of
             * rotation, to intersect with the side of the 
             * triangle drawn at 0 degrees to the point of rotation.
             * This line then forms a triangle by splitting the
             * triangle in two - the triangle we're interested
             * in is the one that doesn't necessarily have an 
             * angle the size of *degrees* in it. This triangle
             * is a right angled triangle, so we can use basic 
             * trig to find what we need (the offsets of x and y.)
             * 
             * The line that we initially drew to form this 
             * second triangle is the magnitude of the y offset
             * needed, and the other side (not the hypotenuse)
             * is the x offset.
             * 
             * So phew, we're done - simply add the x offset to the 
             * x position and likewise with the y offset, and we 
             * have our circle rotation!
             */
            double theta = (180-degrees)/2;
            double c = (distance*sin(degrees))/(sin(theta)); //Sine rule
            double dx = c*cos(theta);
            double dy = c*sin(theta);
            
            setLocation(getExactX()+dx, getExactY()-dy);
        }
    }
    
    /**
     * Get the sine of a number in degrees.
     * @param a the number to manipulate
     * @return the sine of a in degrees
     */
    public double sin(double a)
    {
        return Math.sin(Math.toRadians(a));
    }
    
    /**
     * Get the cosine of a number in degrees.
     * @param a the number to manipulate
     * @return the cosine of a in degrees
     */
    public double cos(double a)
    {
        return Math.cos(Math.toRadians(a));
    }
    
    /**
     * Get the tan of a number in degrees.
     * @param a the number to manipulate
     * @return the tan of a in degrees
     */
    public double tan(double a)
    {
        return Math.tan(Math.toRadians(a));
    }
}
Point class has nothing in it and extends Rotator.
You need to login to post a reply.