• 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头文件:

     1 class CC_DLL CCUserDefault
     2 {
     3 public:
     4     ~CCUserDefault();
     5 
     6     // get value methods
     7 
     8     /**
     9     @brief Get bool value by key, if the key doesn't exist, a default value will return.
    10      You can set the default value, or it is false.
    11     */
    12     bool    getBoolForKey(const char* pKey);
    13     bool    getBoolForKey(const char* pKey, bool defaultValue);
    14     /**
    15     @brief Get integer value by key, if the key doesn't exist, a default value will return.
    16      You can set the default value, or it is 0.
    17     */
    18     int     getIntegerForKey(const char* pKey);
    19     int     getIntegerForKey(const char* pKey, int defaultValue);
    20     /**
    21     @brief Get float value by key, if the key doesn't exist, a default value will return.
    22      You can set the default value, or it is 0.0f.
    23     */
    24     float    getFloatForKey(const char* pKey);
    25     float    getFloatForKey(const char* pKey, float defaultValue);
    26     /**
    27     @brief Get double value by key, if the key doesn't exist, a default value will return.
    28      You can set the default value, or it is 0.0.
    29     */
    30     double  getDoubleForKey(const char* pKey);
    31     double  getDoubleForKey(const char* pKey, double defaultValue);
    32     /**
    33     @brief Get string value by key, if the key doesn't exist, a default value will return.
    34     You can set the default value, or it is "".
    35     */
    36     std::string getStringForKey(const char* pKey);
    37     std::string getStringForKey(const char* pKey, const std::string & defaultValue);
    38 
    39     // set value methods
    40 
    41     /**
    42     @brief Set bool value by key.
    43     */
    44     void    setBoolForKey(const char* pKey, bool value);
    45     /**
    46     @brief Set integer value by key.
    47     */
    48     void    setIntegerForKey(const char* pKey, int value);
    49     /**
    50     @brief Set float value by key.
    51     */
    52     void    setFloatForKey(const char* pKey, float value);
    53     /**
    54     @brief Set double value by key.
    55     */
    56     void    setDoubleForKey(const char* pKey, double value);
    57     /**
    58     @brief Set string value by key.
    59     */
    60     void    setStringForKey(const char* pKey, const std::string & value);
    61     /**
    62      @brief Save content to xml file
    63      */
    64     void    flush();
    65 
    66     static CCUserDefault* sharedUserDefault();
    67     static void purgeSharedUserDefault();
    68     const static std::string& getXMLFilePath();
    69     static bool isXMLFileExist();
    70 
    71 private:
    72     CCUserDefault();
    73     static bool createXMLFile();
    74     static void initXMLFilePath();
    75     
    76     static CCUserDefault* m_spUserDefault;
    77     static std::string m_sFilePath;
    78     static bool m_sbIsFilePathInitialized;
    79 };
    CCUserDefault.h

      其中包括多种方法(getBoolForKey,getFloatForKey,getIntegerForKey等等),可根据具体需要存储的数据类型进行选择。

    具体实现:

      比如在游戏开发过程中,要实现本地存储新手引导中的某一步是否已经访问过,我可以这样:

     1 bool DataHelper::getIsVisit(EnumNewUserGuid type)
     2 {
     3     const char * key = CCString::createWithFormat("NewUserGuid_%d",type)->getCString();
     4     return  CCUserDefault::sharedUserDefault()->getBoolForKey(key, false);
     5 }
     6 
     7 void DataHelper::setVisit(EnumNewUserGuid type)
     8 {
     9     const char * key = CCString::createWithFormat("NewUserGuid_%d",type)->getCString();
    10     CCUserDefault::sharedUserDefault()->setBoolForKey(key, true);
    11 }

      其中,EnumNewUserGuid为新手引导的步骤的枚举。

      下面将使用CCUserDefault实现音效管理。

    2、iOS keychain数据存储

      上篇文章讲到iOS keychain的数据存储方法,本文加上为C++的接口。keychain.h keychain.m文件再贴一次。

    1 #import <Foundation/Foundation.h>
    2 
    3 @interface Keychain : NSObject
    4 //keychain
    5 + (NSMutableDictionary *)getKeychainQuery:(NSString *)service;
    6 + (void)saveData:(NSString *)service data:(id)data;
    7 + (id)loadData:(NSString *)service;
    8 + (void)deleteData:(NSString *)service;
    9 @end
    keychain.h
     1 #import "Keychain.h"
     2 
     3 @implementation Keychain
     4 
     5 //keychain
     6 + (NSMutableDictionary *)getKeychainQuery:(NSString *)service
     7 {
     8     NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
     9                                   (id)kSecClassGenericPassword,(id)kSecClass,
    10                                   service, (id)kSecAttrService,
    11                                   service, (id)kSecAttrAccount,
    12                                   (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
    13                                   nil];
    14     return dict;
    15 }
    16 
    17 + (void)saveData:(NSString *)service data:(id)data
    18 {
    19     //Get search dictionary
    20     NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    21     //Delete old item before add new item
    22     SecItemDelete((CFDictionaryRef)keychainQuery);
    23     //Add new object to search dictionary(Attention:the data format)
    24     [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    25     //Add item to keychain with the search dictionary
    26     SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
    27 }
    28 
    29 + (id)loadData:(NSString *)service
    30 {
    31     id ret = nil;
    32     NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    33     //Configure the search setting
    34     //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
    35     [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    36     [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    37     CFDataRef keyData = NULL;
    38     if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
    39         @try {
    40             ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData];
    41         } @catch (NSException *e) {
    42             CLog(@"Unarchive of %@ failed: %@", service, e);
    43         } @finally {
    44         }
    45     }
    46     if (keyData)
    47         CFRelease(keyData);
    48     return ret;
    49 }
    50 
    51 + (void)deleteData:(NSString *)service
    52 {
    53     NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    54     SecItemDelete((CFDictionaryRef)keychainQuery);
    55 }
    56 
    57 @end
    keychain.m

      下面用keychain记录本地账号:

    DBInfoAccount.h

     1 #include "cocos2d.h"
     2 
     3 using namespace cocos2d;
     4 
     5 class DBInfoAccount {
     6 
     7 public:
     8     
     9     int m_iUserID;
    10     CCString * m_pAccountID;
    11     CCString * m_pPassword;
    12     
    13     DBInfoAccount();
    14     static DBInfoAccount * getInstance();
    15     bool isHasAccount();
    16     
    17     //数据存取
    18     void loadData();
    19     static void saveData();
    20     static void reset();
    21 };

    DBInfoAccount.mm

     1 #import "Keychain.h"
     2 #include "DBInfoAccount.h"
     3 
     4 
     5 
     6 //#define kAccount                @"Account"
     7 #define kAccountAccountID        @"Account_Account_ID"
     8 #define kAccountUserID            @"Account_UserID"
     9 #define kAccountPassword        @"Account_Pwd"
    10 
    11 
    12 
    13 static DBInfoAccount * s_pDBInfoAccount = NULL;
    14 
    15 DBInfoAccount::DBInfoAccount():
    16 m_iUserID(0)
    17 {
    18     m_pAccountID = new CCString("");
    19     m_pPassword = new CCString("");
    20 }
    21 
    22 DBInfoAccount * DBInfoAccount::getInstance()
    23 {
    24     if (s_pDBInfoAccount == NULL) {
    25         s_pDBInfoAccount -> loadData();
    26         if (s_pDBInfoAccount == NULL) {
    27             s_pDBInfoAccount = new DBInfoAccount;
    28         }
    29     }
    30     
    31     return s_pDBInfoAccount;
    32 }
    33 
    34 bool DBInfoAccount::isHasAccount()
    35 {
    36     return m_pAccountID!= NULL && m_pAccountID -> length()>0;
    37 }
    38 
    39 void DBInfoAccount::loadData()
    40 {
    41     if (s_pDBInfoAccount == NULL) {
    42         NSString * accountID = [Keychain loadData: kAccountAccountID];
    43         NSString * userID = [Keychain loadData: kAccountUserID];
    44         NSString * password = [Keychain loadData: kAccountPassword];
    45         s_pDBInfoAccount = new DBInfoAccount;
    46         const char * c_accountID = [accountID cStringUsingEncoding:NSUTF8StringEncoding];
    47         DWORD c_userID = [userID  intValue];
    48         const char * c_password = [password cStringUsingEncoding:NSUTF8StringEncoding];
    49         
    50         if (c_accountID != NULL && c_password != NULL) {
    51             s_pDBInfoAccount -> m_pAccountID -> m_sString = c_accountID;
    52             s_pDBInfoAccount -> m_iUserID  = c_userID;
    53             s_pDBInfoAccount -> m_pPassword -> m_sString = c_password;
    54         }
    55     }
    56 }
    57 
    58 void DBInfoAccount::saveData()
    59 {
    60     NSString * accountID = [NSString stringWithCString:s_pDBInfoAccount->m_pAccountID->getCString() encoding:NSUTF8StringEncoding];
    61     NSString * userID = [NSString stringWithFormat:@"%d",s_pDBInfoAccount->m_iUserID];
    62     NSString * password = [NSString stringWithCString:s_pDBInfoAccount->m_pPassword->getCString() encoding:NSUTF8StringEncoding];
    63     [Keychain saveData:kAccountAccountID data: accountID];
    64     [Keychain saveData:kAccountUserID data: userID];
    65     [Keychain saveData:kAccountPassword data: password];
    66 }
    67 
    68 void DBInfoAccount::reset()
    69 {
    70     [Keychain deleteData:kAccountAccountID];
    71     [Keychain deleteData:kAccountUserID];
    72     [Keychain deleteData:kAccountPassword];
    73 }

      具体用法一目了然,不再赘述。

    二、音效管理。

      废话不说,直接上代码:

     1  void DataHelper::initMusicAndEffect()
     2 {
     3     bool isEffectEnabel = DataHelper::getEffectEnable();
     4     CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(isEffectEnabel);
     5     
     6     bool isMusicEnable = DataHelper::getMusicEnable();
     7     CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(isMusicEnable);
     8 }
     9  bool DataHelper::getEffectEnable()
    10 {
    11     return  CCUserDefault::sharedUserDefault()->getBoolForKey("Effect_Enable", true);
    12 }
    13  bool DataHelper::getMusicEnable()
    14 {
    15     return  CCUserDefault::sharedUserDefault()->getBoolForKey("Music_Enable", true);
    16 }
    17  void DataHelper::setEffectEnable(bool isEnable)
    18 {
    19     CCUserDefault::sharedUserDefault()->setBoolForKey("Effect_Enable", isEnable);
    20     CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(isEnable);
    21 }
    22  void DataHelper::setMusicEnable(bool isEnable)
    23 {
    24     CCUserDefault::sharedUserDefault()->setBoolForKey("Music_Enable", isEnable);
    25     CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(isEnable);
    26 }

      其中,CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(isEffectEnabel),setEffectsVolume为设置的音效大小(0~1)的方法,这里使用false(0)和true(1)直接设置,实现是否设置为静音。

      至于播放背景音乐和音效,最好使用mp3格式的,iOS和安卓同时支持。

      具体:

    1 CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("bg.mp3", true);//播放背景音乐,第二个参数为是否循环播放
    2 
    3 CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("anjian.mp3");//播放音效,比如按键声

    《天天打蚊子》下载地址:https://itunes.apple.com/cn/app/id681203794

    请各位多多支持,给个好评呀!谢谢!或者扫描二维码下载:

    天天打蚊子

     游戏视频:

    后续cocos2d-x技术文章陆续放出,敬请关注!!

  • 相关阅读:
    Android 监听电量的状态
    2017.1-TOP5 Android开源库
    Android实践 -- Android蓝牙设置连接
    Android ListView滚动到指定的位置
    软件原型设计工具
    plupload+struts2实现文件上传下载
    ORACLE 更改username
    单词反转实现
    FatMouse&#39; Trade(杭电1009)
    JS-JavaScript学习笔记(一)
  • 原文地址:https://www.cnblogs.com/chenshengtai/p/tiantiandawenzi.html
Copyright © 2020-2023  润新知