How to move a visible image diagonally?
Asked Answered
O

5

6

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.

Omnirange answered 7/8, 2013 at 19:28 Comment(0)
A
0

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

Astronautics answered 7/8, 2013 at 21:25 Comment(0)
B
3

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.

Bailable answered 7/8, 2013 at 19:32 Comment(1)
Ok, thank-you I will check those out; if I notice what it is I'll be sure to post that.Omnirange
T
2

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.

Thickset answered 7/8, 2013 at 19:33 Comment(5)
Without seeing the rendering code, I'm not sure that will work. If the user hits up and left, the characters movement delta would still be -5,0Dariusdarjeeling
Thank-you, however the results remained the same after I made those changes, though your suggestion made sense to me.Omnirange
does theHero.move(0,5); allow for multiple calls? Like, if the player is moving, would it be possible to call the method move() for theHero a second time?Thickset
@Thickset Take a look at the code the OP has provided, I think you should be able to deduce the answerDariusdarjeeling
This won't help. Only a single event is generated even though two key are held down at the same time. This is why you need to manually track which keys have been pressed.Bailable
D
1

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

Dariusdarjeeling answered 7/8, 2013 at 19:44 Comment(0)
D
0

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

Dixil answered 7/8, 2013 at 19:42 Comment(6)
Apart from rotation, which I'm pretty sure isnt being asked, I don't see how AffineTranform will will help. What's wrong with Graphics#drawInage and simple overlaying images on top of each other?Dariusdarjeeling
.translate() method from AffineTransform?Dixil
Still not sure how that's going to fix the OPs problem :PDariusdarjeeling
0.Make 4 new methods for diagonal movement, then for each: 1. Get the transform from underlying image. 2. transformer.translate(1, 1); to move diagonally to the lower left. 3. transformer.translate(-1, -1); to move diagonally to the upper right. 4. transformer.translate(-1, 1); to move diagonally to the upper right. 5. transformer.translate(1, -1); to move diagonally to the lower right. 6. Bind 4 keys to that, e.g. Q,E,Z,X and voila, image/character can move diagonally with press of one key?Dixil
Which could be achieved via drawImage. We don't have the op's render code, but we can see how they are updating model. Ali, don't tell me, tell the OP ;)Dariusdarjeeling
voila, image/character can move diagonally with press of one key? - that wasn't the requirement. If that was the solution the OP wanted he could just change his code to use: theHero.move(5,5) and bind that to the Q key. No need to rewrite the code to use AffineTransform.Bailable
A
0

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

Astronautics answered 7/8, 2013 at 21:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.