cocos2dx学习之路(九)——声音引擎

了解Cocos2d-x中的声音引擎
掌握SimpleAudioEngine类
掌握音效的控制
Cocos2d-x中的事件分发机制
了解监听器
了解优先级
掌握触摸事件及其应用
其他事件
Cocos2d-x提供了一个SimpleAudioEngine类支持游戏内的音乐和音效。
它可以被用来增加背景音乐,控制游戏音效。
SimpleAudioEngine类
SimpleAudioEngine单例对象

auto audioEngine = SimpleAudioEngine->getInstance();

播放背景音乐和音效
背景音乐和音效都是异步播放的,
声音引擎做了单独的处理,因此需要分别播放

//背景音乐true表示循环播放,false表示播放一次
audioEngine->playBackgroundMusic("音乐文件Resources的相对路径",true);
//音效
audioEngine->playEffect("音乐文件Resources的相对路径",false,1.0f,1.0f,1.0f);

SimpleAudioEngine支持的音频格式
支持的音乐格式

平台 音乐文件格式 备注
Android mp3,mid,ogg,wav 可以播放android、media、MediaPlayer所支持的所有格式
iOS aac,caf,map3,m4a 可以播放android、media、MediaPlayer所支持的所有格式
Android mp3,mid,wav mp3官方文档说支持的是AudioEngine在SimpleAudioEngine引擎底层做了一系列的封装,但是实际cocos2d中SimpleAudioEngine不支持的

支持的音效格式

平台 音效文件格式 备注
Android ogg,wav 对wav的支持不完美
iOS caf,m4a 可以播放Cocos2d-iphone CocosDesion所支持的所有格式
Android mid,wav

声音的控制
注意:
1、暂停与恢复相对应,指的是播放中的音频文件暂时停止,
可以通过恢复的方式从暂停位置继续播放。
2、处于暂停中的声音可以直接被停止,停止后不可以恢复播放,只能
只能重新开始播放。

#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
auto audio = SimpleAudioEngine::getInstance();
//暂停背景音乐
audio->pauseBackgroundMusic();
//暂停音效
audio->pauseEffect();
//暂停所有音效
audio->pauseAllEffects();
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
auto audio = SimpleAudioEngine::getInstance();
//停止背景音乐
audio->stopBackgroundMusic();
//停止音效
audio->stopEffect();
//停止所有音效
audio->stopAllEffects();

恢复与暂停相对应,指的是从暂停位置继续播放音频文件。

#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
auto audio = SimpleAudioEngine::getInstance();
//恢复背景音乐
audio->resumeBackgroundMusic();
//恢复音效
audio->resumeEffect();
//恢复所有音效
audio->resumeAllEffects();

实现背景音乐的控制,要求:
点击按钮播放背景音乐
点击按钮暂停播放背景音乐
点击按钮恢复播放背景音乐
点击按钮停止播放背景音乐

MusicDemo.h

#pragma once
#include "cocos2d.h"
class MusicScene:public Scene
{
public:
	CREATE_FUNC(MusicScene);
	virtual bool init();
};

MusicDemo.cpp
#include "ui/CocosGUI.h"包含的头文件

#include "ui/UIWidget.h"
#include "ui/UILayout.h"
#include "ui/UIButton.h"
#include "ui/UICheckBox.h"
#include "ui/UIRadioButton.h"
#include "ui/UIImageView.h"
#include "ui/UIText.h"
#include "ui/UITextAtlas.h"
#include "ui/UILoadingBar.h"
#include "ui/UIScrollView.h"
#include "ui/UIListView.h"
#include "ui/UISlider.h"
#include "ui/UITextField.h"
#include "ui/UITextBMFont.h"
#include "ui/UIPageView.h"
#include "ui/UIHelper.h"
#include "ui/UIRichText.h"
#include "ui/UIHBox.h"
#include "ui/UIVBox.h"
#include "ui/UIRelativeBox.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "ui/UIVideoPlayer.h"
#include "ui/UIWebView/UIWebView.h"
#endif

#include "ui/GUIExport.h"
#include "ui/UIScale9Sprite.h"
#include "ui/UIEditBox/UIEditBox.h"
#include "ui/UILayoutComponent.h"
#include "ui/UITabControl.h"
#include "editor-support/cocostudio/CocosStudioExtension.h"
#include "MusicDemo.h"
#include "ui/CocosGUI.h"
using namespace ui;
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
//CocosGUI包含了UIButton、UIImage、Textture
bool MusicScene::init()
{
	if(!Scene::init())return false;

	//播放按钮
	Size visibleSize = Director::getInstance()->getVisibleSize();
	//布局的基准点
	Vec2 base = Vec2(visibleSize / 2);
	
	//播放按钮
	Button* _button = Button::create();
	_button ->setTitleText("Play");
	_button ->setTitleFontSize(36);
	_button ->setPositionX(base.x);
	_button ->setPositionY(base.y + _button->getContentSize().height * 1.5 + 15);
	_button->addClickEventListener([](Ref* sender)
	{
		//播放音乐,true 循环播放
		SimpleAudioEngine::getInstance()->playBackgroundMusic("音乐文件相对路径",true);
		//控制音量 参数是浮点数 默认的是1.f  1.2f表示在原声音上放大
		SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(1.2f);
	});
	this->addChild(_button);
	
	//暂停按钮
	_button = Button::create();
	_button ->setTitleText("Pause");
	_button ->setTitleFontSize(36);
	_button ->setPositionX(base.x);
	_button ->setPositionY(base.y + _button->getContentSize().height * 0.5 + 5);
	_button->addClickEventListener([](Ref* sender)
	{
		//暂停播放
		SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
	});
	this->addChild(_button);
	
	//恢复按钮
	_button = Button::create();
	_button ->setTitleText("Resume");
	_button ->setTitleFontSize(36);
	_button ->setPositionX(base.x);
	_button ->setPositionY(base.y + _button->getContentSize().height * 0.5 - 5);
	_button->addClickEventListener([](Ref* sender)
	{
		//恢复播放
		SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
	});
	this->addChild(_button);
	
	//停止按钮
	_button = Button::create();
	_button ->setTitleText("Stop");
	_button ->setTitleFontSize(36);
	_button ->setPositionX(base.x);
	_button ->setPositionY(base.y + _button->getContentSize().height * 0.5 - 15);
	_button->addClickEventListener([](Ref* sender)
	{
		//停止播放
		SimpleAudioEngine::getInstance()->stopBackgroundMusic();
	});
	this->addChild(_button);
	return true;
}

事件分发机制
Cocos2d-x通过事件分发机制响应用户事件
内置支持常见的事件如触摸事件,键盘事件等。
提供了创建自定义事件的方法,满足我们在游戏的开发过程中,特殊的事件响应需求。

什么是事件分发?
当事件发生(例如,用户触摸屏幕,或者敲键盘);EventDispatcher会发布
(Event objects)事件对象到合适的EventListeners,并调用你的回调。
基本元素:
事件监听器:EventListeners
事件分发器:EventDispatcher
事件对象:Event
优先级
使用一个整形的数值,数值较低的监听器比数值较高的监听器,先接收到事件
场景图优先级
是指向节点对象的指针,z-order较高的节点中的监听器比z-order
较低的节点中的,先接收到事件。

事件的吞没
监听器接收到期望的事件
这时事件应该被吞没
触摸事件
什么是触摸事件
当你触摸移动设备的屏幕时,设备感受到被触摸,获取被触摸的位置和信息,然后反馈给你。
提示:如果需要触摸控制屏幕下层节点,可以通过优先级达成这种需求,优先级高的能先处理事件。

//创建单点事件监听器
auto listener1 = EventListenerTouchOneByOne::create();
//按住时触发事件
listener1 ->onTouchBegan = [](Touch* touch,Event* event)
{
	//true表示成功触发
	return true;
};
//按住滑动时触发事件
listener1 ->onTouchMoved = [](Touch* touch,Event* event){};
//释放时时触发事件
listener1 ->onTouchMoved = [=](Touch* touch,Event* event){};
//添加监听器
_eventDispatcher ->addEventListenerWithSceneGraphpriority(listenere1,this);

演示事件的触摸:
TouchLayer.h

#pragma once
#include "cocos2d.h"
class TouchLayer:public Scene
{
public:
	CREATE_FUNC(TouchLayer);
	virtual bool init();
};

TouchLayer.cpp

bool TouchLayer::init()
{
	//设置成当前大小
	this->setContentSize(Director::getInstance()->getVisibleSize());
	//演示触摸事件的处理
	auto listener = EventListenerTouchOneByOne::create();
	
	//添加按下事件
	listener ->onTouchBegan = [](Touch* touch,Event* event)
	{
		log("touch began");
		//true表示成功触发
		return true;
	};
	//添加释放事件
	listener ->onTouchEnded = [](Touch* touch,Event* event)
	{
		log("touch end");
	};
	//添加移动事件
	listener ->onTouchMoved = [](Touch* touch,Event* event)
	{
		log("touch moved");
	};
	//事件分发器必须要先添加事件
	//添加到事件分发器中
	_eventDispatcher ->addEventListenerWithSceneGraphpriority(listenere,this);
	return false;
}

键盘事件

//创建键盘事件监听器
auto listener = EventListenerboard::create();
listener ->onKeyPressed = CC_CALLBACK_2(KeyBoardTest::onKeyPressed,this);
listener ->onKeyReleased = CC_CALLBACK_2(KeyBoardTest::onKeyReleased,this);

//添加键盘事件监听器
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
//实现键盘按键按下事件回调函数
void keyboardTest::onKeyPressed(EventKeyboard::KeyCode KeyCode,Event* event)
{
	log("key with keycode %d pressed",KeyCode);
}
//实现键盘按键释放事件回调函数
void keyboardTest::onKeyReleased(EventKeyboard::KeyCode KeyCode,Event* event)
{
	log("key with keycode %d released",KeyCode);
}

加速度传感器事件
一些移动设备备有加速度传感器,通过监听它的事件获取各方向的加速度。

//启用加速度传感器
Device::setAccelerometerEnabled(true);
//创建加速度传感器
auto listener = EventListenerAcceleration::create(
					CC_CALLBACK_2(AccelerometerTest::onAcceleration,
					this));
_eventDispatcher ->addEventListenerWithSceneGraphpriority(listenere,this);
//加速度传感器事件处理方法
void AccelerometerTest::onAcceleration(Acceleration* acc,Event* event){};

鼠标事件
创建鼠标事件

_mouseListener = EventListenerMouse::create();
_mouseListener ->onMouseMove = CC_CALLBACK_1(MouseTest::omMouseMove,this);
_mouseListener ->onMouseUp = CC_CALLBACK_1(MouseTest::onMouseUp ,this);
_mouseListener ->onMouseDown = CC_CALLBACK_1(MouseTest::onMouseDown ,this);
_mouseListener ->onMouseScroll = CC_CALLBACK_1(MouseTest::onMouseScroll,this);

_eventDispatcher ->addEventListenerWithSceneGraphpriority(_mouseListener ,this);

事件类型

//鼠标按下事件
void MouseTest::omMouseDown(Event* event){}
//鼠标释放事件
void MouseTest::omMouseUp(Event* event){}
//鼠标移动事件
void MouseTest::omMousemove(Event* event){}
//鼠标滚轮事件
void MouseTest::omMouseScroll(Event* event){}

触摸事件传递到下层,控制上层的精灵移动,要求:
上层触摸事件控制该层的左右移动
事件传递到下层
下层事件控制精灵的竖直上下移动

EventDemo.h
#pragma once
#include "cocos2d.h"
class EventScene:public Scene
{
public:
	CREATE_FUNC(EventScene);
	virtual bool init();
};

EventDemo.cpp

#include "TopLayer.h"
#include "BottomLayer.h"
bool EventScene::init()
{
	//创建两个层容器
	//第一个层容器TopLayer中添加一个背景精灵和一个控制精灵
	auto topLayer = TopLayer::create();
	this->addChild(topLayer);

	auto bottomLayer = BottomLayer::create(topLayer->getSprite());
	this->addChild(bottomLayer);
	return true;
}

TopLayer.h

#pragma once
#include "cocos2d.h"
class TopLayer:public Layer
{
public:
	CREATE_FUNC(TopLayer);
	virtual bool init();
	Sprite* getSprite();
private:
	//记录受控制的精灵
	Sprite* _sprite;
	//记录当前坐标点
	Vec2 _position;
};

TopLayer.cpp

bool TopLayer::init()
{
	Size visible = Director::getInstance()->getVisibleSize();
	Vec2 center  = Vec2(visibleSize / 2);
	//创建背景精灵
	Sprite* bg = Sprite::create("图片相对路径");
	bg->setPosition(bg);
	this->addChild(bg);
	//创建受控制精灵
	_sprite = Sprite::create("图片相对路径");
	_sprite ->setPosition(center);
	this->addChild(_sprite);

	//创建一个单点事件监听器
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [this](Touch* touch,Event* event){
		//记录按下的坐标点
		_position = touch->getLocation();
		return true;
	};
	listener->onTouchMoved = [](Touch* touch,Event* event)
	{
		//记录顶层左右水平移动的距离
		float distance = touch->getLocation().x - _position.x;
		//设置TopLayer显示坐标
		auto node = event->getCurrentTarget();
		node->setPositionX(node->getPositionX() + distance);
		//重置当前的触摸点用于下次计算
		_position.x = touch->getLocation().x;
	};
	_eventDispatcher ->addEventListenerWithSceneGraphpriority(listener,this);
	return true;
}

Sprite* TopLayer::getSprite()
{
	return _sprite ;
}

BottomLayer.h

#pragma once
#include "cocos2d.h"
class BottomLayer:public Layer
{
public:
	//重载一个create方法
	static BottomLayer*create(Sprite * sprite);
	CREATE_FUNC(BottomLayer);
	virtual bool init();
private:
	//顶层送控制的精灵对象
	Sprite* _sprite;
	//记录当前坐标点
	Vec2 _position;
};

BottomLayer.cpp

bool BottomLayer::init()
{
	//创建一个单点事件监听器
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [this](Touch* touch,Event* event){
		//记录按下的坐标点
		_position = touch->getLocation();
		return true;
	};
	listener->onTouchMoved = [](Touch* touch,Event* event)
	{
		//记录精灵竖直移动的位置
		float distance = touch->getLocation().y - _position.y;
		//设置受控制精灵的显示坐标
		_sprite->setPositionY(_sprite->getPositionY() + distance);
		//重置当前的触摸点用于下次计算
		_position.y = touch->getLocation().y;
	};
	_eventDispatcher ->addEventListenerWithSceneGraphpriority(listener,this);
	return true;
}
BottomLayer * BottomLayer::create(Sprite * sprite)
{
	auto layer = BottomLayer::create();
	layer->_sprite = sprite;
	return layer;
}

边学边写,如果有哪里不正确的地方还请小伙伴们及时指出来,码字不易还请谅解!

你可能感兴趣的:(cocos2dx,cocos2d,学习,游戏引擎)