2

我有一个关于如何在程序的整个生命周期中更改单个计时器的间隔的问题:

全局变量 Timer 和 interval 在运行时初始设置:

    interval = 800;
    timer();

Board 的 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;
}

棋盘类:每次移动棋子时都会调用 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;      
    }
}

Piece 类:一旦向上箭头被击中,board.timer2(1);将设置全局变量...这应该加快计时器仅适用于当前下落的部分...如果您在下面看到,一旦发生碰撞并被interval调用,将会调用以重置间隔...1createNewPiece()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

一般来说,在游戏中使用多个计时器或更改计时器间隔往往会导致各种混乱(至少在单个渲染/事件区域内)。

你应该做的是给游戏一个永远不会改变的“心跳”计时器,然后根据它们的状态改变移动棋子的移动量(例如,一个定期下落的棋子每次心跳会移动 2 个像素,而一个迅速下降的人会移动 4)。

诚然,这会导致紧张的运动,但这只是意味着您应该相应地调整您的心跳和运动速率,直到它看起来像您想要的那样。

编辑:否则,将所有移动内容从键中删除(这应该发生在计时器的滴答声中),并确保您实际上正在取消并重新创建具有所需新间隔的 TimerTask。

于 2013-05-17T19:02:37.327 回答