平台碰撞和跳跃的奇怪行为

时间:2014-01-13 00:05:57

标签: java swing awt collision-detection

我使用AWT和Swing在java中开发了一个简单的游戏。你所要做的就是用一个空格键来控制一个正方形,这个空格键上下跳转到一个永无止境的平台流。

Weeee!

一切正常,但是当玩家跳下平台,握住空格键并降落在另一个平台上时,他/她将随机弹跳或简单地穿过平台。据我所知,错误在于玩家的行为。

以下是测试它所需的所有代码:

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

    }

}

1 个答案:

答案 0 :(得分:2)

很难100%肯定,但是“看起来”的情况正在发生,你在 Space 事件想要做什么和你的“引力”想要做什么之间的斗争

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

而不是允许用户将密钥保持为......

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 事件......

我要做的是添加一个名为hasJumped的标志。虽然它是true,但您只需忽略任何新的跳转事件。一旦用户释放 Space ,你就重置了这个标志,所以再按一下 Space 会引起一个新的跳跃。

在你的游戏引擎中,我会重置jumping标志,这样一旦你注册了跳跃已经发生的事实,直到它们释放并再次按下 Space ,它不会引发跳跃......

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

我还建议您查看Key Bindings而不是KeyListener

您可以查看JApplet creates a ball that bounces and gets progressively less high in Java之类的内容,例如