0

I am currently trying to move this image I have imported in with the selection of some key bindings. I have done some tests, increasing the amount of pixels it travels at but it seems to only set that as its x and y values not use it as a measure of speed.

This is the code:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Ship1 extends JPanel implements ActionListener, KeyListener {

    private final static String IMAGE_NAME = "ship1_";
    protected ImageIcon ship1[];
    private final int TOTAL_IMAGES = 16;
    private int currentIMAGE = 0;
    private final int ANIMATION_DELAY = 100;
    private int width;
    private int height;
    private int x = 0;
    private int y = 0;
    private int velX = 0;
    private int velY = 0;

    private Timer animationTimer;

    public Ship1() {

        ship1 = new ImageIcon[TOTAL_IMAGES];

        for (int count = 0; count < ship1.length; count++) {
            ship1[count] = new ImageIcon(getClass().getResource("Images/Ship1_/" + IMAGE_NAME + count + ".png"));

            width = ship1[count].getIconWidth();
            height= ship1[count].getIconHeight();
        }

        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
    }

    public void paintComponent (Graphics g) {
        super.paintComponent(g);

        ship1[currentIMAGE].paintIcon(this, g, x, y);

        if (animationTimer.isRunning()) {
            currentIMAGE = (currentIMAGE + 1) % TOTAL_IMAGES;
        }
    }

    public void startAnimation() {
        if (animationTimer == null) {
            currentIMAGE = 0;
            animationTimer = new Timer(ANIMATION_DELAY, new TimerHandler());

            animationTimer.start();
        } else {
            if (!animationTimer.isRunning()) {
                animationTimer.restart();
            }
        }
    }

    public void stopAnimation() {
        animationTimer.stop();
    }

    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }

    private class TimerHandler implements ActionListener {

        public void actionPerformed(ActionEvent actionEvent) {
            repaint();
        }
    }

    public void actionPerformed(ActionEvent e){
        if (x < 0) {
            velX = 0;
            x = 0;
        }
        if (x > 850) {
            velX = 0;
            x = 850;
        }
        if (y < 0) {
            velY = 0;
            y = 0;
        }
        if (y > 650) {
            velY = 0;
            y = 650;
        }

        x = x + velX;
        y = y + velY;

    }

    public void keyPressed (KeyEvent e){
        int c = e.getKeyCode();

        if (c == KeyEvent.VK_LEFT) {
            velX = -1;
            velY = 0;
        }
        if (c == KeyEvent.VK_UP) {
            velX = 0;
            velY = -1;
        }
        if (c == KeyEvent.VK_RIGHT) {
            velX = 1;
            velY = 0;
        }
        if (c == KeyEvent.VK_DOWN) {
            velX = 0;
            velY = 1;
        }
    }

    public void keyTyped(KeyEvent e) {

    }

    public void keyReleased(KeyEvent e) {
            velX = 0;
            velY = 0;
    }

}

So when keys are pressed it moves to that [x][y] location but after release resets to [0][0] as it says in keyReleased but that was meant to stop it from moving not reset position. So it doesn't move around and stop, any ideas?

  • Have you checked that `velX` and `velY` are set as you expect ? What is happening exactly ? – AxelH May 02 '17 at 07:41
  • I am thinking they are the issue. If I change velX = 10 in VK_RIGHT it moves it 10 right but it isn't like a bike going and stopping more just teleporting and then when released teleporting back to its original set position. –  May 02 '17 at 07:42
  • Well, reading your code, it will move 1px per 100ms. So only 10px per seconds. That slow in a 650px width. You can reduce the refresh rate to increase the movement speed without have to much `jumping`. But 2 or 3 px should do it too. – AxelH May 02 '17 at 07:44
  • 1
    1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson May 02 '17 at 07:46
  • dont use swing to create animations! – Stimpson Cat May 02 '17 at 07:48
  • @StimpsonCat It is for an assignment we have been told to use it. Not much I can do to say otherwise. –  May 02 '17 at 07:51
  • @AxelH I have also discovered the x and y value I have are not updating and therefore the image is stuck at [0,0] anyway you can see to prevent this? –  May 02 '17 at 07:51
  • I managed to solve it posting the answer now. –  May 02 '17 at 07:57
  • [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) – MadProgrammer May 02 '17 at 08:06

1 Answers1

0

Okay, so after fiddling about I solved it.

I changed this:

public void keyPressed (KeyEvent e){
        int c = e.getKeyCode();

        if (c == KeyEvent.VK_LEFT) {
            velX = -1;
            velY = 0;
        }
        if (c == KeyEvent.VK_UP) {
            velX = 0;
            velY = -1;
        }
        if (c == KeyEvent.VK_RIGHT) {
            velX = 1;
            velY = 0;
        }
        if (c == KeyEvent.VK_DOWN) {
            velX = 0;
            velY = 1;
        }
    }

to this:

public void keyPressed (KeyEvent e){
        int c = e.getKeyCode();

        if (c == KeyEvent.VK_LEFT) {
            velX = -1;
            velY = 0;
        }
        if (c == KeyEvent.VK_UP) {
            velX = 0;
            velY = -1;
        }
        if (c == KeyEvent.VK_RIGHT) {
            velX = 1;
            velY = 0;
        }
        if (c == KeyEvent.VK_DOWN) {
            velX = 0;
            velY = 1;
        }
        x = x + velX;
        y = y + velY;
    }

The bit at the end now updates the image to move around.

  • The reason is because `Ship1#actionPerformed` was never called. – AxelH May 02 '17 at 08:20
  • Ahhhh I see now! I feel really dumb. –  May 02 '17 at 08:30
  • @AxelH How would I go about adding the call in? –  May 02 '17 at 08:35
  • The `ActionListener` interface is not necessary here. It is used on an action like a button click. Since you already have an interface to listen the key, this is enough. Now just need to know if you want to do the operation in the keylistener or during the GUI update. I don't know Swing enough to answer this because of the synchronized operation. But remove the `ActionListener` because you don't need it (so the `ActionPerformed` overrided). – AxelH May 02 '17 at 08:38
  • @AxelH Thank you for this help! It has solved all the issues! –  May 02 '17 at 08:44