簡體   English   中英

Java中的計時器加速

[英]Timer speeding up in Java

我知道還有其他問題,但是似乎沒有一個問題可以幫助我解決問題。 在我的游戲中,有一個射擊導彈的玩家,向負y飛行,直到其消失在屏幕外,然后回到其原始位置並等待再次射擊。 但是,每次發射導彈時,它都會變得更快,就像Timer()中的延遲變得更短一樣。 編碼:

主班:

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

導彈艙:

public class Missile{

    public BufferedImage sprite;
    public static int x;
    public static int y=504;
    private int interval = 2000;
    private Timer timer2;
    private boolean isAlive = game.player.Player.missileRunning;
    static final AtomicInteger count = new AtomicInteger();
    public static boolean timerReady;

    public Missile(int x){

        this.x=x;
        this.y=504;
        this.sprite=sprite;

        try{
            URL url = this.getClass().getResource("missile.png");
            sprite = ImageIO.read(url);
        } catch(IOException e){System.out.println("Error loading image");}  
    }

    public void Draw(Graphics g){
        g.drawImage(sprite,x,this.y,6,18,null);
    }

    public void update(Graphics g){ //The problem
        if(game.player.Player.missileRunning==true){
            timerReady=true;
            if(checkTimer()){
                timer2 = new Timer();
                timer2.schedule(new Move(), 0, interval);
            }
            this.y = y;
            if(y <= 0){
                game.player.Player.missileRunning=false;
                timerReady=false;
                y=504;
                if(!checkTimer()){
                    timer2.cancel(); 
                    timer2.purge();
                }
                timer2=null;
                reload();
            }
        }
    }

    public boolean checkTimer(){
        if(timerReady){
            return true;
        } else {
            return false;
        }
    }

    class Move extends TimerTask{
        public void run(){
            int keeper = 3;
            if(keeper>0) y-=interval/1000;
        }
    }

    public synchronized void reload(){
        Timer missileBetween = new Timer();

        missileBetween.cancel();
        missileBetween = new Timer();

        TimerTask readyMissile = new TimerTask(){
            public void run(){
                game.player.Player.missileReady=true;
            }
        };

        missileBetween.schedule(readyMissile, 20);
    }

    public static int getNumber(){
        return count.get();
    }

    public static AtomicInteger getAtomic(){
        return count;
    }

}

(我並沒有發布我的所有程序,只是發布了與問題相關的部分) (如果缺少任何內容,請說出它)

謝謝

沒有運行代碼...

timerReady=true;
if(checkTimer()){
    timer2 = new Timer();
    timer2.schedule(new Move(), 0, interval);
}

基本上意味着checkTimer總是會返回true ,這意味着每次調用update ,您都在創建一個ANOTHER Timer ,這可能會創建幾十個計時器,所有這些計時器都是獨立更新的……這將導致對象加速...

這種邏輯和功能應由主循環控制。 在每個周期中,您應該檢查對象的狀態並做出移動或刪除對象的決定,此處不應涉及其他“計時器”或“循環”。

哦,要學會在沒有static情況下做,這會給您帶來更多的問題,然后在這種情況下會解決。

和...

Timer missileBetween = new Timer();
missileBetween.cancel();
missileBetween = new Timer();

...毫無意義,您可以創建一個本地Timer ,然后取消它,即使它實際上並沒有運行,創建一個新的本地實例並安排一些任務...

您丟失了對本地版本的引用,無法再對其進行修改...

您在ShooterGame.run()方法中睡眠的時間是錯誤的。 而不是time = (1000 / fps) - (System.currentTimeMillis() - time); 為什么不簡單地將time = 1000/fps

首次進入運行time循環的while time約為1000/fps因為兩次方法調用之間的時間很少。 未來的運行周期將為您提供一個負數(System.currentTimeMillis()與1000 / fps相比是一個很大的數字),這意味着您將不會調用Thread.sleep(time) 在此處設置一個斷點,然后告訴我們這是否正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM