-1

Searched Google for an answer, found nothing.

I'm starting to work on a 2D game in Java.

Currently in the game, there are supposed to be two tanks controled by two users on the same keyboard.

The way they move on the screen is as follows:

Pressing left and right keys (or A and D keys), should set the angle and rotate the sprite, and pressing the UP arrow key (or the W key), should move the sprite in the direction of the angle, as long as the UP key is pressed.

I got mainly two wierd bugs in the program right now:

  1. Pressing the UP arrow key starts moving the sprite of one of the tanks, but releasing the UP key doesn't stop it from moving.
  2. Rotating a tank with the left and right arrows, rotates the entire screen.

Thought I'd tackle one problem at a time (the first one), but if you got an idea how to solve the other problem, please say.

Here's the mostly relevant parts of the code (tried to make it as short as possible):

Board class, has most of the game logic:

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

import javax.swing.*;

public class Board extends JPanel implements KeyListener, Runnable {

    Tank tank1,tank2;
    boolean[] keysPressed1,keysPressed2;

    public Board(){

        setFocusable(true);
        setBackground(Color.BLACK);
        addKeyListener(this);

        tank1 = new Tank("red");
        tank2 = new Tank("blue");

        Thread gameloop = new Thread(this);
        gameloop.start();

    }

    public void paintComponent(Graphics g){

        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        g2d.rotate( Math.toRadians(tank1.getAngle()), tank1.getCenter().getX(), tank1.getCenter().getY() );
        g2d.drawImage(tank1.getImage(), (int) tank1.getX(), (int) tank1.getY(), this);

        g2d.rotate( Math.toRadians(tank2.getAngle()), tank2.getCenter().getX(), tank2.getCenter().getY() );
        g2d.drawImage(tank2.getImage(), (int) tank2.getX(), (int) tank2.getY(), this);

    }

// simplified version of the game-loop:
    public void run(){

        while( game_is_running ) {

                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.sin(Math.toRadians(tank1.getAngle())));
                    tank1.setDY(2 * Math.cos(Math.toRadians(tank1.getAngle())));
                }

                tank1.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(2 * Math.sin(Math.toRadians(tank2.getAngle())));
                    tank2.setDY(2 * Math.cos(Math.toRadians(tank2.getAngle())));
                }

                tank2.move();

                next_game_tick += SKIP_TICKS;
                loops++;
            }

            repaint();
        }

    }

    public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if(key == KeyEvent.VK_UP || key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT){ tank1.keyPressed(e); }
        if(key == KeyEvent.VK_W || key == KeyEvent.VK_A || key == KeyEvent.VK_D){ tank2.keyPressed(e); }

    }

    public void keyReleased(KeyEvent e) {

        int key = e.getKeyCode();

        if(key == KeyEvent.VK_UP || key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT){ tank1.keyReleased(e); }
        if(key == KeyEvent.VK_W || key == KeyEvent.VK_A || key == KeyEvent.VK_D){ tank2.keyReleased(e); }

    }

    public void keyTyped(KeyEvent arg0) {}

}

Tank class:

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

public class Tank extends Entity {

    public Tank(String type){

        this.type = type;

        if(type=="red"){
            image = new ImageIcon(this.getClass().getResource("sprites/redtank1.PNG")).getImage();
            x = 200 - image.getWidth(null);
            y = 400;
        }
        if(type=="blue"){
            image = new ImageIcon(this.getClass().getResource("sprites/bluetank1.PNG")).getImage();
            x = 850;
            y = 400;
        }

        width = image.getWidth(null);
        height = image.getHeight(null);

        center = new Point( ((int) getX()) + (width/2), ((int) getY() + (height/2)) );

        angle = 0;

        dx = 0;
        dy = 0;

        keysPressed = new boolean[3];

    }

    public void keyPressed(KeyEvent e){

        int key = e.getKeyCode();

        if(key == KeyEvent.VK_LEFT){
            keysPressed[0] = true;
            }

        if(key == KeyEvent.VK_RIGHT){
            keysPressed[1] = true;
            }

        if(key == KeyEvent.VK_UP){
            keysPressed[2] = true;
            }

    }

    public void keyReleased(KeyEvent e){

        int key = e.getKeyCode();

        if(key == KeyEvent.VK_LEFT){
            keysPressed[0] = false;
            }

        if(key == KeyEvent.VK_RIGHT){
            keysPressed[1] = false;
            }

        if(key == KeyEvent.VK_UP){
            keysPressed[2] = false;
            }

    }

}

I have no idea how to solve this, would really appreciate your help. Thanks

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user3150201
  • 1,901
  • 5
  • 26
  • 29
  • Are you running this inside of an IDE? Some times IDEs can cause weird things to happen with key listeners. Try running your program manually. – mako-taco Jan 01 '14 at 14:25
  • 1
    1) For better help sooner, post an [SSCCE](http://sscce.org/). 2) One way to get image(s) for an example is to hot-link to the images seen in [this answer](http://stackoverflow.com/a/19209651/418556). 3) For Swing, typically use key bindings over the AWT based, lower level, `KeyListener`. See [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) for details on how to use them. – Andrew Thompson Jan 01 '14 at 15:05

1 Answers1

0

For the movement problem when you check for keypressed you set the DX and DY. These control movement direction and distance. Upon tank.move() this is executed. You never reset DX and DY to zero so the tank never stops. You need to add a check for keyreleased and set DX and DY to zero.

like so:

if(keysPressed1[2]==false){
 tank1.setDX(0);
 tank1.setDY(0);
}

tank1.move();

if(keysPressed2[2]==false){
 tank2.setDX(0);
 tank2.setDY(0);
}

tank2.move();

For the rotation problem: Instead of calling

g2d.rotate()

you need to call drawImage with a rotation transform.

see, drawImage

g2d.rotate() rotates the entire graphical context.

Here's an example of drawing a rotated image:

 public void paintComponent(Graphics g){

    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;

    AffineTransform tx = new AffineTransform();
    tx.setToRotation(Math.toRadians(tank1.getAngle());
    tx.translate(tank1.getCenter().getX(),  tank1.getCenter().getY());
    g2d.drawImage(tank1.getImage(), tx, this);

    AffineTransform tx2 = new AffineTransform();
    tx2.setToRotation(Math.toRadians(tank2.getAngle());
    tx2.translate(tank2.getCenter().getX(),  tank2.getCenter().getY());
    g2d.drawImage(tank2.getImage(), tx2, this);

}