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 的代码,发现里面确实有很多比较高深的技术点,同时也是有很多问题的,扩展性,耦合,性能,功能等等.于是我们决定从头重构这个产品,做 ...
随机推荐
- 【python】Python的logging模块封装
#!/usr/local/python/bin # coding=utf-8 '''Implements a simple log library. This module is a simple e ...
- java集合类学习笔记之ArrayList
1.简述 ArrayList底层的实现是使用了数组保存所有的数据,所有的操作本质上是对数组的操作,每一个ArrayList实例都有一个默认的容量(数组的大小,默认是10),随着 对ArrayList不 ...
- The server of Apache (一)——apache服务的基本安装过程
一.为了避免端口冲突,需要卸载linux系统中以RPM方式安装的httpd ~] # rpm -qa | grep httpd ~] # rpm -e httpd --nodeps (此处nodeps ...
- Anya and Cubes 搜索+map映射
Anya loves to fold and stick. Today she decided to do just that. Anya has n cubes lying in a line an ...
- Java 实现手机发送短信验证码
Java 实现手机发送短信验证码 采用引入第三方工具的方式,网上查了半天,发现简单的实现方式便是注册一个中国网建的账号,新建账号的时候会附带赠几条免费短信,彩信 ,之后想要在使用就得花钱了.简单的操作 ...
- 使用octave符号运算求解不定积分、微分方程等(兼容matlab)
1.求解1/(1+cos(x))^2的不定积分. 在和学生讨论一道物理竞赛题的时候,出现了这个函数的积分求解需求.查积分表也可写出答案.但是可以使用octave的符号运算工具箱来做. syms x; ...
- tornado 02 输出、输入和URL传参
tornado 02 输出.输入和URL传参 一.输出 write输出到页面 #write可以接受的对象 #write() 可以接受3种对象:bytes Unicode字符(二进制字符) 字典 #如果 ...
- kotlin 注意的地方
1 . kotlin let 用法: let(val -> ) 注意:这 -> 后面不能有 花括号!!!! 2 . kotlin 中 如果使用了 @Transactional 注解.请让 ...
- Ubuntu系统安装WeChat
安装: 1.sudo apt install snapd snapd-xdg-open 2.sudo snap install electronic-wechat 运行: electronic-wec ...
- Subsequence(二分)
A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, a ...