从零开始Android游戏编程(第二版) 第十二章 音乐与音效

原创 2011年01月14日 17:02:00

第十二章 音乐与音效

广告说的好“没有声音再好的戏也出不来”,下面就让我们为程序加入声音效果。

一般情况下,游戏中的声音分为音乐和音效两个部分。直观上的区别,音乐播放的时间较长,资源文件较大。音效播放时间较短,资源文件比较小。在Android中,我们使用两种不同的方法播放音乐和音效。

播放音乐需要用到MediaPlayer类,MediaPlayer本身比较复杂,这里我们只做一个简单的介绍,满足播放音乐的基本要求即可,读者可以参考帮助文档中的内容深入研究。

为了调用方便,我们创建一个Util类,将播放背景音乐的方法封装到Util中

public class Util {

static MediaPlayer mp;

static void playBGM(String path, boolean looping) {

if(mp == null) {

mp = new MediaPlayer();

}

mp.reset();

try {

mp.setDataSource(path);

mp.prepare();

} catch (IllegalArgumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalStateException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

mp.setLooping(looping);

mp.start();

}

}

让我们分析一下这段代码:首先,我们需要一个MediaPlayer实例,然后重置MediaPlayer到Idle状态。注意,这个操作是必需的,如果当前正在播放,不重置状态直接调用setDataSource会抛出异常。然后指定我们要播放的文件,并调用prepare方法进行准备。如果你想指定开始时间(seekTo)必须在prepare之后进行。还可以设定是否循环,最后就是调用start播放了。

封装好后,我们可以方便的使用这个函数,我们在SceneStartMenu中重载start方法

public void start(SurfaceHolder surfaceHolder){

Util.playBGM("/sdcard/sample.mid", false);

}

这样,程序运行后就开始播放音乐了。还要注意的是,我们应该在适当的时候释放MediaPlayer占用的资源。

运行一下编辑好的代码看看效果吧。sample.mid在res/raw目录下。

下面让我来学习如何播放音效,它将使用完全不同的方法SoundPool。SoundPool虽然是基于MediaPlayer的,但是他被优化用来同时播放多个文件,而且不适合播放较大的文件,可以说,他就是为播放音效定制的。下面就让我们看一下播放音效的代码:

private static int MAX_CHANNEL = 6;

private static SoundPool soundPool;

private static HashMap soundPoolMap;

private static AudioManager audioManager;

首先设定声道数,如果同时播放的音频超过这个数量,最先播放的音频就会被关闭。然后定义SoundPool变量。大家注意soundPoolMap这个变量,下面会重点讲解。

public static void playSE(String path, float volume, int loop, float rate) {

if(soundPool == null) {

soundPool = new SoundPool(MAX_CHANNEL, AudioManager.STREAM_MUSIC, 10);

}

if(soundPoolMap == null) {

soundPoolMap = new HashMap();

}

if(!soundPoolMap.containsKey(path)) {

soundPoolMap.put(path, soundPool.load(path, 1));

}

这里我们要讲解一下soundPoolMap。在音频被播放前需要先将它载入到内存,载入后,会得到一个streamID,SoundPool中的很多函数都使用这个ID来控制特定的音频流。所以,我们将这个ID保存到map中,并与音频文件的路径相对应。后面就可以通过路径来找到这段音频流了。

if(volume < 0) {

if(audioManager == null)

audioManager = (AudioManager)Main.getInstance()

.getSystemService(Context.AUDIO_SERVICE);

volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

}

while(soundPool.play(soundPoolMap.get(path),

volume, volume, 0, loop, rate) == 0);

}

这个方法并不是很科学,最好还是在初始化的时候载入音频,大家可以另行撰写一个load方法。

public void playSE(String path) {

playSE(path, -1f, 0, 1f);

}

public void stopSE(String path) {

if(soundPool != null && soundPoolMap != null

&& soundPoolMap.containsKey(path)) {

soundPool.stop(soundPoolMap.get(path));

}

}

修改SceneStartMenu中的start函数测试一下吧

public void start(SurfaceHolder surfaceHolder){

// Util.playBGM("/sdcard/sample.mid", false);

Util.playSE("/sdcard/system11.ogg");

Util.playSE("/sdcard/system12.ogg");

}

现在,这部教程终于可以告一段落了,虽然有点虎头蛇尾,但我大概已经讲解了制作一个简单游戏所用到的各方面的知识。如果还有不足,请读者留言补充,大家互相学习,一起提高。最终我在教程中没有完成坦克大战,不过我会基于坦克大战设计一个新的游戏,不再使用Java,而是一个全新的跨平台框架,到时候再与大家分享我的心得。

本章示例程序http://u.115.com/file/f1435ee7e8
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【读书笔记《Android游戏编程之从零开始》】19.游戏开发基础(游戏音乐与音效)

在一款游戏中,除了华丽的界面 UI 直接吸引玩家外,另外重要的就是游戏的背景音乐与音效;合适的背景音乐以及精彩的音效搭配会令整个游戏上升一个档次。 在 Android 中。常用于播放游戏背景音乐的类...

从零开始Android游戏编程(第二版)

没想到重新打开这篇文档已经是一年之后了。去年三月,我停止了这一系列文章的写作。六月,离开了工作了五年的公司。作为公司的创始人和业务主管,我不能容忍它发展的如此缓慢,而合伙人却很享受这种慢节奏的生活。九...
  • yexing
  • yexing
  • 2011-01-14 17:20
  • 7193

从零开始Android游戏编程(第二版) 前言

前言 没想到重新打开这篇文档已经是一年之后了。 去年三月,我停止了这一系列文章的写作。六月,离开了工作了五年的公司。作为公司的创始人和业务主管,我不能容忍它发展的如此缓慢,而合伙人却很享受这种慢节...
  • yexing
  • yexing
  • 2011-01-14 16:07
  • 2307

从零开始Android游戏编程(第二版) 第十一章 演员(Actor)、视口(ViewWindow),演出开始

第十一章 演员(Actor)、视口(ViewWindow),演出开始 本章内容与第七章、第八章关系非常密切,如果对这两章的内容不熟悉请大家先浏览一下七、八章,再回来看本章。 Actor是一个接口,...
  • yexing
  • yexing
  • 2011-01-14 16:47
  • 3982

从零开始Android游戏编程(第二版) 第八章 地图的设计和实现

第八章 地图的设计和实现 这本来是第十章,前面计划还有两章的内容,一是跟第四章一样,完成一个Asteroid游戏作为小结,总结一下前面讲过的Sprite的用法,并演示NPC和子弹的处理方法。但是,在...
  • yexing
  • yexing
  • 2011-01-14 16:29
  • 6055

从零开始Android游戏编程(第二版) 第七章 精灵、帧动画与碰撞检测

第七章 精灵、帧动画与碰撞检测 经过前几章的学习,大家对使用位图、接受用户控制应该已经有了初步的概念,也可以运用这些知识完成简单的小游戏。这一章中,我们会为游戏中最重要的部分——图形处理建立一个基本...
  • yexing
  • yexing
  • 2011-01-14 16:26
  • 9874

从零开始Android游戏编程(第二版) 第六章 SurfaceView动画

第六章 SurfaceView动画 难度:中等 前面介绍的内容,还是比较简单的,应用这些知识,可以完成一些非实时游戏,比如井字棋等,或者一些画面刷新不是很频繁、实时性不强的游戏,比如我们前面做的扫...
  • yexing
  • yexing
  • 2011-01-14 16:22
  • 8238

从零开始Android游戏编程(第二版) 第二章 创建第一个程序Hello Tank

第二章 创建第一个程序Hello Tank 难度:容易 现在开始,我们要真正写作Android程序了。虽然前面安装过程那么复杂,但是写起程序来却是非常简单。而且为了让大家有一个直观的认识,本文不会...
  • yexing
  • yexing
  • 2011-01-14 16:11
  • 7025

从零开始Android游戏编程(第二版) 第四章 响应用户事件

第四章 响应用户事件 上一章介绍了如何显示文字和图片,一般来说,下一步就该讲到动画了。可是我们前面说了,使用View不是最终的选择,要实现动画还需要很多复杂的代码。相对来说,学习如何响应用户事件要简...
  • yexing
  • yexing
  • 2011-01-14 16:14
  • 6673

从零开始Android游戏编程(第二版) 第九章 游戏程序的生命周期

第九章 游戏程序的生命周期 在讲解游戏程序的生命周期之前,让我们先看看普通Android应用的生命周期。关于生命周期,SDK附带的文档上有详细的解释,让我们打开文档,找到andorid.app->A...
  • yexing
  • yexing
  • 2011-01-14 16:30
  • 5238
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)