[英]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.