[英]How Can I Make My Jump Animation Work All At Once?
我在让我的游戏角色跳跃方面遇到了一些问题。 我已经将我的跳转 function 设置为空格键,但是跳转 animation 不会一下子发生。 相反,按空格键会导致角色每次向上移动一点,直到达到最大跳跃高度限制。 然后,一旦它达到那个高度,按下空间会导致玩家每次向下移动一点,直到达到地面极限。 按住空格键的时候看起来很正常,但是一旦松开,角色就卡在了松开空格键的地方。 我希望通过单击空格键一次完成所有序列。 我已经查看了我的代码很长一段时间,并尝试更改我从 JPanel 为我的 Player class 调用“act”方法的位置。 这是我的播放器 class ,其中的跳跃功能应该被分配其值:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Player {
ImageIcon movements[];
ImageIcon leftMove[];
ImageIcon move[];
ImageIcon attack;
boolean ableAttack, canJump;
int count, x, y, width, height;
int fallingSpeed = 0;
int gravity = 1;
int jumpPower = -20;
public Player(int count, int x, int y) {
this.x = x;
this.y = y;
this.count = count;
movements = new ImageIcon[8];
leftMove = new ImageIcon[8];
attack = new ImageIcon("attackRight.gif");
this.width = 80;
this.height = 130;
for (int i = 0; i < 8; i++) {
movements[i] = new ImageIcon("right_"+(i + 1) + ".png");
leftMove[i] = new ImageIcon("go_"+(i+1)+".png");
}
move = movements.clone();
}
public void act() {
if (isOnGround()) {
canJump = true;
jump();
} else {
canJump = false;
fall();
}
}
public void jump() {
fallingSpeed = jumpPower;
fall();
}
public void fall() {
y += fallingSpeed;
fallingSpeed = fallingSpeed + gravity;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public boolean isOnGround() {
if (y > 410)
return true;
return false;
}
public void setAttack(boolean attack) {
ableAttack = attack;
}
public void setImageArrLeft() {
move = leftMove.clone();
attack = new ImageIcon("attack.gif");
}
public void setImageArrRight() {
move = movements.clone();
attack = new ImageIcon("attackRight.gif");
}
public void increaseCount() {
count++;
}
public void myDraw(Graphics g) {
if (ableAttack) {
g.drawImage(attack.getImage(), x, y, width + 30, height + 10, null);
}
else {
g.drawImage(move[count % 8].getImage(), x, y, width, height, null);
}
}
}
然后,在我的 JPanel class 中,我在我的 keyPressed 方法下调用 Player class 中的 act() 方法,从 KeyListener 接口检查 VK_ENTER:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MyPanel extends JPanel implements ActionListener, MouseListener, MouseMotionListener, KeyListener{
int mouseX, mouseY, x = 100, y = 420;
Timer timer;
ImageIcon background = null;
Player p;
public MyPanel() {
timer = new Timer(60, this);
p = new Player((int)(Math.random() * 8), x, y);
background = new ImageIcon("battlefield1.png");
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background.getImage(), 0, 0, 1375, 750, null);
p.myDraw(g);
repaint();
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==timer) {
}
}
public void mouseClicked(MouseEvent me) {}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me) {}
public void mousePressed(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {}
public void mouseDragged(MouseEvent me) {}
public void mouseMoved(MouseEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
p.increaseCount();
if (x < 1300)
x += 10;
p.setX(x);
p.setImageArrRight();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
p.increaseCount();
if (x > 0)
x -= 5;
p.setX(x);
p.setImageArrLeft();
}
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
p.setAttack(true);
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
p.act();
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
p.setAttack(false);
}
}
您需要更好地了解 animation(通常),尤其是游戏循环。
Swing 使用被动渲染方法,因此您需要设置一个“游戏循环”来更新游戏的 state,同时考虑到用户给出的任何输入,然后安排重绘。
这意味着,您不能在KeyListener
中更新播放器的 state,而是需要设置一个 state 允许“游戏循环”更新整体 Z9ED39E2EA931586B6A985A6942EF573。
这是一个非常基本的例子......
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MyPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyPanel extends JPanel implements ActionListener, MouseListener, MouseMotionListener, KeyListener {
int mouseX, mouseY, x = 100, y = 420;
Timer timer;
Player p;
public MyPanel() {
timer = new Timer(60, this);
p = new Player((int) (Math.random() * 8), x, y);
setBackground(Color.BLUE);
addKeyListener(this);
setFocusable(true);
}
@Override
public void addNotify() {
super.addNotify();
timer.start();
}
@Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
p.myDraw(g);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == timer) {
p.update();
repaint();
}
}
public void mouseClicked(MouseEvent me) {
}
public void mouseEntered(MouseEvent me) {
}
public void mouseExited(MouseEvent me) {
}
public void mousePressed(MouseEvent me) {
}
public void mouseReleased(MouseEvent me) {
}
public void mouseDragged(MouseEvent me) {
}
public void mouseMoved(MouseEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
p.increaseCount();
if (x < 1300) {
x += 10;
}
p.setX(x);
p.setImageArrRight();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
p.increaseCount();
if (x > 0) {
x -= 5;
}
p.setX(x);
p.setImageArrLeft();
}
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
p.setAttack(true);
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
p.act();
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
p.setAttack(false);
}
}
public class Player {
boolean ableAttack, canJump;
int count, x, y, width, height;
int fallingSpeed = 0;
int gravity = 1;
int jumpPower = -20;
private boolean isJumping = false;
public Player(int count, int x, int y) {
this.x = x;
this.y = y;
this.count = count;
width = 10;
height = 10;
}
public void act() {
if (isOnGround()) {
jump();
// canJump = true;
// jump();
//
// } else {
// canJump = false;
// fall();
}
}
public void jump() {
isJumping = true;
fallingSpeed = jumpPower;
fall();
}
public void fall() {
y += fallingSpeed;
fallingSpeed = fallingSpeed + gravity;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public boolean isOnGround() {
if (y > 410) {
return true;
}
return false;
}
public void setAttack(boolean attack) {
ableAttack = attack;
}
public void setImageArrLeft() {
}
public void setImageArrRight() {
}
public void increaseCount() {
count++;
}
public void update() {
if (isJumping) {
if (!isOnGround()) {
fall();
} else {
isJumping = false;
}
}
}
public void myDraw(Graphics g) {
g.setColor(Color.RED);
g.fillRect(x, y, width, height);
}
}
}
就个人而言,我会使用Key Bindings over KeyListener
,因为它将解决键盘焦点的直接问题并提供更可配置的方法。
这意味着“输入状态”将独立于玩家,并且游戏循环将负责控制玩家 state 基于游戏 state
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.