How to move a visible image diagonally?

4.2k views Asked by At

I have been trying to figure out how to make a visible image move diagonally in an applet window.

If you press up, down, left, or right the image (a gif) moves accordingly, however if you try to press two keys at once (up and right at the same time for example) the image only moves in the direction you pressed second (even if you press the keys at the same time there is still a microscopic delay).

There might be a simple way to fix this that I am just not aware of, or perhaps a workaround someone has figured out... I appreciate any help or advice that can be given.

Thank-you

Hero Class (this class defines what the "Hero" is; in this case a simple pixel man, and what he can do)

import objectdraw.*;
import java.awt.*;

public class Hero extends ActiveObject {

private DrawingCanvas canvas;
private VisibleImage player;

public Hero(Location initLocation, Image playerPic, DrawingCanvas aCanvas) {
canvas = aCanvas;

player = new VisibleImage(playerPic, canvas.getWidth()/3,
         canvas.getWidth()/3, canvas);
start();

}
public void run() 
{

}

public void move(double dx, double dy) 
{
player.move(dx, dy);
}
}

HeroGame class (this class creates the "Hero" and specifies the location, as well as what keys are used to make him move)

import objectdraw.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HeroGame extends WindowController implements KeyListener {
private Hero theHero;
private Image playerPic;
private Location initLocation;
public void begin() {
    playerPic = getImage("player.gif");
    canvas.addKeyListener ( this );
    this.addKeyListener ( this );
    requestFocusInWindow();
    theHero = new Hero(initLocation, playerPic, canvas);
    }
public void keyTyped( KeyEvent e ) { }
public void keyReleased( KeyEvent e ) { }
public void keyPressed( KeyEvent e ) {

    if ( e.getKeyCode() == KeyEvent.VK_UP ) {
        theHero.move(0,-5);
    }
    else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
        theHero.move(0,5);
    }
    else if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
        theHero.move(-5,0);
    }
    else if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
        theHero.move(5,0);
    }
  }
}

Thank-you once more for taking the time to read this and hopefully help.

5

There are 5 answers

0
c.s. On BEST ANSWER

This is a rather usual situation in games that accept keyboard input. The problem is that your game needs to act on all keys that are currently pressed as far as the game is concerned (meaning all keys for which a KEY_RELEASE event has not been fired yet).

KeyListener will only notify you for the last key pressed (and will keep notifying you for that same key if you hold it pressed) so you need to keep track of the state for the rest of the keys yourself.

To get an idea on how to do that, search for Keyboard polling (here an example) a popular technique where you don't act immediately to the player's input but rather store the key presses in a queue and later poll that queue at regular intervals (i.e. in your game loop) to decide what keys are pressed or not and act accordingly.

I hope this helps

1
camickr On

I would suggest you use Swing (JApplet) and Key Bindings. See Motion Using the Keyboard for problems with using a KeyListener along with a solution for handling multiple keys being pressed at the same time.

5
bas On

change

if ( e.getKeyCode() == KeyEvent.VK_UP ) {
    theHero.move(0,-5);
}
else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
    theHero.move(0,5);
}
else if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
    theHero.move(-5,0);
}
else if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
    theHero.move(5,0);
}

to

if ( e.getKeyCode() == KeyEvent.VK_UP ) {
    theHero.move(0,-5);
}
if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
    theHero.move(0,5);
}
if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
    theHero.move(-5,0);
}
if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
    theHero.move(5,0);
}

And it should react on both keys.

6
Evgheni Crujcov On

What you need to do is access the underlying AffineTransform class of the image, and set the right Translation methods. That would allow you to move the image anyway (by any # of degrees, in any direction) with one press of a key (that you bind to that call).

Read on this: http://docs.oracle.com/javase/7/docs/api/java/awt/geom/AffineTransform.html

0
MadProgrammer On

Instead of your if-else statement for the key, you should be using a series of if statements.

Instead of setting the hero's direction for both the x and y movement in these if statements, you should only be updating the appropriate delta

For (a very simplified) example...

if (up) yDelta = -5;
if (down) yDelta = 5;
if (left) xDelta = -5;
if (right) xDelta = 5;

hero.move(xDelta, yDelta);

I also agree with camickr