根据键盘输入让我的精灵朝某个方向面对-Java游戏 [英] Getting my sprite to face in a certain direction based on Keyboard input - Java Game

查看:55
本文介绍了根据键盘输入让我的精灵朝某个方向面对-Java游戏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,通过遵循大量不同的教程,我已经用Java组成了一个基本的游戏-问题是我无法设法弄清楚如何让我的精灵朝不同的方向移动.这是我主要的代码

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 move in different directions. Here is the code for my main

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

在这个游戏中我有两个玩家,但是我真的对如何在所需方向上将精灵方向改变22.5%保持不动,因此,如果我按玩家1的向上键,它将使我的车向北旋转22.5%,依此类推.我有一个Sprite工作表,每个角色每次角度变化22.5%时都有16个Sprite,这确实让我感到困惑,我不确定如何实现此目标,

I have two players in this game but i'm really stuck on how i can change the sprites direction by 22.5% in a desired direction so if i pressed the up key for player 1 it would rotate my car 22.5% north etc. I have a sprite sheet with 16 sprites for each player for every change in angle by 22.5% This is really confusing me and i'm not sure how i can implement this,

感谢您抽出宝贵的时间

推荐答案

这是旋转精灵的基本示例

This is a basic example of spinning a sprite

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

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.

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

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

真正的魔力发生在字符 paint 方法中...

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

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

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

这篇关于根据键盘输入让我的精灵朝某个方向面对-Java游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆