如何在动作之间延迟棋盘游戏以便播放声音
在设计的棋盘游戏中,每个用户都有一个有100个单元的网格。用户单击计算机网格中的一个单元格,它会发出声音并更改为不同的颜色。计算机然后自动点击用户网格中的一个单元格,这会发出声音并更改为不同的颜色。如何在动作之间延迟棋盘游戏以便播放声音
用户的点击通过MouseListener(和MouseClicked方法)处理。目前,该方法所做的最后一件事就是调用computerMove()方法。此方法在将当前播放器改回人类之前执行并执行计算机移动。当人类再次点击鼠标时,游戏继续进行。
理想情况下,我希望每个玩家移动之间有一段暂停(也许是一秒)。但是,由于computerMove方法在MouseClicked方法内被调用,所以这很麻烦。通过使用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();
}
}
鼠标点击相应的方法:
@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方法()(撞击声很相似):
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);
}
}
您应该可以添加一个侦听器并对声音的结尾作出反应。 看到这个问题: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();
}
}
}
}
我会考虑在nextTurn
里面调用computerMove
,并在nextTurn
里面等待。
不幸的是,如果我这样做,当我点击一个正方形时声音正常播放,然后稍微延迟,然后正方形改变颜色,并且计算机正方形立即改变颜色和他的声音播放。延迟是在错误的地方。我需要它来后,我点击的广场已经改变颜色 – 2013-04-30 22:19:33
您可以使用Thread.sleep中的computerMove()
来暂停执行。您可以使用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);
这实际上只是冻结了我的JFrame。它一次播放第一个声音,并冻结整个电路板。不知道为什么。 – 2013-04-30 22:27:41
不可能将其实现输入处理和图形重画,例如一个视频游戏模式更有意义每1/60秒醒来,处理输入,更新游戏状态/ mdoels,重画屏幕,然后等到下一个1/60秒? – Patashu 2013-04-30 22:47:58
可能 - 这只是我不知道该怎么做! – 2013-04-30 22:53:12
在C#中你会使用XNA,我不确定是否有Java的等价物,但它绝对值得使用谷歌搜索,因为我100%肯定人们已经想到了这个难点:) – Patashu 2013-04-30 22:57:36