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技術文章陸續放出,敬請關注!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM