基于键盘输入让我的精灵面向某个方向 – Java Game

所以我通过跟随一堆不同的教程将java基本游戏放在一起 – 问题是我无法弄清楚如何让我的精灵向不同的方向移动。 这是我的主要代码

package com.game.src.main; import java.awt.Canvas; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.image.BufferStrategy; import java.awt.image.BufferedImage; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import javax.swing.JFrame; public class Game extends Canvas implements Runnable { private static final long serialVersionUID = 1L; public static final int WIDTH = 850; public static final int HEIGHT = 650; public static final int SCALE = 1; public final String TITLE = "Racing Game!"; static ServerSocket serverSocket; static Socket socket; static DataOutputStream out; private boolean running = false; private Thread thread; private BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB); private BufferedImage spriteSheet = null; private BufferedImage spriteSheet2 = null; private BufferedImage background = null; private BufferedImage MenuBackground = null; private Player p; private Player2 p2; private Menu menu; public static enum STATE { MENU, GAME }; public static STATE State = STATE.MENU; public void init() { BufferedImageLoader loader = new BufferedImageLoader(); try { spriteSheet = loader.loadImage("/Sprite_Sheet.png"); background = loader.loadImage("/Track.png"); MenuBackground = loader.loadImage("/MenuBG.fw.png"); } catch (IOException e) { e.printStackTrace(); } menu = new Menu(); addKeyListener(new KeyInput(this)); this.addMouseListener(new MouseInput()); p = new Player(365, 500, this); p2 = new Player2(365, 550, this); } private synchronized void start() { if(running) return; running = true; thread = new Thread(this); thread.start(); } private synchronized void stop() { if(!running) return; running = false; try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.exit(1); } public void run() { init(); long lastTime = System.nanoTime(); final double amountOfTicks = 60.0; double ns = 1000000000 / amountOfTicks; double delta = 0; int updates = 0; int frames = 0; long timer = System.currentTimeMillis(); while(running) { long now = System.nanoTime(); delta += (now - lastTime) / ns; lastTime = now; if(delta >= 1) { tick(); updates++; delta--; } render(); frames++; if(System.currentTimeMillis() - timer > 1000) { timer += 1000; System.out.println(updates + " FPS, TICKS " + frames); updates = 0; frames = 0; } } stop(); } private void tick() { if(State == STATE.GAME){ p.tick(); p2.tick(); } } private void render() { BufferStrategy bs = this.getBufferStrategy(); if(bs == null) { createBufferStrategy(3); return; } Graphics g = bs.getDrawGraphics(); g.drawImage(image, 0, 0, getWidth(), getHeight(), this); g.drawImage(MenuBackground, 0, 0, null); if(State == STATE.GAME){ //Drawing the main games background g.drawImage(background, 0, 0, null); p.render(g); p2.render(g); } else if(State == STATE.MENU){ menu.render(g); } g.dispose(); bs.show(); } public void keyPressed(KeyEvent e){ int key = e.getKeyCode(); if(State == STATE.GAME){ if(key == KeyEvent.VK_RIGHT){ p.setVelX(5); } if(key == KeyEvent.VK_D){ p2.setVelX2(5); } else if(key == KeyEvent.VK_LEFT) { p.setVelX(-5); } else if(key == KeyEvent.VK_A) { p2.setVelX2(-5); } else if(key == KeyEvent.VK_DOWN) { p.setVelY(5); } else if(key == KeyEvent.VK_S) { p2.setVelY2(5); } else if(key == KeyEvent.VK_UP) { p.setVelY(-5); } else if(key == KeyEvent.VK_W) { p2.setVelY2(-5); } } } public void keyReleased(KeyEvent e){ int key = e.getKeyCode(); if(key == KeyEvent.VK_RIGHT){ p.setVelX(0); } if(key == KeyEvent.VK_D){ p2.setVelX2(0); } else if(key == KeyEvent.VK_LEFT) { p.setVelX(0); } else if(key == KeyEvent.VK_A) { p2.setVelX2(0); } else if(key == KeyEvent.VK_DOWN) { p.setVelY(0); } else if(key == KeyEvent.VK_S) { p2.setVelY2(0); } else if(key == KeyEvent.VK_UP) { p.setVelY(0); } else if(key == KeyEvent.VK_W) { p2.setVelY2(0); } } public static void main(String args[]) throws Exception { Game game = new Game(); game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); JFrame frame = new JFrame(game.TITLE); frame.add(game); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setVisible(true); game.start(); System.out.println("Starting server...."); serverSocket = new ServerSocket(7777); System.out.println("Server started"); socket = serverSocket.accept(); System.out.println("Connecting from: " + socket.getInetAddress()); out = new DataOutputStream(socket.getOutputStream()); out.writeUTF("This is a test of Java Sockets"); System.out.println("Data has been sent"); } public BufferedImage getSpriteSheet() { return spriteSheet; } public BufferedImage getSpriteSheet2() { return spriteSheet2; } } 

这是我的玩家类

 package com.game.src.main; import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; public class Player { private double x; private double y; private double velX = 0; private double velY = 0; private BufferedImage player; BufferedImageLoader loader = new BufferedImageLoader(); BufferedImage SpriteSheet = null; public Player(double x, double y, Game game) { this.x = x; this.y = y; //New instance of Sprite sheet - reading from buffered image loader SpriteSheet ss = new SpriteSheet(game.getSpriteSheet()); player = ss.grabImage(1, 1, 50, 50); try { SpriteSheet = loader.loadImage("/Sprite_Sheet.png"); } catch(Exception e) { e.printStackTrace(); } } public void tick() { x+=velX; y+=velY; //Adding basic collision if(x = 850 - 100) { x = 850 - 100; } if(y = 650 - 100){ y = 650 - 100; } } public void render(Graphics g){ //Draw Track Color c1 = Color.green; g.setColor( c1 ); g.fillRect( 150, 200, 550, 300 ); //grass Color c2 = Color.black; g.setColor( c2 ); g.drawRect(50, 100, 750, 500); // outer edge g.drawRect(150, 200, 550, 300); // inner edge Color c3 = Color.yellow; g.setColor( c3 ); g.drawRect( 100, 150, 650, 400 ); // mid-lane marker Color c4 = Color.white; g.setColor( c4 ); g.drawLine( 425, 500, 425, 600 ); // start line g.drawImage(player, (int)x, (int)y, null); } public double getX(Graphics g){ return x; } public double getY(){ return y; } public void setX(double x){ this.x = x; } public void setY(double y){ this.y = y; } public void setVelX(double velX){ this.velX = velX; } public void setVelY(double velY){ this.velY = velY; } } 

我在这个游戏中有两个玩家,但是我真的坚持如何在所需的方向上将精灵方向改变22.5%所以如果我按下玩家1的向上键,它将把我的汽车旋转22.5%向北等我有每个玩家有16个精灵的精灵表每个角度变化22.5%这真让我感到困惑,我不知道如何实现这个,

谢谢你花时间看

这是旋转精灵的基本示例

纺织

这是什么维护是一个虚拟状态, Player对象检查该状态以确定应如何相应地更改它。 这将操作与结果分开,这意味着可以用一些其他操作替换操作(向上箭头键),但仍然可以获得相同的结果。

此示例还使用了键绑定API ,它没有遇到与KeyListener相同的焦点相关问题,但这是一个纯粹的Swing API,不能与Canvas兼容,但是一个很好的演示;)

真正的魔力发生在角色paint方法中……

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

基本上,这会创建一个AffineTransformation ,然后复合以产生我们需要的结果。 也就是说,首先它的锚位置被转换为字符x / y位置,然后围绕字符中心点旋转。 因为它已被翻译,我们可以简单地将字符绘制在0x0。 这更容易然后尝试在虚拟空间中的其他地方计算字符旋转锚 – 恕我直言

向上向下箭头键可旋转角色。 按下时,角色将继续旋转,这是示例的一个function,用于演示目的。

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

请记住,这只是用于呈现概念的一个例子;)