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

岁酱吖の 提交于 2019-11-29 18:16:41

This is a basic example of spinning a sprite

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 ;)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!