1

在我正在设计的棋盘游戏中,每个用户都有一个包含 100 个单元格的网格。用户单击计算机网格中的一个单元格,该单元格会发出声音并变为不同的颜色。然后计算机会自动单击用户网格中的一个单元格,该单元格会发出声音并更改为不同的颜色。

用户的点击是通过 MouseListener(和 MouseClicked 方法)处理的。目前,该方法所做的最后一件事是调用 computerMove() 方法。此方法在将当前玩家变回人类之前执行并执行计算机移动。当人类再次点击鼠标时,游戏继续进行。

理想情况下,我希望在每个玩家移动之间暂停(也许一秒钟)。但是,由于在 MouseClicked 方法中调用了 computerMove 方法,因此这很麻烦。通过使用 Thread.sleep 甚至 TimerTask,我能做的最好的事情就是减慢人类玩家的移动速度。但是,只要玩家点击鼠标,计算机就会立即做出响应。

有人对我如何实施延迟有任何建议吗?我是否需要更改调用方法的方式?

计算机移动方法:

    public void computerMove() {
    if (currentTurn == computer) {
        int xPos = randomGenerator.nextInt(10);
        int yPos = randomGenerator.nextInt(10);
        LogicCell attackedCell = new LogicCell(xPos, yPos);
        playerGridLogic.addCellsThatHaveBeenAttacked(attackedCell);

        if (playerGridLogic.getCellsWithShips().contains(attackedCell)) {
            playerGrid.getCellArray()[xPos][yPos].setBackground(Color.ORANGE);
            hitSound();
        }
        else {
            playerGrid.getCellArray()[xPos][yPos].setBackground(Color.MAGENTA);
            missSound();
        }
        nextTurn();
    }
}

对应的 MouseClick 方法:

        @Override
    public void mouseClicked(MouseEvent e) {
        if (allComputerShipsPlaced && currentTurn == human) {
            ViewCell currentCell = (ViewCell) e.getSource();
            xPos = currentCell.getXPos();
            yPos = currentCell.getYPos();
            LogicCell attackedCell = new LogicCell(xPos, yPos);
            computerGridLogic.addCellsThatHaveBeenAttacked(attackedCell);

            if (computerGridLogic.getCellsWithShips().contains(attackedCell)) {
                cellArray[xPos][yPos].setBackground(Color.ORANGE);
                hitSound();
            }
            else {
                cellArray[xPos][yPos].setBackground(Color.MAGENTA);
                missSound();
            }
            nextTurn();
            computerMove();
        }
    }

missSound 方法()(hitSound 非常相似):

    public static void missSound() {
    try {
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
        clip.start();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}

编辑:我尝试将声音类更改为此,但无济于事:

    public static void hitSound()
{
    try
    {
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File("bomb-explosion.wav")));
        clip.start();

        LineListener listener = new LineListener() {
            public void update(LineEvent event) {
                if (event.getType() != Type.STOP) {
                    return;
                }
                try {
                    queue.take();
                } catch (InterruptedException e) {
                    //ignore this
                }
            }
        };
        clip.addLineListener(listener);
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}
4

3 回答 3

1

您应该能够添加一个监听器并对声音的结尾做出反应。看到这个问题:如何等待 java 声音剪辑完成播放?

这对我有用:

public class Test {
    public static void main(String[] args) {
        final Object foo = new Object();
        Clip clip;
        try {
            clip = AudioSystem.getClip();
            clip.open(AudioSystem.getAudioInputStream(new File("go.wav")));
            clip.addLineListener(new LineListener() {
                public void update(LineEvent event) {
                    if(event.getType() == LineEvent.Type.STOP){
                        System.out.println("done playing");
                        synchronized(foo) {
                            foo.notify();
                        }

                    }
                }
            });
            clip.start();
        } catch (Exception e) {
            e.printStackTrace();
        }

        synchronized(foo) {
            try {
                foo.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2013-04-30T22:24:43.470 回答
0

我会考虑在里面打电话,computerMove在里面nextTurn做等待nextTurn

于 2013-04-30T22:16:03.047 回答
0

您可以使用Thread.sleepcomputerMove()暂停执行。您可以使用clip.getMicrosecondsLength来获取音效的长度(以微秒为单位)。将其乘以 1000 并将其传递给 sleep 以等待音效完成。

Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
clip.start();
int lengthInMilliseconds = clip.getMicrosecondLength() * 1000;
Thread.sleep(lengthInMilliseconds);
于 2013-04-30T22:16:12.677 回答