微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何让我的跳跃动画一次全部生效?

如何解决如何让我的跳跃动画一次全部生效?

我在让我的游戏角色跳跃时遇到了一些问题。我已将我的跳跃功能设置为空格键,但跳跃动画不会同时发生。相反,按空格会使角色每次向上移动一点,直到达到最大跳跃高度限制。然后,一旦它达到该高度,按下空间会使玩家每次向下移动一点,直到达到地面限制。按住空格键时看起来很正常,但是一旦松开,角色就会卡在松开空格键的空气中。我希望只需按一下空格键就可以一次全部发生。我已经查看了我的代码很长一段时间,并尝试更改我从 JPanel 为我的 Player 类调用“act”方法的位置。这是我的 Player 类,其中的跳跃功能旨在为其分配值:

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(),width + 30,height + 10,null);
        } 
        else {
            g.drawImage(move[count % 8].getimage(),height,null);
        }   
    }
}

然后,在我的 JPanel 类中,我在 keypressed 方法调用 Player 类中的 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),y);
        background = new ImageIcon("battlefield1.png");
        addKeyListener(this);
        setFocusable(true);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(background.getimage(),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);

    }
}

解决方法

您需要更好地理解动画(一般)和游戏循环。

Swing 使用被动渲染方法,因此您需要设置一个“游戏循环”来更新游戏状态,考虑用户提供的任何输入,然后安排重绘。

这意味着,您不能在 KeyListener 中更新玩家的状态,而是需要设置一个允许“游戏循环”更新整体状态的状态。

这是一个非常基本的例子...

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

就我个人而言,我会使用 Key Bindings 而不是 KeyListener,因为它将解决键盘焦点的直接问题并提供更可配置的方法。

这意味着“输入状态”将独立于玩家,游戏循环将负责根据游戏状态控制玩家状态变化

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。