主要的调整就是将HelloWorldScene改成了MainSecne,然后将Player作为了MainScene的私有成员变量来处理。修改了人物图片,使用了网上找到的三国战纪的人物素材代替我之前画的很差劲的人物素材。
是gif动画,下载了之后用photeshop分解成了一个个png图片。
然后在window下用破解的TexturePacker生成了role.plist和role.png文件。
改动后的代码还增加了移动的部分。
MainScene.cpp部分代码:
_listener_touch = EventListenerTouchOneByOne::create(); _listener_touch->onTouchBegan = CC_CALLBACK_2(MainScene::onTouchBegan,this); _eventDispatcher->addEventListenerWithSceneGraphPriority(_listener_touch, this);
Player.cpp部分代码:
void Player::walkTo(Vec2 dest) { if (_seq) this->stopAction(_seq); auto curPos = this->getPosition(); if (curPos.x > dest.x) this->setFlippedX(true); else this->setFlippedX(false); auto diff = dest - curPos; auto time = diff.getLength() / _speed; auto moveTo = MoveTo::create(time, dest); auto func = [&]() { this->stopAllActions(); this->playAnimationForever("stay"); _seq = nullptr; }; auto callback = CallFunc::create(func); _seq = Sequence::create(moveTo, callback, nullptr); this->runAction(_seq); this->playAnimationForever("walk"); }
效果:
#ifndef __MainScene__ #define __MainScene__ #include "cocos2d.h" #include "Player.h" USING_NS_CC; class MainScene : public cocos2d::Layer { public: static cocos2d::Scene* createScene(); virtual bool init(); void menuCloseCallback(cocos2d::Ref* pSender); CREATE_FUNC(MainScene); bool onTouchBegan(Touch* touch, Event* event); private: Player* _hero; Player* _enemy; EventListenerTouchOneByOne* _listener_touch; }; #endif
#include "MainScene.h" Scene* MainScene::createScene() { auto scene = Scene::create(); auto layer = MainScene::create(); scene->addChild(layer); return scene; } bool MainScene::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); SpriteFrameCache::getInstance()->addSpriteFramesWithFile("images/role.plist","images/role.png"); Sprite* background = Sprite::create("images/background.png"); background->setPosition(origin + visibleSize/2); this->addChild(background); //add player _hero = Player::create(Player::PlayerType::HERO); _hero->setPosition(origin.x + _hero->getContentSize().width/2, origin.y + visibleSize.height/2); this->addChild(_hero); //add enemy1 _enemy = Player::create(Player::PlayerType::ENEMY); _enemy->setPosition(origin.x + visibleSize.width - _enemy->getContentSize().width/2, origin.y + visibleSize.height/2); this->addChild(_enemy); _hero->playAnimationForever("stay"); _enemy->playAnimationForever("stay"); _listener_touch = EventListenerTouchOneByOne::create(); _listener_touch->onTouchBegan = CC_CALLBACK_2(MainScene::onTouchBegan,this); _eventDispatcher->addEventListenerWithSceneGraphPriority(_listener_touch, this); return true; } void MainScene::menuCloseCallback(cocos2d::Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } bool MainScene::onTouchBegan(Touch* touch, Event* event) { Vec2 pos = this->convertToNodeSpace(touch->getLocation()); _hero->walkTo(pos); log("MainScene::onTouchBegan"); return true; }
#ifndef __Player__ #define __Player__ #include "cocos2d.h" USING_NS_CC; class Player : public Sprite { public: enum PlayerType { HERO, ENEMY }; bool initWithPlayerType(PlayerType type); static Player* create(PlayerType type); void addAnimation(); void playAnimationForever(std::string animationName); void walkTo(Vec2 dest); private: PlayerType _type; std::string _name; int _animationNum = 5; float _speed; std::vector<int> _animationFrameNums; std::vector<std::string> _animationNames; Sequence* _seq; }; #endif
#include "Player.h" #include <iostream> bool Player::initWithPlayerType(PlayerType type) { std::string sfName = ""; std::string animationNames[5] = {"attack", "dead", "hit", "stay", "walk"}; _animationNames.assign(animationNames,animationNames+5); switch (type) { case PlayerType::HERO: { _name = "hero"; sfName = "hero-stay0000.png"; int animationFrameNums[5] = {10, 12, 15, 30, 24}; _animationFrameNums.assign(animationFrameNums, animationFrameNums+5); _speed = 125; break; } case PlayerType::ENEMY: { _name = "enemy"; sfName = "enemy-stay0000.png"; int animationFrameNums[5] = {21, 21, 24, 30, 24}; _animationFrameNums.assign(animationFrameNums, animationFrameNums+5); break; } } this->initWithSpriteFrameName(sfName); this->addAnimation(); return true; } Player* Player::create(PlayerType type) { Player* player = new Player(); if (player && player->initWithPlayerType(type)) { player->autorelease(); return player; } else { delete player; player = NULL; return NULL; } } void Player::addAnimation() { auto animation = AnimationCache::getInstance()->getAnimation(String::createWithFormat("%s-%s", _name.c_str(), _animationNames[0].c_str())->getCString()); if (animation) return; for (int i = 0; i < _animationNum; i ++) { auto animation = Animation::create(); animation->setDelayPerUnit(1.0f / 10.0f); for (int j = 0; j < _animationFrameNums[i]; j ++) { auto sfName = String::createWithFormat("%s-%s%04d.png", _name.c_str(), _animationNames[i].c_str(), j)->getCString(); animation->addSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(sfName)); if (!animation) log("hello ha ha"); } AnimationCache::getInstance()->addAnimation(animation, String::createWithFormat("%s-%s", _name.c_str(), _animationNames[i].c_str())->getCString()); } } void Player::playAnimationForever(std::string animationName) { auto str = String::createWithFormat("%s-%s", _name.c_str(), animationName.c_str())->getCString(); bool exist = false; for (int i = 0; i < _animationNum; i ++) { if (animationName == _animationNames[i]) { exist = true; break; } } if (exist == false) return; auto animation = AnimationCache::getInstance()->getAnimation(str); auto animate = RepeatForever::create(Animate::create(animation)); this->runAction(animate); } void Player::walkTo(Vec2 dest) { if (_seq) this->stopAction(_seq); auto curPos = this->getPosition(); if (curPos.x > dest.x) this->setFlippedX(true); else this->setFlippedX(false); auto diff = dest - curPos; auto time = diff.getLength() / _speed; auto moveTo = MoveTo::create(time, dest); auto func = [&]() { this->stopAllActions(); this->playAnimationForever("stay"); _seq = nullptr; }; auto callback = CallFunc::create(func); _seq = Sequence::create(moveTo, callback, nullptr); this->runAction(_seq); this->playAnimationForever("walk"); }
补充:
EventDispatcher事件分发机制先创建事件,注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流。