Java 玩家对象移动一个方向但转向另一个方向
当游戏第一次开始时,玩家将从0(右)方向开始。按向右键(vk_right)将播放器精灵向左旋转,但方向设置为将播放器发送到(看起来)正确的方向。左键和右键更改角色的方向变量,而上/下键加速/减速角色 我不太擅长三角学,所以我可能在这里和那里有一些错误(这就是为什么我张贴这篇文章)。我似乎不明白如何让角色朝着他“看”的方向移动(方向变量) 下面是Player.java类:Java 玩家对象移动一个方向但转向另一个方向,java,swing,graphics,trigonometry,radians,Java,Swing,Graphics,Trigonometry,Radians,当游戏第一次开始时,玩家将从0(右)方向开始。按向右键(vk_right)将播放器精灵向左旋转,但方向设置为将播放器发送到(看起来)正确的方向。左键和右键更改角色的方向变量,而上/下键加速/减速角色 我不太擅长三角学,所以我可能在这里和那里有一些错误(这就是为什么我张贴这篇文章)。我似乎不明白如何让角色朝着他“看”的方向移动(方向变量) 下面是Player.java类: package rpg2d; import java.awt.Image; import java.awt.event.Ke
package rpg2d;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
public class Player implements KeyListener{
private double x,y,direction;
private double speed;
private final int max_speed;
private int hp,lives;
private Image img;
//other variables
public Player(int x, int y, int hp, int lives, String imgpath) {
this.x = x;
this.y = y;
this.hp = hp;
this.lives = lives;
img = new ImageIcon(this.getClass().getResource(imgpath)).getImage();
//loads the player image from the string path
max_speed = 6;
speed = 0;
direction = 0;
}
//returns the direction the player is 'facing' as an int
public int getDirection() {
return (int)direction;
}
//updates the player's location
public void move() {
x += speed * Math.cos(-1*direction);
y += speed * Math.sin(-1*direction);
}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
turn(.6);
//this is meant to turn the player int a clockwise direction by 0.6
} else if (key == KeyEvent.VK_RIGHT){
turn(-.6);
//counterclockwise by 0.6
}
if (key == KeyEvent.VK_DOWN){
speed -= 0.3;
if(speed < 0) speed = 0;
//decelerate until stopped
} else if (key == KeyEvent.VK_UP){
speed += 0.3;
if(speed > max_speed) speed = max_speed;
//accelerates until it hits maximum speed
}
}
private void turn(double degrees) {
direction += degrees;
if(direction > 180) direction -= 180;
else if(direction < -180) direction += 180;
/* I honestly don't know whether 180 and -180 are the max and min
* for Polar Coordinates, so this could be a problem.
*/
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent arg0) {
}
public int getX() {
return (int)x;
}
public int getY() {
return (int)y;
}
public double getWidth() {
return img.getWidth(null);
}
public double getHeight() {
return img.getHeight(null);
}
public Image getImg() {
return img;
}
}
我做了一些改进:
public void move() {
x += speed * Math.cos(Math.toRadians(direction));
y += speed * Math.sin(Math.toRadians(direction));
}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
turn(-.6);
//this is meant to turn the player int a clockwise direction by 0.6
} else if (key == KeyEvent.VK_RIGHT){
turn(.6);
//counterclockwise by 0.6
}
.....//rest of code}
private void turn(double degrees) {
direction += degrees;
if(direction > 180) direction = 180;
else if(direction < 180) direction = 0;
}
公共作废移动(){
x+=速度*Math.cos(Math.toRadians(方向));
y+=速度*Math.sin(Math.toRadians(方向));
}
@凌驾
按下公共无效键(按键事件e){
int key=e.getKeyCode();
if(key==KeyEvent.VK_左){
转(-.6);
//这意味着将玩家int顺时针旋转0.6圈
}else if(key==KeyEvent.VK_RIGHT){
转弯(.6);
//逆时针方向0.6
}
..…//代码的其余部分}
私人空位转弯(双度){
方向+=度;
如果(方向>180)方向=180;
否则,如果(方向<180)方向=0;
}
我做了一些改进:
public void move() {
x += speed * Math.cos(Math.toRadians(direction));
y += speed * Math.sin(Math.toRadians(direction));
}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
turn(-.6);
//this is meant to turn the player int a clockwise direction by 0.6
} else if (key == KeyEvent.VK_RIGHT){
turn(.6);
//counterclockwise by 0.6
}
.....//rest of code}
private void turn(double degrees) {
direction += degrees;
if(direction > 180) direction = 180;
else if(direction < 180) direction = 0;
}
公共作废移动(){
x+=速度*Math.cos(Math.toRadians(方向));
y+=速度*Math.sin(Math.toRadians(方向));
}
@凌驾
按下公共无效键(按键事件e){
int key=e.getKeyCode();
if(key==KeyEvent.VK_左){
转(-.6);
//这意味着将玩家int顺时针旋转0.6圈
}else if(key==KeyEvent.VK_RIGHT){
转弯(.6);
//逆时针方向0.6
}
..…//代码的其余部分}
私人空位转弯(双度){
方向+=度;
如果(方向>180)方向=180;
否则,如果(方向<180)方向=0;
}
增加迪恩的努力
在没有图像的情况下,我创建了一个简单的箭头形状,它开始指向右边
public Player(int x, int y, int hp, int lives, String imgpath) {
this.x = x;
this.y = y;
this.hp = hp;
this.lives = lives;
//img = new ImageIcon(this.getClass().getResource(imgpath)).getImage();
BufferedImage arrow = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = arrow.createGraphics();
g2d.setColor(Color.RED);
g2d.drawLine(0, 0, 16, 8);
g2d.drawLine(16, 8, 0, 16);
g2d.drawLine(0, 16, 0, 0);
g2d.dispose();
img = arrow;
max_speed = 6;
speed = 0;
direction = 0;
}
现在,这个渲染开始时很好
当我开始移动播放器时,我遇到了一些问题,所以我稍微更新了画图代码
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform trans = new AffineTransform();
trans.setToIdentity();
trans.translate(player.x, player.y);
trans.rotate(Math.toRadians(player.getDirection()), player.getWidth() / 2, player.getHeight() / 2);
g2d.setTransform(trans);
g2d.drawImage(player.getImg(), 0, 0, (int) player.getWidth(), (int) player.getHeight(), null);
g2d.dispose();
g2d = (Graphics2D) g.create();
g2d.drawString("X: " + player.getX() + " Y: " + player.getY(), 5, 10);
g2d.dispose();
trans.setToIdentity();
}
基本上,我复制了图形
上下文
Graphics2D g2d = (Graphics2D) g.create();
使用仿射变换
,我将上下文转换为玩家的当前位置,这简化了旋转代码,因为我不需要偏移锚点
trans.translate(player.x, player.y);
trans.rotate(Math.toRadians(player.getDirection()), player.getWidth() / 2, player.getHeight() / 2);
这也意味着更容易绘制图像
g2d.drawImage(player.getImg(), 0, 0, (int) player.getWidth(), (int) player.getHeight(), null);
这一切的美妙之处在于,所有更改都与图形
上下文的副本相关,您不需要“撤消”所有更改…只是不要忘记在完成后处理副本
我也不鼓励您使用keylister
,而是更喜欢使用
我还将线程
和java.util.Timer
替换为javax.swing.Timer
public void gameLoop() {
Timer timer = new Timer(16, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
update();
screen.repaint();
}
});
timer.start();
}
另外,请注意,
scheduleAtFixedRate
的最后一个参数是调用之间的毫秒数,因此您当前的代码大约生成16fps。60fps大约是16毫秒…加上Dean的努力
在没有图像的情况下,我创建了一个简单的箭头形状,它开始指向右边
public Player(int x, int y, int hp, int lives, String imgpath) {
this.x = x;
this.y = y;
this.hp = hp;
this.lives = lives;
//img = new ImageIcon(this.getClass().getResource(imgpath)).getImage();
BufferedImage arrow = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = arrow.createGraphics();
g2d.setColor(Color.RED);
g2d.drawLine(0, 0, 16, 8);
g2d.drawLine(16, 8, 0, 16);
g2d.drawLine(0, 16, 0, 0);
g2d.dispose();
img = arrow;
max_speed = 6;
speed = 0;
direction = 0;
}
现在,这个渲染开始时很好
当我开始移动播放器时,我遇到了一些问题,所以我稍微更新了画图代码
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform trans = new AffineTransform();
trans.setToIdentity();
trans.translate(player.x, player.y);
trans.rotate(Math.toRadians(player.getDirection()), player.getWidth() / 2, player.getHeight() / 2);
g2d.setTransform(trans);
g2d.drawImage(player.getImg(), 0, 0, (int) player.getWidth(), (int) player.getHeight(), null);
g2d.dispose();
g2d = (Graphics2D) g.create();
g2d.drawString("X: " + player.getX() + " Y: " + player.getY(), 5, 10);
g2d.dispose();
trans.setToIdentity();
}
基本上,我复制了图形
上下文
Graphics2D g2d = (Graphics2D) g.create();
使用仿射变换
,我将上下文转换为玩家的当前位置,这简化了旋转代码,因为我不需要偏移锚点
trans.translate(player.x, player.y);
trans.rotate(Math.toRadians(player.getDirection()), player.getWidth() / 2, player.getHeight() / 2);
这也意味着更容易绘制图像
g2d.drawImage(player.getImg(), 0, 0, (int) player.getWidth(), (int) player.getHeight(), null);
这一切的美妙之处在于,所有更改都与图形
上下文的副本相关,您不需要“撤消”所有更改…只是不要忘记在完成后处理副本
我也不鼓励您使用keylister
,而是更喜欢使用
我还将线程
和java.util.Timer
替换为javax.swing.Timer
public void gameLoop() {
Timer timer = new Timer(16, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
update();
screen.repaint();
}
});
timer.start();
}
另外,请注意,
scheduleAtFixedRate
的最后一个参数是调用之间的毫秒数,因此您当前的代码大约生成16fps。60fps大约是16毫秒…如果这是我的问题,我会去掉底部的咆哮,因为它会分散注意力,没有任何作用。如果您花时间更详细地描述您的代码,以便我们能够理解,那么这个问题会更好地解决。如果我能一目了然地理解你的代码,我现在可能已经给了你一个答案。另外,在Swing应用程序中使用java.util.Timer通常是不安全的。最好使用javax.swing.Timer.Sorry来解释这个问题。信息技术