剑孤寒的小站

人生的价值不是用时间,而是用深度去衡量的!
posts - 75, comments - 290, trackbacks - 0, articles - 0

    在一个优秀的游戏中,音乐和音效往往能起到画龙点睛的作用,这一节我们就来学习如何在GGE中播放音乐和音效。
    GGE自带了音频解码播放功能,不需要使用base或fmod等音效库。在GGE中提供了一个Sound_Load()函数用于载入音乐和音效,支持wav和ogg格式的音频文件,如果载入成功则返回一个ggeSound指针,例如:

   m_sound = Sound_Load("Fire1.ogg"); //载入音效
    m_music = Sound_Load("eyes on me.ogg"true); //载入音乐

    要载入音效只需简单的调用Sound_Load()函数,并传入音效文件名即可,如果是载入音乐的话,一般需要将音乐转换成ogg格式,并且将Sound_Load()函数的第二个参数传入true,表示以流方式载入。需要注意的是,以流方式载入的ogg文件比较节省内存(wav格式无效),但无法同一时间播放多次,例如碰到同时响起两声枪响这种情况,如果以流方式载入,调用两次播放函数实际上只能听到一声枪响,所以音效一般不使用流方式载入。
    音乐和音效载入后都可以调用ggeSound::Play()函数来播放,播放时可以动态修改音量、频率、声道平衡,也可以暂停和恢复播放。例如在OnUpdate(float dt)函数中添加如下代码对音乐和音效进行控制:

 switch (Input_GetKey())
        
{
        
case 'Q':
            m_music
->Play(true); //音乐循环播放
            break;

        
case 'W':
            m_music
->Stop();
            
break;

        
case 'A':
            m_music
->Pause();
            
break;

        
case 'S':
            m_music
->Resume();
            
break;

        
case 'Z':
            
if (m_musicVolume > 0) m_musicVolume--;
            m_music
->SetVolume(m_musicVolume);
            
break;

        
case 'X':
            
if (m_musicVolume < 100) m_musicVolume++;
            m_music
->SetVolume(m_musicVolume);
            
break;

        
case 'E':
            
if (m_soundVolume > 0) m_soundVolume--;
            m_sound
->SetVolume(m_soundVolume);
            
break;

        
case 'R':
            
if (m_soundVolume < 100) m_soundVolume++;
            m_sound
->SetVolume(m_soundVolume);
            
break;

        
case 'D':
            
if (m_soundPan > -100) m_soundPan--;
            m_sound
->SetPan(m_soundPan);
            
break;

        
case 'F':
            
if (m_soundPan < 100) m_soundPan++;
            m_sound
->SetPan(m_soundPan);
            
break;

        
case 'C':
            m_soundpPitch 
-= dt * 0.5f;
            
if (m_soundpPitch < 0) m_soundpPitch = 0;
            m_sound
->SetPitch(m_soundpPitch);
            
break;

        
case 'V':
            m_soundpPitch 
+= dt  * 0.5f;
            
if (m_soundpPitch > 10.0f) m_soundpPitch = 10.0f;
            m_sound
->SetPitch(m_soundpPitch);
            
break;

        
case VK_SPACE:
            m_sound
->Play();
            
break;
        }

    因为音乐是以流方式载入的,每次按下Q键会让音乐重新开始播放,音效不是以流方式载入的,所以每次按下空格键即使之前的音效没播放完也能听到新的声音。
    在GGE中还提供了一个ggeMusic模块,这个是专门用来播放midi音乐的,不过这个现在用得比较少,就不详细介绍了,大致使用方法跟ggeSound一样,如果有需要可以查看文档。


Feedback

# re: Galaxy2D游戏引擎教程6 - 音乐和音效[未登录]  回复  更多评论   

2010-04-23 17:01 by 小白
期待博主什么时候来个小型完整的RPG游戏教材就好了,方便下我们这些个新手

# re: Galaxy2D游戏引擎教程6 - 音乐和音效  回复  更多评论   

2010-04-24 18:07 by 剑孤寒
嗯,如果有时间的话会弄一个综合性的小游戏来做教材,真希望一天能有48小时,可以每天有点时间做自己的东西啊-_-

# re: Galaxy2D游戏引擎教程6 - 音乐和音效[未登录]  回复  更多评论   

2010-04-25 12:41 by 断杆破枪头
3.1
ggeFont 里的print函数是不是有问题啊?

我在代码里面
初始坐标是300,200
移动增量是1.5
m_RolePosFon->print(680,30,"角色坐标: %d,%d",m_RolePos.x,m_RolePos.y);
坐标显示有问题 还是我用的有问题呢

# re: Galaxy2D游戏引擎教程6 - 音乐和音效[未登录]  回复  更多评论   

2010-04-25 15:03 by 断杆破枪头
截图的函数是不是也有问题啊

老是默认生成一个这个文件 snapshot.png

我代码是这样的
PATH_GAME_SCRNSHOT 宏定义为"ScrnShot\\"目录下面

if (Input_IsKeyDown(GGEK_F12))
{
char fnstr[200];
static SYSTEMTIME t;
GetSystemTime(&t);
sprintf(fnstr,"%sSword%d%d%d_%d.jpg",PATH_GAME_SCRNSHOT,
t.wYear,t.wMonth,t.wDay,
GetTickCount());
Graph_Snapshot(fnstr,IMAGE_JPG);
}

# re: Galaxy2D游戏引擎教程6 - 音乐和音效  回复  更多评论   

2010-04-26 09:17 by 剑孤寒
@断杆破枪头
1.请确定m_RolePos.x和m_RolePos.y是否是浮点数,如果是,应该这样调用:m_RolePosFon->print(680,30,"角色坐标: %f,%f",m_RolePos.x,m_RolePos.y);
2.可能是因为跟默认的截图快捷键冲突了,你可以试着换一个按键作为截图键看看是否有效,下个版本加一个默认截图按键开关好了

# re: Galaxy2D游戏引擎教程6 - 音乐和音效[未登录]  回复  更多评论   

2010-04-26 16:22 by 断杆破枪头
第二个问题解决了,第一个问题加类型转换就好了(int)

# re: Galaxy2D游戏引擎教程6 - 音乐和音效[未登录]  回复  更多评论   

2010-04-26 19:09 by 断杆破枪头
大场景卷动 怎么做啊 ?
就是你那个演示里面 地图的移动

# re: Galaxy2D游戏引擎教程6 - 音乐和音效  回复  更多评论   

2010-04-27 11:47 by 剑孤寒
这个可以用ggeImage来实现,
先用ggeImage载入地图:
ggeImage *MapImage = Image_Load("map.jpg");
可以载入任意大小的图片,
不受显卡最大纹理尺寸的限制,
(因为像《轩辕剑3》等游戏有些地图尺寸是非常大的,
如果超过了显卡的最大纹理尺寸地图就显示不出来了,
用ggeImage就不用担心这个问题了)

然后再用下面的代码把地图画出来:
MapImage->SetRect((int)sceneX, (int)sceneY, (int)sceneX + ScreenWidth, (int)sceneY + ScreenHeight);
MapImage->Render(0, 0);

调用ggeImage::SetRect()函数设置要显示的地图区域,
ScreenWidth和ScreenHeight表示屏幕尺寸,
如果你的屏幕大小为640x480,
则ScreenWidth=640,ScreenHeight = 480,
sceneX和sceneY为地图显示区域左上角坐标,
假设主角的实际坐标为(400, 400),
为了让主角在屏幕中间即主角的坐标屏幕坐标为(320, 240),
所以要将地图往左上角移动,
即sceneX = 400 - 320; sceneY = 400 - 240;
最后调用ggeImage::Render()将地图画出来就可以了

# re: Galaxy2D游戏引擎教程6 - 音乐和音效[未登录]  回复  更多评论   

2015-10-03 13:39 by shepherd
正在写一个语音播放类,发现老是出错,就做了个简单的演示程序。
具体问题是:加载同一个声音资源后,不叠加,一次一次的播放没问题,但是叠加播放就出错。大神帮忙看一下呗。
#include <stdlib.h>
#include "inc/ggebase.h"
#include "inc/ggesound.h"

using namespace gge;

ggeSound *st;
gUInt changing_color = 0xFFFFFFFF;

//帧函数
bool Frame()
{
//开始渲染
if (Graph_BeginScene())
{
//清屏
Graph_Clear();

if(Input_GetKey() == VK_SPACE)
{
changing_color = 0xFF000000 + (gUInt)(rand() * 0xFFFFFF);
st->PlayEx();
}
Graph_RenderQuad(100.0f, 120.0f, 140.0f, 160.0f, changing_color);

//结束渲染
Graph_EndScene();
}
return false;
}

int main(HINSTANCE, HINSTANCE, LPSTR, int)
{
//创建游戏引擎
if (!Engine_Create(GGE_VERSION)) return 0;

System_SetState(GGE_TITLE, "Galaxy2D Game Engine - Initiate");
//设置帧函数
System_SetState(GGE_FRAMEFUNC, Frame);
//设置帧率
System_SetState(GGE_FPS, 60);
System_SetState(GGE_USESOUND, true); //是否开启声音:是


//系统初始化
if (System_Initiate())
{
st = Sound_Load("d://1.wav", false);
//开始运行帧函数
System_Start();
}

//关闭引擎,释放资源
Engine_Release();
return 0;
}

# re: Galaxy2D游戏引擎教程6 - 音乐和音效  回复  更多评论   

2015-10-04 19:01 by 剑孤寒
@shepherd
已经修复了,请下载最新版引擎,感谢反馈

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理