五毛的cocos2d-x学习笔记07-计时器、数据读写、文件读写
调度器:
定时任务是通过调度器实现的。cocos2d-x推荐用调度器而不是其他方法实现定时任务。Node类都知道如何调度和取消调度事件。
有3种调度器:
- 默认调度器:schedulerUpdate()
- 自定义调度器:schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay)
- schedule(SEL_SCHEDULE selector, float delay)
- 单次调度器:scheduleOnce(SEL_SCHEDULE selector, float delay)
取消调度器:
- 默认调度器:unschedulerUpdate()
- 自定义调度器:unschedule(SEL_SCHEDULE selector, float delay)
- 单次调度器:unschedule(SEL_SCHEDULE selector, float delay)
使用默认调度器,该调度器是使用Node的刷新事件update方法,该方法在每帧绘制之前都会被调用一次。Node类默认没有启用update事件的,所以你需要重写这个update方法。update有一个float类型的形参。
使用自定义调度器:自定义的方法必须要有一个float类型的形参。
使用单次调度器:自定义的方法必须要有一个float类型的形参。
栗子:使用调度器实现定时调用移动文本标签:
1 #ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__ 3 4 #include "cocos2d.h" 5 6 class HelloWorld : public cocos2d::Layer 7 { 8 private: 9 cocos2d::LabelTTF *label; 10 public: 11 // there's no 'id' in cpp, so we recommend returning the class instance pointer 12 static cocos2d::Scene* createScene(); 13 14 // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone 15 virtual bool init(); 16 17 // a selector callback 18 void menuCloseCallback(cocos2d::Ref* pSender); 19 20 // implement the "static create()" method manually 21 CREATE_FUNC(HelloWorld); 22 23 void update(float delta) override; 24 25 void timerHandler(float delta); 26 }; 27 28 #endif // __HELLOWORLD_SCENE_H__
1 #include "HelloWorldScene.h" 2 3 USING_NS_CC; 4 5 Scene* HelloWorld::createScene() 6 { 7 // 'scene' is an autorelease object 8 auto scene = Scene::create(); 9 10 // 'layer' is an autorelease object 11 auto layer = HelloWorld::create(); 12 13 // add layer as a child to scene 14 scene->addChild(layer); 15 16 // return the scene 17 return scene; 18 } 19 20 // on "init" you need to initialize your instance 21 bool HelloWorld::init() 22 { 23 ////////////////////////////// 24 // 1. super init first 25 if ( !Layer::init() ) 26 { 27 return false; 28 } 29 30 label = LabelTTF::create("Hello, Cocos", "Courier", 30); 31 32 addChild(label); 33 34 //scheduleUpdate(); 35 36 schedule(schedule_selector(HelloWorld::timerHandler), 0.2f); 37 38 return true; 39 } 40 41 42 void HelloWorld::menuCloseCallback(Ref* pSender) 43 { 44 Director::getInstance()->end(); 45 46 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) 47 exit(0); 48 #endif 49 } 50 51 void HelloWorld::update(float delta){ 52 //log("update"); 53 label->setPosition(label->getPosition()+Vec2(1,1)); 54 //the following line has the same effect with the above line. 55 //label->runAction(MoveBy::create(1.0f, Point(1, 1))); 56 } 57 58 void HelloWorld::timerHandler(float delta){ 59 label->setPosition(label->getPosition() + Vec2(1, 1)); 60 }
首选项:
使用文件存取数据不方便用户的存取。本地数据存储有两种方法,一是UserDefault,二是SQLite数据库。
UserDefault是一个单例类,数据存到以UserDefault命名的xml文件,保存方式是一个map,即key-value的键值对。存取数据通过tinyxml2。
首选项的读取,我觉得类似于Android的SharedPreferences。
1 // on "init" you need to initialize your instance 2 bool HelloWorld::init() 3 { 4 ////////////////////////////// 5 // 1. super init first 6 if ( !Layer::init() ) 7 { 8 return false; 9 } 10 UserDefault::getInstance()->setStringForKey("data" , "success"); 11 log("%s", UserDefault::getInstance()->getStringForKey("data", "fail").c_str()); 12 return true; 13 }
文件读写:
写入目录的获取比较麻烦,各个平台不同,所以用C++自己的文件读写行不通。
使用cocos2d-x自己的文件读写:当前程序的文档目录
init
plist文件操作:
plist文件是苹果应用程序的配置文件,任何的配置文件都是可以用plist去写的。
plist文件是特定格式的xml 文件。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 <plist version="1.0"> 4 <dict> 5 <key>array</key> 6 <array> 7 <integer>0</integer> 8 <integer>1</integer> 9 <integer>2</integer> 10 </array> 11 <key>bool</key> 12 <true/> 13 <key>data</key> 14 <data> 15 </data> 16 <key>date</key> 17 <date>2015-02-16T16:47:11Z</date> 18 <key>dict</key> 19 <dict> 20 <key>age</key> 21 <string>20</string> 22 <key>name</key> 23 <string>Alice</string> 24 </dict> 25 <key>number</key> 26 <integer>123456</integer> 27 <key>string</key> 28 <string>hello world!</string> 29 </dict> 30 </plist>
1 bool HelloWorld::init() 2 { 3 ////////////////////////////// 4 // 1. super init first 5 if ( !Layer::init() ) 6 { 7 return false; 8 } 9 10 FileUtils *fu = FileUtils::getInstance(); 11 ValueMap plist = fu->getValueMapFromFile("test.plist"); 12 13 log("string = %s", (plist["string"].asString()).c_str()); 14 ValueMap& dict = plist["dict"].asValueMap(); 15 log("name = %s", (dict["name"].asString()).c_str()); 16 log("age = %s", (dict["age"].asString()).c_str()); 17 ValueVector& array = plist["array"].asValueVector(); 18 for (int i = 0; i < array.size(); i++) { 19 Value& value = array[i]; 20 log("%d", value.asInt()); 21 } 22 return true; 23 }
调试运行:
xml文件操作:
data.xml文件内容如下:
1 <data> 2 <p name="ZhangSan" age="10"></p> 3 <p name="LiSi" age="11"></p> 4 </data>
cocos2d-x内置了API操作xml,首先需要引入头文件:
include<tinyxml2/tinyxml2.h>;
1 bool HelloWorld::init() 2 { 3 ////////////////////////////// 4 // 1. super init first 5 if ( !Layer::init() ) 6 { 7 return false; 8 } 9 10 auto doc = new tinyxml2::XMLDocument();//首先需要创建文档 11 doc->Parse(FileUtils::getInstance()->getStringFromFile("data.xml").c_str());//解析字符串 12 auto root = doc->RootElement();//获取到根节点,根据根节点查找到子对象 13 14 //外层循环遍历所有的子项,内存循环遍历当前子项所有的属性 15 for (auto e = root->FirstChildElement(); e!=null; e = e->NextSiblingElement()){ 16 std::string str; 17 for (auto attr = e->FirstAttribute(); attr; attr = attr->Next()){ 18 str += attr->Name(); 19 str += ":"; 20 str += attr->Value(); 21 str += ","; 22 } 23 log("%s",str.c_str()); 24 } 25 26 return true; 27 }
json数据操作:
cocos2d-x内置了json工具,需要引入相应的头文件:
#include <json/document.h>
1 bool HelloWorld::init() 2 { 3 ////////////////////////////// 4 // 1. super init first 5 if ( !Layer::init() ) 6 { 7 return false; 8 } 9 10 rapidjson::Document doc; 11 //Parse<unsigned int parseFlags>(const Ch *str): 12 //parseFlags 指解析的方式,一般用默认的解析方式,只需要传入0就好了 13 doc.Parse<0>(FileUtils::getInstance()->getStringFromFile("data.json").c_str()); 14 log("%s", doc[(rapidjson::SizeType)0]["name"].GetString()); 15 return true; 16 }