I have the following code:
package myprojectgame.entities.creature;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import myprojectgame.Game;
import myprojectgame.Handler;
import myprojectgame.gfx.Animation;
import myprojectgame.gfx.Assets;
import myprojectgame.input.KeyManager;
import static myprojectgame.input.KeyManager.keys;
public abstract class Player extends Creature {
// Animations ---> while moving
private Animation down;
private Animation up;
private Animation left;
private Animation right;
// Animations --> idle
private Animation down_idle;
private Animation up_idle;
private Animation left_idle;
private Animation right_idle;
// Last pressed boolean variable --> initialize it to down
public boolean lastPressed = handler.getKeyManager().down;
public Player(Handler handler,float x, float y) {
super(handler,x, y,Creature.DEFAULT_CREATURE_WIDTH,Creature.DEFAULT_CREATURE_HEIGHT);
bounds.x = 16;
bounds.y = 14;
bounds.width = 25;
bounds.height = 43;
// Animations --> while moving instantiation
down = new Animation(300,Assets.player_down);
left = new Animation(300,Assets.player_left);
right = new Animation(300,Assets.player_right);
up = new Animation(300,Assets.player_up);
// Animations --> while idle instantiation
down_idle= new Animation(500,Assets.player_down_idle);
right_idle= new Animation(500,Assets.player_right_idle);
left_idle= new Animation(500,Assets.player_left_idle);
up_idle= new Animation(500,Assets.player_up_idle);
}
@Override
public void tick() {
down.tick();
up.tick();
right.tick();
left.tick();
down_idle.tick();
up_idle.tick();
right_idle.tick();
left_idle.tick();
getInput();
move();
handler.getCamera().centerOnEntity(this);
}
private void getInput() {
xMove = 0;
yMove = 0;
if (handler.getKeyManager().up) {
yMove = -speed;
lastPressed = handler.getKeyManager().up;
}
if (handler.getKeyManager().down) {
yMove = speed;
lastPressed = handler.getKeyManager().down;
}
if (handler.getKeyManager().left) {
xMove = -speed;
lastPressed = handler.getKeyManager().left;
}
if (handler.getKeyManager().right) {
xMove = speed;
lastPressed = handler.getKeyManager().right;
}
}
@Override
public void render(Graphics g) {
g.drawImage(getCurrentAnimationFrame(),(int) (x - handler.getCamera().getxOffset()), (int) (y - handler.getCamera().getyOffset()),(width),(height), null);
}
private BufferedImage getCurrentAnimationFrame() {
if (handler.getKeyManager().left && lastPressed == handler.getKeyManager().left) {
return left.getCurrentFrame();
} else if ( !(handler.getKeyManager().left)) {
return left_idle.getCurrentFrame();
}
if (handler.getKeyManager().right && lastPressed == handler.getKeyManager().right) {
return right.getCurrentFrame();
} else if ( !(handler.getKeyManager().right) && lastPressed == handler.getKeyManager().right) {
return right_idle.getCurrentFrame();
}
if (handler.getKeyManager().up && lastPressed == handler.getKeyManager().up) {
return up.getCurrentFrame();
} else if ( !(handler.getKeyManager().up) && lastPressed == handler.getKeyManager().up ) {
return up_idle.getCurrentFrame();
}
if (handler.getKeyManager().down && lastPressed == handler.getKeyManager().down) {
return down.getCurrentFrame();
} else if ( !(handler.getKeyManager().down) && lastPressed ==
handler.getKeyManager().down ) {
return down_idle.getCurrentFrame();
}
return null;
}
}
The problem is that I cannot get my getCurrentAnimationFrame()
method to return the proper idle animations(or in this iteration of my code,any other animation besides left
and left_idle
).
My keys are defined in my KeyManager
class like this:
up = keys[KeyEvent.VK_W] || keys[KeyEvent.VK_UP];
down = keys[KeyEvent.VK_S] || keys[KeyEvent.VK_DOWN];
left = keys[KeyEvent.VK_A] || keys[KeyEvent.VK_LEFT];
right = keys[KeyEvent.VK_D] || keys[KeyEvent.VK_RIGHT];
How can I properly implement Key events/strokes to return the right animations on key release/key press?
Your conditions and boolean logic are overcomplicated:
private void getInput() {
xMove = 0;
yMove = 0;
if (handler.getKeyManager().up) {
yMove = -speed;
lastPressed = handler.getKeyManager().up;
}
//...
}
private BufferedImage getCurrentAnimationFrame() {
if (handler.getKeyManager().left && lastPressed == handler.getKeyManager().left) {
return left.getCurrentFrame();
} else if ( !(handler.getKeyManager().left)) {
return left_idle.getCurrentFrame();
}
//...
return null;
}
Is same as:
private void getInput() {
xMove = 0;
yMove = 0;
KeyManager km = handler.getKeyManager();
if (km.up) {
yMove = -speed;
lastPressed = true;
}
//...
}
private BufferedImage getCurrentAnimationFrame() {
KeyManager km = handler.getKeyManager();
if (km.left && lastPressed) {
// replaced lastPressed == handler.getKeyManager().left since km.left must be true
return left.getCurrentFrame();
} else if (!km.left) {
return left_idle.getCurrentFrame();
}
//...
return null;
}
I do not see where are you setting lastPressed
to false
, looks to me it will be set to true (with first key press) and remains true
. Since it is always true
, your condition in getCurrentAnimationFrame
is effectively:
private BufferedImage getCurrentAnimationFrame() {
KeyManager km = handler.getKeyManager();
if (km.left) {
return left.getCurrentFrame();
} else {
return left_idle.getCurrentFrame();
}
//UNREACHABLE CODE!
return null;
}
Even if it doesn't remain true, your code is like if left, return left animation, if not left return left idle animation
. I think your somehow mixed booleans with key codes as you say "lastPressed variable is supposed to store the value of the last pressed key".
I would probably define direction enum:
public enum DirectionEnum {
LEFT, RIGHT, UP, DOWN;
}
And use it like this:
DirectionEnum lastPressed = null;
private void getInput() {
xMove = 0;
yMove = 0;
KeyManager km = handler.getKeyManager();
if (km.up) {
yMove = -speed;
lastPressed = DirectionEnum.UP;
}
//...
}
private BufferedImage getCurrentAnimationFrame() {
KeyManager km = handler.getKeyManager();
if (lastPressed == null) {
if (km.left) {
return left.getCurrentFrame();
}
//...
} else {
switch (lastPressed) {
case DOWN:
if (!km.down){
return down_idle.getCurrentFrame();
}
break;
//...
default:
throw new RuntimeException("Invalid direction " + lastPressed);
}
}
return null;
}
But I do not know if it is correct, because lastPressed
will be null
only first time (or never), and then you will see only idle animations. So you should probably decide when to set lastPressed
back to null
?