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 面向对象十一 super函数
python 面向对象十一 super函数 super函数用来解决钻石继承. 一.python的继承以及调用父类成员 父类: class Base(object): def __init__(se ...
- Java面向对象之继承extends 入门实例
一.基础概念 (一)继承的好处: 1.继承:提高了代码的复用性. 2.让类与类之间产生了关系,给多态这个特征提供了前提. (二)继承的种类: 1.单继承:一个类只能有一个父类. 2.多继承:一个类可以 ...
- SpringMVC的简单介绍及使用
一.简介 1.SpringMVC和Spring的关系: >软件开发的三层架构: web层[表示层.表现层]---->Service层---->Dao[DataBase Access ...
- selenium+PhantomJS简单爬虫
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' Created on 2017年10月19日 @author: zzy ''' import tim ...
- 关于“java.lang.OutOfMemoryError : unable to create new native Thread”的报错问题
好吧 我发誓这是postgresql的Mirroring Controller的RT测试的最后一个坑了. 在这个RT测试的最后,要求测试Mirroring Controller功能在长时间运行下的稳定 ...
- Python开发MapReduce系列(一)WordCount Demo
原创,转发请注明出处. MapReduce是hadoop这只大象的核心,Hadoop 中,数据处理核心就是 MapReduce 程序设计模型.一个Map/Reduce 作业(job) 通常会把输入的数 ...
- input 和 select
var source = $('input[name="source"]:checked').val(); var completenum = $("#completen ...
- WebApi接口 - 响应输出xml和json 转
格式化数据这东西,主要看需要的运用场景,今天和大家分享的是webapi格式化数据,这里面的例子主要是输出json和xml的格式数据,测试用例很接近实际常用情况:希望大家喜欢,也希望各位多多扫码 ...
- 【转】IntelliJ IDEA下自动生成Hibernate映射文件以及实体类
1.构建项目并添加项目结构配置以及配置初始参数 1.1.如图将基本的架子搭建好 1.2.点击File,弹出的菜单中点击Project Structure: 1.3.点击左侧的Modul ...
- BZOJ - 2648 KD树 最近点查询
省赛后躺尸几天又回来更新了,内容是说好的KD树.. 具体操作从代码中感受一下 感觉已经把KD树尽量封装好了(虽然全局的D看着极不顺眼) 需要注意的是估值函数的判断条件 #include<bits ...