Cocos2d-x手游技术分享(1)-【天天打蚊子】数据存储与音效篇
前言:
手游项目《天天打蚊子》终于上线,特地写几篇技术分享文章,分享一下其中使用到的技术,其中使用cocos2d-x引擎,首选平台iOS,也请有iPhone或者iPad的朋友帮忙下载好评。十分感谢。
目前完美支持iPhone4、iPhone 4S、iPhone 5、iPad所有版本,iOS 5以上开始支持。
目前开发团队3个人,本人客户端+服务端,另有1名客户端,1名美术,目前创业刚刚起步,请各位好友支持!
《天天打蚊子》下载地址:https://itunes.apple.com/cn/app/id681203794
一、Cocos2d-x中的数据存储。
1、CCUserDefault数据存储
CCUserDefault头文件:
class CC_DLL CCUserDefault
{
public:
~CCUserDefault(); // get value methods /**
@brief Get bool value by key, if the key doesn't exist, a default value will return.
You can set the default value, or it is false.
*/
bool getBoolForKey(const char* pKey);
bool getBoolForKey(const char* pKey, bool defaultValue);
/**
@brief Get integer value by key, if the key doesn't exist, a default value will return.
You can set the default value, or it is 0.
*/
int getIntegerForKey(const char* pKey);
int getIntegerForKey(const char* pKey, int defaultValue);
/**
@brief Get float value by key, if the key doesn't exist, a default value will return.
You can set the default value, or it is 0.0f.
*/
float getFloatForKey(const char* pKey);
float getFloatForKey(const char* pKey, float defaultValue);
/**
@brief Get double value by key, if the key doesn't exist, a default value will return.
You can set the default value, or it is 0.0.
*/
double getDoubleForKey(const char* pKey);
double getDoubleForKey(const char* pKey, double defaultValue);
/**
@brief Get string value by key, if the key doesn't exist, a default value will return.
You can set the default value, or it is "".
*/
std::string getStringForKey(const char* pKey);
std::string getStringForKey(const char* pKey, const std::string & defaultValue); // set value methods /**
@brief Set bool value by key.
*/
void setBoolForKey(const char* pKey, bool value);
/**
@brief Set integer value by key.
*/
void setIntegerForKey(const char* pKey, int value);
/**
@brief Set float value by key.
*/
void setFloatForKey(const char* pKey, float value);
/**
@brief Set double value by key.
*/
void setDoubleForKey(const char* pKey, double value);
/**
@brief Set string value by key.
*/
void setStringForKey(const char* pKey, const std::string & value);
/**
@brief Save content to xml file
*/
void flush(); static CCUserDefault* sharedUserDefault();
static void purgeSharedUserDefault();
const static std::string& getXMLFilePath();
static bool isXMLFileExist(); private:
CCUserDefault();
static bool createXMLFile();
static void initXMLFilePath(); static CCUserDefault* m_spUserDefault;
static std::string m_sFilePath;
static bool m_sbIsFilePathInitialized;
};
CCUserDefault.h
其中包括多种方法(getBoolForKey,getFloatForKey,getIntegerForKey等等),可根据具体需要存储的数据类型进行选择。
具体实现:
比如在游戏开发过程中,要实现本地存储新手引导中的某一步是否已经访问过,我可以这样:
bool DataHelper::getIsVisit(EnumNewUserGuid type)
{
const char * key = CCString::createWithFormat("NewUserGuid_%d",type)->getCString();
return CCUserDefault::sharedUserDefault()->getBoolForKey(key, false);
} void DataHelper::setVisit(EnumNewUserGuid type)
{
const char * key = CCString::createWithFormat("NewUserGuid_%d",type)->getCString();
CCUserDefault::sharedUserDefault()->setBoolForKey(key, true);
}
其中,EnumNewUserGuid为新手引导的步骤的枚举。
下面将使用CCUserDefault实现音效管理。
2、iOS keychain数据存储
上篇文章讲到iOS keychain的数据存储方法,本文加上为C++的接口。keychain.h keychain.m文件再贴一次。
#import <Foundation/Foundation.h> @interface Keychain : NSObject
//keychain
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service;
+ (void)saveData:(NSString *)service data:(id)data;
+ (id)loadData:(NSString *)service;
+ (void)deleteData:(NSString *)service;
@end
keychain.h
#import "Keychain.h" @implementation Keychain //keychain
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service
{
NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassGenericPassword,(id)kSecClass,
service, (id)kSecAttrService,
service, (id)kSecAttrAccount,
(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
nil];
return dict;
} + (void)saveData:(NSString *)service data:(id)data
{
//Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Delete old item before add new item
SecItemDelete((CFDictionaryRef)keychainQuery);
//Add new object to search dictionary(Attention:the data format)
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
//Add item to keychain with the search dictionary
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
} + (id)loadData:(NSString *)service
{
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Configure the search setting
//Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData];
} @catch (NSException *e) {
CLog(@"Unarchive of %@ failed: %@", service, e);
} @finally {
}
}
if (keyData)
CFRelease(keyData);
return ret;
} + (void)deleteData:(NSString *)service
{
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
} @end
keychain.m
下面用keychain记录本地账号:
DBInfoAccount.h
#include "cocos2d.h"
using namespace cocos2d;
class DBInfoAccount {
public:
int m_iUserID;
CCString * m_pAccountID;
CCString * m_pPassword;
DBInfoAccount();
static DBInfoAccount * getInstance();
bool isHasAccount();
//数据存取
void loadData();
static void saveData();
static void reset();
};
DBInfoAccount.mm
#import "Keychain.h"
#include "DBInfoAccount.h" //#define kAccount @"Account"
#define kAccountAccountID @"Account_Account_ID"
#define kAccountUserID @"Account_UserID"
#define kAccountPassword @"Account_Pwd" static DBInfoAccount * s_pDBInfoAccount = NULL; DBInfoAccount::DBInfoAccount():
m_iUserID()
{
m_pAccountID = new CCString("");
m_pPassword = new CCString("");
} DBInfoAccount * DBInfoAccount::getInstance()
{
if (s_pDBInfoAccount == NULL) {
s_pDBInfoAccount -> loadData();
if (s_pDBInfoAccount == NULL) {
s_pDBInfoAccount = new DBInfoAccount;
}
} return s_pDBInfoAccount;
} bool DBInfoAccount::isHasAccount()
{
return m_pAccountID!= NULL && m_pAccountID -> length()>;
} void DBInfoAccount::loadData()
{
if (s_pDBInfoAccount == NULL) {
NSString * accountID = [Keychain loadData: kAccountAccountID];
NSString * userID = [Keychain loadData: kAccountUserID];
NSString * password = [Keychain loadData: kAccountPassword];
s_pDBInfoAccount = new DBInfoAccount;
const char * c_accountID = [accountID cStringUsingEncoding:NSUTF8StringEncoding];
DWORD c_userID = [userID intValue];
const char * c_password = [password cStringUsingEncoding:NSUTF8StringEncoding]; if (c_accountID != NULL && c_password != NULL) {
s_pDBInfoAccount -> m_pAccountID -> m_sString = c_accountID;
s_pDBInfoAccount -> m_iUserID = c_userID;
s_pDBInfoAccount -> m_pPassword -> m_sString = c_password;
}
}
} void DBInfoAccount::saveData()
{
NSString * accountID = [NSString stringWithCString:s_pDBInfoAccount->m_pAccountID->getCString() encoding:NSUTF8StringEncoding];
NSString * userID = [NSString stringWithFormat:@"%d",s_pDBInfoAccount->m_iUserID];
NSString * password = [NSString stringWithCString:s_pDBInfoAccount->m_pPassword->getCString() encoding:NSUTF8StringEncoding];
[Keychain saveData:kAccountAccountID data: accountID];
[Keychain saveData:kAccountUserID data: userID];
[Keychain saveData:kAccountPassword data: password];
} void DBInfoAccount::reset()
{
[Keychain deleteData:kAccountAccountID];
[Keychain deleteData:kAccountUserID];
[Keychain deleteData:kAccountPassword];
}
具体用法一目了然,不再赘述。
二、音效管理。
废话不说,直接上代码:
void DataHelper::initMusicAndEffect()
{
bool isEffectEnabel = DataHelper::getEffectEnable();
CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(isEffectEnabel); bool isMusicEnable = DataHelper::getMusicEnable();
CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(isMusicEnable);
}
bool DataHelper::getEffectEnable()
{
return CCUserDefault::sharedUserDefault()->getBoolForKey("Effect_Enable", true);
}
bool DataHelper::getMusicEnable()
{
return CCUserDefault::sharedUserDefault()->getBoolForKey("Music_Enable", true);
}
void DataHelper::setEffectEnable(bool isEnable)
{
CCUserDefault::sharedUserDefault()->setBoolForKey("Effect_Enable", isEnable);
CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(isEnable);
}
void DataHelper::setMusicEnable(bool isEnable)
{
CCUserDefault::sharedUserDefault()->setBoolForKey("Music_Enable", isEnable);
CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(isEnable);
}
其中,CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(isEffectEnabel),setEffectsVolume为设置的音效大小(0~1)的方法,这里使用false(0)和true(1)直接设置,实现是否设置为静音。
至于播放背景音乐和音效,最好使用mp3格式的,iOS和安卓同时支持。
具体:
CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("bg.mp3", true);//播放背景音乐,第二个参数为是否循环播放
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("anjian.mp3");//播放音效,比如按键声
《天天打蚊子》下载地址:https://itunes.apple.com/cn/app/id681203794
请各位多多支持,给个好评呀!谢谢!或者扫描二维码下载:

游戏视频:
后续cocos2d-x技术文章陆续放出,敬请关注!!
Cocos2d-x手游技术分享(1)-【天天打蚊子】数据存储与音效篇的更多相关文章
- Memcache技术分享:介绍、使用、存储、算法、优化、命中率
1.memcached 介绍 1.1 memcached 是什么? memcached 是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发 ...
- 【恒天云技术分享系列10】OpenStack块存储技术
原文:http://www.hengtianyun.com/download-show-id-101.html 块存储,简单来说就是提供了块设备存储的接口.用户需要把块存储卷附加到虚拟机(或者裸机)上 ...
- Kooboo CMS技术文档之三:切换数据存储方式
切换数据存储方式包括以下几种: 将文本内容存储在SqlServer.MySQL.MongoDB等数据库中 将站点配置信息存储在数据库中 将后台用户信息存储在数据库中 将会员信息存储在数据库中 将图片. ...
- 建一座安全的“天空城” ——揭秘腾讯WeTest如何与祖龙共同挖掘手游安全漏洞
作者:腾讯WeTest手游安全测试团队商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest导读 <九州天空城3D>上线至今,长期稳定在APP Store畅销排行的前 ...
- Unity手游引擎安全解析及实践
近日,由Unity主办的"Unity技术开放日"在广州成功举办,网易移动安全技术专家卓辉作为特邀嘉宾同现场400名游戏开发者分享了网易在手游安全所积累的经验.当下,很多手游背后都存 ...
- 龙之谷手游WebVR技术分享
主要面向Web前端工程师,需要一定Javascript及three.js基础:本文主要分享内容为基于three.js开发WebVR思路及碰到的问题:有兴趣的同学,欢迎跟帖讨论. 目录:一.项目体验1. ...
- 手游录屏直播技术详解 | 直播 SDK 性能优化实践
在上期<直播推流端弱网优化策略 >中,我们介绍了直播推流端是如何优化的.本期,将介绍手游直播中录屏的实现方式. 直播经过一年左右的快速发展,衍生出越来越丰富的业务形式,也覆盖越来越广的应用 ...
- 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...
- UWP 手绘视频创作工具技术分享系列
开篇先来说一下写这篇文章的初衷. 初到来画,通读了来画 UWP App 的代码,发现里面确实有很多比较高深的技术点,同时也是有很多问题的,扩展性,耦合,性能,功能等等.于是我们决定从头重构这个产品,做 ...
随机推荐
- Linux原理与实践
Linux 中的文件及权限 -rwxr-xr-x 1 cat animal 68 03-31 21:47 sleep.sh 三种用户角色: r 4 w 2 x 1 user ,文件的所有者 group ...
- kill 进程的一些小细节
终止前台进程,可以用Ctrl+C组合键.但对于后台进程需要用kill命令. kill PID 还可以加信号(参数),默认情况下是编号为15的信号.term信号将终止所有不能捕捉该信号的进程. -s 可 ...
- CF165D Beard Graph
$ \color{#0066ff}{ 题目描述 }$ 给定一棵树,有m次操作. 1 x 把第x条边染成黑色 2 x 把第x条边染成白色 3 x y 查询x~y之间的黑边数,存在白边输出-1 \(\co ...
- GCD BZOJ2818 [省队互测] 数学
题目描述 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 输入输出格式 输入格式: 一个整数N 输出格式: 答案 输入输出样例 输入样例#1: 复制 4 ...
- 文件句柄NSFileHandle
//一.读取 //1.以只读方式打开 NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:txtPath]; //2.读取所有内容 ...
- java 实现在线阅读 .pdf
1.资源的本地地址 2.设置响应头 3.代码实现 @ResponseBody @RequestMapping(value = "/read") @ApiOperation(valu ...
- python学习之路---day26
网络的基本知识点 一:网络通信原理 连接两台计算机之间的Internet之间的协议一系列协议为互联网协议 互联网协议的功能是:定义计算机如何接入Internet,以及Internet的计算机通信标准 ...
- abp + angular 项目 图标字体注意事项
用的字体建议下载到本地,否则部署环境没有网络的话,则图片字体会不正常显示.
- 不要重复发明轮子-C++STL
闫常友 著. 中国铁道出版社. 2013/5 标准的C++模板库,是算法和其他一些标准组件的集合. . 1.类模板简介 2.c++中的字符串 3.容器 4.c++中的算法 5.迭代器 6.STL 数值 ...
- 1076 Wifi密码 (15 分)
下面是微博上流传的一张照片:“各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1:B-2:C-3:D-4:请同学们自己作答,每两日一 ...