4
\$\begingroup\$

This is a follow-up question to my last one. I am developing a game which has an Icon on a JLabelwhich the user controls with WASD keys. Right now it can go up, down, left, and right, but I want to know how I can make it move diagonally if two keys are held. I have recreated a short example and posted it below along with a gif(sorry, it's not very smooth), and I am hoping you can help me out. Thanks!

public class Experiments extends JFrame {
    javax.swing.Timer movement;
    int x = 230;
    int y = 120;
    boolean wPressed, aPressed, sPressed, dPressed;

    public Experiments() {
        layoutGame();
        setTitle("Example");
        setSize(500, 350);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void layoutGame() {
        JLabel bg = new JLabel();
        bg.setIcon(new ImageIcon(this.getClass().getClassLoader().getResource("space.png")));
        add(bg, BorderLayout.CENTER);

        JLabel you = new JLabel();
        you.setBounds(x, y, 50, 50);
        you.setIcon(new ImageIcon(this.getClass().getClassLoader().getResource("happy.png")));
        bg.add(you, JLabel.CENTER);

        JTextPane direction = new JTextPane();
        direction.setText("Direction");
        add(direction, BorderLayout.SOUTH);
        move(you);

        direction.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                movement.stop();
                if(e.getKeyChar() == 'w') {
                    wPressed = true;
                    move(you);
                } else if (e.getKeyChar() == 'a') {
                    aPressed = true;
                    move(you);
                } else if (e.getKeyChar() == 's') {
                    sPressed = true;
                    move(you);
                } else if (e.getKeyChar() == 'd') {
                    dPressed = true;
                    move(you);
                }
                direction.setText(null);
            }
            public void keyReleased(KeyEvent e) {
                wPressed = false;
                aPressed = false;
                sPressed = false;
                dPressed = false;
            }
        });
    }

    private void move(JLabel icon) {
        int delay = 10; //milliseconds
        ActionListener taskPerformer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                if(icon.getX() >= 0 && icon.getX() <= 450 && icon.getY() >= 0 && icon.getY() <= 250) {
                    if (wPressed) {
                        y = y - 4;
                    } else if(aPressed) {
                        x = x - 4;
                    } else if(sPressed) {
                        y = y + 4;
                    } else if(dPressed) {
                        x = x + 4;
                    }
                    icon.setBounds(x, y, 50, 50);
                    icon.repaint();
                }
            }
        };
        movement = new javax.swing.Timer(delay, taskPerformer);
        movement.start();
    }

    public static void main(String[] args) {
        new Experiments();
    }
}

The output is smooth, but I had to make a gif, so it looks bumpy(sorry again): enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ What have you tried? Do you think checking wPressed and aPressed would be the logic needed to go in the up-left direction? \$\endgroup\$ – Cedric Martens Jul 9 '17 at 3:29
  • 5
    \$\begingroup\$ All you really need to do is change the else if to ifs and put move(you) to the bottom. \$\endgroup\$ – Nathan Merrill Jul 9 '17 at 3:45
  • \$\begingroup\$ Also, by setting all movement to 0 when ANY key is released, it's going to frustrate players. You need to check which key was released and set that isPressed value to false. \$\endgroup\$ – Draco18s Aug 12 '17 at 23:10
3
\$\begingroup\$

The logic is simple (as shown in the comments). You'll want to make the movement values the sum of potential values, according to which keys are pressed. However, to make the distance traveled constant, you must normalize the vector. The vector is the xy pair of movement values (e.g. <+1,0> or <-1,+1>). Normalizing means making the magnitude (length) of the vector one, to become a unit vector. To do this, you must divide each component (x and y) by it's magnitude. To calculate the magnitude, use the length formula from algebra class:

// dx and dy are the respective movement values
mag = sqrt(dx*dx + dy*dy)
dx /= mag
dy /= mag

That way, you will always move at the same speed, whether going diagonally or not.

\$\endgroup\$
-3
\$\begingroup\$
centy = stamp('cat6',120,120,120)
centy.move//any coordinate you want.(x,y,milliseconds)
\$\endgroup\$
  • 2
    \$\begingroup\$ It's not clear how this solves the problem posed in the question above. The identifier centy doesn't appear in the original question's code. Can you edit your answer to elaborate on the change you're recommending to solve the problem? \$\endgroup\$ – DMGregory Mar 17 '18 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.