2
\$\begingroup\$

I want to make an RPG game in which I move tile by tile. So when I hit up, the tile row that I am on decreases by one for example. Also, it's supposed to be a slow movement so that I can see the change in tile, i.e. I can see my sprite move from tile to tile. Currently, with the code I have, when I hit a direction on my keyboard, I move several blocks within seconds and by the time I release the button I have already gotten a nullPointerException error because I have left the map. How can I slow down the movement?

\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

This sounds like an input problem. You need to check your inputs to see if you've already processed a key press. Keep the state of the keyboard from the last frame and check it when you're on your new frame. Only move if the key was not being pressed in the previous frame. Similar to responding to the event of pressing the key instead of the key being down.

For example:

currentKeys.fillFromKeyboard();

if(currentKeys.isDown(Key.UP) && !previousKeys.isDown(Key.Up))
    character.moveUp();

...

previousKeys.fill(currentKeys);

That will apply one move to each key press. If you wanted to have a held key repeat movements you can do something like:

int repeatDelay = 500; //time in MS that we'll delay before repeating a key

if(currentKeys.isDown(Key.UP) && (getCurrentGameTime() - timeMoved) >= repeatDelay) {
    character.moveUp();
    timeMoved = getCurrentGameTime();
}

Additionally, you should probably be checking bounds when moving. So check that your character's position + movement amount is withing world bounds, before moving.

\$\endgroup\$
2
  • \$\begingroup\$ moveUp would also have to be changed to be aware of if the character is currently moving, otherwise tapping up a few times would still move the character upwards several blocks. \$\endgroup\$ Commented Jul 8, 2012 at 18:53
  • \$\begingroup\$ @CiscoIPPhone Good point. The move up command can either queue up movements if the character is currently moving or additional moves can be ignored. I think expected behavior would be to ignore the additional input, but that's something you'll have to play test. \$\endgroup\$
    – House
    Commented Jul 8, 2012 at 18:57
1
\$\begingroup\$

Just a note on structure - you are calling repaint(); in your update(); function, but it would probably be better if you didn't chain the calls like that, but rather have those in your main game loop, ie.:

while(true) {
   update();
   render();  // if you use double-buffering, which you probably should
   repaint();
}
\$\endgroup\$
0
1
\$\begingroup\$

This is the code I used.

// These numbers represent the different directions in movement.
private final int STILL = 0, LEFT = 1, UP = 2, RIGHT = 3, DOWN = 4,
        STOP = 5;
// The current direction of movement of the player.
public int movement = 0;

// The move method, like any other player class.
private void move() {
// The keyboard input class works like this:
// If the up keyboard button is pressed, player.movement = player.UP,
// if right is pressed, player.movement = player.RIGHT, etc.
// and if no key is pressed, player.movement = player.STILL;

    if (movement == UP) {
        moveUp();
    }
    if (movement == LEFT) {
        moveLeft();
    }
    ....
    if (movement == STILL) {
        setDx(0);
        setDy(0);
    }
}

private void moveLeft() {
// Because this intends to work on a tile grid, this method checks if
// the tile to the left of the player is occupied.
    if (!tileIsOccupied(LEFT)) {
// The player can press a key every 200 ms. Sets the time moved to this 
// point in time. If a player attempts to move before those 200 ms are
// over, no movement will occur.
        setTimeMoved(getCurrentTime());
// This tile is essential the tile to the left of the player.
        Tile tile = getGrid().getTiles()[getTileRow() - 1][getTileColumn()];
// If the xpos of the player is greater than the xpos of the tile, keep moving
// left.
        if (getXpos() > tile.getXpos()) {
            setDx(-1);
            setXpos(getXpos() + getDx());
        }
// If the xpos of the player is less than or equal to that of the tile, 
// set the player's position equal to the tiles. In other words, when
// the player has moved to the tile.
// Set this current tile to equal the player's tile, and movement is reset to
// still. 
        if (getXpos() <= tile.getXpos()) {
            setTileColumn(tile.getTileColumn());
            setTileRow(tile.getTileRow());
            setXpos(tile.getXpos());
            setMovement(STILL);
        }
    } else
        movement = STILL;
}

// It's essential that the update function be called on a loop. Otherwise, the
// player will not move. 
public void update() {
    move();
}
\$\endgroup\$
3
  • \$\begingroup\$ -1 Answers that are just code are poor. Generally it doesn't explain things as nicely as some text, and in this case, it makes the answer too localized to this question, making it less useful to future visitors. It's not even commented code. \$\endgroup\$
    – House
    Commented Dec 22, 2012 at 15:49
  • \$\begingroup\$ I added comments. Hopefully this will be more useful to future visitors. \$\endgroup\$
    – helsont
    Commented Dec 22, 2012 at 16:29
  • \$\begingroup\$ That's better, it explains the code, but it doesn't explain how you solved the problem. \$\endgroup\$
    – House
    Commented Dec 22, 2012 at 16:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .