2

プログラムの存続期間中に単一のタイマーの間隔を変更する方法について質問があります。

グローバル変数 実行時に最初に設定されるタイマーと間隔:

    interval = 800;
    timer();

ボードのタイマー クラス:

public void timer() {
    int delay = 1000;

    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            if (pause && gameWon){
                message = "You've won!";
            }
            else if (pause) {               
                seconds++;
            }
            else {
                seconds = 0;
                newPiece.autoMove();
            }
        }
    }, delay, interval);    
}

ボード クラス: タイマーの交換間隔:

public void timer2(int val) {
    interval = val;
}

Board クラス: Check Bottom Full は、ピースが移動するたびに呼び出されます。その中でchangeLevel()、スコアがインクリメントされた後に呼び出され、スコアに基づいてレベルをインクリメントする必要があるかどうかを確認します。

//loop through all rows starting at bottom (12 rows)
public void checkBottomFull() {
    int lines = 0;
    for(int row = totalRows-1; row > 0; row--) {
        while (isFull(row)) {       
            lines++;
            clearRow(row);   
        }
    }
    totalScore += tallyScore(lines);    
    //check if level needs to be changed based on current score...
    changeLevel();
    //reset lines after score has been incremented
    lines=0;
}

Board クラス:ChangeLevel()レベルをインクリメントし、スコアをリセットし、すべての行をクリアします...ステートメントがレベルに基づいてタイマーswitchのグローバル変数を変更することがわかります。interval

public void changeLevel () {
    int max = (level+1)*changeLevelMultiplier;
    if (totalScore >= max) {
        level++;
        totalScore = 0;
        for(int row = 0; row < grid.length; row++) {
            for(int col = 0; col < grid[row].length; col++) {
                grid[row][col] = null;              
            }       
        }
        //timer(0);
    }
    if (level == finalLevel) {
        pause = true;
        gameWon = true;
        System.out.println("YOU HAVE WON");         
    }
    switch (level) {
    //each level increases drop speed by .10 seconds
        case 1: interval = 700;
                break;
        case 2: interval = 600;
                break;
        case 3: interval = 500;
                break;
        case 4: interval = 400;
                break;
        case 5: interval = 300;
                break;              
        default: interval = 800;
                break;      
    }
}

ピースクラス: 上矢印がヒットboard.timer2(1);されると、グローバル変数interval1... に設定されます。これにより、タイマーが高速化されます。現在落下しているピースに対してのみ... 以下のように、衝突が発生しcreateNewPiece()て呼び出されるとtimer2(800);、間隔をリセットするために呼び出されます...

        //hard drop
        if (keycode == KeyEvent.VK_UP) {
            board.timer2(1);
            for (int i = 0; i < tile.length; i++) {
                calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);                               
            }       
            clearCurrPosition();
            for (int i = 0; i < tile.length; i++) {
                board.checkEndGame(tile[i].getRow(), tile[i].getCol());
            }

            board.checkBottomFull();
            if (isCollision()) board.createNewPiece();
            move(); 
        }

ボード クラス:下部に衝突が発生すると呼び出されます...これは、グローバル変数をにリセットするためcreateNewPiece()にも呼び出されます。timer2(800);interval800

public void createNewPiece() {
    //current playable piece becomes what the nextPiece was
    currPiece = nextPiece;
    newPiece = new Piece(this, nextPiece, getColor(), false);

    //generate next piece
    nextPiece = randomPiece();
    timer2(800);    
}

問題は、intervalグローバル変数が変更されると、間隔がリセットされないように見えることです。プログラムの存続期間中、現在のタイマーの速度を変更するにはどうすればよいですか?

ありがとう

4

1 に答える 1

2

一般的に言えば、ゲームで複数のタイマーを使用したり、タイマー間隔を変更したりすると、あらゆる種類の混乱が生じる傾向があります (少なくとも 1 つのレンダリング/イベント領域内で)。

あなたがしなければならないことは、決して変化しない単一の「ハートビート」タイマーをゲームに与え、次にそのステータスに基づいて移動するピースの移動量を変更することです (たとえば、定期的に落ちるピースはハートビートごとに 2 ピクセル移動しますが、急速に落下するものは移動します 4)。

確かに、これはぎくしゃくした動きにつながる可能性がありますが、それは、希望どおりに見えるまで、それに応じて心拍数と動きの速度を調整する必要があることを意味します.

編集:それ以外の場合は、キーアップからすべての動きを取り除き(タイマーのティックで発生するはずです)、実際にキャンセルして、希望する新しい間隔で TimerTask を再作成していることを確認してください。

于 2013-05-17T19:02:37.327 に答える