0
\$\begingroup\$

I am trying to make a dodging game, where objects fall from the top of the window that the player must dodge or collect, depending on whether it is a triangle or a circle. Right now I am doing the layout, and making the moveable icon, which is a smiley face emoji. I am using a keyListener to move the icon(using WASD controls). Right now when you want to move the image with the keyPressed method you have to press and release the keys, rather than holding them. How can I make the icon move just by holding the keys, instead of pressing and releasing the keys rapidly?

Info: The background is a JLabel which the player chooses at the beginning through a JOptionPane. All of the background images are in the source folder, and are all 500*300 pixel jpg's. My application is run on a Mac OS X, if that helps at all.

Thanks, and here's my Program:

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

public class Dodge extends JFrame {
    private static final long serialVersionUID = 1l;
    String[] backDrops = {"space", "sky", "snow", "rain", "beach", "grass"};
    ImageIcon backDrop;
    String[] options = {"Easy", "Medium", "Difficult"};
    String result;
    String bd;
    int x; 
    int y;
    int difficulty;
    int wait = difficulty * 500;
    Graphics g;

    public Dodge() {
        getPreferences();
        layoutGame();
        setTitle("Dodge The Objects!");
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
        setResizable(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private void getPreferences() {
        JOptionPane.showMessageDialog(this, "Welcome to Dodge. The rules are simple:"
                + "\n\t\t\t\t1. Choose a level"
                + "\n\t\t\t\t2. Choose a back drop"
                + "\n\t\t\t\t3. Use the arrow keys to move"
                + "\n\t\t\t\t4. Avoid triangles and collect the circles");

          JOptionPane difficultyChoice = new JOptionPane("\t\t\t\t\t\t\t\t\t\t\tChoose your difficulty:",
                JOptionPane.PLAIN_MESSAGE, JOptionPane.YES_NO_OPTION, 
                null, options, options[1]);
          JDialog difficultyWindow = difficultyChoice.createDialog(null, "1. Difficulty");
          difficultyWindow.setVisible(true);
          result = (String) difficultyChoice.getValue();
          if(difficultyChoice.equals("Easy")) {
              difficulty = 3;
          } else if(difficultyChoice.equals("Medium")) {
              difficulty = 2;
          } else if(difficultyChoice.equals("Difficult")) {
              difficulty = 1;
          }

          JOptionPane backDropOption = new JOptionPane("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tChoose your back drop:",
                    JOptionPane.PLAIN_MESSAGE, JOptionPane.YES_NO_OPTION, 
                    null, backDrops, backDrops[0]);
          JDialog backDropWindow = backDropOption.createDialog(null, "2. Back Drop");
          backDropWindow.setVisible(true);
          bd = (String) backDropOption.getValue();
          backDrop = new ImageIcon(this.getClass().getClassLoader().getResource(bd + ".png"));
    }

    private void layoutGame() {
        JLabel title = new JLabel("Dodge The Enemies!");
        Font titleFont = new Font(Font.SERIF, Font.BOLD, 32);
        title.setFont(titleFont);
        title.setHorizontalAlignment(JLabel.CENTER);
        title.setBackground(Color.BLACK);
        title.setForeground(Color.WHITE);
        title.setOpaque(true);
        add(title, BorderLayout.NORTH);

        JLabel background = new JLabel();
        background.setIcon(backDrop);
        add(background, BorderLayout.CENTER);

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

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

        direction.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyChar() == 'w') {
                    y-=2;
                } else if (e.getKeyChar() == 's') {
                    y+=2;
                } else if (e.getKeyChar() == 'a') {
                    x-=2;
                } else if (e.getKeyChar() == 'd') {
                    x+=2;
                }
                you.setBounds(x, y, 50, 50);
                direction.setText("   \t   \t   \t   ");
            }
        });
    }

    public static void main(String[] args){
        try {
            String className = UIManager.getCrossPlatformLookAndFeelClassName();
            UIManager.setLookAndFeel(className);
        }
        catch (Exception e) {}

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Dodge();
            }
        });
    }
}
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Especially with falling objects, you are going to need to look into something called a "game loop".

What a "game loop" allows you to do, basically, is have actions that are repeated over and over; but unlike a normal loop, it's properly timed to achieve what we mostly know as "FPS" or "Frames per Second" which basically measures how quickly your game loops every second.

Here's a very good resource on game loops: http://www.java-gaming.org/index.php?topic=24220.0

In theory, when you have your game loop, what you will do is set a boolean to true when you press a button like 'w', 'a', 's', or 'd' and in your loop have an if-statement that checks whether one of those booleans are true and then moves your JLabel like before.

ex.

/* ... */

    direction.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyChar() == 'w') {
                wIsPressed = true;
            }
            // a, s, d
            // ...
        });

/* ... */

    // In game loop
    if (wIsPressed) {
        y -= 2;
    }
    // a, s, d
    // ...

    you.setBounds(x, y, 50, 50);

/* ... */

You will also need to have a listener for when a key is released, not just pressed to set those boolean to false.

The KeyAdapter class has a keyReleased method to override alongside the keyPressed.

https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyAdapter.html

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .