EDIT: Added code.
In a 2D Java game, I have two tanks on the screen. Their controls:
Tank 1
- Move forward: UP arrow key
- Adjust angle of movement (and rotate sprite): LEFT arrow and RIGHT arrow.
- Shoot missile: ENTER key.
Tank 2
- Move forward: W key
- Adjust angle of movement (and rotate sprite): A key and D key.
- Shoot missile: G key.
The program uses Key Bindings to do this.
I have a wierd bug:
Pressing W, D, and G at the same time - works. (aka: rotating the sprite to the right and adjusting the movement angle, while moving in that angle and shooting missiles at the same time).
But doing that exact same thing, except instead of D, I press A - doesn't work. The missiles don't shoot. (Aka: W + D + G = works. But W + A + G = doesn't work. The missiles don't happen).
However, this problem doesn't happen with the other tank. The other tank can do UP + LEFT + ENTER at the same time (equivalent of W + A + G for the first tank).
I need this game to work fluidly on any standard keyboard, because it's a 2-player game where precision and timing is important.
Is there a problem with my code?
Thanks
KBThread
class - the class the does the key-bindings.
When a key is pressed, a flag inside an array is set (true). When it's released, the flag is set to false.
Another class (the one with most of the game), checks what keys are pressed by checking their flags, and does things accordingly.
public class KBThread implements Runnable {
Board b;
Action upAction,leftAction,rightAction,wAction,aAction,dAction,upReleased,leftReleased,rightReleased,wReleased,dReleased,aReleased,
enterAction, gAction;
InputMap inputMap;
ActionMap actionMap;
boolean[] keysPressed1,keysPressed2;
ArrayList missiles1,missiles2;
Tank tank1,tank2;
public KBThread(Board b){
this.b = b;
inputMap = b.getInputMap();
actionMap = b.getActionMap();
tank1 = b.tank1;
tank2 = b.tank2;
keysPressed1 = tank1.getKeys();
keysPressed2 = tank2.getKeys();
missiles1 = tank1.getMissiles();
missiles2 = tank2.getMissiles();
}
public void run() {
// Keys pressed
leftAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed1[0] = true;
}
};
rightAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed1[1] = true;
}
};
upAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed1[2] = true;
}
};
aAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed2[0] = true;
}
};
dAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed2[1] = true;
}
};
wAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed2[2] = true;
}
};
enterAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
missiles1.add( new Missile( tank1.getX(), tank1.getY(), "blue" , tank1.getAngle() , tank1) );
}
};
gAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
missiles2.add( new Missile( tank2.getX(), tank2.getY(), "red", tank2.getAngle() , tank2) );
}
};
// Keys released
leftReleased = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed1[0] = false;
}
};
rightReleased = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed1[1] = false;
}
};
upReleased = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed1[2] = false;
}
};
aReleased = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed2[0] = false;
}
};
dReleased = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed2[1] = false;
}
};
wReleased = new AbstractAction(){
public void actionPerformed(ActionEvent e){
keysPressed2[2] = false;
}
};
inputMap.put(KeyStroke.getKeyStroke("UP"),"upAction");
inputMap.put(KeyStroke.getKeyStroke("LEFT"),"leftAction");
inputMap.put(KeyStroke.getKeyStroke("RIGHT"),"rightAction");
inputMap.put(KeyStroke.getKeyStroke("W"),"wAction");
inputMap.put(KeyStroke.getKeyStroke("A"),"aAction");
inputMap.put(KeyStroke.getKeyStroke("D"),"dAction");
inputMap.put(KeyStroke.getKeyStroke("ENTER"),"enterAction");
inputMap.put(KeyStroke.getKeyStroke("G"),"gAction");
actionMap.put("upAction",upAction);
actionMap.put("leftAction",leftAction);
actionMap.put("rightAction",rightAction);
actionMap.put("wAction",wAction);
actionMap.put("aAction",aAction);
actionMap.put("dAction",dAction);
actionMap.put("enterAction",enterAction);
actionMap.put("gAction",gAction);
inputMap.put(KeyStroke.getKeyStroke("released UP"),"upReleased");
inputMap.put(KeyStroke.getKeyStroke("released LEFT"),"leftReleased");
inputMap.put(KeyStroke.getKeyStroke("released RIGHT"),"rightReleased");
inputMap.put(KeyStroke.getKeyStroke("released W"),"wReleased");
inputMap.put(KeyStroke.getKeyStroke("released A"),"aReleased");
inputMap.put(KeyStroke.getKeyStroke("released D"),"dReleased");
actionMap.put("upReleased",upReleased);
actionMap.put("leftReleased",leftReleased);
actionMap.put("rightReleased",rightReleased);
actionMap.put("wReleased",wReleased);
actionMap.put("aReleased",aReleased);
actionMap.put("dReleased",dReleased);
}
}
Part of the game-loop. This manages moving sprites and shooting missiles.
keysPressed1 = tank1.getKeys();
keysPressed2 = tank2.getKeys();
if(keysPressed1[0]==true)tank1.setAngle(tank1.getAngle()-3);
if(keysPressed1[1]==true)tank1.setAngle(tank1.getAngle()+3);
if(keysPressed1[2]==true){
tank1.setDX(2 * Math.cos(Math.toRadians(tank1.getAngle())));
tank1.setDY(2 * Math.sin(Math.toRadians(tank1.getAngle())));
}
if(keysPressed1[2]==false){
tank1.setDX(0);
tank1.setDY(0);
}
tank1.move();
for(int i=0;i<missiles1.size();i++){
m = (Missile) missiles1.get(i);
m.move();
}
if(keysPressed2[0]==true)tank2.setAngle(tank2.getAngle()-3);
if(keysPressed2[1]==true)tank2.setAngle(tank2.getAngle()+3);
if(keysPressed2[2]==true){
tank2.setDX( (-1) * ( 2 * Math.cos(Math.toRadians(tank2.getAngle()) ) ));
tank2.setDY( (-1) * (2 * Math.sin(Math.toRadians(tank2.getAngle()) ) ));
}
if(keysPressed2[2]==false){
tank2.setDX(0);
tank2.setDY(0);
}
tank2.move();
for(int i=0;i<missiles2.size();i++){
m = (Missile) missiles2.get(i);
m.move();
}