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

2011/3/14

Pushing crates.

hesh hesh

2011/3/14

#
Hello! I'm trying to make a game in which crates are to be moved (pushed) around towards specific locations in a grid by the player class. It includes the following separate classes: Player, Block, Crate and Goal. The Blocks are solid and can't move, the Crates are solid and can be moved, but only if the field on the other side of them is free. The player class can be moved around the grid by the player with the arrow keys, taking one step each time it is pressed. I already got the player class to move around using the arrow keys. I'm trying to find a way to allow it to push the crates. So: if the player class is in a field horizontally or vertically next to a crate class and the field on the other side of the crate is free and the player class is moved into the direction of the crate, both the player and the crate should be moved in the specific direction. So I've got it pretty clear on how I want it and what conditions are attached but I don't have a clue on how to get this into my program. I'm wondering whether I should be making a single canMove() method. Note that the program will need to check different fields for each arrow key being pressed. Maybe I could add extra conditions to the main movement programming. For example: IF i press my left arrow key AND there is no Block class in the field left of my class. THEN : setLocation(getX() - 1, getY()); IF i press my left arrow key AND there is a crate class in the field left of my class AND the field left of that crate (2 fields left of my class) is empty THEN : setLocation(getX() - 1, getY()); AND set location of the crate one field to the left. But I'd have to combine them to make them work at the same time. And I still wouldn't know whether that would work, let alone what methods I'd need to work this out. Can anybody help? Any ideas?
davmac davmac

2011/3/17

#
Having a single canMove() method would be a fine idea, though you'd need to give it a direction. You just have to convert your pseudo code in to real Java code. Eg: IF i press my left arrow key AND there is no Block class in the field left of my class. THEN : setLocation(getX() - 1, getY()); Becomes: if (Greenfoot.isKeyDown("left")) { if (getOneObjectAtOffset(-1, 0, Block.class) != null) { setLocation(getX() - 1, getY()); } } You just need to translate the rest of the pseudo-code. Give it a shot.
hesh hesh

2011/3/19

#
Hey there! Thanks a lot for your input! I think I almost got it working now. The movement is doing what it should do around blocks. I tried translating the other part, but I've got a few questions. This is what I have in a processKeys() code, on the LEFT arrow key: String key = Greenfoot.getKey(); if("left".equals(key)) { if(getOneObjectAtOffset(-1, 0, Block.class) == null) { setLocation(getX() - 1, getY()); } if(getOneObjectAtOffset(-1, 0, Crate.class) != null) { if(getObjectsAt(-2, 0, null) == null) { setLocation(crate.class, getX() - 1, getY()); } } } The first error i get is regarding 'if(getObjectsAt(-2, 0, null) == null)'. It claims not to be able to find this method. 'cannot find symbol - method getObjectsAt(int,int,<nulltype>)'. I'm pretty confident I found this on the documentation page greenfoot links to. That page said 'null' after the second comma meant it would search for objects of any class, which is what I'm looking for. The second problem lies in the line 'setLocation(crate.class, getX() - 1, getY());'. I'm pretty sure this method doens't even exist. But I don't have a clue what else to use, so it was a pure guess really. What is the best way to move (or to get the World to move) another Object with a certain location in the grid one position to the left? Or is this only possible from the certain class' code itself? Thanks in advance.
davmac davmac

2011/3/19

#
"getObjectsAt" is a World method, which you're calling from an Actor. It's possible to do this, but it doesn't work in the way you're using it (it requires different syntax, it needs absolute coordinates, and it will never return null). You can however use "getOneObjectAtOffset" just as you already have. I.e. just change "getObjectsAt" in your example code to "getOneObjectAtOffset". However: The method setLocation(), as you suspect, can't be used in the way you are trying to here. What you're really trying to do is: 1) see if there is a crate one position to the left and 2) if there is, see if the place to the left of it is free and 3) if so, move the crate into the free spot. To do this the code should look more like: Crate c = (Crate) getOneObjectAtOffset(-1, 0, Crate.class); if (c != null) { if (getOneObjectAtOffset(-2,0,null) == null) { c.setLocation(c.getX() - 1, c.getY()); } } This should replace what you currently have as: if(getOneObjectAtOffset(-1, 0, Crate.class) != null) { if(getObjectsAt(-2, 0, null) == null) { setLocation(crate.class, getX() - 1, getY()); } }
JetLennit JetLennit

2013/4/6

#
The
  if (Greenfoot.isKeyDown("left")) {
        if (getOneObjectAtOffset(-1, 0, Block.class) != null) {
            setLocation(getX() - 1, getY());
        }
    }
isnt working for me.... has greenfoot changed how it works in an update?
JetLennit JetLennit

2013/4/6

#
never mind... i fixed it
kristal kristal

2014/10/14

#
How did you solve this?
danpost danpost

2014/10/14

#
@kristal, although I cannot say how JetLennit solved this, I can say how I would solve it (which is a bit different from the method used above). I would add a method in the Crate class for moving the crate. The method would check to see if it can move in the direction given as parameter value(s), move in that direction (if possible), and return a boolean value (true/false) to indicate whether it moved or not. The method could start something like this:
public boolean isMoved(int dx, int dy)
Then, the code to move or move while pushing a crate in the Player class could use lines something like this:
Crate crate = getOneObjectAtOffset(dx, dy, Crate.class);
if (crate == null || crate.isMoved(dx, dy)) setLocation(getX()+dx, getY()+dy);
One thing missing from this discussion is checking to see if the offsets land on a valid gridsquare. That is, whether the player or the crate is against the edge of the world and trying to move toward it. This will have to be worked out before (a) checking for a crate in the player class; and (b) checking to see if the crate can move in the crate class.
You need to login to post a reply.