本节课的视频教程地址是:第六课在此
如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,可以免费领取30天学习时间,免费拿极客学院VIP,1000+高清视频,学习Android、HTML5、iOS各种开发技术,限时领取,手快的戳:http://e.jikexueyuan.com/invite/index.html?ZnJvbV9jb2RlPVkxblJUZSZ1bmFtZT1TdW9vTCZjaGFubmVsPWludml0ZV8xMDB3X3NoYXJlYnV0dG9uX2RpcmVjdDE=,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持!

转载请注明出处:http://blog.csdn.net/suool/article/details/46851335

前言

经过前面五节课的学习我们目前还剩的未完成的工作就是游戏的核心场景——游戏场景。这节课我们就来学习如何实现游戏的核心场景。(核心场景的逻辑功能完成放在下一课。)

根据我们在第一课中对整个核心游戏场景的基本分析和分解可以知道,游戏场景主要分为三层,分别是:
地图层:包含一个多层滚动视差地图以及我们的游戏实体
控制层:控制英雄动作的按钮以及游戏暂停的按钮所在的层
实体状态展示层:展示实体和怪物当前状态的层

所以,本节课我们主要要学习的就是如何分析和实现这三个层。

游戏主场景地图层的实现

这一部分主要是两个知识点:

  • 视差节点ParallaxNode学习
  • 地图层的分析和实现
    因为我们游戏的地图场景要模仿现实世界中的物理规则,所以游戏场景不可能是一张背景图片就可以解决的。整个游戏的环境是由四层图片贴成的,一个是不会动的”远处“背景,剩下三个是按照现实世界视差效果移动的三层地图:人物前面的草丛,人物所在的地面,任务后面的房屋。
    如下图示:

视差节点ParallaxNode学习

首先要知道什么是视差?
视差的含义是指对象的位置相对于背景的变化取决于观察者的位置。毕竟三维世界的特性被广泛的应用于在二维游戏创造出景深的效果。
示意图如下:

在Cocos2d-x中有一个视差节点ParallaxNode提供了根据他视差比例决定子节点卷动速度变快或变慢。
其次就是视差节点 ParallaxNode类的学习

  • 重点API函数
  • 使用场景和示例
//Parallax(视差) #ifndef __CCPARALLAX_NODE_H__
#define __CCPARALLAX_NODE_H__#include "base_nodes/CCNode.h"
/*#include "support/data_support/ccArray.h"*/NS_CC_BEGINstruct _ccArray;/*** @addtogroup tilemap_parallax_nodes* @{*//** @brief ParallaxNode: A node that simulates a parallax scroller      //模拟视差滚动的节点children 移动的 faster / slower 是根据 parent 视差比确定的*/
class CC_DLL ParallaxNode : public Node
{
public:// Create a Parallax(视差) nodestatic ParallaxNode * create();/** 使用 z-顺序,视差比和位置偏移 在内容里面添加一个 child It returns self, 你可以连接几个 addChilds.@since v0.8* @js ctor*/ParallaxNode();/*** @js NA* @lua NA*/virtual ~ParallaxNode();// 防止编译器警告:“包括函数隐藏重载虚函数”using Node::addChild;// 将节点添加到ParallaxNode上边,各个参数的意义:第一个参数是要添加的节点,第二个参数是zorder,决定显示的顺序,第三个参数是速率,这个如何理解,就是如果你得node移动的速度是1,那么你得速度是相对于这个1的多少,这里写得是(0.5,0)意思就是当我的parallax向左移动的1个单位的时候,该子节点移动的就是0.5个单位,y方向上没有速度,最后一个是坐标,注意这个坐标是相对于node节点的坐标,而不是当前的层void addChild(Node * child, int z, const Point& parallaxRatio, const Point& positionOffset);/** 为 Parallax(视差) 节点设置一个 layer 数组 */void setParallaxArray( struct _ccArray *parallaxArray) { _parallaxArray = parallaxArray; }/** Returns Parallax(视差) 节点的 layer 数组 */struct _ccArray* getParallaxArray() { return _parallaxArray; }const struct _ccArray* getParallaxArray() const { return _parallaxArray; }//// Overrides//virtual void addChild(Node * child, int zOrder, int tag) override;virtual void removeChild(Node* child, bool cleanup) override;virtual void removeAllChildrenWithCleanup(bool cleanup) override;virtual void visit(void) override;protected:Point absolutePosition();Point    _lastPosition;struct _ccArray* _parallaxArray;
};// end of tilemap_parallax_nodes group
/// @}NS_CC_END#endif //__CCPARALLAX_NODE_H__

再看下他的实现源码:

#include "CCParallaxNode.h"
#include "ccCArray.h"NS_CC_BEGIN
/** PointObject用于记录CCParallaxNode孩子节点的ratio和offset属性 **/  class PointObject : public Ref
{
public:static PointObject * create(Point ratio, Point offset){PointObject *ret = new PointObject();ret->initWithPoint(ratio, offset);ret->autorelease();return ret;}bool initWithPoint(Point ratio, Point offset){_ratio = ratio;_offset = offset;_child = nullptr;return true;}inline const Point& getRatio() const { return _ratio; };inline void setRatio(const Point& ratio) { _ratio = ratio; };inline const Point& getOffset() const { return _offset; };inline void setOffset(const Point& offset) { _offset = offset; };inline Node* getChild() const { return _child; };inline void setChild(Node* child) { _child = child; };private:Point _ratio;Point _offset;Node *_child; // weak ref
};
// 构造函数
ParallaxNode::ParallaxNode()
{_parallaxArray = ccArrayNew(5);        _lastPosition = Point(-100,-100);
}
// 析构函数
ParallaxNode::~ParallaxNode()
{if( _parallaxArray ){ccArrayFree(_parallaxArray);_parallaxArray = nullptr;}
}
// 创建函数
ParallaxNode * ParallaxNode::create()
{ParallaxNode *ret = new ParallaxNode();ret->autorelease();return ret;
}
// 添加子节点
void ParallaxNode::addChild(Node * child, int zOrder, int tag)
{CC_UNUSED_PARAM(zOrder);CC_UNUSED_PARAM(child);CC_UNUSED_PARAM(tag);CCASSERT(0,"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead");
}
//
void ParallaxNode::addChild(Node *child, int z, const Point& ratio, const Point& offset)
{CCASSERT( child != nullptr, "Argument must be non-nil");// 记录属性PointObject *obj = PointObject::create(ratio, offset);obj->setChild(child);// 扩容ccArrayAppendObjectWithResize(_parallaxArray, (Ref*)obj);// 当ParallaxNode的位置不是(0,0)时添加孩子,会发生比较诡异的事情  Point pos = this->absolutePosition();pos.x = -pos.x + pos.x * ratio.x + offset.x;pos.y = -pos.y + pos.y * ratio.y + offset.y;child->setPosition(pos);Node::addChild(child, z, child->getTag());
}void ParallaxNode::removeChild(Node* child, bool cleanup)
{// 删除属性for( int i=0;i < _parallaxArray->num;i++){PointObject *point = (PointObject*)_parallaxArray->arr[i];if (point->getChild() == child){ccArrayRemoveObjectAtIndex(_parallaxArray, i, true);break;}}// 删除NodeNode::removeChild(child, cleanup);
}void ParallaxNode::removeAllChildrenWithCleanup(bool cleanup)
{ccArrayRemoveAllObjects(_parallaxArray);Node::removeAllChildrenWithCleanup(cleanup);
}Point ParallaxNode::absolutePosition()
{Point ret = _position;Node *cn = this;//层层向上计算,获得绝对坐标,至于为什么需要这样,下面有段注释 while (cn->getParent() != nullptr){cn = cn->getParent();ret = ret + cn->getPosition();}return ret;
}/*
The positions are updated at visit because:
- using a timer is not guaranteed that it will called after all the positions were updated
- overriding "draw" will only precise if the children have a z > 0
*/
void ParallaxNode::visit(Renderer *renderer, const kmMat4 &parentTransform, bool parentTransformUpdated)
{//    Point pos = position_;//    Point    pos = [self convertToWorldSpace:Point::ZERO];Point pos = this->absolutePosition();if( ! pos.equals(_lastPosition) ){// 计算所有孩子相对于CCParallaxNode的位置,注意当我们移动CCParallaxNode位置时,表现出来的其实是孩子位置的改变,这种变化是本类的核心设计。  for( int i=0; i < _parallaxArray->num; i++ ) {PointObject *point = (PointObject*)_parallaxArray->arr[i];//例如CCParallaxNode绝对位置为100,表现出来的是孩子位置为-100,CCParallaxNode的移动我们不能感知,但孩子的位置却发生了变化。  //简单点就是类似于一个摄像头场景的移动,摄像头未动,风景变了  //如果ratio为1,则postion == offset  //如果ratio为(0,1),则position < offset,移动速度慢  //如果ratio为(1,xx),则postion > offset,移动速度快  float x = -pos.x + pos.x * point->getRatio().x + point->getOffset().x;float y = -pos.y + pos.y * point->getRatio().y + point->getOffset().y;       //孩子的位置是通过上面两行计算出来的,因此手动设置其postion不会有任何作用 point->getChild()->setPosition(Point(x,y));}// 更新位置_lastPosition = pos;}Node::visit(renderer, parentTransform, parentTransformUpdated);
}NS_CC_END

以上就是Cocos2d-x的视差节点的实现过程。使用起来非常简单,但是实现过程值得我们去借鉴和思考。

地图层的分析和实现

下面就是我们的游戏的地图层的实现代码:

/*!* \file GameMap.h* \date 2015/06/08 11:19** \author SuooL* Contact: hu1020935219@gmail.com** \brief ** TODO: long description** \note
*/#ifndef __GameMap__H__
#define __GameMap__H__#include "cocos2d.h"
USING_NS_CC;class Hero;class GameMap : public Node
{
public:GameMap();~GameMap();// 初始化地图void InitMap(const char *map_name1,const char *map_name2, const char *map_name3);//根据精灵的位置移动地图,visibleSize为当前窗口的大小void MoveMap(Hero *hero);//判断地图是否到达边缘bool JudgeMap(Hero *hero);CREATE_FUNC(GameMap);
private:Sprite* m_map1;Sprite* m_map2;Sprite* m_map3;ParallaxNode* parallax;
};#endif

cpp文件:

/*!* \class GameMap** \ingroup GroupName** \brief ** TODO: long description** \note ** \author SuooL** \version 1.0** \date 六月 2015** Contact: hu1020935219@gmail.com**/#include "GameMap.h"
#include "GlobalDefine.h"
#include "Hero.h"
#include "cocos2d.h"USING_NS_CC;GameMap::GameMap()
{m_map1 = NULL;m_map2 = NULL;m_map3 = NULL;
}
GameMap::~GameMap()
{
}void GameMap::InitMap(const char *map_name1,const char *map_name2,const char *map_name3)
{this->m_map1 = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(map_name1));this->m_map2 = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(map_name2));this->m_map3 = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(map_name3));m_map1->setAnchorPoint(Point(0, 0));m_map1->setTag(11);m_map2->setAnchorPoint(Point(0, 0));m_map3->setAnchorPoint(Point(0, 0));parallax = ParallaxNode::create();parallax->addChild(m_map1, 1, Point(1.18, 0), Point(0,360));parallax->addChild(m_map2, 2, Point(1, 0), Point(0,0));parallax->addChild(m_map3, 3, Point(0.7, 0), Point(0, 0));this->setAnchorPoint(ccp(0, 0));this->addChild(parallax);log("%f%f", parallax->getPositionX(), parallax->getPositionY());log("%f%f", parallax->getContentSize().width, parallax->getContentSize().height);log("%f%f", m_map1->getContentSize().width, m_map1->getContentSize().height);
}void GameMap::MoveMap(Hero *hero)//
{auto map = (Sprite*)parallax->getChildByTag(11);if (hero->JudgePosition(WINSIZE) && hero->HeroDirecton == false)//精灵运动到中间,地图才移动{if (this->getPositionX() >= -(m_map2->getContentSize().width - WINSIZE.width))//防止地图左边运动后超出边缘this->setPosition(this->getPositionX() - hero->m_iSpeed, this->getPositionY());log("map is %f", this->getPositionX());}if (hero->JudgePosition(WINSIZE) && hero->HeroDirecton == true)//精灵运动到中间,地图才移动{log("Hero Walk Left %f", hero->getPositionX());log("map is %f", this->getPositionX());if (this->getPositionX() <= -10)                      //防止地图左边运动后超出边缘this->setPosition(this->getPositionX() + hero->m_iSpeed, this->getPositionY());}
}
bool GameMap::JudgeMap(Hero *hero)
{if (this->getPositionX() >= -(m_map2->getContentSize().width - WINSIZE.width) && hero->HeroDirecton == false)//防止地图左边运动后超出边缘return false;else if (this->getPositionX() <= -10 && hero->HeroDirecton == true)  //防止地图左边运动后超出边缘return false;else //地图已经移动到达边缘return true;
}

游戏主场景控制层的分析和实现

这一部分也是有两个点:

  • ControlButton的学习和使用
  • 控制层的分析和实现
    因为整个控制的组成如下:(暂停按钮没有框出来)

    可以看出都是按钮。其中被框出来的按钮时ControlButton制作的,而暂停按钮则是以前的MenuItemSprite制作的。
    为什么要用ControlButton呢?因为用户按按钮的时候有很多种情况判断,但是MenuItem系的按钮事件都封装的很简单,如果此处采用MenuItem会实际用手操作的时候发现有一堆的问题。

ControlButton的学习和使用


上面就是ControlButton的类图。可以看出其继承自Control控件类,这个类在之前讲ControlSlider的时候就说过。
ControlButton使用的背景图片是点九图CCScale9Sprite,可以使得按钮在变大的情况下,尽量保持棱角不失真。
1、按钮状态

    /** The possible state for a control.  */enum class State{NORMAL         = 1 << 0, // The normal, or default state of a control—that is, enabled but neither selected nor highlighted.HIGH_LIGHTED   = 1 << 1, // Highlighted state of a control. A control enters this state when a touch down, drag inside or drag enter is performed. You can retrieve and set this value through the highlighted property.DISABLED       = 1 << 2, // Disabled state of a control. This state indicates that the control is currently disabled. You can retrieve and set this value through the enabled property.SELECTED       = 1 << 3  // Selected state of a control. This state indicates that the control is currently selected. You can retrieve and set this value through the selected property.};

2、按钮事件

    enum class EventType{TOUCH_DOWN           = 1 << 0,    // A touch-down event in the control.DRAG_INSIDE          = 1 << 1,    // An event where a finger is dragged inside the bounds of the control.DRAG_OUTSIDE         = 1 << 2,    // An event where a finger is dragged just outside the bounds of the control.DRAG_ENTER           = 1 << 3,    // An event where a finger is dragged into the bounds of the control.DRAG_EXIT            = 1 << 4,    // An event where a finger is dragged from within a control to outside its bounds.TOUCH_UP_INSIDE      = 1 << 5,    // A touch-up event in the control where the finger is inside the bounds of the control.TOUCH_UP_OUTSIDE     = 1 << 6,    // A touch-up event in the control where the finger is outside the bounds of the control.TOUCH_CANCEL         = 1 << 7,    // A system event canceling the current touches for the control.VALUE_CHANGED        = 1 << 8      // A touch dragging or otherwise manipulating a control, causing it to emit a series of different values.};

3、绑定按钮事件的方法

    /*** Adds a target and action for a particular event (or events) to an internal* dispatch table.* The action message may optionnaly include the sender and the event as* parameters, in that order.* When you call this method, target is not retained.** @param target The target object that is, the object to which the action* message is sent. It cannot be nil. The target is not retained.* @param action A selector identifying an action message. It cannot be NULL.* @param controlEvents A bitmask specifying the control events for which the* action message is sent. See "CCControlEvent" for bitmask constants.*/virtual void addTargetWithActionForControlEvents(Ref* target, Handler action, EventType controlEvents);/*** Removes a target and action for a particular event (or events) from an* internal dispatch table.** @param target The target object梩hat is, the object to which the action* message is sent. Pass nil to remove all targets paired with action and the* specified control events.* @param action A selector identifying an action message. Pass NULL to remove* all action messages paired with target.* @param controlEvents A bitmask specifying the control events associated with* target and action. See "CCControlEvent" for bitmask constants.*/virtual void removeTargetWithActionForControlEvents(Ref* target, Handler action, EventType controlEvents);

常用操作如下

//
class ControlButton : public Control
{
/***     创建ControlButton的方法*/static ControlButton* create();static ControlButton* create(Scale9Sprite* sprite);static ControlButton* create(Node* label, Scale9Sprite* backgroundSprite);static ControlButton* create(const std::string& title, const std::string& fontName, float fontSize);
//###############################################################################//使用点九图CCScale9Sprite,设置在指定State下的 背景精灵virtual void setBackgroundSpriteForState(Scale9Sprite* sprite, State state);//使用精灵帧SpriteFrame,设置在指定State下的 背景精灵//其实在内部实现的代码,实际上是利用精灵帧spriteFrame创建了点九图Scale9Sprite作为背景精灵virtual void setBackgroundSpriteFrameForState(SpriteFrame* spriteFrame, State state);//获取在指定State下的 背景图virtual CCScale9Sprite* getBackgroundSpriteForState(State state);
/***     继承于父类*/virtual void setEnabled(bool enabled);     //是否启用virtual void setSelected(bool enabled);    //是否选中virtual void setHighlighted(bool enabled); //是否高亮
};
//

更多操作参见源码。
关于Control控件类大家可以看下这篇文章的分析:http://www.2cto.com/kf/201407/313448.html
关于ControlButton的分析参见这篇文章:http://shahdza.blog.51cto.com/2410787/1543349
看过之后就会对这些有一个差不多的理解了。
具体控制层的代码在下面和展示层一起贴出来。

实体状态展示层的分析和实现

主要组成如下:

可以看出其实就两个进度条的使用。因此我们用到了Cocos2d-x提供的ProgressTimer控件。

ProgressTimer的学习和使用

这个类的学习和使用已经有人写了非常好的说明教程,参加此处:http://shahdza.blog.51cto.com/2410787/1546707, 我这里就不做复用性的工作了。

下面是整个主场景的分析和实现代码(无逻辑处理部分)

// 头文件
/*!
* \file GameLayer.h
* \date 2015/06/13 16:55
*
* \author SuooL
* Contact: hu1020935219@gmail.com
*
* \brief 游戏场景
*
* TODO: long description
*
* \note
*/#ifndef __GameLayer__H__
#define __GameLayer__H__#include <iostream>
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "ActionTool.h"
#include "GlobalData.h"
#include "GlobalDefine.h"
#include "extensions/cocos-ext.h"
#include "Monster.h"USING_NS_CC;
using namespace extension;class Hero;
class ProgressBar;
class GameMap;class GameLayer : public Layer
{
public:static Scene* createScene();virtual bool init();// 暂停void gamePause(Ref* pSender);void gameOver(float delta);void gameVictory(float delta);// 技能--拳击--脚踢--超级技能--蹦void fistAttack(Ref* pSender, Control::EventType type);void footAttack(Ref* psender, Control::EventType type);void comboAttack(Ref* pSender, Control::EventType type);void jump(Ref* pSender, Control::EventType type);// 前进,后退void forward(Ref* pSender, Control::EventType type);void backward(Ref* pSender, Control::EventType type);virtual void update(float delta);CREATE_FUNC(GameLayer);private:// 英雄&怪物Hero* m_pHero;Monster* m_pMonster1;GameMap* myMap;// 背景条Sprite* m_pBG;// 血条,能量前景条ProgressTimer* m_pHPBar;ProgressTimer* m_pMPBar;ControlButton * m_pComboBtn;Sprite* m_pComboPic;};#endif

cpp文件

/*!
* \class GameLayer
*
* \ingroup GroupName
*
* \brief
*
* TODO: long description
*
* \note
*
* \author SuooL
*
* \version 1.0
*
* \date 六月 2015
*
* Contact: hu1020935219@gmail.com
*
*/
#include "GameLayer.h"
#include "GameMap.h"
#include "Hero.h"
#include "Monster.h"
#include "PauseLayer.h"
#include "GateMapLayer.h"
#include "MonsterOne.h"
#include "extensions/cocos-ext.h"
#include "cocostudio/CocoStudio.h"USING_NS_CC;
using namespace CocosDenshion;
using namespace cocos2d::extension; //引用cocos2d::extension命名空间Scene* GameLayer::createScene()
{Scene* scene = Scene::create();GameLayer* layer = GameLayer::create();scene->addChild(layer);return scene;
}bool GameLayer::init()
{if (!Layer::init()){return false;}if (getBoolFromXML(MUSIC_KEY)){float music = getFloatFromXML(MUSICVOL)*100.0f;aduioEngine->setBackgroundMusicVolume(getFloatFromXML(MUSICVOL));if (SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying()){aduioEngine->pauseBackgroundMusic();aduioEngine->playBackgroundMusic("Sound/gameBGM.wav", true);}elseaduioEngine->playBackgroundMusic("Sound/gameBGM.wav", true);}elseaduioEngine->pauseBackgroundMusic();velocity = 10.0f;m_bDirection = false;m_bRun = false;m_bJump = false;SpriteFrameCache::getInstance()->addSpriteFramesWithFile("pnglist/mapBefore.plist");SpriteFrameCache::getInstance()->addSpriteFramesWithFile("pnglist/mapRoad.plist");String *bgName = String::createWithFormat("bgmap%d.png", m_iSelectGate);String *midName = String::createWithFormat("MapMiddle%d.png", m_iSelectGate);String *groundName = String::createWithFormat("MapGround%d.png", m_iSelectGate);String *beforeName = String::createWithFormat("MapBefore%d.png", m_iSelectGate);String *comoboName = String::createWithFormat("comboBtn%d.png", m_iSelectGate);auto bgPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(bgName->getCString()));bgPic->setPosition(WINSIZE.width / 2, WINSIZE.height / 2);this->addChild(bgPic, 0);myMap = GameMap::create();myMap->InitMap(midName->getCString(), groundName->getCString(), beforeName->getCString());this->addChild(myMap, 1);// 界面控制键初始化// 技能键auto m_pFistBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("fist.png"));auto m_pFistBtn = ControlButton::create(m_pFistBG);m_pFistBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("fist.png"))->getContentSize());auto m_pFootBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("foot.png"));auto m_pFootBtn = ControlButton::create(m_pFootBG);m_pFootBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("foot.png"))->getContentSize());auto m_pJumpBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jump.png"));auto m_pJumpBtn = ControlButton::create(m_pJumpBG);m_pJumpBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jump.png"))->getContentSize());auto m_pComboBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(comoboName->getCString()));m_pComboBtn = ControlButton::create(m_pComboBG);m_pComboBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(comoboName->getCString()))->getContentSize());// 按键背景auto m_pFistPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("quan.png"));auto m_pFootPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("jiao.png"));auto m_pJumpPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tiao.png"));m_pComboPic = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tiao.png"));auto m_pFistPicSize = m_pFistPic->getContentSize();m_pFistBtn->setPosition(ccp(m_pFistPicSize.width / 2, m_pFistPicSize.height / 2));m_pFistBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::fistAttack), Control::EventType::TOUCH_UP_INSIDE);auto m_pFootPicSize = m_pFootPic->getContentSize();m_pFootBtn->setPosition(ccp(m_pFootPicSize.width / 2, m_pFootPicSize.height / 2));m_pFootBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::footAttack), Control::EventType::TOUCH_UP_INSIDE);auto m_pJumpPicSize = m_pJumpPic->getContentSize();m_pJumpBtn->setPosition(ccp(m_pJumpPicSize.width / 2.0 - 1.5, m_pJumpPicSize.height / 2));m_pJumpBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::jump), Control::EventType::TOUCH_UP_INSIDE);auto m_pComboPicSize = m_pComboPic->getContentSize();m_pComboBtn->setPosition(ccp(m_pComboPicSize.width / 2 - 1.5, m_pComboPicSize.height / 2));m_pComboBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::comboAttack), Control::EventType::TOUCH_UP_INSIDE);m_pFistPic->addChild(m_pFistBtn, 1);m_pFootPic->addChild(m_pFootBtn, 1);m_pJumpPic->addChild(m_pJumpBtn, 1);m_pComboPic->addChild(m_pComboBtn, 1);m_pFistPic->setPosition(WINSIZE.width - 230, 76);m_pFootPic->setPosition(WINSIZE.width - 73, 76);m_pJumpPic->setPosition(WINSIZE.width - 60, 220);m_pComboPic->setPosition(WINSIZE.width - 387, 76);m_pComboPic->setVisible(false);this->addChild(m_pFistPic, 1);this->addChild(m_pFootPic, 1);this->addChild(m_pJumpPic, 1);this->addChild(m_pComboPic, 1);// 行走控制键,暂停键auto puaseGameItem = MenuItemSprite::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("pauseNormal.png")),Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("pauseSelected.png")),CC_CALLBACK_1(GameLayer::gamePause, this)); // Pauseauto backwardBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directionNormal.png"));auto backwardSelBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directionSelected.png"));auto backwardBtn = ControlButton::create(backwardBG);backwardBtn->setBackgroundSpriteForState(backwardSelBG, Control::State::HIGH_LIGHTED);backwardBtn->setZoomOnTouchDown(false);backwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::backward), Control::EventType::TOUCH_DOWN);backwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::backward), Control::EventType::TOUCH_UP_INSIDE);backwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::backward), Control::EventType::DRAG_OUTSIDE);backwardBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directionNormal.png"))->getContentSize());auto forwardBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directForNor.png"));auto forwardSelBG = Scale9Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directForSel.png"));auto forwardBtn = ControlButton::create(forwardBG);forwardBtn->setBackgroundSpriteForState(forwardSelBG, Control::State::HIGH_LIGHTED);forwardBtn->setZoomOnTouchDown(false);forwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::forward), Control::EventType::TOUCH_DOWN);forwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::forward), Control::EventType::TOUCH_UP_INSIDE);forwardBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(GameLayer::forward), Control::EventType::DRAG_OUTSIDE);forwardBtn->setPreferredSize(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("directForNor.png"))->getContentSize());puaseGameItem->setPosition(WINSIZE.width - 50, WINSIZE.height - 48);backwardBtn->setPosition(117, 70);forwardBtn->setPosition(304, 70);auto menuWalk = Menu::create(puaseGameItem, NULL);menuWalk->setPosition(Point::ZERO);this->addChild(backwardBtn, 1);this->addChild(forwardBtn, 1);this->addChild(menuWalk, 1);// 状态条m_pBG = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("barGround.png"));m_pHPBar = ProgressTimer::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("HPBar.png")));m_pHPBar->setType(ProgressTimer::Type::BAR);m_pHPBar->setMidpoint(ccp(0, 0.5));m_pHPBar->setBarChangeRate(ccp(1, 0));m_pHPBar->setPercentage(100);m_pMPBar = ProgressTimer::create(Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("MPBar.png")));m_pMPBar->setType(ProgressTimer::Type::BAR);m_pMPBar->setMidpoint(ccp(0, 0.5));m_pMPBar->setBarChangeRate(ccp(1, 0));m_pMPBar->setPercentage(0);m_pHPBar->setPosition(240, 45);m_pMPBar->setPosition(226, 30);m_pBG->addChild(m_pHPBar);m_pBG->addChild(m_pMPBar);m_pBG->setPosition(260, WINSIZE.height - 60);this->addChild(m_pBG, 1);// 英雄m_pHero = Hero::create();m_pHero->InitHeroSprite("idle.png", 1);m_pHero->setPosition(100, 360);this->addChild(m_pHero, 3);// MonsterOne *monster = MonsterOne::createWithMapAndHero(myMap, m_pHero);this->scheduleUpdate();return true;
}// 拳击
void GameLayer::fistAttack(Ref* pSender, Control::EventType type)
{
}// 腿击
void GameLayer::footAttack(Ref* psender, Control::EventType type)
{}//
void GameLayer::jump(Ref* pSender, Control::EventType type)
{
}void GameLayer::comboAttack(Ref* pSender, Control::EventType type)
{}void GameLayer::gamePause(Ref* pSender)
{
}void GameLayer::backward(Ref* pSender, Control::EventType type)
{if (m_pHero->IsAttack && m_pHero->m_bIsJumping == true){return;}switch (type){case cocos2d::extension::Control::EventType::TOUCH_DOWN://m_bRun = true;//m_bDirection = true;break;case cocos2d::extension::Control::EventType::DRAG_INSIDE:break;case cocos2d::extension::Control::EventType::DRAG_OUTSIDE://m_bRun = false;//m_pHero->StopAnimation();break;case cocos2d::extension::Control::EventType::DRAG_ENTER:break;case cocos2d::extension::Control::EventType::DRAG_EXIT:break;case cocos2d::extension::Control::EventType::TOUCH_UP_INSIDE://m_bRun = false;//m_pHero->StopAnimation();break;case cocos2d::extension::Control::EventType::TOUCH_UP_OUTSIDE:break;case cocos2d::extension::Control::EventType::TOUCH_CANCEL:break;case cocos2d::extension::Control::EventType::VALUE_CHANGED:break;default:break;}
}void GameLayer::forward(Ref* pSender, Control::EventType type)
{if (m_pHero->IsAttack && m_pHero->m_bIsJumping == true){return;}switch (type){case cocos2d::extension::Control::EventType::TOUCH_DOWN://m_bRun = true;//m_bDirection = false;break;case cocos2d::extension::Control::EventType::DRAG_INSIDE:break;case cocos2d::extension::Control::EventType::DRAG_OUTSIDE://m_bRun = false;//m_pHero->StopAnimation();break;case cocos2d::extension::Control::EventType::DRAG_ENTER:break;case cocos2d::extension::Control::EventType::DRAG_EXIT:break;case cocos2d::extension::Control::EventType::TOUCH_UP_INSIDE://m_bRun = false;//m_pHero->StopAnimation();break;case cocos2d::extension::Control::EventType::TOUCH_UP_OUTSIDE:break;case cocos2d::extension::Control::EventType::TOUCH_CANCEL:break;case cocos2d::extension::Control::EventType::VALUE_CHANGED:break;default:break;}
}void GameLayer::gameOver(float delta)
{}void GameLayer::gameVictory(float delta)
{}bool GameLayer::isAttackMonster(Hero * hero, Monster* monster)
{
}void GameLayer::update(float delta)
{}

以上就是本节课的主要内容,转载请注明出处:http://blog.csdn.net/suool/article/details/46851335
下节课我们将学习游戏项目中的核心功能场景的逻辑功能分析与实现。

本节课的视频教程地址是:第六课在此
如果本教程有帮助到您,希望您能点击进去观看一下,而且现在注册成为极客学院的会员,验证手机号码和邮箱号码会赠送三天的会员时间,手机端首次也可以领取五天的会员时间哦(即使是购买年会员目前也仅仅是年费260),成为极客学院学习会员可以无限制的下载和观看所有的学院网站的视频,谢谢您的支持!

【Cocos游戏实战】功夫小子第六课之游戏主功能场景的分析和实现相关推荐

  1. 【Cocos游戏实战】功夫小子第七课之游戏主功能场景逻辑功能和暂停功能场景的分析和实现...

    CSDN的markdown编辑器是吃屎了么! !.什么玩意.!写了一半写不了东西还全没了,搞个毛线! 本节课的视频教程地址是:第七课在此  假设本教程有帮助到您,希望您能点击进去观看一下,并且如今注冊 ...

  2. 第六课 利用站群赚钱的思路分析

    网赚项目之站群 第六课 利用站群赚钱的思路分析 1. 做排名,放广告 2. 做淘宝客 迄今为止,淘客已经成为一个职业,而且很多人也挺羡慕,因为坐在家里办公,每月就有上万的收入.其实如这行还不是很难.特 ...

  3. 《迅雷链精品课》第六课:主流区块链数据存储分析(一)

    上一节课我们学习了区块链中的账户与账本,了解区块链账户的特点和本质.今天我们将系统地学习区块链数据存储,在课程学习前,大家可以先思考下列问题:区块链的数据是如何存储的?区块链如何在没有中心信任节点的情 ...

  4. python 写游戏好简单啊,我用键盘可以随意控制角色了【python 游戏实战 04】

    前言 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课 ...

  5. 这是我第一次使用代码创建出一个窗口【python 游戏实战 01】

    前言 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课 ...

  6. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(8)我们开始做一个数字小游戏吧

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

  7. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(10)无底洞的循环

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

  8. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(7)我用函数写了个特洛伊木马

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

  9. 《看聊天记录都学不会Python到游戏实战?太菜了吧》(9)集万家之长不死 python

    本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课程也将 ...

最新文章

  1. Linux文件中的stat结构
  2. MySQL索引背后的数据结构及算法原理【转】
  3. python学习第二十八节(进程,线程)
  4. SMW0上传文件到数据库层详解
  5. jdba怎么连接mysql_一、JAVA通过JDBC连接mysql数据库(连接)
  6. 6.3.2线索二叉树
  7. Java实现的时钟置换算法_时钟页面置换算法
  8. 2021-10-11关于Ubuntu安装搜狗输入法
  9. .p7b证书转成iis使用的.pfx证书
  10. 微云存储空间多大_微云免费存储容量由1T降为10G,百度还能坚持多久?
  11. android电源管理白名单,刷BIOS工具分享(白名单,高级菜单,电源管理)
  12. 出现错误/ncnn/src/cpu.cpp:426: undefined reference to `stderr'完美解决方案。
  13. 串口485接法图_RS-485 2线和4线的接法
  14. java里面有radix树吗_基数树(radix tree)
  15. 【PHP基础-3】PHP常用运算符
  16. 专家揭示连锁加盟陷阱
  17. 数仓建模—增量数据处理
  18. 设计模式初探-观察者模式(OBSERVER)又称发布-订阅(Publish-Subscribe)依赖(Dependents)
  19. 数据库安全那些事儿 访安华金和CEO
  20. Hadoop学习----HDFS

热门文章

  1. javascript编写的网页小游戏,很给力
  2. 写在2021新年到来前
  3. 【Book】剑指Offer -- By 何海涛
  4. 双折射晶体偏振干涉效应
  5. 谷歌大胃王,欲占领所有渠道--谷歌电视
  6. 扔鸡蛋问题(四种解法)
  7. 大数据24小时:今日头条因“不正当竞争”起诉百度,金山云47天内获46亿元融资
  8. 五大派玩家角逐移动资讯市场,微博如何成“另类”?
  9. linux命令之查看ip地址
  10. 计算机系统必须配置,AI运行需要什么电脑配置?(复杂路径,且流畅)