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

2013/3/17

My actor only moves on the X and Y axes and their diagonals?

RobTheRipper RobTheRipper

2013/3/17

#
public class AllyAnt extends Actor
{
    
    
    
    public void act() 
    {
        clickToMove();
        move(1);
    }   
    
    public void clickToMove()
    {
        
        // it moves in the general directions of where i click, by only following on the x and y axes and their diagonals, yet the sprite of the actor does turn to where it SHOULD move... please any help would be appreciated :)
        if(Greenfoot.mouseClicked(null))
        {
             MouseInfo mouse = Greenfoot.getMouseInfo();
             int MouseX = mouse.getX();
             int MouseY = mouse.getY();
             int targetX = MouseX - getX();
             int targetY = MouseY - getY();
             double angle = Math.toDegrees(Math.atan2(targetY,targetX));
             int direction = (int)angle;            
             setRotation(direction);
            
        }
    }
       
        
       
    }
    
   

danpost danpost

2013/3/18

#
One way to correct this is to save the original location; and each act method increase the move amount, locate the actor back at the original location and move the new amount toward the objective.
RobTheRipper RobTheRipper

2013/3/18

#
thank you for the quick reply! im very new to greenfoot, so i really have no idea how to go about doing that... :P
danpost danpost

2013/3/18

#
The problem with moving only one pixel at a time is apparent with the horizontal, vertical, and diagonal movement (other angles are not realized). To fix this we can record the initial location as well as the target location and each act cycle move one closer to the target from the initial location. This way only the first move will be only one pixel in length; all future moves will be one more than the last, until the target is reached.
public class AllyAnt extends Actor
{
    int homeX, homeY, targetX, targetY, moveAmt;
    boolean hasTarget; // initialized by default to false

    public void act() 
    {
        if (!hasTarget) clickToMove(); else move();
    }   
    
    public void clickToMove()
    {
        if (Greenfoot.mouseClicked(null))
        {
            hasTarget = true; // flag target acquired
            homeX = getX();
            homeY = getY(); // save initial location
            MouseInfo mouse = Greenfoot.getMouseInfo();
            targetX = mouse.getX();
            targetY = mouse.getY(); // save target location
            turnTowards(targetX, targetY); // face target location
            moveAmt = 0; // initialize move counter
        }
    }

    public void move()
    {
        setLocation(homeX, homeY); // reset initial location
        moveAmt++; // increment move counter
        move(moveAmt); // move new amount toward target
        if (getX() == targetX && getY() == targetY) hasTarget = false; // check reached target
    }
}
davmac davmac

2013/3/18

#
RobTheRipper, you might like to read this previous discussion which explains the issue.
RobTheRipper RobTheRipper

2013/3/19

#
thank you danpost, for that is an excellent method of doing exactly what i need :D!!! hopefully i will get to thinking like a programmer, the more i learn.
davmac davmac

2013/3/19

#
There's a problem with the code posted above - the ant may never actually hit its target, because turnTowards is only accurate to a degree. So, the check on line 31 might never succeed.
RobTheRipper RobTheRipper

2013/3/20

#
can you explain more on how the turnTowards() method might not work? and also will using the Math.atan2() function and converting it to a degree, and setting the rotation to that degree work better? EDIT:also another idea is maybe to set the rotation or turnTowards() method in the move() method, so that everytime is cycles it, it re-aplys the target, maybe for more precise targeting? just an idea, do not know if will fix the problem :P
danpost danpost

2013/3/20

#
Turning towards the objective every act cycle will help keep you in line, but not ensure that you will not pass up the objective if and when you do reach it. Using the Math.atan2 function is only another way to come up with the angle to turn toward and will not work any better. Better might be to keep track of the line between the original location and the target. Dividing this distance by the move amount will give us an approximate number of cycles needed to reach the target. If we divide the difference in the x-values and the difference in the y-values by this amount will give us the real amount to move each cycle. The following class code is tested and works (I have not seen it fail, yet). The final location of the actor moving to the target may be off by a pixel.
import greenfoot.*;

public class AllyAnt extends Actor
{
    int targetX, targetY;
    boolean hasTarget; // initialized by default to false
    double realX, realY, amtX, amtY;

    public void act() 
    {
        if (!hasTarget) clickToMove(); else move();
    }   
    
    public void clickToMove()
    {
        if (Greenfoot.mouseClicked(null))
        {
            hasTarget = true; // flag target acquired
            MouseInfo mouse = Greenfoot.getMouseInfo();
            targetX = mouse.getX();
            targetY = mouse.getY(); // save target location
            double dist = Math.hypot(targetY-getY(), targetX-getX()); // get distance to travel
            int totalDist = (int) (dist+.4999); // get total distance rounded to nearest int
            amtX = (double)(targetX-getX())/(double)totalDist; // x distance to move each act
            amtY = (double)(targetY-getY())/(double)totalDist; // y distance to move each act
            realX = (double)getX(); // set real x location
            realY = (double)getY(); // set real y location
        }
    }

    public void move()
    {
        realX += amtX;
        realY += amtY; // set new real location
        setLocation((int)realX, (int)realY); // move to new location
        if (Math.hypot(targetX-getX(), targetY-getY())<2) hasTarget = false; // check reached target
    }
}
You need to login to post a reply.