I am trying to make a simple game, and i need my spaceship to rotate on its centre (using A and D keys) , and move relative to the direction it is facing (W and S Keys).
I got the math for the movement and rotation mostly figured out, but im having an issue with the key listeners.
When i compile, the key listener works fine for th e first couple of key presses. But if i hold down A (rotate left while being pressed down) and then switch to D and then switch to A again, it stops working. Any other combination of key presses also results in this.
Basically, if i press the keys too much eventually it will stop working. If i go slow, it will start to work again after i press the key i want to work a few times. BUT if i press a bunch of keys at once (hit A, then D, then W in quick succession), then it completely stops working, and all keys become unresponsive.
This is not a processing speed issue i think, as the program does not crash, or produce any memory errors.
I have read up on similar issues, and saw that people suggested to not use KeyListeners, and use KeyBindings instead, but i tried both and got the exact same issues.
Here is the UPDATED code for my program (tried to make an MCVE): The portion i commented out in the middle was the code for the keybinding.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.math.*;
import java.net.URL;
public class Game extends JPanel implements ActionListener{
private Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
JFrame frame = new JFrame();
private Ship ship = new Ship();
private Timer gameTimer, turnRight, turnLeft, moveForward, moveBackward;
private static final int IFW = JComponent.WHEN_IN_FOCUSED_WINDOW;
public Game(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Study Buddy Menu");
frame.setSize(800,700);
frame.setLocation(dim.width/2 - 400, dim.height/2 - 350);
turnLeft = new Timer(20, new ActionListener(){
public void actionPerformed(ActionEvent e) {
ship.setAngle(ship.getAngle() + ship.getTurnSpeed());
}
});
turnRight = new Timer(20, new ActionListener(){
public void actionPerformed(ActionEvent e) {
ship.setAngle(ship.getAngle() - ship.getTurnSpeed());
}
});
moveForward = new Timer(20, new ActionListener(){
public void actionPerformed(ActionEvent e) {
ship.setX(ship.getX() + (float)Math.cos(Math.toRadians(ship.getAngle())));
ship.setY(ship.getY() - (float)Math.sin(Math.toRadians(ship.getAngle())));
System.out.println("UP");
}
});
moveBackward = new Timer(20, new ActionListener(){
public void actionPerformed(ActionEvent e) {
ship.setX(ship.getX() - (float)Math.cos(Math.toRadians(ship.getAngle())));
ship.setY(ship.getY() + (float)Math.sin(Math.toRadians(ship.getAngle())));
System.out.println("DOWN");
}
});
this.setFocusable(true);
this.requestFocus();
/*getInputMap(IFW).put(KeyStroke.getKeyStroke('d'), "right");
getActionMap().put("right", new MoveAction("d"));
getInputMap(IFW).put(KeyStroke.getKeyStroke('a'), "left");
getActionMap().put("left", new MoveAction("a"));
getInputMap(IFW).put(KeyStroke.getKeyStroke('w'), "up");
getActionMap().put("up", new MoveAction("w"));
getInputMap(IFW).put(KeyStroke.getKeyStroke('s'), "down");
getActionMap().put("down", new MoveAction("s"));*/
this.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
//TURN
if(e.getKeyCode() == KeyEvent.VK_D){
turnLeft.start();
turnRight.stop();
}
if(e.getKeyCode() == KeyEvent.VK_A){
turnRight.start();
turnLeft.stop();
}
//MOVE
if(e.getKeyCode() == KeyEvent.VK_W){
moveForward.start();
moveBackward.stop();
}
if(e.getKeyCode() == KeyEvent.VK_S){
moveBackward.start();
moveForward.stop();
}
}
public void keyReleased(KeyEvent e){
turnRight.stop();
turnLeft.stop();
moveForward.stop();
moveBackward.stop();
}
});
frame.add(this);
repaint();
gameTimer = new Timer(20, this);
gameTimer.start();
frame.setVisible(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
ship.draw(g);
}
public void actionPerformed(ActionEvent e) {
repaint();
}
private class MoveAction extends AbstractAction {
String d = null;
MoveAction(String direction) {
d = direction;
}
public void actionPerformed(ActionEvent e) {
switch (d){
case "d": turnLeft.start(); turnRight.stop();break;
case "a": turnRight.start(); turnLeft.stop();break;
case "w": moveForward.start(); moveBackward.stop();break;
case "s": moveBackward.start(); moveForward.stop();break;
}
}
}
class main {
public void main(String[] args) {
Game game = new Game();
}
}
class Ship {
private float x, y, radius, speed, angle, turnSpeed;
private Image icon;
public Ship(){
x = 400;
y = 350;
speed = 1;
radius = 20;
angle = 90;
turnSpeed = 5;
try {
icon = ImageIO.read(new URL("https://i.stack.imgur.com/L5DGx.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
//GETTERS
public float getX(){
return x;
}
public float getY(){
return y;
}
public float getTurnSpeed(){
return turnSpeed;
}
public float getAngle(){
return angle;
}
public float getRadius(){
return radius;
}
public float getSpeed(){
return speed;
}
public Image getIcon(){
return icon;
}
//SETTERS
public void setX(float X){
x = X;
}
public void setTurnSpeed(float S){
turnSpeed = S;
}
public void setY(float Y){
y = Y;
}
public void setAngle(float A){
angle = A;
}
public void setSpeed(float S){
speed = S;
}
public void setRadius(float R){
radius = R;
}
public void setIcon(Image image){
icon = image;
}
//DRAW
public void draw(Graphics g){
Graphics2D g2d = (Graphics2D) g;
AffineTransform at = new AffineTransform();
at.setToRotation(Math.toRadians(angle-90), x, y);
//at.translate(x, y);
g2d.setTransform(at);
g2d.drawImage(icon,(int)(x - radius), (int)(y - radius),(int)(radius * 2),(int)(radius * 2), null);
g2d.dispose();
}
}
}