以下是从一个cocos2d-x游戏项目里摘出来的代码。
类RubishField的头文件RubishField.h:
class RubishField : public cocos2d::CCScene
{
public :
bool init ();
private :
bool MusicOn ; //!<音乐是否是处于启用状态。
}; //class GameOverScene:public cocos2d:CCScene
成员 变量MusicOn的作用是作为背景音乐的状态开关 ,标志着背景音乐当前是否要播放。
类RubishField的代码文件RubishField.cpp:
bool RubishField:: init ()
{
if (CCScene::init()) //超类初始化成功。
{
MusicOn= true ; //音乐处于启用状态。
//设置音乐按钮的图片:
bool MusicOn = CCUserDefault :: sharedUserDefault() -> getBoolForKey( "Music" , true ); //获取配置,是否要播放音乐。
if (MusicOn) //要播放音乐。
{
//显示音乐启用状态的图片:
MusicItem->setNormalSpriteFrame(MscOnFrm); //显示声音被启用。
} //if (ShdPlMsc) //要播放音乐。
else //不播放音乐。
{
//显示音乐禁用状态的图片:
MusicItem->setNormalSpriteFrame(MscOfFrm); //显示声音被禁用。
} //else //不播放音乐。
return true ;
} //if (CCScene::init())
else
{
return false ;
} //else
} //bool GameOverScene::init()
这里只摘录了一小段。
在 bool RubishField:: init () 里,本来的意图是要实现这样的逻辑:
1.MusicOn的默认值是true;
2. 从配置文件里读取配置 项,作为MusicOn的真正值 ;
3.根据MusicOn的值来显示图片,或者是显示禁用状态,或者是显示启用状态。
在代码中另一处,会处理这个图片的点击事件,点击一次则切换MusicOn一次,同时根据最新 的MusicOn值来做出动作,播放背景音乐或是停止背景音乐 ,切换图片以反映出当前的音乐状态 。并且 将MusicOn的最新值存储到配置项里。
1. 在上次退出之前,将音乐切换到禁用状态,即成员变量MusicOn为false并且被存储到配置项里;
2. 第二次启动,音乐 将根据配置项的值不播放,同时音乐状态图标会显示“禁用”状态,到这里为止,一切正常;
3. 此时点击 一下音乐状态图标,预期的效果是开始播放音乐,并且音乐状态图标切换 成“启用”状态。而实际的结果是,音乐没有开始播放,音乐状态图标也没有切换成启用状态,需要再点击一次,才会得到预期的结果,并且之后逻辑都是正确的(指的是点击音乐状态图标的效果,连续点击多次)。
1. init()函数中,MusicOn这个成员变量首先被设置成true,于是音乐开关的逻辑值此时为true;
2. init()函数中,接下来的代码,本意想要读取配置 项作为音乐开关的新值,然而写代码时犯了个错误,声明了一个叫做MusicOn的局部变量 (见代码里加了深色背景的那个变量) ,它屏蔽掉了成员变量 MusicOn,并且局部变量MusicOn的值被读入为false (而成员变量MusicOn的值仍然保持为true) ,于是紧接 着的代码里,显示出了“禁用”音乐的图标;
3. 用户点击音乐切换图标,此时已经执行的是别的回调函数了,init()里的那个局部变量MusicOn已经离开生命周期,此时音乐切换回调函数按照真正的成员变量MusicOn的值来做动作,由于此时成员变量MusicOn的值为true,所以 再 次 将音乐状态图标“切换”为“禁用”图片,并且“停止”播放背景音乐;
4. 直到再次点击音乐切换图标,一切的逻辑才终于逃离了那个局部变量MusicOn的影响。
1. 最好是能结对编程。别人的眼睛往往一下子就能找到原因。本座自己找这个问题狠花了点时间。
2. 保持个好的习惯,引用成员变量时最好是带上this。 this->MusicOn。
未知美女
精灵
雷政富
HxLauncher: Launch Android applications by voice commands