Getting my sprite to face in a certain direction based on Keyboard input - Java Game

前端 未结 1 617
后悔当初
后悔当初 2020-12-22 05:33

So I\'ve pretty much thrown together a basic game in java by following a bunch of different tutorials - the problem is i cant manage to figure out how to get my sprite to mo

相关标签:
1条回答
  • 2020-12-22 05:56

    This is a basic example of spinning a sprite

    Spinning

    What this is maintain's a virtual state which the Player object inspects in order to determine how it should be changed accordingly. This separates the action from the result, meaning that it would be possible to substitute the action (arrow up key) with some other action, but still obtain the same result.

    This example also uses the key bindings API, which doesn't suffer from the same focus related issues that KeyListener does, but this is a pure Swing API and won't be compatiable with Canvas, but is a nice demonstration ;)

    The real magic occurs in the characters paint method...

    public void paint(Graphics2D g2d) {
        Graphics2D g = (Graphics2D) g2d.create();
        AffineTransform at = new AffineTransform();
        at.translate(x, y);
        at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
        g.transform(at);
        g.drawImage(character, 0, 0, null);
    }
    

    Basically, this creates a AffineTransformation which is then compounded to produce the result we need. That is, first it's anchor position is translated to the characters x/y position and then rotated about the characters center point. Because it's been translated, we can simply paint the character at 0x0. This much easier then try to calculate the characters rotation anchor somewhere else in virtual space - IMHO

    The character is rotated by pressing either the Up or Down arrow keys. While pressed, the character will continue to rotate, this is a feature of the example for demonstration purpose.

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.geom.AffineTransform;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.AbstractAction;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class RotateCharater {
    
        public static void main(String[] args) {
            new RotateCharater();
        }
    
        public RotateCharater() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private DefaultState state;
            private Player player;
    
            public TestPane() {
                player = new Player();
                state = new DefaultState();
    
                InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upKeyPressed");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upKeyReleased");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downKeyPressed");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downKeyReleased");
    
                ActionMap am = getActionMap();
                am.put("upKeyPressed", new UpKeyAction(state, true));
                am.put("upKeyReleased", new UpKeyAction(state, false));
                am.put("downKeyPressed", new DownKeyAction(state, true));
                am.put("downKeyReleased", new DownKeyAction(state, false));
    
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        player.update(state);
                        repaint();
                    }
                });
                timer.start();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                player.paint(g2d);
                g2d.dispose();
            }
    
            public class UpKeyAction extends AbstractAction {
    
                private DefaultState state;
                private boolean pressed;
    
                public UpKeyAction(DefaultState state, boolean pressed) {
                    this.state = state;
                    this.pressed = pressed;
                }
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    state.setUpKeyPressed(pressed);
                }
    
            }
            public class DownKeyAction extends AbstractAction {
    
                private DefaultState state;
                private boolean pressed;
    
                public DownKeyAction(DefaultState state, boolean pressed) {
                    this.state = state;
                    this.pressed = pressed;
                }
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    state.setDownKeyPressed(pressed);
                }
    
            }
        }
    
        public interface State {
    
            public boolean isUpKeyPressed();
            public boolean isDownKeyPressed();
    
        }
    
        public class DefaultState implements State {
    
            private boolean upKeyPressed;
            private boolean downKeyPressed;
    
            public boolean isDownKeyPressed() {
                return downKeyPressed;
            }
    
            public boolean isUpKeyPressed() {
                return upKeyPressed;
            }
    
            public void setDownKeyPressed(boolean downKeyPressed) {
                this.downKeyPressed = downKeyPressed;
                upKeyPressed = false;
            }
    
            public void setUpKeyPressed(boolean upKeyPressed) {
                this.upKeyPressed = upKeyPressed;
                downKeyPressed = false;
            }
    
        }
    
        public class Player {
    
            private BufferedImage character;
            private int x = 100 - 32, y = 100 - 32;
            private double angle;
    
            public Player() {
                try {
                    character = ImageIO.read(getClass().getResource("/Character.png"));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
    
            public void paint(Graphics2D g2d) {
                Graphics2D g = (Graphics2D) g2d.create();
                AffineTransform at = new AffineTransform();
                at.translate(x, y);
                at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
                g.transform(at);
                g.drawImage(character, 0, 0, null);
            }
    
            public void update(State state) {
    
                if (state.isUpKeyPressed()) {
                    angle -= 22.5;
                } else if (state.isDownKeyPressed()) {
                    angle += 22.5;
                }
    
            }
    
        }
    
    }
    

    Remember, this is just an example used to present the concept ;)

    0 讨论(0)
提交回复
热议问题