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

2015/3/15

Box moving problem

EduandErnst EduandErnst

2015/3/15

#
Hi there, I have a small problem with a box in my game. I'm trying to push and drag a box. Well pushing the box wasn't very difficult, I wrote it like that.
// box class
public int speed = 3;
public void act(){
moveRight();
}
public void moveRight(){
if (getOneIntersectingObject(Boy.class) != null && Boy.facingRight == true){
setLocation(getX() +speed, getY());
}
else if (getOneIntersectingObject(Boy.class != null && Boy.facingRight == false){
setLocation(getX() -speed, getY());
}
}
// player class
public static facingRight = true;
private Box boxmoving;
public player(Box moving){
boxmoving = moving;
}
public void act(){
checkKeys();
}
public void checkKeys(){
if (Greenfoot.siKeyDown("control") && Greenfoot.isKeyDown("right") && getOneIntersectingObject(Box.class) != null && facingRight == true){
dx = boxmoving.speed;
pushBoxRight(); // referes to the animation methode
}
else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("left") && getOneIntersectingObject(Box.class) != null && facingRight == false){
dx = -boxmoving.speed;
pushBoxLeft(); // referes to the animation methode
}
}
But with getOneIntersectingObject I wasn't properly able to drag the box to the left/right. I tried it with getObjectsInRange but it didn't work either. Any suggestions?
danpost danpost

2015/3/15

#
The main question to ask yourself is this: "What object is actually doing the actions?" When you look at it with this in mind, you will see that the box really has no actions -- it only has re-actions. It is the Boy object that performs the actions and that is where the movement of the box should be controlled from. The box only moves, by being dragged or pushed, when the Boy object moves. So, when the Boy object moves, check for a box to push or drag and move it the same direction the Boy object moved.
EduandErnst EduandErnst

2015/3/15

#
Ok, I re-wrote it a little.
Actor actor = getOneIntersectingObject(Box.class);
if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("right") && facingRight == false && actor != null){
            dx = 0;

            actor.setLocation(actor.getX() +boxmoving.speed, actor.getY());
            super.setLocation(getX() +boxmoving.speed, getY());
            dragBoxRight();
        }
        else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("left") && facingRight == true && actor != null){
            dx = 0;

            actor.setLocation(actor.getX() -boxmoving.speed, actor.getY());
            super.setLocation(getX() -boxmoving.speed, getY());
            dragBoxLeft();
        }
        else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("right") && facingRight == true && actor != null){
            dx = 0;

            actor.setLocation(actor.getX() +boxmoving.speed, actor.getY());
            super.setLocation(getX() +boxmoving.speed, getY());
            pushBoxRight();
        }
        else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("left") && facingRight == false && actor != null){
            dx = 0;

            actor.setLocation(actor.getX() -boxmoving.speed,actor.getY());
            super.setLocation(getX() -boxmoving.speed, getY());
            pushBoxLeft();
        }
        else if (Greenfoot.isKeyDown("right") && actor != null){
            dx = -dx;
        }
        else if (Greenfoot.isKeyDown("left") && actor != null){
            dx = +dx;
        }
Well I can move the box all around but the problem is that once I touch the box, I'm like caught and can't get away from it.
danpost danpost

2015/3/15

#
Make sure you removed all movement code from the Box class. Then, only use the control key to allow 'dragging' of a box. Pushing a box only requires that the box be in front (or ahead) of the boy in the direction he is moving; but, dragging a box requires the boy to 'grab' onto it -- hence the extra key press. Once the control key is released, dragging should discontinue.
EduandErnst EduandErnst

2015/3/15

#
I see what you mean, but I have difficulties doing it.
danpost danpost

2015/3/15

#
EduandErnst wrote...
I see what you mean, but I have difficulties doing it.
Instead of just saying that ^^^, explain and show code.
EduandErnst EduandErnst

2015/3/15

#
Well, I'm not much further.^^ I created a boolean "dragging" ..
private boolean dragging;
 else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("left") && actor != null && facingRight == false && dragging == true){
            dx = 0;
            dragging = false;
            actor.setLocation(actor.getX() -boxmoving.speed, actor.getY());
            super.setLocation(getX() -boxmoving.speed, getY());
            dragBoxLeft();

        }
        else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("right") && actor != null && facingRight == true && dragging == true){
            dx = 0;
            dragging = false;
            actor.setLocation(actor.getX() +boxmoving.speed, actor.getY());
            super.setLocation(getX() +boxmoving.speed, getY());
            dragBoxRight();
        }
        else if (Greenfoot.isKeyDown("right") && actor != null && facingRight == true){
            dx = 0;

            actor.setLocation(actor.getX() +boxmoving.speed, actor.getY());
            super.setLocation(getX() +boxmoving.speed, getY());
            pushBoxRight();
        }
        else if (Greenfoot.isKeyDown("left") && actor != null && facingRight == false){
            dx = 0;

            actor.setLocation(actor.getX() -boxmoving.speed, actor.getY());
            super.setLocation(getX() -boxmoving.speed, getY());
            pushBoxLeft();
        }

if (!Greenfoot.isKeyDown("control") && dragging == false){
dragging = true;
}
The Problem remains, I'm stuck in the box once I touch it. And another issue is, that when I drag the box left/right and try to push the box afterwards while "control" is still pressed it shows the wrong animation.
danpost danpost

2015/3/15

#
You should not need the 'dragging' field; in fact, you do not need a 'facingRight' field as well. You can simplify the code by collecting data before acting on it:
int dx = 0;
if (Greenfoot.isKeyDown("left")) dx--;
if (Greenfoot.isKeyDown("right")) dx++;
if (dx == 0) return; // no movement
Actor pushed = getOneObjectAtOffset(dx*40, 0, Box.class);
Actor pulled  = getOneObjectAtOffset(-dx*40, 0, Box.class);
if (! Greenfoot.isKeyDown("control")) pulled = null;
if (dx > 0) /** set right image */ else /** set left image */
move(dx*speed);
if (pushed != null) pushed.move(dx*speed);
if (pulled != null) pulled.move(dx*speed);
This should push and pull boxes as desired. Just adjust the offset value, '40', on lines 5 and 6 and the 'speed'. on lines 9 through 11; also, put the proper 'setImage' statements in line 8.
EduandErnst EduandErnst

2015/3/15

#
I'm sure your method works just well but the actual if statement is much longer and your code wouldn't fit into it. And properly re-writing it without knowing what you did is almost impossible. I'll just give you the whole if statement, so you can see what I'm trying to.
private int frame = 1;
    private double gravity = 0;
    private double acceleration = 0.3;
    public static boolean facingRight = true;
    private boolean jumpingRight;
    private boolean jumpingLeft;
    private int jumpFrameL;
    private int jumpFrameR;
    public int ForwardJumpLeft;
    public int ForwardJumpRight;
    private boolean jumpingAheadLeft;
    private boolean jumpingAheadRight;
    private int jumpStrength = 13;

    private boolean activejumpL;
    private boolean activejumpR;

    private boolean followupR = false;
    private boolean followupL = false;
    private boolean jumppossibility;

    

    private boolean standRight;
    private boolean standLeft;

    private int framepushboxright;
    private int framepushboxleft;
    private int framedragboxright;
    private int framedragboxleft;

    private int moveupR;
    private int moveupL;
    private int movedownR;
    private int movedownL;

    private int dx = 0;

    private boolean draggingR = false;
    private boolean draggingL = false;
    
    private Box boxmoving;

    public Boy(Box moving){
        boxmoving = moving;

    }

   
    public void act() 
    {
        keyControl();
        checkframe();
        checkFallRight();
        checkFallLeft();

        if (jumpingRight == true && jumpingLeft == false ) {
            animateStraightJumpingRight();
        }
        if (jumpingLeft == true && jumpingRight == false ) {
            animateStraightJumpingLeft();
        }
        if (jumpingAheadRight == true && jumpingAheadLeft == false && jumpingRight == false && jumpingLeft == false){
            jumpAheadRight();
        }
        if (jumpingAheadLeft == true && jumpingAheadRight == false && jumpingRight == false && jumpingLeft == false){
            jumpAheadLeft();
        }

    }

    public void keyControl(){
        Actor actor = getOneIntersectingObject(Box.class);

        /*
         * Checks both, "right" and "up" key. If both are pressed, jumpRight methode gets called, as well as jumpingAheadRight gets enabled in order to play the animation, which is placed in the act methode.
         * ActivejumpL/R are getting enabled in order to prevent double-jumping. If clause for prevention on the bottom of move methode.
         */
        if (Greenfoot.isKeyDown("right") && Greenfoot.isKeyDown("up") && !activejumpR && facingRight == true && jumppossibility == true && followupL == false){ // jumppossibility only is enabled when boy is on ground
            while (dx <= 20){ // counts down realy quickly, to jump further in order to bouchne over broader gaps
                dx++;
            }

            jumpRight(); // "goto" jump methode.
            facingRight = true; // tells the programm which pic. to choose when boy lands
            activejumpR = true; // enables activejumpR to prevent boy from double jumping, you have to release key "up" in order to disable it.
            activejumpL = true; // enables activejumpL to prevent boy from double jumping, you have to release key "up" in order to disable it.
            jumppossibility = false; // prevents from jumping straight while still in air (double-jump) 
            if (!Greenfoot.isKeyDown("control")) // prevents boy from switching Frames between jumping and pushing in case Image has false offset
                jumpingAheadRight = true;
            jumpingAheadLeft = false;
            if (getOneIntersectingObject(Box.class) != null || getOneIntersectingObject(Ladder.class) != null)// prevents boy from jumping through boxes
                dx = 0;
        }
        /*
         * Checks if key "right" is pressed while implementing forwardjump to the right. 
         * If right key is pressed boy get speed boost to jump further and it keeps the forwardjump-animation running.
         */
        else if (Greenfoot.isKeyDown("right") && followupR == true && followupL == false){ // gets enabled in case upper jump movement hasn't been finished.
            facingRight = true; // tells the programm which pic. to choose when boy lands
            activejumpR = true; // enables activejumpR to prevent boy from double jumping, you have to release key "up" in order to disable it.
            activejumpL = true; // enables activejumpL to prevent boy from double jumping, you have to release key "up" in order to disable it.
            jumpingAheadRight = true; // enables the animation for jumping right
            jumpingAheadLeft = false; // disables the animation for jumping left
            jumppossibility =  false; // prevents from jumping straight while still in air (double-jump) 
            if (getOneIntersectingObject(Box.class) != null || getOneIntersectingObject(Ladder.class) != null)// prevents boy from jumping through boxes
                dx = 0;
        }
        /*
         * Checks both, "left" and "up" key. If both are pressed, jumpLeft methode gets called, as well as jumpingAheadLeft gets enabled in order to play the animation, which is placed in the act methode.
         * ActivejumpL/R are getting enabled in order to prevent double-jumping. If clause for prevention on the bottom of move methode.
         */
        else if (Greenfoot.isKeyDown("left") && Greenfoot.isKeyDown("up") && !activejumpL && facingRight == false && jumppossibility == true && followupR == false){ // jumppossibility only is enabled when boy is on ground
            while (dx >= -20){ // counts down realy quickly, to jump further in order to bouchne over broader gaps
                dx--;
            }
            jumpLeft(); // "goto" jump methode.
            facingRight = false; // tells the programm which pic. to choose when boy lands
            activejumpL = true; // enables activejumpL to prevent boy from double jumping, you have to release key "up" in order to disable it.
            activejumpR = true; // enables activejumpR to prevent boy from double jumping, you have to release key "up" in order to disable it.
            jumppossibility = false; // prevents from jumping straight while still in air (double-jump) 
            if (!Greenfoot.isKeyDown("control"))// prevents boy from switching Frames between jumping and pushing in case Image has false offset
                jumpingAheadRight = false;
            jumpingAheadLeft = true;
            if (getOneIntersectingObject(Box.class) != null || getOneIntersectingObject(Ladder.class) != null) // prevents boy from jumping through boxes.
                dx = 0;
        }
        /*
         * Checks if key "left" is pressed while implementing forwardjump to the left. 
         * If left key is pressed boy gets speed boost to jump further and it keeps the forwardjump-animation running.
         */
        else if (Greenfoot.isKeyDown("left") && followupL == true && followupR == false){ // gets enabled in case upper jump movement hasn't been finished.
            facingRight = false; // tells the programm which pic. to choose when boy lands
            activejumpR = true; // enables activejumpR to prevent boy from double jumping, you have to release key "up" in order to disable it.
            activejumpL = true; // enables activejumpL to prevent boy from double jumping, you have to release key "up" in order to disable it.
            jumpingAheadRight = false; // disables the animation for jumping right
            jumpingAheadLeft = true; // enables the animation for jumping left
            jumppossibility = false; // prevents from jumping straight while still in air (double-jump) 
            if (getOneIntersectingObject(Box.class) != null || getOneIntersectingObject(Ladder.class) != null)// prevents boy from jumping through boxes
                dx = 0;
        }

        /*
         * Checks "STRG - Control" key as well as right/left key to move the box around.
         * Also checks if a box is in front of boy to invoce walking through boxes. 
         */

        
        else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("left") && actor != null && facingRight == false && dragging == true){
            dx = 0;

            dragging = false;
            actor.setLocation(actor.getX() -boxmoving.speed, actor.getY());
            super.setLocation(getX() -boxmoving.speed, getY());
            dragBoxLeft();
        }
        else if (Greenfoot.isKeyDown("control") && Greenfoot.isKeyDown("right") && actor != null && facingRight == true && dragging == true){
            dx = 0;

            dragging = false;
            actor.setLocation(actor.getX() +boxmoving.speed, actor.getY());
            super.setLocation(getX() +boxmoving.speed, getY());
            dragBoxRight();
        }
        else if (Greenfoot.isKeyDown("right") && actor != null && facingRight == true){
            dx = 0;

            actor.setLocation(actor.getX() +boxmoving.speed, actor.getY());
            super.setLocation(getX() +boxmoving.speed, getY());
            pushBoxRight();
        }
        else if (Greenfoot.isKeyDown("left") && actor != null && facingRight == false){
            dx = 0;

            actor.setLocation(actor.getX() -boxmoving.speed, actor.getY());
            super.setLocation(getX() -boxmoving.speed, getY());
            pushBoxLeft();
        }
         
        /*
         * Crane movement
        */

       
        /*
         * Ladder up/down movement
         */

        else if (Greenfoot.isKeyDown("up") && getOneIntersectingObject(Ladder.class) != null  && facingRight == true){
            setLocation(getX(), getY() -5);
            moveUpRight();
        }
        else if (Greenfoot.isKeyDown("up") && getOneIntersectingObject(Ladder.class) != null && facingRight == false){
            setLocation(getX(), getY() -5);
            moveUpLeft();
        }
        else if (Greenfoot.isKeyDown("down") && getOneIntersectingObject(Ladder.class) != null){
            setLocation(getX(), getY() +5);
        }

        else if (getOneIntersectingObject(Ladder.class) != null && facingRight == true){
            int spriteWidth = getImage().getWidth();
            int lookForLadder = (int) (spriteWidth/2);
            dx = 0;
            setLocation(lookForLadder +830, getY());
            setImage(ladderRUaD1);
        }
        else if (getOneIntersectingObject(Ladder.class) != null && facingRight == false){
            int spriteWidth = getImage().getWidth();
            int lookForLadder = (int) (spriteWidth/2);
            dx = 0;
            setLocation(lookForLadder+850, getY());
            setImage(ladderLUaD1);
        }

        /*
         * Checks right/left key
         */
        else if (Greenfoot.isKeyDown("right") && followupR == false)
        {
            facingRight = true;
            jumpFrameR = 0;
            jumpFrameL = 0;
            ForwardJumpRight = 0;
            jumpingRight = false;
            jumpingLeft = false;
            WalkRight();
            fallRight();
            if (dx < 10) 
                dx++;
            if (dx > 10)
                dx--;
        }
        else if (Greenfoot.isKeyDown("left") && followupL == false)
        {
            facingRight = false;
            jumpFrameR = 0;
            jumpFrameL = 0;
            ForwardJumpLeft = 0;

            jumpingRight = false;
            jumpingLeft = false;

            WalkLeft();
            fallLeft();

            if (dx > -10)
                dx--;
            if (dx < -10)
                dx++;
        }

        /*
         * jumping straight
         * Checks key "up" and if boy if is facing right or left. If he stands to the right 
         */
        else if (Greenfoot.isKeyDown("up") &&  facingRight == true && jumpingRight == false && jumpingLeft == false && jumppossibility == true && getOneIntersectingObject(Ladder.class) == null){
            jumpRight();
            dx = 0;
            jumpingRight = true;
            jumpingLeft = false;

        }
        else if (Greenfoot.isKeyDown("up") &&  facingRight == false && jumpingRight == false && jumpingLeft == false && jumppossibility == true && getOneIntersectingObject(Ladder.class) == null){
            jumpLeft();
            dx = 0;
            jumpingRight = false;
            jumpingLeft = true;

        }

        /*
         * Sets apro. pic when animation stops.
         */

        else if (facingRight == true && jumpingRight == false && jumpingLeft == false && followupL == false && followupR == false && !Greenfoot.isKeyDown("right")){
            while (dx > 0){
                dx--;
                return;
            }
            while (dx < 0){
                dx++;
                return;
            }

            if (!Greenfoot.isKeyDown("control"))
                setImage(boyFacingR);
        }         
        else if (facingRight == false && jumpingRight == false && jumpingLeft == false && followupL == false && followupR == false){
            while (dx < 0){
                dx++;
                return;
            }
            while (dx > 0){
                dx--;
                return;
            }

            if (!Greenfoot.isKeyDown("control"))
                setImage(boyFacingL);
        }

        /*
         * Checks if boy is jumping and Left/Right key is pressed. If right/left key is pressed while jumping = true, the boy cannot move.
         * Prevents the boy to move while jumping straight. 
         */
        
        if (jumpingRight && Greenfoot.isKeyDown("right") || jumpingRight && Greenfoot.isKeyDown("left")){
            dx = 0;
        }
        if (jumpingLeft && Greenfoot.isKeyDown("left") || jumpingLeft && Greenfoot.isKeyDown("right")){
            dx = 0;
        } 

        /*
         * "(Checks Key "up")". If it's not pressed and activeJumpR/L = true, it resets activeJumpR/L to prevent double-jumps. 
         */

        if (!Greenfoot.isKeyDown("up") && activejumpR){ // if key "up" was pressed and boy is facing right activejumpR is true, which gets disabled again when key "up" was released.
            activejumpR = false;
        }
        if (!Greenfoot.isKeyDown("up") && activejumpL){
            activejumpL = false;
        }

        /*
         * Checks Key ("control"). If it's not pressed and dragging = true, it resets dragging.
         */

        
        setLocation(getX() + dx, getY());
    }
danpost danpost

2015/3/16

#
I still do not have a full picture of what you need. You did not post the entire class, but eliminated some of the methods that would give a better understanding of what is needed. It would be good if you could explain exactly how you want your actor to behave under all the different circumstances it could be in (during each stage of jumping, moving, standing, etc.). There are so many fields!! Most of them are probably not used or not needed. Is there a specific distance a box must be pushed or dragged for each move? or, can they be left just about anywhere?
EduandErnst EduandErnst

2015/3/16

#
I only left out the jumping and the animation methods, cause I didn't think they would be of interest. Yes the field is quite large but I don't know a proper way around all this booleans and the integers are only for the animations, well I could put them in the specific metode but testing it's better to see whether it's counting up correctly. The box can be left anywhere. It is placed at a specific position in the world and in order to win the game it has to be moved to a specific position from where you can reach a platform.
danpost danpost

2015/3/16

#
The code I provided was not to 'fit' into your code -- it was to replace your code. First, let me explain that this code should be used after determining that the boy is not currently jumping. Adding extra documentation to explain, we have this:
/** getting user input for direction of movement */
int dx = 0; // for user direction
if (Greenfoot.isKeyDown("left")) dx--;
if (Greenfoot.isKeyDown("right")) dx++;
/** if not movement directed */
if (dx == 0)
{
    /** set standing image here */
    // return; can possibly be used here to exit the method at this point
}
/** getting possible boxes being moved */
Actor pushed = getOneObjectAtOffset(dx*40, 0, Box.class); // possible box in front
Actor pulled  = getOneObjectAtOffset(-dx*40, 0, Box.class); // possible box behind
/** removing as possibility box behind if not user directed to drag */
if (! Greenfoot.isKeyDown("control")) pulled = null; // do not drag any box behind
/** controlling the current image */
if (dx > 0) /** run right animation */ else /** run left animation */
/** moving the boy and any boxes that need moved */
move(dx*speed); // move boy
if (pushed != null) pushed.move(dx*speed); // move box in front, if any
if (pulled != null) pulled.move(dx*speed); // move box behind, if any and moving
Notice that lines 1 through 13 was basically collecting the needed data and lines 14 through 21 performs the actions needed based on that data. Well, lines 6 through 10 does act upon the previous data collected. It seems like the only reason for the 'boxmoving' field and a Box object being brought in through the constructor is to get the speed of a box object. If the speed is constant, then, in the Box class, make the speed field a 'public static final int' value. Then, you can just use 'Box.speed' in this class and dispense with the 'boxmoving' field. Let me know if I am wrong about the use of the field.
EduandErnst EduandErnst

2015/3/16

#
Yes that's right the constructor is pretty useless as well as the boxmoving field. Anyhow I now solved it pretty well with your code, only sometimes when I run into the box and try to move away from it again I get trapped but this could be (or probably is) caused by the pictures I'm currently using... But there is one more issue with my box. I want to climb on top of it. So I will need to get the x and y coordinates and the height of the box, as far as I know I can get them with getX() getY() and getImage().getHeight() So I was thinking like
if (pushed != null || pulled != null){
            int boxHeight = pushed.getImage().getHeight();
            int boxWidth = pushed.getImage().getWidth();
            int newX = pushed.getX() - (boxWidth + getImage().getHeight())/2;
            int newY = pushed.getY() - (boxHeight + getImage().getHeight())/2;
            
            if (getY() == newY)
                gravity = 0;
            if (Greenfoot.isKeyDown("up"))
                setLocation(newX+200, newY);
        }
But I'm moving through the top of the box. My jumping method checks if I'm on ground and if so gravity = 0; that's why I'm trying to set gravity to 0 when I'm at the newY position.
danpost danpost

2015/3/16

#
The actors held by 'pushed' and 'pulled' should only be used in conjunction with the horizontal movement of the boy. The offsets used to get a box that is intersected while moving vertically would not be the same as that used for 'pushed' and 'pulled'; so, obviously, you cannot just used those. The vertical movement should be done separately and before the horizontal movement. And yes, you will be using 'getY()' and 'getImage().getHeight()', but not 'getX()' as it has nothing to do with where to boy stops when intersecting a box while moving vertically. You may want to look at my Jump and Run Demo w/Moving Platform scenario to see how I coded its movement. The only thing you would need to add to something like that would be the image animations.
You need to login to post a reply.