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

2013/9/29

need help with move(double)

1
2
RUMMAKER RUMMAKER

2013/9/29

#
because greenfoot uses an int move, there is the problem where when moving at the speed of 1 you can only move in 8 directions, so im trying to solve this with a double move where i store the double and update the x and y displacements. but it's not working quite right :/ and i don't know what i did wrong. the code
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.lang.Math;
/**
 * move in double
 * 
 * @author RUMMAKER 
 * @version 1.0
 */
public class SmoothMover extends Actor
{
    public double vecterX;
    public double vecterY;
    public double currentX;
    public double currentY;
    public int moveX;
    public int moveY;
    public int angle;
    public void move(double speed)
    {
        angle = getRotation();
        vecterX = Math.cos((double)angle)*speed;
        vecterY = Math.sin((double)angle)*speed;
        
        currentX += vecterX;
        currentY += vecterY;
        
        moveX = (int)currentX;
        moveY = (int)currentY;
        setLocation(getX() + moveX, getY() + moveY);
        
        currentX -= (double)moveX;
        currentY -= (double)moveY;
    }
}
Where are you getting the error?
RUMMAKER RUMMAKER

2013/9/29

#
well I'm not getting an error, and things can sorta do what i intended (moves at any angle no matter the speed) but i have weird bugs where things move in the opposite direction and sometimes in a completely random direction so it's probably something wrong with the math :/
Ah.... Why do you have the variables that are only used in move() outside the method? Are they important in other parts of your code?
RUMMAKER RUMMAKER

2013/9/29

#
well it's just a habit of mine i guess, but i don't think it makes any difference :/. oh and it's a parent class, so everything in the game im making is extended from SmoothMover instead of actor
If you want the variables to reset everytime, they won't because you have them out of the method. Whenever you want the variables to reset, you should call them inside the method. Everytime the method is called, the variables will reset back to 0, instead of constantly adding more and more to them, as you're doing in your method.
But if that's what you actually want, then keep it. The bug is probably somewhere else if that's the case. I've only looked at the syntax of your code and not the math.
RUMMAKER RUMMAKER

2013/9/29

#
yeah i want the variables to stay the same because i need them to store the doubles.
RUMMAKER RUMMAKER

2013/9/29

#
edit: but now it doesnt behave like its suppose to ... D: oops now i feel stupid xD just read the doc again and im suppose to use radians
danpost danpost

2013/9/29

#
I agree that some of the fields should be local to the 'move' method. But, on the other hand, 'speed' should be declared in this class. Also, you should add the 'addedToWorld' method to this class to set the initial values of 'currentX', and 'currentY'. Finally, 'moveX' and 'moveY' would be better names as 'newX' and 'newY' and your setLocation statement should not use 'getX' and 'getY' in it, Another thing is your last step is setting your 'double' values to the value of 'int' fields, thereby losing any precision gained by using doubles to begin with. Here is my suggested revision:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.lang.Math;
/**
 * move in double
 * 
 * @author RUMMAKER 
 * @version 1.0
 */
public class SmoothMover extends Actor
{
    public double currentX;
    public double currentY;
    public int speed;

    public void addedToWorld(World world)
    {
        currentX = getX();
        currentY = getY();
    }

    public void move()
    {
        int angle = getRotation();
        double vectorX = Math.cos((double)angle)*speed;
        double vectorY = Math.sin((double)angle)*speed;

        if (!isInsideWorld(currentX+vectorX, currentY+vectorY)) return;

        currentX += vectorX;
        currentY += vectorY;
        setLocation((int)currentX, (int)currentY);
    }

    private boolean isInsideWorld(double x, double y)
    {
        if ((int)x < 0 || (int)x >= getWorld().getWidth()) return false;
        if ((int)y < 0 || (int)y >= getWorld().getHeight()) return false;
        return true;
    }
}
I added the 'isInsideWorld' method to keep the actual location as close to the saved 'double' location as possible (so the saved location does not go way outside world bounds while the actor moves or sits along the edge of the world; then you would have to wait for the values to return to within bounds before the actor would move back off the edge). With the 'addedToWorld' method and the 'speed' field being declared in the SmoothMover class, you will need to remove the 'addedToWorld' method and the 'speed' field declarations from all the subclasses (you can still set the speed in the constructors of the subclasses).
RUMMAKER RUMMAKER

2013/9/29

#
well i tried out your code danpost but the problem with objects moving in the opposite direction still happens :/. I'm also not sure if i am suppose to convert the angle into radians (on the java doc it says to convert to radians but when i convert the angle to radians weird things happen (although it fixes the moving in opposite direction bug))
danpost danpost

2013/9/29

#
Yes, you do need to convert them to radians (I overlooked that). Change lines 24 and 25 (of my code) to:
double vectorX = Math.cos(((double)angle)*Math.PI/180.0)*(double)speed;
double vectorY = Math.sin(((double)angle)*Math.PI/180.0)*(double)speed;
When you say, "weird things happen", what exactly is happening? I decided to repost the code with the changes:
import greenfoot.*;

public class SmoothMover extends Actor
{
    public double currentX, currentY;
    public int speed;

    public void addedToWorld(World world)
    {
        currentX = getX();
        currentY = getY();
    }

    public void move()
    {
        int angle = getRotation();
        double vectorX = Math.cos(((double)angle)*Math.PI/180.0)*(double)speed;
        double vectorY = Math.sin(((double)angle)*Math.PI/180.0)*(double)speed;

        if (!isInsideWorld(currentX+vectorX, currentY+vectorY)) return;

        currentX += vectorX;
        currentY += vectorY;
        setLocation((int)currentX, (int)currentY);
    }

    private boolean isInsideWorld(double x, double y)
    {
        if ((int)x < 0 || (int)x >= getWorld().getWidth()) return false;
        if ((int)y < 0 || (int)y >= getWorld().getHeight()) return false;
        return true;
    }
}
RUMMAKER RUMMAKER

2013/9/29

#
tyty it works perfect now the weird problem happened because instead of doing: double vectorX = Math.cos(((double)angle)*Math.PI/180.0)*(double)speed; double vectorY = Math.sin(((double)angle)*Math.PI/180.0)*(double)speed; i did angle = Math.toRadians(getRotation()); <--- noob at java and computer programming in general. so can you explain to me why toRadians(angle) did not work? because to me wouldnt toRadians return the same thing as )angle)*Math.PI/180.0 would?
danpost danpost

2013/9/29

#
You will have to post the complete line (not just the function) to find the problem.
RUMMAKER RUMMAKER

2013/9/29

#
what worked:
public void move()  
    {  
        int angle = getRotation();  
        double vectorX = Math.cos(((double)angle)*Math.PI/180.0)*(double)speed;  
        double vectorY = Math.sin(((double)angle)*Math.PI/180.0)*(double)speed; 
  
        if (!isInsideWorld(currentX+vectorX, currentY+vectorY)) return;  
  
        currentX += vectorX;  
        currentY += vectorY;  
        setLocation((int)currentX, (int)currentY);  
    }  
what didnt work :
public void move()  
    {  
        int angle = Math.toRadians(getRotation());  
        double vectorX = Math.cos(((double)angle)*(double)speed;  
        double vectorY = Math.sin(((double)angle)*(double)speed; 
  
        if (!isInsideWorld(currentX+vectorX, currentY+vectorY)) return;  
  
        currentX += vectorX;  
        currentY += vectorY;  
        setLocation((int)currentX, (int)currentY);  
    }  
There are more replies on the next page.
1
2