这里主要为敌人添加了一个移动动作和攻击动作。
移动动作是很简略的我动他也动的方式。
攻击动作是很简单的我打他也打的方式。
效果:
代码:
#ifndef __Progress__ #define __Progress__ #include "cocos2d.h" USING_NS_CC; class Progress : public Sprite { public: bool init(const char* background, const char* fillname); /* the inputs are SpriteFrame Names. they should be loaded into SpriteFrameCache before calling this. */ static Progress* create(const char* background, const char* fill); void setFill(ProgressTimer* fill){_fill=fill;} void setProgress(float percentage){_fill->setPercentage(percentage);} float getProgress() { return _fill->getPercentage(); } private: ProgressTimer* _fill; }; #endif
#include "Progress.h" bool Progress::init(const char* background, const char* fillname) { this->initWithSpriteFrameName(background); ProgressTimer* fill = ProgressTimer::create(Sprite::createWithSpriteFrameName(fillname)); this->setFill(fill); this->addChild(fill); fill->setType(ProgressTimer::Type::BAR); fill->setMidpoint(Point(0,0.5)); fill->setBarChangeRate(Point(1.0, 0)); fill->setPosition(this->getContentSize()/2); fill->setPercentage(100); return true; } Progress* Progress::create(const char* background, const char* fillname) { Progress* progress = new Progress(); if(progress && progress->init(background,fillname)) { progress->autorelease(); return progress; } else { delete progress; progress = NULL; return NULL; } }
#ifndef __Player__ #define __Player__ #include "cocos2d.h" #include "Progress.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 playAnimation(std::string animationName); void walkTo(Vec2 dest); Sequence* getSeq() { return _seq; } void getHit(); void autoDoAction(Player* hero); void autoAttack(Player* hero); Progress* getProgress() { return _progress; } private: PlayerType _type; std::string _name; int _animationNum = 5; float _speed; std::vector<int> _animationFrameNums; std::vector<std::string> _animationNames; Sequence* _seq; Progress* _progress; bool _isShowBar; }; #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"; _isShowBar = false; 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"; _isShowBar = true; int animationFrameNums[5] = {21, 21, 24, 30, 24}; _animationFrameNums.assign(animationFrameNums, animationFrameNums+5); _speed = 70; break; } } this->initWithSpriteFrameName(sfName); this->addAnimation(); auto size = this->getContentSize(); _progress = Progress::create("small-enemy-progress-bg.png","small-enemy-progress-fill.png"); _progress->setPosition( size.width/2, size.height + _progress->getContentSize().height/2); this->addChild(_progress); if(!_isShowBar) { _progress->setVisible(false); } return true; } Player* Player::create(PlayerType type) { Player* player = new Player(); if (player && player->initWithPlayerType(type)) { player->autorelease(); player->setAnchorPoint(Vec2(0.5, 0)); 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::playAnimation(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 func = [&]() { this->stopAllActions(); this->playAnimationForever("stay"); _seq = nullptr; }; auto callback = CallFunc::create(func); auto animate = Sequence::create(Animate::create(animation), callback,NULL); 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); this->stopAllActions(); this->playAnimationForever("walk"); _seq = Sequence::create(moveTo, callback, nullptr); this->runAction(_seq); } void Player::getHit() { float blood = _progress->getProgress(); if (_name == "hero") blood -= 3; else blood -= 5; _progress->setProgress(blood); log(String::createWithFormat("hit now blood is %f", blood)->getCString()); if (blood <= 0) { log(String::createWithFormat("%s is dead.", _name.c_str())->getCString()); auto func = [&]() { this->stopAllActions(); this->playAnimation("dead"); }; auto callback = CallFunc::create(func); _seq = Sequence::create(callback, nullptr); this->runAction(_seq); this->_progress->setVisible(false); this->setVisible(false); return; } } void Player::autoDoAction(Player* hero) // just for _enemy { Vec2 dest = hero->getPosition(); 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; if (diff.x > 0) diff.x -= 90; else diff.x += 90; if (diff.y > 0) diff.y -= 20; else diff.y += 20; 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); this->stopAllActions(); this->playAnimationForever("walk"); _seq = Sequence::create(moveTo, callback, nullptr); this->runAction(_seq); } void Player::autoAttack(Player* hero) // just for _enemy { float blood = _progress->getProgress(); if (blood <= 0) return; Vec2 del = this->getPosition() - hero->getPosition(); if (del.length() <= 100) { this->playAnimation("attack"); hero->getHit(); } }
#ifndef __MainScene__ #define __MainScene__ #include "cocos2d.h" #include "Player.h" #include "Progress.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); void attackCallback(Ref* pSender); private: Player* _hero; Player* _enemy; EventListenerTouchOneByOne* _listener_touch; Progress* _progress; }; #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"); SpriteFrameCache::getInstance()->addSpriteFramesWithFile("images/ui.plist","images/ui.pvr.ccz"); 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); auto attackItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(MainScene::attackCallback, this)); attackItem->setPosition(Vec2(origin.x + visibleSize.width - attackItem->getContentSize().width/2 , origin.y + attackItem->getContentSize().height/2)); // create menu, it's an autorelease object auto menu = Menu::create(attackItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); _progress = Progress::create("player-progress-bg.png","player-progress-fill.png"); _progress->setPosition(_progress->getContentSize().width/2, this->getContentSize().height - _progress->getContentSize().height/2); this->addChild(_progress); 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"); _enemy->autoDoAction(_hero); return true; } void MainScene::attackCallback(Ref* pSender) { _hero->stopAllActions(); _hero->playAnimation("attack"); Vec2 del = _hero->getPosition() - _enemy->getPosition(); float distance = del.length(); log(String::createWithFormat("distance == %f", distance)->getCString()); if (distance <= 100.0) { _enemy->getHit(); } _enemy->autoAttack(_hero); _progress->setProgress(_hero->getProgress()->getProgress()); }
------------华丽的分割线------------
最近工作上出了一点事情。可能暂时就写到这里了。希望以后有机会能够再补上接下来的内容。
参考教程:http://www.cocos.com/doc/tutorial/lists?id=85
项目github地址:https://github.com/moonlightpoet/HuanHero