Cocos2d-x:学习笔记(2017.05.12更新)
2017-05-01 20:41
387 查看
1.参考链接汇总
官方接口文档关于Cocos2d-x中addchild和removeChild方法的参数的解析
Cocos2d-x3.2 Menu菜单的创建
cocos 中熟练运用场景的切换
cocos2dx一个场景添加多个层
Cocos2d-x Layer锚点设置
cocos2d-x convertToWorldSpace 和 convertToNodeSpace
cocos2d-x 延迟执行一段代码1 顺序执行动作+延迟动作+CallFunc
Cocos2d-x v3.6制作射箭游戏(三)
菜鸟学习Cocos2d-x 3.x——浅谈动画
cocos2d-x“无法打开源文件”
cocos2d-x 坐标研究
深入理解 cocos2d-x 坐标系
Cocos2d-x解析XML文件,解决中文乱码
Cocos2d-x 通过虚拟按键控制人物移动
【平凡晓声 Cocos2d-x】虚拟按键控制精灵移动2
android Drawbitmap 画一个图片(Rect 的作用)
C++中数字与字符串之间的转换
Cocos2d-X中使用ProgressTimer实现一些简单的效果
菜鸟学习Cocos2d-x 3.x——浅谈动作Action
Cocos2dx学习笔记12:cocos2dx进度条(ProgressTimer)
cocos2dx[3.4](25)——瓦片地图TiledMap
cocos2dx 中 如果一个精灵被击中了,需要消失,用什么函数来实现呢?
Cocos2d-x v3.3中UserDefault保存的XML文件位置
2.创建Sprite
auto bg = Sprite::create("level-background-0.jpg"); bg->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); this->addChild(bg, 0);
使用plist:
auto spritecache = SpriteFrameCache::getInstance(); spritecache->addSpriteFramesWithFile("level-sheet.plist"); mouse = Sprite::createWithSpriteFrameName("gem-mouse-0.png"); mouse->setPosition(Vec2(origin.x + visibleSize.width / 2, 0));
使用动画第一帧:
// 创建一张贴图 auto texture = Director::getInstance()->getTextureCache()->addImage("$lucia_2.png"); // 从贴图中以像素单位切割,创建关键帧 auto frame0 = SpriteFrame::createWithTexture(texture, CC_RECT_PIXELS_TO_POINTS(Rect(0, 0, 113, 113))); // 使用第一帧创建精灵 player = Sprite::createWithSpriteFrame(frame0); player->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height/2)); addChild(player, 3);
3.创建MenuItem
auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + closeItem->getContentSize().height/2)); auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1);
void HelloWorld::menuCloseCallback(Ref* pSender) { Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif }
4.创建Layer
stoneLayer = Layer::create(); stoneLayer->setPosition(Vec2(0, 0)); stoneLayer->setAnchorPoint(Vec2(0, 0)); stoneLayer->ignoreAnchorPointForPosition(false); stoneLayer->addChild(stone); mouseLayer = Layer::create(); mouseLayer->setPosition(Vec2(0, origin.y + visibleSize.height / 2)); mouseLayer->setAnchorPoint(Vec2(0, 0)); mouseLayer->ignoreAnchorPointForPosition(false); mouseLayer->addChild(mouse); this->addChild(stoneLayer, 1); this->addChild(mouseLayer, 1);
5.显示中文字符
CCDictionary* message = CCDictionary::createWithContentsOfFile("Chinese.xml"); auto nameKey = message->valueForKey("Name"); const char* Name = nameKey->getCString(); auto IDKey = message->valueForKey("ID"); const char* ID = IDKey->getCString(); auto label = Label::createWithTTF(Name, "fonts/FZSTK.ttf", 24); auto label1 = Label::createWithTTF(ID, "fonts/Marker Felt.ttf", 24); // position the label on the center of the screen label->setPosition(Vec2(origin.x + visibleSize.width/2, origin.y + visibleSize.height - label->getContentSize().height)); label1->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height - label->getContentSize().height-label1->getContentSize().height));
<?xml version="1.0" encoding="UTF-8"?> <dict> <key>Name</key> <string>名字</string> <key>ID</key> <string>学号</string> </dict>
6. 播放背景英语
#include <SimpleAudioEngine.h> #define MUSIC_FILE "666.mp3"
以下是menuItem的触发函数,点击一下播放音乐,再点击一下停止音乐
void HelloWorld::display_music(Ref* pSender) { CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(MUSIC_FILE); CocosDenshion::SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5); if (count % 2 == 0) CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic(MUSIC_FILE, true); else CocosDenshion::SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic(); count++; }
7.定义动画(使用plist)
在AppDelegate.cpp中,SpriteFrameCache::getInstance()->addSpriteFramesWithFile("level-sheet.plist"); char _totalFrames = 7; char _frameName[40]; Animation* diamondAnimation = Animation::create(); for (int i = 0; i < _totalFrames; i++) { sprintf(_frameName, "pulled-diamond-%d.png", i); diamondAnimation->addSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(_frameName)); } diamondAnimation->setDelayPerUnit(0.1); AnimationCache::getInstance()->addAnimation(diamondAnimation, "diamondAnimation");
在GameSence.cpp中,
Animate* diamondAnimate = Animate::create(AnimationCache::getInstance()->getAnimation("diamondAnimation")); diamond->runAction(RepeatForever::create(diamondAnimate));
通过texture定义动画:
// 定义存储动画帧的vector cocos2d::Vector<SpriteFrame*> attack; // 创建一张贴图 auto texture = Director::getInstance()->getTextureCache()->addImage("$lucia_2.png"); // 攻击动画 attack.reserve(17); for (int i = 0; i < 17; i++) { auto frame = SpriteFrame::createWithTexture(texture, CC_RECT_PIXELS_TO_POINTS(Rect(113*i,0,113,113))); attack.pushBack(frame); } auto attack_animation = Animation::createWithSpriteFrames(attack, 0.1f); attack_animation->setRestoreOriginalFrame(true); AnimationCache::getInstance()->addAnimation(attack_animation, "attackAnimation");
8.触摸监听器
EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(GameSence::onTouchBegan, this); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
bool GameSence::onTouchBegan(Touch *touch, Event *unused_event) {}
9.获得visibleSize与origin
Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin();
10.设置锚点
mouseLayer->setAnchorPoint(Vec2(0, 0)); mouseLayer->ignoreAnchorPointForPosition(false);
11.MoveTo使用
auto moveTo = MoveTo::create(2, mouseLayer->convertToNodeSpace(location)); mouse->runAction(moveTo);
12.世界坐标系与本地坐标系的转换
auto location = mouse->getPosition(); location = mouseLayer->convertToWorldSpace(location); auto moveTo = MoveTo::create(1, stoneLayer->convertToNodeSpace(location)); stone->runAction(moveTo);
13.延迟函数的实现(异步操作)
auto _delayTime = DelayTime::create(0.5); auto _func = CallFunc::create([this]() { stoneLayer->removeChild(stone); stone = Sprite::create("stone.png"); stone->setPosition(Vec2(560, 480)); stoneLayer->addChild(stone); }); auto _seq = Sequence::create(_delayTime, _func, NULL); this->runAction(_seq);
14.设置背景
// 设置背景 auto bg = Sprite::create("background.jpg"); bg->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); this->addChild(bg, 0);
使用TileMap
// 设置背景 TMXTiledMap* tmx = TMXTiledMap::create("map.tmx"); tmx->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); tmx->setAnchorPoint(Vec2(0.5, 0.5)); tmx->setScale(Director::getInstance()->getContentScaleFactor()); this->addChild(tmx, 0);
15.创建倒计时
// 创建倒计时 time = Label::createWithTTF("120", "fonts/arial.ttf", 36); time->setPosition(Vec2(origin.x+visibleSize.width/2, origin.y+visibleSize.height-30)); this->addChild(time); schedule(schedule_selector(HelloWorld::updateTime), 1); dtime = 120;
// 事件更新函数 void HelloWorld::updateTime(float delta) { dtime--; if (dtime < 0) dtime = 0; char str[10]; sprintf(str, "%d", dtime); // 将int类型转化为字符串char*类型 time->setString(str); }
16.游戏的hp条
// 进度条定义 cocos2d::ProgressTimer* pT; // hp条 Sprite* sp0 = Sprite::create("hp.png", CC_RECT_PIXELS_TO_POINTS(Rect(0, 320, 420, 47))); // 进度条框 Sprite* sp = Sprite::create("hp.png", CC_RECT_PIXELS_TO_POINTS(Rect(610, 362, 4, 16))); // 进度条 // 使用hp条设置progressBar pT = ProgressTimer::create(sp); pT->setScaleX(90); pT->setAnchorPoint(Vec2(0, 0)); pT->setType(ProgressTimerType::BAR); // 定义进度条类型 pT->setBarChangeRate(Point(1, 0)); pT->setMidpoint(Point(0, 1)); pT->setPercentage(100); pT->setPosition(Vec2(origin.x+14*pT->getContentSize().width,origin.y + visibleSize.height - 2*pT->getContentSize().height)); addChild(pT,1); sp0->setAnchorPoint(Vec2(0, 0)); sp0->setPosition(Vec2(origin.x + pT->getContentSize().width, origin.y + visibleSize.height - sp0->getContentSize().height)); addChild(sp0,0);
17.游戏方向键WSAD定义
// 方向键 auto buttonW = Button::create("W.png", "W.png"); auto buttonS = Button::create("S.png", "S.png"); auto buttonA = Button::create("A.png", "A.png"); auto buttonD = Button::create("D.png", "D.png"); buttonW->setPosition(Vec2(origin.x + 60, origin.y + 60)); buttonS->setPosition(Vec2(origin.x + 60, origin.y + 20)); buttonA->setPosition(Vec2(origin.x + 20, origin.y + 20)); buttonD->setPosition(Vec2(origin.x + 100, origin.y + 20)); // W键事件处理函数 buttonW->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) { switch (type) { case ui::Widget::TouchEventType::BEGAN: schedule(schedule_selector(HelloWorld::moveW), 0.3f); break; case ui::Widget::TouchEventType::ENDED: unschedule(schedule_selector(HelloWorld::moveW)); break; } }); // S键事件处理函数 buttonS->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) { switch (type) { case ui::Widget::TouchEventType::BEGAN: schedule(schedule_selector(HelloWorld::moveS), 0.3f); break; case ui::Widget::TouchEventType::ENDED: unschedule(schedule_selector(HelloWorld::moveS)); break; } }); // A键事件处理函数 buttonA->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) { switch (type) { case ui::Widget::TouchEventType::BEGAN: schedule(schedule_selector(HelloWorld::moveA), 0.3f); break; case ui::Widget::TouchEventType::ENDED: unschedule(schedule_selector(HelloWorld::moveA)); break; } }); // D键事件处理函数 buttonD->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) { switch (type) { case ui::Widget::TouchEventType::BEGAN: schedule(schedule_selector(HelloWorld::moveD), 0.3f); break; case ui::Widget::TouchEventType::ENDED: unschedule(schedule_selector(HelloWorld::moveD)); break; } }); this->addChild(buttonW); this->addChild(buttonS); this->addChild(buttonA); this->addChild(buttonD); // 方向键D的移动 void HelloWorld::moveD(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), // MoveBy::create(0.15f, Vec2(10, 0))); auto location = player->getPosition(); if (location.x + 20 >= visibleSize.width) { auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(visibleSize.width-location.x-10, 0)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); return; } auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(20, 0)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); } // 方向键A的移动 void HelloWorld::moveA(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), //MoveBy::create(0.15f, Vec2(-10, 0))); auto location = player->getPosition(); if (location.x - 20 <= 0) { auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(-location.x+10, 0)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); return; } auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(-20, 0)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); } // 方向键W的移动 void HelloWorld::moveW(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), //MoveBy::create(0.15f, Vec2(0, 10))); auto location = player->getPosition(); if (location.y + 20 >= visibleSize.height) { auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, visibleSize.height-location.y-10)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); return; } auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, 20)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); } // 方向键S的移动 void HelloWorld::moveS(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), //MoveBy::create(0.15f, Vec2(0, -10))); auto location = player->getPosition(); if (location.y - 20 <= 0) { auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, -location.y+10)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); return; } auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, -20)), Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(seq); }
上面的按钮实现的是点击按钮移动,松开按钮停止移动。但是这种实现可能会有bug,莫名其妙人物就不受控制了。所以我将之改为点击一下移动一下,即松开鼠标按钮后人物才会移动:
// 方向键D的移动 void HelloWorld::moveD(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), // MoveBy::create(0.15f, Vec2(10, 0))); player->setFlipX(false); auto location = player->getPosition(); if (location.x + 20 >= visibleSize.width) { //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(visibleSize.width-location.x-10, 0)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(visibleSize.width - location.x - 10, 0))); return; } //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(20, 0)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(20, 0))); } // 方向键A的移动 void HelloWorld::moveA(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), //MoveBy::create(0.15f, Vec2(-10, 0))); player->setFlipX(true); auto location = player->getPosition(); if (location.x - 20 <= 0) { //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(-location.x+10, 0)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(-location.x + 10, 0))); return; } //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(-20, 0)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(-20, 0))); } // 方向键W的移动 void HelloWorld::moveW(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), //MoveBy::create(0.15f, Vec2(0, 10))); auto location = player->getPosition(); if (location.y + 20 >= visibleSize.height) { //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, visibleSize.height-location.y-10)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(0, visibleSize.height - location.y - 10))); return; } //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, 20)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(0, 20))); } // 方向键S的移动 void HelloWorld::moveS(float dt) { //auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation")), //MoveBy::create(0.15f, Vec2(0, -10))); auto location = player->getPosition(); if (location.y - 20 <= 0) { //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, -location.y+10)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(0, -location.y + 10))); return; } //auto seq = Sequence::createWithTwoActions(MoveBy::create(0.6f, Vec2(0, -20)), //Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); //player->runAction(seq); player->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("runAnimation"))); player->runAction(MoveBy::create(0.6f, Vec2(0, -20))); }
18.实现动画Animation的回调函数
auto callFunc = CallFunc::create([&] {isDone = true; }); auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("attackAnimation")), callFunc);
19.通过互斥锁避免动画重叠进行
(1)首先我在类中新添加一个isDone成员,当isDone为false时,说明player正在执行动画;当isDone为true时,说明player已经执行完动画;(2)将isDone初始为true,即可执行状态;
(3)在X、Y的点击事件处理函数的开始部分(在执行动画之前),添加一个条件判断,判断isDone是否为true。如果为true,则继续执行下面的代码,如果为false,则return函数;
(4)然后利用Sequence的createTwoAction来实现动画完成后的回调函数,回调函数的功能就是将isDone的值赋为true。
// 技能键X的事件处理函数
buttonX->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) {
switch (type) {
case ui::Widget::TouchEventType::BEGAN:
break;
case ui::Widget::TouchEventType::ENDED:
if (isDone == false) return; // 动画未完成,不能执行新动画
else isDone = false; // 开始执行动画
if (pT->getPercentage() == 0) return; // 进度条为0时不可再执行该动画
auto callFunc = CallFunc::create([&] {isDone = true; }); // 定义动画执行完毕的回调函数
/*Animate* deadAnimation = Animate::create(AnimationCache::getInstance()->getAnimation("deadAnimation"));
auto action = Sequence::create(callFunc);*/
auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("deadAnimation")),
callFunc);
player->runAction(seq);
//player->runAction(deadAnimation);
if (pT->getPercentage() - 40 >= 0) { // 每次X操作减少进度条40
pT->setPercentage(pT->getPercentage() - 40);
}
else {
pT->setPercentage(0);
}
break;
}
});
// 技能键Y的事件处理函数
buttonY->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) {
switch (type) {
case ui::Widget::TouchEventType::BEGAN:
break;
case ui::Widget::TouchEventType::ENDED:
if (isDone == false) return;
else isDone = false;
/*Animate* attackAnimation = Animate::create(AnimationCache::getInstance()->getAnimation("attackAnimation"));
player->runAction(attackAnimation);*/
auto callFunc = CallFunc::create([&] {isDone = true; }); auto seq = Sequence::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("attackAnimation")), callFunc);
player->runAction(seq);
if (pT->getPercentage() + 40 <= 100) {
pT->setPercentage(pT->getPercentage() + 40);
}
else {
pT->setPercentage(100);
}
break;
}
});
this->addChild(buttonX);
this->addChild(buttonY);
return true;
}
20.自定义调度器
switch (type) { case ui::Widget::TouchEventType::BEGAN: schedule(schedule_selector(HelloWorld::moveS), 0.3f); break; case ui::Widget::TouchEventType::ENDED: unschedule(schedule_selector(HelloWorld::moveS)); break;
21.Lambada函数
buttonA->addTouchEventListener([&](Ref* sender, Widget::TouchEventType type) { switch (type) { case ui::Widget::TouchEventType::BEGAN: schedule(schedule_selector(HelloWorld::moveA), 0.3f); break; case ui::Widget::TouchEventType::ENDED: unschedule(schedule_selector(HelloWorld::moveA)); break; } });
22. 单例模式示例
class Factory:public cocos2d::Ref { public: //获取单例工厂 static Factory* getInstance(); //生成一个怪物,并存储到容器中管理 Sprite* createMonster(); //让容器中的所有怪物都往角色移动,通过容器管理所有的怪物很方便 void moveMonster(Vec2 playerPos,float time); //移除怪物 void removeMonster(Sprite*); //判断碰撞 Sprite* collider(Rect rect); //初始化怪物帧动画 void initSpriteFrame(); private: Factory(); Vector<Sprite*> monster; cocos2d::Vector<SpriteFrame*> monsterDead; static Factory* factory; };
// Monster.cpp Factory* Factory::factory = NULL; Factory::Factory() { initSpriteFrame(); } // 获取单例 Factory* Factory::getInstance() { if (factory == NULL) { factory = new Factory(); } return factory; } // 生成monster死亡的动画帧并存入到vector数组中 void Factory::initSpriteFrame() { auto texture = Director::getInstance()->getTextureCache()->addImage("Monster.png"); monsterDead.reserve(4); for (int i = 0; i < 4; i++) { auto frame = SpriteFrame::createWithTexture(texture, CC_RECT_PIXELS_TO_POINTS(Rect(258 - 48 * i, 0, 42, 42))); monsterDead.pushBack(frame); } // 将这个动画加入到AnimationCache中 auto monsterdead_animation = Animation::createWithSpriteFrames(monsterDead, 0.1f); AnimationCache::getInstance()->addAnimation(monsterdead_animation, "monsterDeadAnimation"); } // 新建一个monster Sprite* Factory::createMonster() { Sprite* mons = Sprite::create("Monster.png", CC_RECT_PIXELS_TO_POINTS(Rect(364,0,42,42))); monster.pushBack(mons); return mons; } // 遍历删除与参数一致的monster void Factory::removeMonster(Sprite* sp) { cocos2d:Vector<Sprite*>::iterator it = monster.begin(); for (; it != monster.end(); it++) { if (*it == sp) { monster.erase(it); return; } } } // 实现monster朝着player的方向移动 void Factory::moveMonster(Vec2 playerPos,float time){ cocos2d:Vector<Sprite*>::iterator it = monster.begin(); for (; it != monster.end(); it++) { Vec2 monsterPos = (*it)->getPosition(); Vec2 direction = playerPos - monsterPos; direction.normalize(); // 得到该向量的单位向量,即向量除以向量的模 (*it)->runAction(MoveBy::create(time, direction*30)); } } // 当monster在rect的范围内时,返回指向该monster的指针 Sprite* Factory::collider(Rect rect) { cocos2d:Vector<Sprite*>::iterator it = monster.begin(); for (; it != monster.end(); it++) { Vec2 monsterPos = (*it)->getPosition(); if (rect.containsPoint(monsterPos)) { return (*it); } } return NULL; }
23.Monster朝Player方向移动
// 实现monster朝着player的方向移动 void Factory::moveMonster(Vec2 playerPos,float time){ cocos2d:Vector<Sprite*>::iterator it = monster.begin(); for (; it != monster.end(); it++) { Vec2 monsterPos = (*it)->getPosition(); Vec2 direction = playerPos - monsterPos; direction.normalize(); // 得到该向量的单位向量,即向量除以向量的模 (*it)->runAction(MoveBy::create(time, direction*30)); } }
24.碰撞检测
// 当monster在rect的范围内时,返回指向该monster的指针 Sprite* Factory::collider(Rect rect) { cocos2d:Vector<Sprite*>::iterator it = monster.begin(); for (; it != monster.end(); it++) { Vec2 monsterPos = (*it)->getPosition(); if (rect.containsPoint(monsterPos)) { return (*it); } } return NULL; } // 检测碰撞 // getBoundingBox()用于获取精灵外框区域 void HelloWorld::detectHit(float delta) { auto factory = Factory::getInstance(); Sprite* collision = factory->collider(player->getBoundingBox()); if (collision != NULL) { buttonX(); Animate* monsterDead = Animate::create(AnimationCache::getInstance()->getAnimation("monsterDeadAnimation")); collision->runAction(monsterDead); //collision->setVisible(false); // 碰到人物后怪物消失 CCActionInterval* fadeout = CCFadeOut::create(2); collision->runAction(fadeout); factory->removeMonster(collision); } }
25.生成处于随机位置的精灵
// 生成怪物 void HelloWorld::createMonster(float delta) { auto factory = Factory::getInstance(); auto monster = factory->createMonster(); monster->setPosition(random(origin.x, origin.x + visibleSize.width), random(origin.y, origin.y + visibleSize.height)); this->addChild(monster, 3); factory->moveMonster(player->getPosition(), 5); }
26.同步实现两个动画
// collision 是一个精灵对象 Animate* monsterDead = Animate::create(AnimationCache::getInstance()->getAnimation("monsterDeadAnimation")); collision->runAction(monsterDead); //collision->setVisible(false); // 碰到人物后怪物消失 CCActionInterval* fadeout = CCFadeOut::create(2); collision->runAction(fadeout);
27. 精灵的翻转
player->setFlipX(true); player->setFlipX(false);
28. 增加player左右各40的攻击范围
Rect playerRect = player->getBoundingBox(); Rect attackRect = Rect(playerRect.getMinX() - 40, playerRect.getMinY(), playerRect.getMaxX() - playerRect.getMinX() + 80, playerRect.getMaxY() - playerRect.getMinY());
Rect 的第一二个参数为左下角的x,y坐标,第三个参数为宽,第四个参数为高。
29. 渐渐淡出消失的动画
CCActionInterval* fadeout = CCFadeOut::create(2); collision->runAction(fadeout); factory->removeMonster(collision);
30. 本地存储UserDefault
# define database UserDefault::getInstance() database->setIntegerForKey("killNum", dtime); // 当set完后,数据不会马上保存到XML文件中。所以一定要记得用flush()来保存数据,否则会丢失 database->flush(); // 查询xml存放的路径 log("%s", FileUtils::getInstance()->getWritablePath().c_str());
31. HttpClient
POST请求HttpRequest* request = new HttpRequest(); request->setUrl("http://localhost:8080/login"); request->setRequestType(HttpRequest::Type::POST); request->setResponseCallback(CC_CALLBACK_2(LoginScene::onHttpRequestComplete, this)); request->setTag("POST test"); String str = "username=" + textField->getString(); const char* postData = str.getCString(); request->setRequestData(postData, strlen(postData)); cocos2d::network::HttpClient::getInstance()->send(request); request->release(); void LoginScene::onHttpRequestComplete(HttpClient *sender, HttpResponse *response) { if (!response) { return; } if (!response->isSucceed()) { log("response fail!"); log("error buffer:%s", response->getErrorBuffer()); return; } std::vector<char> *buffer = response->getResponseData(); printf("Http Text, dump data: "); for (unsigned int i = 0; i < buffer->size(); i++) { printf("%c", (*buffer)[i]); } printf("\n"); string head = ""; std::vector<char> *header = response->getResponseHeader(); for (unsigned int i = 0; i < header->size(); i++) { head += (*header)[i]; } // 在登录请求完毕后,获取该用户的gameSessionId Global::gameSessionId = Global::getSessionIdFromHeader(head); UserDefault* default = UserDefault::getInstance(); default->setStringForKey("Me", Global::gameSessionId); }
GET请求
HttpRequest* request = new HttpRequest(); string str = "http://localhost:8080/rank?top=" + rank_str; request->setUrl(str.c_str()); request->setRequestType(HttpRequest::Type::GET); request->setTag("GET test"); vector<string> headers; headers.push_back("Cookie: GAMESESSIONID=" + Global::gameSessionId); request->setHeaders(headers); request->setResponseCallback(CC_CALLBACK_2(GameScene::onHttpRequestComplete1, this)); cocos2d::network::HttpClient::getInstance()->send(request); request->release(); // rank的请求完成函数 void GameScene::onHttpRequestComplete1(HttpClient *sender, HttpResponse *response) { if (!response) { return; } if (!response->isSucceed()) { log("response fail!"); log("error buffer:%s", response->getErrorBuffer()); return; } std::vector<char> *buffer = response->getResponseData(); printf("Http Text, dump data: "); string str; for (unsigned int i = 0; i < buffer->size(); i++) { printf("%c", (*buffer)[i]); str += (*buffer)[i]; } printf("\n"); // rank_field->setString(str); // 对返回的json进行解析 rapidjson::Document d; d.Parse<0>(str.c_str()); string info = d["info"].GetString(); str = ""; for (unsigned int i = 1; i < info.size(); i++) { if (info[i] != '|') { str += info[i]; } else { str += "\n"; } } rank_field->setString(str); }
32. 实现自动化登录
从createScene函数中开刀:Scene* LoginScene::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); Global::gameSessionId = UserDefault::getInstance()->getStringForKey("Me"); if (Global::gameSessionId != "") { auto layer = GameScene::create(); scene->addChild(layer); } else { // 'layer' is an autorelease object auto layer = LoginScene::create(); // add layer as a child to scene scene->addChild(layer); } // return the scene return scene; }
33.页面跳转
以跳转GameScene页面为例:// 页面跳转 auto sc = GameScene::createScene(); Director::getInstance()->pushScene(sc);
相关文章推荐
- cocos2d-x学习笔记(持续更新)
- (转载)cocos2d-x学习笔记(持续更新)
- cocos2d-x学习笔记(持续更新)
- Cocos2d-js 热更新学习笔记
- Cocos2d-x 3.6版本学习笔记-热更新
- cocos2d-x学习笔记(持续更新)
- ACE学习笔记--持续更新中
- ASP.NET MVC 1.0 学习笔记(随时更新)
- Win32Asm学习笔记[不断更新]
- jquery.Validation.js 学习笔记 [待更新](API 和 DEMO等)
- MyEclipse 学习笔记与使用技巧(不断更新)
- Java6学习笔记53——枚举类型(更新)
- .net 4.0 学习笔记(2)—— CLR和BCL的更新
- wpf学习笔记-更新数据源
- [2008-04-09 10:31]IDA Pro Plug-in 学习笔记(不断更新ing)
- JavaScript学习笔记已经更新完毕
- 关于c++的学习情况,不再更新了,因为找到了更好的笔记记录工具
- 3D学习笔记之一句话总结(不断更新中)
- (更新中)JavaScript学习笔记
- OpenCV学习笔记(4)视频文件的读取与保存(2010-01-23 更新)