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

2013/4/20

Maze help

1
2
3
Gingervitis Gingervitis

2013/4/20

#
I have created a very nice maze but my ball goes right through all of the horizontal walls and it cannot go through the verticals walls sometimes. Can someone help me out with my code?
public class Ball extends Animal
{
    private int x = 3;
    private boolean moving = false;

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

    public void checkKeypress()
    {

        if (Greenfoot.isKeyDown("left"))
        {

            move(-x);
            turn(-5);

        }
        setRotation(360);
        if (Greenfoot.isKeyDown("right"))
        {

            move(x);
            turn(5);

        }
        setRotation(90);  
        if (Greenfoot.isKeyDown("up"))  
        { 
            move(-x);

        }  
        if (Greenfoot.isKeyDown("down"))  
        {
            move(x);

        } 
        setRotation(0);

        

    }
    
    public void checkHitHWall()
    {
        Actor Ball = getOneObjectAtOffset(getImage().getWidth()/2, getImage().getHeight()/2, HWall.class);
        
        if (Ball != null) x = x*-1;
           
        
        
    }
    
    public void checkHitVWall()
    {
        Actor Ball= getOneObjectAtOffset(getImage().getWidth()/2, getImage().getHeight()/2, VWall.class);
        
        if (Ball != null) x = x*-1;
    }
}
I originally had different code but my teacher told me to try to use the 'getOneObjectAtOffset' method.
danpost danpost

2013/4/20

#
Each wall will have a different set of signs for the offsets and since your walls are either horizontal or vertical, you only need one offset for each wall (the other offset should be zero). However, better would be just to use the 'getOneIntersectingObject' or the 'getIntersectingObjects' method. Using one of these you can check for all vertical walls or all horizontal walls at the same time and, if moving toward to wall (determined by the sign of the move direction and which order along that axis the wall and the ball are), then reverse the direction along that axis.
danpost danpost

2013/4/20

#
The main logic follows: if intersecting horizontal wall if (moving up) and (ballY - wallY > 0) then move down if (moving down) and (wallY - ballY > 0) then move up if intersecting vertical wall if (moving right) and (wallX - ballX > 0) then move left if (moving left) and (ballX - wallX > 0) then move right
Gingervitis Gingervitis

2013/4/20

#
When you say 'if (moving)' and the direction, should I have 'if(Greenfoot.isKeyDown("up")" or whatever the direction is or should I do the moving up down left or right a different way.
danpost danpost

2013/4/20

#
moving right is: xSpeed > 0 ---> move left is: xSpeed = -xSpeed moving left is: xSpeed < 0 ----> move right is: xSpeed = -xSpeed moving up is: ySpeed < 0 ----> move down is: ySpeed = -ySpeed moving down is: ySpeed > 0 ----> move up is: ySpeed = -ySpeed
Gingervitis Gingervitis

2013/4/20

#
I did my best to try to do what you said and that just made the ball move up when down key pressed, down when up key pressed, etc. and goes right through the walls.... here is my code.
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Ball here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Ball extends Animal
{
    private int xSpeed = 3;
    private int ySpeed = 3;
    /**
     * Act - do whatever the Ball wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        checkKeypress();
        checkHitHWallRight();
        checkHitHWallLeft();
        checkHitVWallUp();
        checkHitVWallDown();
    }  

    public void checkKeypress()
    {       
        if (Greenfoot.isKeyDown("left"))
        {

            move(-xSpeed);
            turn(-5);

        }
        setRotation(360);
        if (Greenfoot.isKeyDown("right"))
        {

            move(xSpeed);
            turn(5);

        }
        setRotation(90);  
        if (Greenfoot.isKeyDown("up"))  
        { 
            move(-ySpeed);

        }  
        if (Greenfoot.isKeyDown("down"))  
        {
            move(ySpeed);

        } 
        setRotation(0);
    }
    
    public void checkHitHWallRight()
    {           
        Actor ball = getOneIntersectingObject(HWall.class);  
        if (ball != null && xSpeed > 0) xSpeed = -xSpeed;         
    }
    
     public void checkHitHWallLeft()
    {                   
        Actor ball = getOneIntersectingObject(HWall.class);  
        if (ball != null && xSpeed > 0) xSpeed = -xSpeed;         
    }
    
    public void checkHitVWallUp()
    {
        Actor ball = getOneIntersectingObject(VWall.class);  
        if (ball != null && ySpeed < 0) ySpeed = -ySpeed;
    }
    
    public void checkHitVWallDown()
    {
        Actor ball = getOneIntersectingObject(VWall.class);  
        if (ball != null && ySpeed > 0) ySpeed = -ySpeed;
    }
}
danpost danpost

2013/4/20

#
You only but one of the two conditions in each part. Review what I had said.
Gingervitis Gingervitis

2013/4/20

#
I'm not sure how to set up the code for that....
danpost danpost

2013/4/20

#
ballY - wallY > 0 is: getY() - wall.getY() > 0 So, the 'checkHitVWallUp' method would be:
public void checkHitVWallUp() // which probably should be 'checkHitHWallUp'
{
    Actor wall = getOneIntersectingObject(VWall.class); // again: HWall.class
    if (wall != null && ySpeed < 0 && getY()-wall.getY() > 0) ySpeed = -ySpeed;
}
Why you are calling the wall objects returned from the 'getOneIntersectingObject' method calls 'ball' objects, I do not know. Why you are calling the horizontal walls VWalls and the vertical walls HWalls, I do not know. A bounce that changes the balls movement in the vertical direction is a bounce off a horizontal wall and a bounce that changes the balls movement in the horizontal direction is a bounce off a vertical wall.
Gingervitis Gingervitis

2013/4/21

#
Ok. Is this the code I should have?
public class Ball extends Animal
{
    private int xSpeed = 3;
    private int ySpeed = 3;
    /**
     * Act - do whatever the Ball wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        checkKeypress();
        checkHitHWallUp();
        checkHitHWallDown();
        checkHitVWallRight();
        checkHitVWallLeft();
    }  

    public void checkKeypress()
    {       
        if (Greenfoot.isKeyDown("left"))
        {

            move(-xSpeed);
            turn(-5);

        }
        setRotation(360);
        if (Greenfoot.isKeyDown("right"))
        {

            move(xSpeed);
            turn(5);

        }
        setRotation(90);  
        if (Greenfoot.isKeyDown("up"))  
        { 
            move(-ySpeed);

        }  
        if (Greenfoot.isKeyDown("down"))  
        {
            move(ySpeed);

        } 
        setRotation(0);
    }

    public void checkHitHWallUp() // which probably should be 'checkHitHWallUp'  
    {  
        Actor wall = getOneIntersectingObject(HWall.class); // again: HWall.class  
        if (wall != null && ySpeed < 0 && getY()-wall.getY() > 0) ySpeed = -ySpeed;  
    }
    
    public void checkHitHWallDown() 
    {  
        Actor wall = getOneIntersectingObject(HWall.class);   
        if (wall != null && ySpeed > 0 && wall.getY()-getY() > 0) ySpeed = -ySpeed;  
    }
    
    public void checkHitVWallLeft() 
    {  
        Actor wall = getOneIntersectingObject(VWall.class);   
        if (wall != null && xSpeed < 0 && getX()-wall.getX() > 0) xSpeed = -xSpeed;  
    }
    
    public void checkHitVWallRight() 
    {  
        Actor wall = getOneIntersectingObject(VWall.class);   
        if (wall != null && xSpeed > 0 && wall.getX()-getX() > 0) xSpeed = -xSpeed;  
    }
danpost danpost

2013/4/21

#
That appears to be a lot better! How is it working (as far as detecting walls)? It probably is not working to well as far as direction of movement, however.
Gingervitis Gingervitis

2013/4/21

#
I had done the best I could to follow the example of the code above and use it for the other directions... There are still problems with the movements and the ball still goes through some of the walls. It appears that there is a glitch that allows the ball to pass through the wall when you press certain keys in a specific way. Also when I touch a wall it sets the direction opposite and it sets everything to the inverse of the initial movements.....
danpost danpost

2013/4/21

#
You want your user-controlled ball to move forward and backward with the up and down keys and turn left and right with the left and right keys. Therefore, first control the turn, then move and check collisions. I would write it something like this:
public void act()
{
    checkTurns();
    move();
    checkWalls();
}

private checkTurns()
{
    if (Greenfoot.isKeyDown("left")) turn(-5);
    if (Greenfoot.isKeyDown("right")) turn(5);
}

private move()
{
    int d = 0;
    if (Greenfoot.isKeyDown("up")) d++;
    if (Greenfoot.isKeyDown("down")) d--;
    move(3*d);
}

private void checkWalls()
{
    VWall vWall = (VWall)getOneIntersectingObject(VWall.class);
    if (vWall != null)
    { // if moving toward vertical wall, bounce
        if (((getRotation() > 270 || getRotation < 90) && vWall.getX() > getX()) ||
            ((getRotation() > 90 && getRotation() < 270) && vWall.getX() < getX())
                setRotation(540-getRotation());
    }
    HWall hWall = (HWall)getOneIntersectingObject(HWall.class);
    if (hWall != null)
    { // if moving toward horizontal wall, bounce
        if ((getRotation() > 180 && hWall.getX() < getX()) ||
            (getRotation() < 180 && hWall.getX() > getX()))
            setRotation(360-getRotation());
    }
}
Gingervitis Gingervitis

2013/4/21

#
I have two questions. What is the variable 'd', and should I replace all of the code I previously posted with the one you provided?
danpost danpost

2013/4/21

#
It would replace most of it, which would include 'act', 'checkKeypress', and all the 'checkHit...' methods. I guess you would also remove your two instance fields 'xSpeed' and 'ySpeed'; so,.. yeah, it would be your whole Ball class code. The 'd' is short for direction which is just used locally to determine which way to move (forward: 1; none: 0; or, backward: -1). That multiplied by the speed (3) gives the appropriate movement.
There are more replies on the next page.
1
2
3