基于键盘输入让我的精灵面向某个方向-Java游戏

基于键盘输入让我的精灵面向某个方向-Java游戏,java,sprite,direction,Java,Sprite,Direction,因此,我已经按照一系列不同的教程,用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 j

因此,我已经按照一系列不同的教程,用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 < 0 + 50) {
        x = 0 + 50;
    }
    if(x >= 850 - 100) {
        x = 850 - 100;
    }
    if(y < 0 + 100) {
        y = 0 + 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;
}
}
package com.game.src.main;
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.image.buffereImage;
公开课选手{
私人双x;
私人双y;
私人双velX=0;
私有双精度=0;
私人缓冲图像播放器;
BufferedImageLoader=新的BufferedImageLoader();
BuffereImage SpriteSheet=null;
公共玩家(双x,双y,游戏){
这个.x=x;
这个。y=y;
//Sprite表的新实例-从缓冲图像加载程序读取
SpriteSheet ss=新的SpriteSheet(game.getSpriteSheet());
player=ss.grabImage(1,1,50,50);
试一试{
SpriteSheet=loader.loadImage(“/Sprite_Sheet.png”);
}
捕获(例外e){
e、 printStackTrace();
}
}
公共空白勾号(){
x+=velX;
y+=0;
//添加基本冲突
如果(x<0+50){
x=0+50;
}
如果(x>=850-100){
x=850-100;
}
如果(y<0+100){
y=0+100;
}
如果(y>=650-100){
y=650-100;
}
}
公共空间渲染(图形g){
//画轨道
颜色c1=颜色。绿色;
g、 setColor(c1);
g、 fillRect(150200550300);//草
颜色c2=颜色。黑色;
g、 setColor(c2);
g、 drawRect(50100750500);//外边缘
g、 drawRect(150200550300);//内边缘
颜色c3=颜色。黄色;
g、 setColor(c3);
g、 drawRect(100150650400);//中间车道标记
颜色c4=颜色。白色;
g、 setColor(c4);
g、 抽绳(425500425600);//起始线
g、 drawImage(播放器,(整数)x,(整数)y,空);
}
公共双getX(图形g){
返回x;
}
公共双盖{
返回y;
}
公共无效集x(双x){
这个.x=x;
}
公共空间设置(双y){
这个。y=y;
}
公共无效设置级别(双级别){
this.velX=velX;
}
公共无效设置(双重设置){
这是一个很好的例子;
}
}
我有两个玩家在这个游戏中,但我真的被困在我如何可以改变22.5%的精灵方向在一个理想的方向,所以如果我按下了玩家1的向上键,它会旋转我的车22.5%的北方等。我有一个精灵表,每个玩家16个精灵,每改变22.5%的角度。这真的让我困惑,我不知道我该怎么做可以实施这个,


感谢您花时间查看

这是一个旋转精灵的基本示例

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

此示例还使用了,它不会遇到与
keysister
相同的焦点相关问题,但这是一个纯Swing API,与
Canvas
不兼容,而是一个很好的演示;)

真正的魔法发生在角色
绘画
方法中

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);
}
基本上,这会创建一个
仿射变换
,然后将其复合以产生我们需要的结果。也就是说,首先将其定位点位置转换为字符的x/y位置,然后围绕字符中心点旋转。因为它已被翻译,所以我们可以简单地在0x0处绘制角色。这比计算虚拟空间中其他地方的角色旋转锚点(IMHO)要容易得多

通过按向上或向下箭头键旋转角色。按下时,角色将继续旋转,这是示例的一个功能,用于演示

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

        }

    }

}

请记住,这只是一个用于展示概念的示例;)

我想我已经理解了它的工作原理,但是我想知道是否有任何方法可以在键盘输入上使用不同的精灵,例如if else if(key==KeyEvent.VK_LEFT{p.setVelX(-5);}不仅要移动精灵,还要将正在使用的精灵更改为面向左侧的精灵?是的,这是非常可能的。您需要设置某种状态,以便代码的渲染部分知道它应该渲染什么