In Java game, pressing one key cancels a different key that's still pressed

I'm making a 2D game in java.

In the game, pressing the left and right arrow keys rotates a sprite and manipulates a variable named 'angle'. Pressing the up arrow key, computes the direction where the sprite should move depending on the 'angle' variable.

This works, but I'm unable to manipulate the angle while moving, aka have left or right keys be pressed at the same time the up arrow is pressed.

Pressing the up arrow makes the program ignore the fact the one of the arrow keys is pressed.

I have searched the forum and found one suggestion how to handle that, but I'm not sure it's the best for my program. (What I found: How do I handle simultaneous key presses in Java?)

Here's some code:

Relevant methods of Thing class:

    public void keyPressed(KeyEvent e){

    int key = e.getKeyCode();

    if(key==KeyEvent.VK_LEFT){ setAngle(getAngle()-5); 
            leftPressed=true; // *new* }
    if(key==KeyEvent.VK_RIGHT)setAngle(getAngle()+5);{
            rightPressed=true; // *new* }
    if(key==KeyEvent.VK_UP){

        dy = (float) ( Math.sin( getAngle() ) ) * 5;
        dx = (float) ( Math.sin( 90-getAngle() ) ) * 5;
                    if(leftPressed==true)angle-=5; // *new*
        if(rightPressed==true)angle+=5; // *new*

    }

public void move(){
    x += dx;
    y += dy;
}

}

The Board class (the class that manages the game:)

package learningMovement;

import java.util.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener, KeyListener {

    Thing t;

    Timer timer;

    public Board(){
        setBackground(Color.BLACK);
        timer = new Timer(10,this);
        t = new Thing();
        setFocusable(true);
        timer.start();
        addKeyListener(this);
    }

    public void paintComponent(Graphics g)
    {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.rotate( Math.toRadians(t.getAngle()), t.getX() + (t.getWidth()/2), t.getY() + (t.getHeight()/2) );
        g2d.drawImage(t.getImage(),(int)t.getX(),(int)t.getY(),this);

    }

    public void actionPerformed(ActionEvent e){

        t.move();
        repaint();

    }

    public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if(key==KeyEvent.VK_LEFT)t.keyPressed(e);
        if(key==KeyEvent.VK_RIGHT)t.keyPressed(e);
        if(key==KeyEvent.VK_UP)t.keyPressed(e);

    }

    public void keyReleased(KeyEvent e) {

        int key = e.getKeyCode();

        if(key==KeyEvent.VK_LEFT)t.keyReleased(e);
        if(key==KeyEvent.VK_RIGHT)t.keyReleased(e);
        if(key==KeyEvent.VK_UP)t.keyReleased(e);

    }

    public void keyTyped(KeyEvent arg0) {}



}

How do I fix this? Thanks

Answers


You should wrap the keys.

Create keys[] and if a key pressed change the keys[] don't activate the events like movement:

void keyPressed(){
     if(key==KeyEvent.VK_something)keys[something]=true;
}
void keyReleased(){
     if(key==KeyEvent.VK_something)keys[something]=false;
}

and inside your loop, when you update the game logic, check for key events:

if(keys[up] == true)moveUp();
if(keys[right] == true)rotateRight();

That way both rotate and move will be active at the same time, without cancelling each other.


KeyListener will only raise a single event. That means, when ever keyPressed is called, it represents on a single key event.

Instead, what you need to do, is on each time keyPressed is triggered, you need to set a flag, indicating what key was pressed. When keyReleased is triggered, you need to reset the flag.

You then need a method that can process these flags and decisions about what do based on the state of these flags...

Lastly avoid KeyListener, is focus issues which are just a pain to deal with. Instead, I'd recommend that you use Key Bindings instead

For example...


Need Your Help

Java - Add to a string within a Lambda expression

java foreach lambda

I'm quite new to Java, I tried looking around on StackOverflow/Google but couldn't find an answer to my problem.

Taking control of WSDL/XSD from WCF-SVCUtil (Annotations, Schema Namespaces, and Schema Locations)

wcf xsd wsdl

In the WSDL that is generated from a WCF service, there are a few problems that I'd like to take control of a little more. First, is there a way to add annotations to the xsd files generated with the