在我正在设计的棋盘游戏中,每个用户都有一个包含100个单元格的网格。用户单击计算机网格中的单元格,该单元格发出声音并更改为不同的颜色。然后,计算机会自动单击用户网格中的单元格,该单元格会发出声音并更改为不同的颜色。
用户的点击通过MouseListener(和MouseClicked方法)处理。目前,该方法所做的最后一件事是调用computerMove()方法。该方法在将当前播放器更改回人之前执行并执行计算机移动。当人类再次点击鼠标时,游戏就会继续进行。
理想情况下,我想在每个玩家之间进行暂停(可能是一秒钟)。但是,由于在MouseClicked方法中调用了computerMove方法,因此这很麻烦。通过使用Thread.sleep甚至是TimerTask,我能做的最好的事情就是减慢人类玩家的向下移动速度。但是,只要玩家点击鼠标,计算机就会立即响应。
有人对我如何实施延迟有任何建议吗?我是否需要更改调用方法的方式?
ComputerMove方法:
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);
}
}
答案 0 :(得分:1)
您应该能够添加一个侦听器并对声音的结尾作出反应。 请参阅此问题:how can I wait for a java sound clip to finish playing back?
这对我有用:
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();
}
}
}
}
答案 1 :(得分:0)
我会考虑在computerMove
内拨打nextTurn
,并在nextTurn
内进行等待。
答案 2 :(得分:0)
您可以使用computerMove()
中的Thread.sleep暂停执行。您可以使用clip.getMicrosecondsLength以微秒为单位获取声音效果的长度。将它与1000相乘并将其传递给睡眠以等待声音效果完成。
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
clip.start();
int lengthInMilliseconds = clip.getMicrosecondLength() * 1000;
Thread.sleep(lengthInMilliseconds);