1

I'm coding a game and I'm using Java's Swing. And right now i'm trying to get the KeyListeners and Action listeners to work.

What I'm trying to do is to make my object to move according to what key i'm pressing. (Left,Right,Up,Down), But for some reason nothing happens when i press either of these keys, but when i press 3 of them at the same time. the object is strangely moving to the left..

So here's my code for the class to create the Runner-object:

import java.awt.*;


public class Runner{
    private int xpos, ypos, base, side;

    public Runner(int b, int h ) {
        base = b;
        side = h;
    }
    public void setPosition(int x, int y){
        xpos = x;
        ypos = y;
    }
    public void view(Graphics g) {
        int x[] = { xpos, xpos-base/2, xpos + base/2};
        int y[] = { ypos, ypos + side, ypos + side };
        g.setColor(Color.lightGray);
        g.fillPolygon( x, y, 3 );
        g.setColor(Color.darkGray);
        g.drawLine(xpos, ypos, xpos, ypos + side);
    }
    public void shoot(Graphics g){
        g.setColor(Color.red);
        g.drawLine(xpos,ypos, xpos, 0);
    }
}

And here's the code thats suppose to run the damn thing:

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


public class RunningGame extends JPanel implements KeyListener, ActionListener{
    Runner rs;
    int x,y;
    Timer t;
    boolean shot = false;
    boolean left = false, right = false, up = false, down = false;

    public RunningGame() {
        x = 100;
        y = 150;
        rs = new Runner(40,60);
        rs.setPosition(x,y);
        this.addKeyListener(this);
        this.setBackground(Color.black);
        t = new Timer(40, this);
        t.start();
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        rs.view(g);
        if(shot) rs.shoot(g);
    }
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 37) {left = true;}
        if (e.getKeyCode() == 39) {right = true;}
        if (e.getKeyCode() == 38) {up = true;}
        if (e.getKeyCode() == 40) {down = true;}
        if (e.getKeyCode() == 32) {shot = true;}

        rs.setPosition(x,y);
        this.repaint();
}
    public void keyReleased(KeyEvent e){
        if (e.getKeyCode() == 37) left = false;
        if (e.getKeyCode() == 39) right = false;
        if (e.getKeyCode() == 38) up = false;
        if (e.getKeyCode() == 40) down = false;
        if (e.getKeyCode() == 32) shot = false;
        this.repaint();
    }
public void keyTyped(KeyEvent e){}
    public void actionPerformed(ActionEvent e) {
        if (left) {
            if(right){
                right = false;
                x = x - 10; shot = false;
            }
        }
        if (right) {
            if(left){
            left = false;
            x = x + 10; shot = false;
            }
        }
        if (up) {
            if(down){
                down = false;
                y = y - 10; shot = false;
            }
        }
        if (down) {
            if(up){
                up = false;
                y = y + 10; shot = false;
            }
        }
        rs.setPosition(x,y);
        this.repaint();
}

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(300, 300); f.setLocation(100,100);
        f.setTitle("Running");
        RunningGame p = new RunningGame();
        f.add(p); f.setVisible(true);
        p.requestFocus();

    }
}

(This is not the final code it's just using an example with a spaceship, later i will use a different object, just wanna test the KeyListener and ActionListener so it works before proceeding.)

Anyways can anyone help me make the space ship move smoothly? and without having to release all keys to activate another? i.e If i hold left i want it to be able to press another button. so that if i press right, the space ship will start to move in that direction instead.

//MrElephants

  • 1
    if you using only four keys, then you must use [KeyBinding](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html), instead of KeyListeners – nIcE cOw Apr 12 '12 at 16:18
  • I'm going to suggest you take a look at [my answer to a similar question](http://stackoverflow.com/a/10077580/544963). If that isn't enough, just let me know and I'll help you. :) – fireshadow52 Apr 12 '12 at 16:44

1 Answers1

2

In the blocks that look like:

if (left) {
    if(right){
        right = false;
        x = x - 10; shot = false;
    }
}

I think you should have x = x - 10; outside the second if:

if (left) {
    if(right){
        right = false;
        shot = false;
    }
    x = x - 10;
}

although I'm not really sure what that inner if is for, maybe you should remove it completely (but keep the x -= 10 etc.). This should be sufficient to make the movement seem natural.

Richante
  • 4,353
  • 19
  • 23
  • Oh thanks! :) I just did what you said and it worked perfectly! and now that you mentioned it, it made perfect sense that's how it must be. – MrElephants Apr 12 '12 at 17:09
  • Oh and the inner `if` was meant to be so that if i press the opposite button to the one I'm holding, (for example Left and Right), the ship wouldn't just stop, but start going in the other way instead. But if you know a better way of doing this I'd be glad to hear it!:) cause i was thinking on how to do that properly! – MrElephants Apr 12 '12 at 17:15
  • For this you'd want to modify the code in keyPressed(), I think - so if right is pressed, set `left = false; right = true`. This might still give strange behaviour if you hold left and press+release right. To get the kind of behaviour you'd expect, I think you would want to be storing the order in which keys are pressed. I think this would be overkill though. – Richante Apr 12 '12 at 17:19
  • Yeah i was thinking if there was a way to store the order easily but, the way you said worked much better than the way i'd put it!So thanks! – MrElephants Apr 12 '12 at 17:30