简体   繁体   English

我怎样才能让我的 Jump Animation 同时工作?

[英]How Can I Make My Jump Animation Work All At Once?

I'm having a bit of an issue with getting my game characters to jump.我在让我的游戏角色跳跃方面遇到了一些问题。 I've set my jump function as the space key, but the jump animation doesn't happen all at once.我已经将我的跳转 function 设置为空格键,但是跳转 animation 不会一下子发生。 Instead, pressing space causes the character to move a little up every time until it reaches the maximum jump height limit.相反,按空格键会导致角色每次向上移动一点,直到达到最大跳跃高度限制。 Then, once it reaches that height, pressing space causes the player to move a little down every time until it reaches the ground limit.然后,一旦它达到那个高度,按下空间会导致玩家每次向下移动一点,直到达到地面极限。 It looks normal when the space button is being held down, but once it is released, the character is stuck in the air where the space bar was released.按住空格键的时候看起来很正常,但是一旦松开,角色就卡在了松开空格键的地方。 I want the sequence to happen all at once with one click of the space bar.我希望通过单击空格键一次完成所有序列。 I've looked at my code for quite some time and tried changing where I call the "act" method I have for my Player class from the JPanel.我已经查看了我的代码很长一段时间,并尝试更改我从 JPanel 为我的 Player class 调用“act”方法的位置。 Here is my Player class where the jump feature is meant to be assigned its values:这是我的播放器 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);
        }   
    }
}

Then, in my JPanel class, I call the act() method in the Player class under my keyPressed method, checking for VK_ENTER, from the KeyListener interface:然后,在我的 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);

    }
}

You need a better understand of animation (generally) and games loops in particular.您需要更好地了解 animation(通常),尤其是游戏循环。

Swing uses a passive rendering approach, so you need to set up a "game loop" which updates the state of the game, taking into account any inputs the user has given, and then schedule a repaint. Swing 使用被动渲染方法,因此您需要设置一个“游戏循环”来更新游戏的 state,同时考虑到用户给出的任何输入,然后安排重绘。

This means, you can not update the state of the player in the KeyListener , instead, you need to setup a state which allows the "game loop" to update the overall state.这意味着,您不能在KeyListener中更新播放器的 state,而是需要设置一个 state 允许“游戏循环”更新整体 Z9ED39E2EA931586B6A985A6942EF573。

This is very basic example...这是一个非常基本的例子......

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

Personally, I would make use Key Bindings over KeyListener , as it will solve the immediate issue of keyboard focus and provide a more configurable approach.就个人而言,我会使用Key Bindings over KeyListener ,因为它将解决键盘焦点的直接问题并提供更可配置的方法。

This would mean that the "input state" would be independent of the player and the game loop would become responsible for taking control over the player state change based on the game state这意味着“输入状态”将独立于玩家,并且游戏循环将负责控制玩家 state 基于游戏 state

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM