Java中的定时器加速

Java中的定时器加速,java,timer,delay,Java,Timer,Delay,我知道这方面还有其他问题,但似乎没有一个能帮助我解决问题。在我的游戏中,有一个玩家发射一枚导弹,朝负y方向飞去,直到它从屏幕上消失,回到原来的位置,等待再次发射。然而,每次发射导弹时,它都会变快,就像计时器()中的延迟变短一样。守则: 主要类别: public class ShooterGame extends JFrame{ static int playerX=500; static int playerY=520; InputHandler input = new

我知道这方面还有其他问题,但似乎没有一个能帮助我解决问题。在我的游戏中,有一个玩家发射一枚导弹,朝负y方向飞去,直到它从屏幕上消失,回到原来的位置,等待再次发射。然而,每次发射导弹时,它都会变快,就像计时器()中的延迟变短一样。守则:

主要类别:

public class ShooterGame extends JFrame{
    static int playerX=500;
    static int playerY=520;

    InputHandler input = new InputHandler(this);
    public static Player player = new Player(playerX,playerY,50,50);

    public static void main(String[] args){
        ShooterGame game = new ShooterGame();
        game.run();
        System.exit(0);
    }

    static int windowWidth = 1300;
    static int windowHeight = 600;
    static int fps = 30;
    public static BufferedImage backBuffer = new BufferedImage(windowWidth, windowHeight, BufferedImage.TYPE_INT_RGB);
    public static Graphics bbg;

    public void run(){
        boolean running = true;

        initialize();

        while(running){
            long time = System.currentTimeMillis();

            update();
            draw();

            time = (1000 / fps) - (System.currentTimeMillis() - time);

            if (time > 0) { 
                try{ 
                    Thread.sleep(time); 
                } 
                    catch(Exception e){}; 
            };
        }

    }

    public void initialize(){
        setTitle("--- Shooter Game ---");
        setSize(windowWidth, windowHeight);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void update(){
        player.update(input);
    }

    public void draw(){

        Graphics g = getGraphics(); 

        Graphics bbg = backBuffer.getGraphics(); 

        bbg.setColor(Color.BLACK); 
        bbg.fillRect(0, 0, windowWidth, windowHeight); 
        player.Draw(bbg);
        enemie1.Draw(bbg,10,100);

        if(game.player.Player.missileRunning) game.player.Player.missile.Draw(bbg);

        g.drawImage(backBuffer, 0, 0, this); 
    }

    public static Graphics getMainGraphics(){
        return bbg;
    }
}
球员级别:

public class Player{

    private BufferedImage sprite;
    public BufferedImage missileSprite;
    public int x, y, width, height;
    private int fixedX;
    private final double speed = 5.0d;
    public static Missile missile;
    public static boolean missileRunning = false;
    public static boolean missileReady = true;

    public Player(int x, int y, int width, int height){
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        missile = new Missile(this.x);

        try{
            URL url = this.getClass().getResource("ship.png");
            sprite = ImageIO.read(url);
        } catch(IOException e){}

        try{
            URL url2 = this.getClass().getResource("missile.png");
            missileSprite = ImageIO.read(url2);
        } catch(IOException e){}
    }

    public void keyPlayer(double delta, InputHandler i){
        if(i.isKeyDown(KeyEvent.VK_D)){
            if(this.x>=1240) return;
            else this.x+=speed*delta;
        }

        if(i.isKeyDown(KeyEvent.VK_A)){
            if(this.x<=0) return;
            else this.x-=speed*delta;
        }

        if(i.isKeyDown(KeyEvent.VK_SPACE)){
            if(missileReady){ 
                try {
                    AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("C:/Users/Gabriel/Desktop/Programacao/Other/java/ShootGame/game/player/Fire.wav").getAbsoluteFile());
                    Clip clip = AudioSystem.getClip();
                    clip.open(audioInputStream);
                    clip.start();
                } catch(Exception ex) {
                    System.out.println("Error with playing sound.");
                    ex.printStackTrace();
                }
                missile.x=this.x + 20;
                missileRunning=true; 
            }
        }

    }

    public void update(InputHandler inputP){
        keyPlayer(2.0, inputP);
        updateMissile(game.ShooterGame.backBuffer.getGraphics());
    }

    public void updateMissile(Graphics g){
        if(missileRunning){ 
            missileReady=false;
            missile.update(g);
        }
    }

    public Rectangle missileBounds(){
        return new Rectangle(missile.x, game.player.Missile.y, 6, 18);
    }

    public void Draw(Graphics a){
        a.drawImage(sprite,x,y,width,height,null);
    }

    public Rectangle getBounds(){
        return new Rectangle(x,y,width,height);
    }
}
公共类播放器{
私有缓冲图像精灵;
公共缓冲区映像传输;
公共整数x,y,宽度,高度;
私有int-fixedX;
私人最终双速=5.0d;
公共静态导弹;
公共静态布尔missileRunning=false;
公共静态布尔值missileReady=true;
公共播放器(整数x,整数y,整数宽度,整数高度){
这个.x=x;
这个。y=y;
这个。宽度=宽度;
高度=高度;
导弹=新导弹(this.x);
试一试{
URL URL=this.getClass().getResource(“ship.png”);
sprite=ImageIO.read(url);
}捕获(IOE){}
试一试{
URL url2=this.getClass().getResource(“飞弹.png”);
missileSprite=ImageIO.read(url2);
}捕获(IOE){}
}
public void键盘播放器(双三角,InputHandler i){
if(i.isKeyDown(KeyEvent.VK_D)){
如果(this.x>=1240)返回;
否则,这个.x+=速度*增量;
}
if(i.isKeyDown(KeyEvent.VK_A)){

如果(this.x不运行代码

timerReady=true;
if(checkTimer()){
    timer2 = new Timer();
    timer2.schedule(new Move(), 0, interval);
}
基本上意味着
checkTimer
将始终返回
true
,这意味着每次调用
update
,您都在创建另一个
Timer
,这可能会创建几十个定时器,所有定时器都会独立更新游戏状态…这将导致对象加速

这种逻辑和功能应该由主循环控制。在每个循环中,您应该检查对象的状态,并做出移动或移除对象的决定,这里不应该涉及其他“计时器”或“循环”

哦,要学会不用
静态
,它会给你带来更多的问题,在这种情况下,它会解决的

而且

Timer missileBetween = new Timer();
missileBetween.cancel();
missileBetween = new Timer();
…是没有意义的,您创建一个本地
计时器,取消它,即使它实际上没有运行,创建一个新的本地实例并安排一些任务


您失去了对本地版本的引用,无法在不运行代码的情况下再修改…

timerReady=true;
if(checkTimer()){
    timer2 = new Timer();
    timer2.schedule(new Move(), 0, interval);
}
基本上意味着
checkTimer
将始终返回
true
,这意味着每次调用
update
,您都在创建另一个
Timer
,这可能会创建几十个定时器,所有定时器都会独立更新游戏状态…这将导致对象加速

这种逻辑和功能应该由主循环控制。在每个循环中,您应该检查对象的状态,并做出移动或移除对象的决定,这里不应该涉及其他“计时器”或“循环”

哦,要学会不用
静态
,它会给你带来更多的问题,在这种情况下,它会解决的

而且

Timer missileBetween = new Timer();
missileBetween.cancel();
missileBetween = new Timer();
…是没有意义的,您创建一个本地
计时器,取消它,即使它实际上没有运行,创建一个新的本地实例并安排一些任务


您失去了对本地版本的引用,无法再修改…

您在
ShooterGame.run()
方法中睡眠的时间是错误的。而不是
time=(1000/fps)-(System.currentTimeMillis()-time);
为什么不干脆
time=1000/fps


第一次在运行中输入
while
循环
time
大约为
1000/fps
,因为两个方法调用之间的时间间隔很短。以后的运行周期将给您一个负数(System.currentTimeMillis()与1000/fps相比是一个很大的数字)这意味着您将不会调用
Thread.sleep(time)
。在那里设置断点并告诉我们这是否正确。

您在
ShooterGame.run()
方法中睡眠的时间是错误的。而不是
time=(1000/fps)-(System.currentTimeMillis()-time);
为什么不干脆
time=1000/fps


第一次在运行中输入
while
循环
time
大约为
1000/fps
,因为两个方法调用之间的时间间隔很短。以后的运行周期将给您一个负数(System.currentTimeMillis()与1000/fps相比是一个很大的数字)这意味着您将不会调用
Thread.sleep(time)
。在那里设置断点并告诉我们这是否正确。

您每次发射导弹时都在计划新任务(使用新计时器),但旧任务仍在运行。
timerReady=true;
然后
if(checkTimer()){
你看起来没有可疑吗?
ShooterGame
run
方法是主循环,它应该负责更新游戏状态、绘制游戏状态和维护帧数……注意:你有
int keeper=3;if(keeper>0)y-=interval/1000;
为什么要测试3是否大于0?@gabzerbinato否。查看导弹.update。您的程序创建一个计时器,并计划移动对象(因此
Move.run
interval
毫秒调用一次)。然后,稍晚一点,您的程序再次执行相同的操作-创建一个新计时器,并计划一个移动对象(因此现在
Move.run
每隔
interval
ms调用一次,每隔
interval
ms调用另一次-您要求它发生两次,所以它发生两次)。然后,下次调用
导弹.update
时,您将再次计划它(因此现在它将每隔
时间间隔发生三次),依此类推。您正在计划一项新任务(在