如何在动作之间延迟棋盘游戏以便播放声音

问题描述:

在设计的棋盘游戏中,每个用户都有一个有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); 
    } 
} 
+0

不可能将其实现输入处理和图形重画,例如一个视频游戏模式更有意义每1/60秒醒来,处理输入,更新游戏状态/ mdoels,重画屏幕,然后等到下一个1/60秒? – Patashu 2013-04-30 22:47:58

+0

可能 - 这只是我不知道该怎么做! – 2013-04-30 22:53:12

+0

在C#中你会使用XNA,我不确定是否有Java的等价物,但它绝对值得使用谷歌搜索,因为我100%肯定人们已经想到了这个难点:) – Patashu 2013-04-30 22:57:36

您应该可以添加一个侦听器并对声音的结尾作出反应。 看到这个问题: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(); 
      } 
     } 
    } 
} 
+0

我试过实现这个(在上面的OP中发布的结果),但我仍然没有得到适当的延迟。 – 2013-04-30 22:34:30

+0

我添加了一个代码示例。 – Sarien 2013-04-30 22:43:19

+0

我已经添加了另一个同步主线程的例子。这应该使事情变得更简单。在你的尝试中,你为什么调用queue.take()而不是nextturn()? – Sarien 2013-04-30 22:58:17

我会考虑在nextTurn里面调用computerMove,并在nextTurn里面等待。

+0

不幸的是,如果我这样做,当我点击一个正方形时声音正常播放,然后稍微延迟,然后正方形改变颜色,并且计算机正方形立即改变颜色和他的声音播放。延迟是在错误的地方。我需要它来后,我点击的广场已经改变颜色 – 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); 
+0

这实际上只是冻结了我的JFrame。它一次播放第一个声音,并冻结整个电路板。不知道为什么。 – 2013-04-30 22:27:41