具有平台碰撞和跳跃的奇怪行为 [英] Strange behavior with platform collision and jumping

查看:65
本文介绍了具有平台碰撞和跳跃的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用AWT和Swing开发了一个简单的Java游戏.您要做的就是用空格键控制一个正方形,该空格键可以上下跳跃到无休止的平台流中.

I have developed a simple game in java using AWT and Swing. All you do is control a square with the spacebar that jumps up and down onto a never-ending stream of platforms.

一切正常,但是当玩家跳下平台,握住空格键并降落在另一个平台上时,他/她将随机弹跳或简单地跌落平台.据我所知,错误与播放器的行为有关.

Everything works fine, but when a player jumps off a platform, holds the spacebar, and lands on another platform, he/she will randomly bounce or simply drop through the platform. From what I can tell, the error lies somewhere with the Player's behavior.

这是测试它的全部代码:

Here's the all the code needed to test it:

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class main {

    private static JFrame gui;
    private static Container pane;
    private static JPanel panel;    

    public static void main(String[] args) {
        gui = new JFrame();
        gui.setSize(500,500);
        gui.setTitle("An Experiment");
        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pane=gui.getContentPane();
        panel = new ColorPanel(Color.WHITE, 500, 500);
        pane.add(panel);
        gui.setVisible(true);
        gui.pack();
    }

    //****************
    //ColorPanel class
    //****************

    private static class ColorPanel extends JPanel{
        private static final long serialVersionUID = -1101242028703991986L;
        private Timer timer, dtimer;
        private KeyListener k;
        private Platform platform;
        private Player player;
        private int difficulty, score;

        public ColorPanel(Color backColor, int width, int height){
            setBackground(backColor);
            setPreferredSize(new Dimension(width, height));
            difficulty=-1;
            score=0;

            platform = new Platform(new Point(240,250), 50);

            player=new Player(width/2, height/2-100);

            k=new keyboardListener();
            addKeyListener(k);
            setFocusable(true);

            timer = new javax.swing.Timer(15, new timerListener());
            timer.start();

            dtimer = new javax.swing.Timer(50000, new difficultyListener());
            dtimer.start();
        }

        public void paintComponent(Graphics g){
            super.paintComponent(g);
            if(player.getY()<500){
                platform.draw(g);
                player.draw(g);
            }else{
                timer.stop();
                dtimer.stop();
                setBackground(Color.BLACK);
                g.setColor(Color.RED);
                g.drawString("Game Over.", 215, 230);
                g.setColor(Color.YELLOW);
                g.drawString("Platforms cleared: "+score, 200, 240);
                g.drawString("End difficulty: "+Math.abs(difficulty), 200, 250);

            }
        }

        private class timerListener implements ActionListener{
            public void actionPerformed(ActionEvent e){         
                //Player control
                player.move(platform);

                repaint();
            }
        }

        private class difficultyListener implements ActionListener{
            public void actionPerformed(ActionEvent e){
                difficulty--;
                if(difficulty<=-10){
                    dtimer.stop();
                }
            }
        }
        private class keyboardListener implements KeyListener{
            @Override
            public void keyPressed(KeyEvent e){
                //space=32
                if(e.getKeyCode()==32){
                    player.setJumping(true);
                }
            }
            @Override
            public void keyReleased(KeyEvent e){
                if(e.getKeyCode()==32){
                    player.setJumping(false);
                }
            }
            @Override
            public void keyTyped(KeyEvent e) {
            }   
        }
    }

    //************
    //Player class
    //************

    private static class Player {

        private int x, y, w, h, initialSpeed, speed, endingSpeed, acceleration, jumpHeight, timeCount;
        private boolean isJumping, onPlatform;
        private Timer accel;

        public Player(int x1, int y1){
            x=x1;
            y=y1;
            w=15;
            h=15;
            isJumping=false;
            onPlatform=false;
            speed=3;
            accel=new Timer(50, new timerListener());
        }

        public void draw(Graphics g){
            g.drawRect(x, y, w, h);
        }

        public void move(Platform p){
            //platform collision
            onPlatform=false;
            if((x>p.getP1().getX() && x<p.getP2().getX()) || (x+w>p.getP1().getX() && x+w<p.getP2().getX())){
                if(Math.abs(y+h-p.getP1().getY())<2){
                    onPlatform=true;
                }
            }   
            //speed update and movement
            if(isJumping && y>0 && jumpHeight>=-140){
                y+=speed;
                jumpHeight+=speed;
            }else if(onPlatform){
                speed=0;
            }else if(!onPlatform){
                jumpHeight=0;
                if(!isJumping && speed!=3){
                    setSpeed(3);
                }
                y+=speed;
            }
            if(jumpHeight<-140){
                jumpHeight=0;
            }
        }

        public void setJumping(boolean b){
            if(onPlatform && b && jumpHeight>=-140){
                isJumping=true;
                speed=-4;
            }else{
                isJumping=false;
                setSpeed(3);
            }
        }

        public int getY(){
            return y;
        }

        public void setSpeed(int s){
            //speed=starting speed + acceleration*time
            timeCount=0;
            initialSpeed=speed;
            endingSpeed=s;
            if(speed>s){
                acceleration=-1;
            }else{
                acceleration=1;
            }
            accel.start();
        }

        private class timerListener implements ActionListener{
            public void actionPerformed(ActionEvent e){
                timeCount++;
                if(Math.abs(speed-endingSpeed)<=0.5){
                    accel.stop();
                }else if(acceleration<0 && initialSpeed+acceleration*timeCount>0){
                    speed--;
                }else{
                    speed=initialSpeed+acceleration*timeCount;
                }
            }
        }

    }

    //**************
    //Platform class
    //**************

    private static class Platform {

        private Point p1, p2;

        public Platform(Point p, int l){
            p1=p;
            p2=new Point((int)(p1.getX()+l), (int)(p1.getY()));
        }

        public Point getP1(){
            return p1;
        }
        public Point getP2(){
            return p2;
        }

        public void draw(Graphics g){
            g.drawLine((int)(p1.getX()), (int)(p1.getY()), (int)(p2.getX()), (int)(p2.getY()));
        }

    }

}

推荐答案

很难百分百确定,但是看起来"到底是怎么回事,是您在 Space 事件想做的事以及您的重力"想做的事.

It's difficult to be 100% sure, but what it "looks" like is happening, is you have a fight between what the Space event wants to do and what your "gravity" wants to do.

请记住,当 Space 按下时,您将收到多个按键事件,具体取决于操作系统的键盘延迟/定时(例如,您每秒可能收到多个事件)

Remember, while the Space is down, you will be receiving multiple key events depending on the OS's keyboard delay/timing (you may receive several events per second for example)

而不是让用户像...那样按下键.

Instead of allowing the user to keep the key down like...

private class keyboardListener implements KeyListener{
    @Override
    public void keyPressed(KeyEvent e){
        //space=32
        if(e.getKeyCode()==32){
            player.setJumping(true);
        }
    }
    @Override
    public void keyReleased(KeyEvent e){
        if(e.getKeyCode()==32){
            player.setJumping(false);
        }
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }   
}

尝试忽略任何新的 Space 事件...

Try ignoring any new Space events...

我要做的是添加一个称为 hasJumped 之类的标志.当它为 true 时,您只需忽略任何新的跳转事件.用户释放 Space 后,您将重置该标志,以便再次按下 Space 会导致新的跳转.

What I would do is add a flag called something like hasJumped. While it's true, you would simply ignore any new jump events. Once the user releases the Space, you reset the flag so another press on Space would cause a new jump.

在您的游戏引擎中,我将重置 jumping 标志,以便一旦您注册了发生跳跃的事实,直到释放并按下 Space 再次,它不会触发跳跃...

In you game engine, I would reset the jumping flag so that once you've registered the fact that a jump has occurred, until they release and press the Space again, it won't trigger a jump...

private class keyboardListener implements KeyListener{
    @Override
    public void keyPressed(KeyEvent e){
        //space=32
        if(e.getKeyCode()==32){
            if (!player.hasJumped()) {
                player.setJumping(true);
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e){
        if(e.getKeyCode()==32){
            player.hasJumped(false);
        }
    }
    //...
}

我还建议您查看键绑定通过 KeyListener

您可以看一下 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆