Cocos2dx以游戏促力学习

提要:

学习Cocos2dx编程书上的游戏案例,跳跳跳跳,没了~


初始化游戏

  1. 先在工程添加筛选器,添加一个Game筛选器,里面又有包含关卡的场景筛选器以及玩家和食物的实体筛选器。

  2. 在实体筛选器书写food.cpp和food.h文件,作用是提供精灵获取和绑定功能的类,如下。

  3. 在实体筛选器书写Player.cpp和Player.h文件如下。

  4. 在场景筛选器书写guanScene.cpp和guanScene.h文件如下,即关场景,关卡场景。

  5. 需要注意的是必须去AppDelegate.cpp中修改默认启动场景。

  6. 在AppDelegate.cpp中先添加#include "guanScene.h"头文件,在修改如下参数。

    bool AppDelegate::applicationDidFinishLaunching() {
    	...... //省略上面
        // create a scene. it's an autorelease object
       // auto scene = HelloWorld::createScene(); 默认启动的场景
    	auto scene = guanScene::createScene(); //自己创建的游戏关卡场景
    
        // run
        director->runWithScene(scene);
    
        return true;
    }
    
  7. 再次记录在AppDelegate.cpp下修改窗口大小如下。

    bool AppDelegate::applicationDidFinishLaunching() {
        // initialize director
        auto glview = director->getOpenGLView();
        if(!glview) {
     //...
        }
    	glview->setFrameSize(960, 640); //设置窗口大小
    //...
        return true;
    }
    

无限滚动地图

  1. 了解update函数。

  2. 实现代码:this->scheduleUpdate();效果如下。

    //首先在场景头文件中声明一个update函数
    virtual void update(float u); //定义一个update函数来实现重写
    //再在场景.cpp文件中进行重写定义
    void guanScene::update(float u)
    {
    	log("update is good"); //场景每帧运行的线程都会打印一次这个日志
    }
    


3. 重写update函数,实现连续滚动效果。

void guanScene::update(float u)
{
	int PosX1 = mybgSprite1->getPositionX(); //获取背景1的X坐标
	int PosX2 = mybgSprite2->getPositionX(); //获取背景2的X坐标
	
	int bgspeed = 1; //背景滚动速度

	//两张图片向左滚动,X坐标每次都减1
	PosX1 -= bgspeed; 
	PosX2 -= bgspeed;

	//获取背景图片的大小
	Size bgSize = mybgSprite1->getContentSize();

	//当第一个地图完全离开屏幕时,第二个地图刚好出现在屏幕上,让他们紧贴在一起
	if (PosX1 <= -bgSize.width / 2) //coco2dx对象描点是图片中间
	{
		PosX1 = bgSize.width + bgSize.width / 2;
	}
	//当第二个地图完全离开屏幕时,第一个地图刚好出现在屏幕上,让他们紧贴在一起
	if (PosX2 <= -bgSize.width / 2)
	{
		PosX2 = bgSize.width + bgSize.width / 2;
	}

	mybgSprite1->setPositionX(PosX1);
	mybgSprite2->setPositionX(PosX2);
}

解锁会动的角色

  1. 在头文件声明两个函数,一个是跳跃按钮函数一个是按钮回调函数。

    void createJump(); //跳跃按钮函数
    void starMenuCallback(cocos2d::Ref* p); //按钮回调
    
  2. 在.cpp文件中定义。

    void guanScene::createJump()
    {
    	Size getSize = Director::getInstance()->getVisibleSize();
    
    	//使用类 MenuItemImage 来创建一个菜单项,第一个参数是按钮没有被单击图片,第二个参数是按钮被单击图片
    	//第三个参数是为按钮的点击事件指定了一个回调函数
    	MenuItemImage* starMenuItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png", this, menu_selector(guanScene::starMenuCallback));
    	
    	//创建一个Menu来包含这个按钮
    	Menu* newMenu = Menu::create(starMenuItem, NULL);
    	newMenu->setPosition(Point(getSize.width-60,getSize.height-230));
    	this->addChild(newMenu, 1);
    }
    void guanScene::starMenuCallback(Ref* p)
    {
    		//创建跳跃动作
    		auto jump = JumpBy::create(0.5f, Point(0, 0), 40, 1);
    
    		//执行动作
    		this->myPlayer->runAction(jump);
    }
    
  3. 实现效果。

创建金币

  1. 创建金币对象的文件,如下。

    //zhufood.h
    #ifndef _ZHUFOOD_H_
    #define _ZHUFOOD_H_
    #include "food.h"
    
    class zhufood :public food {
    
    public:
    	zhufood();
    	~zhufood();
    	CREATE_FUNC(zhufood);
    	virtual bool zhufoodinit();
    
    	void show(); 
    	void hide(); //隐藏
    	void reboot(); //重置
    	bool isAlive(); //判断是否为活动状态
    
    private:
    	bool myAlive; //标记金币活动状态
    
    };
    
    #endif
    
    //zhufood.cpp
    #include "zhufood.h"
    
    zhufood::zhufood()
    {
    	myAlive = false;
    }
    zhufood::~zhufood(){}
    
    bool zhufood::zhufoodinit()
    {
    	return true;
    }
    
    void zhufood::show()
    {
    	if (getSprite()!= NULL)
    	{
    		setVisible(true); //设置为可见
    		myAlive = true;
    	}
    }
    
    void zhufood::hide()
    {
    	if (getSprite()!= NULL)
    	{
    		setVisible(false); //设置为不可见
    		reboot(); //重置
    		myAlive = false;
    	}
    }
    
    void zhufood::reboot()
    {
    	if (getSprite()!= NULL)
    	{
    		//初始化金币坐标, CCRANDOM_0_1随机数
    		setPosition(Point(800 + CCRANDOM_0_1() * 2000, 200 - CCRANDOM_0_1() * 100));
    	}
    }
    
    bool zhufood::isAlive()
    {
    	return myAlive;
    }
    
  2. 为实现更好的管理金币这一事务,创建一个管理它的类。

  3. 创建金币管理类,如下。

    //zhufoodManager.h
    #ifndef _ZHUFOODMANAGER_H_
    #define _ZHUFOODMANAGER_H_
    
    #include "cocos2d.h"
    #include "zhufood.h"
    USING_NS_CC;
    
    #define MAX_ZHUFOOD 10 //最大数量
    
    class zhufoodManager :public Node {
    	
    public:
    	CREATE_FUNC(zhufoodManager);
    	virtual bool init();
    
    	virtual void update(float a); //重写update函数
    private:
    	void createZhuFood(); //创建金币对象zhufood
    
    	Vector<zhufood*> myzhufoodlist; //存放zhufood对象的列表
    };
    
    #endif
    
    //zhufoodManager.cpp
    #include "zhufoodManager.h"
    #include "Player.h"
    #include "zhufood.h"
    
    bool zhufoodManager::init()
    {
    	createZhuFood(); //创建对象
    	this->scheduleUpdate(); //开启update函数的调用
    	return true;
    }
    
    void zhufoodManager::createZhuFood()
    {
    	zhufood* zhu = NULL;
    	Sprite* sprite = NULL;
    
    	for (int i = 0; i < MAX_ZHUFOOD; i++)
    	{	
    		//创建金币对象zhufood
    		zhu = zhufood::create();
    		zhu->bangSprite(Sprite::create("100yuan.jpg")); //绑定对象,在food.h中声明了
    		zhu->setScale(0.25f); //缩小到0.25倍大小
    		zhu->reboot();
    
    		//添加金币对象
    		this->addChild(zhu);
    
    		//保存金币对象到列表中
    		myzhufoodlist.pushBack(zhu);
    	}
    }
    
    void zhufoodManager::update(float a) 
    {
    	for (auto zhufood : myzhufoodlist)
    	{
    		//如果金币处于活动状态
    		if (zhufood->isAlive())
    		{
    			zhufood->setPositionX(zhufood->getPositionX() - 4);
    			//如果金币X坐标小于0,则超出了屏幕范围,则隐藏起来
    			if (zhufood->getPositionX() < 0)
    				zhufood->hide();
    		}
    		else
    		{
    			//金币处于非活动状态则让金币出场
    			zhufood->show();
    		}	
    	}
    }
    
  4. 在场景.cpp文件的init函数中进行创建金币管理类对象。

    //记得在场景.cpp中添加zhufoodManager.h头文件
    bool guanScene::init()
    {
    	//...
    	//创建金币管理器
    	zhufoodManager* manager = zhufoodManager::create();
    	this->addChild(manager,4);
    
    	//初始化背景图片
    	initBG();
    	this->scheduleUpdate(); //启动update函数
    	return true;
    }
    

主角静态变动态(GIF的实现和应用)

  1. 前提:找一组GIF动画用PS打开把每个图层都导出为png图片并给予编号,如下。

  2. 在项目的资源文件夹(Resources)下新建一个zhujue名称的文件夹以存放动作图片,如下。

  3. 两种实现方法,均在场景.cpp文件的init函数实现即可,如下。

    //第一种是使用Animation类创建一个动画效果
    
    //使用Animation类创建一个动画效果,每一个动作就是一个Asnimate对象,借用精灵实现
    //注意:首先应在场景.h头文件定义一个Sprite* mysprite;以便让精灵实现动作
    bool guanScene::init()
    {
    	//...
    	mysprite = Sprite::create("zhujue/bashen1.png"); //创建精灵
    	mysprite->setPosition(Point(getSize.width/2, getSize.height / 2));
    	this->addChild(mysprite, 1); //加入层显示,设置为1保证提前绘画
    
    	auto myAnimation = Animation::create(); //创建序列帧动画
    	for (int a = 1; a < 8; a++)
    	{
    		char nameSize[66] = { 0 }; //设置主角名称数组的长度
    		sprintf(nameSize, "zhujue/bashen%d.png", a); //利用for循环进行遍历
    		myAnimation->addSpriteFrameWithFile(nameSize); //加入到序列帧动画中
    	}
    	myAnimation->setDelayPerUnit(0.05f); //设置两帧动画之间的间隔时间
    	myAnimation->setLoops(-1); //设置循环次数,-1为无限循环
    	myAnimation->setRestoreOriginalFrame(true); //设置在动画播放结束恢复到第一帧图片
    
    	auto myAnimate = Animate::create(myAnimation); //创建动画播放的对象Animate
    	mysprite->runAction(myAnimate); //执行Animate对象
        //第二种是coco2dx提供的图片帧的实现方式,第一种比较方便,第二种留下备忘
        //...
        return true;
    }
    
  4. 让主角跳起来,应重写回调函数starMenuCallback(Ref* p),如下。

    void guanScene::starMenuCallback(Ref* p)
    {
    		//创建跳跃动作
    		auto jump = JumpBy::create(0.5f, Point(0, 0), 40, 1);
    
    		//执行动作
    		this->mysprite->runAction(jump);
    }
    
  5. 效果如下,当然背景换了个金币图片,在创建金币的第三条代码里有写入,同时也换了张背景。

  6. 完成。

吃金币,碰撞检测的实现

  1. 既然使用了GIF动画实现主角效果了,那么就可以完全删除Player.h和Player.cpp文件了,把主角的相关操作都放在金币文件zhufood.h进行管理,如下。

    //zhufood.h
    #ifndef _ZHUFOOD_H_
    #define _ZHUFOOD_H_
    #include "food.h" //提供精灵绑定与获取
    
    
    class zhufood :public food {
    
    public:
    	//...
        //新增碰撞检测函数,因为GIF主角是Sprite实现的所以提供Sprite*对象
    	bool pengzhuang(Sprite* player); //碰撞检测
    
    	void eat(Sprite* player); //碰撞功能实现
    
    
    private:
    	bool myAlive; //标记金币活动状态
    
    };
    
    #endif
    
    //zhufood.cpp
    #include "zhufood.h"
    
    //...
    zhufood::zhufood()
    {
    	myAlive = false;
    	myHp = 100; //将主角初始血量设为100;
    }
    //...
    bool zhufood::pengzhuang(Sprite* player) //碰撞检测
    {
    	//获取碰撞检查的对象,Node对象或继承了Node的类都拥有一个getBoundingBox()函数,
    	//getBoundingBox()会返回一个矩形,这个矩形就是Node对象的图片外围矩形
    	Rect nowPlayer = player->getBoundingBox();
    	Point getPos = getPosition();
    
    	//判断BoundingBox和金币中心点是否相交
    	return nowPlayer.containsPoint(getPos);
    }
    
    void zhufood::eat(Sprite* player)
    {
    	if (getSprite() == NULL) //判断精灵是否存在
    	{
    		return;
    	}
    	myHp -= 10;
    	if (myHp < 0)
    	{
    		myHp == 0;
    	}
    }
    
    //zhufoodManager.cpp 在update函数定义中实现金币消失的功能及主角受伤
    #include "zhufoodManager.h"
    #include "zhufood.h"
    
    	//...
    void zhufoodManager::update(float a) 
    {
    	//...
    		//如果金币X坐标小于0则隐藏金币
    		if (zhufood->getPositionX() < 0)
    			zhufood->hide();
    		else if (zhufood->pengzhuang(myPlayer))
    		{
    			zhufood->eat(myPlayer); //主角受伤
    			zhufood->hide(); //金币隐藏
    		}
    	}
    }
    	//...
    //最终在场景.cpp文件中进行碰撞(主角和金币接触,金币消失)的实现
    bool guanScene::init()
    {
    	//...
    	//创建金币管理器
    	zhufoodManager* manager = zhufoodManager::create();
    	this->addChild(manager,4);
    	manager->bangPlayer(mysprite);
        //...
    	return true;
    
    }
    
  2. 碰撞检测完成。

游戏进度条功能及标签功能

  1. 首先在场景.h文件中顶下如下。

    class guanScene :public Scene { 
        //...
    public:
        void createJindu(); //创建进度条
    private:
    	//创建进度条
    	ProgressTimer* progressTimer; //声明进度条指针
    	LabelTTF* labelTTF; //声明标签指针
    };
    
  2. 在场景.cpp文件中进行定义,如下。

    void guanScene::createJindu()
    {
    	//创建一个进程条和进度条边框
    	Vec2 vec2 = Director::getInstance()->getVisibleOrigin(); //Vec2(原名Point)可二维坐标可维度
    	Size getSize = Director::getInstance()->getVisibleSize();
    	//创建一个进度条精灵边框
    	auto progressbgSp = Sprite::create("bgjindu.png");
    	progressbgSp->setScale(0.8f); //缩小到0.8倍大小
    	progressbgSp->setPosition(Vec2(vec2.x + getSize.width / 4, vec2.y + getSize.height / 4));
    	this->addChild(progressbgSp, 3);
    
    	//创建一个进度条精灵
    	auto progressSp = Sprite::create("jindu.png");
    	progressSp->setScale(0.8f); //缩小到0.8倍大小
    	progressTimer = ProgressTimer::create(progressSp);
    	progressTimer->setType(kCCProgressTimerTypeBar);
    	progressTimer->setPosition(Vec2(vec2.x + getSize.width / 4, vec2.y + getSize.height / 4));
    	//进度动画方向
    	progressTimer->setMidpoint(Vec2(0, 0));
    	//进度条宽高变化
    	progressTimer->setBarChangeRate(Vec2(1, 0));
    	progressTimer->setPercentage(0); //设置进度为0%
    	this->addChild(progressTimer, 3);
    	//创建标签
    	labelTTF = CCLabelTTF::create("0", "Thonburi", 20);
    	labelTTF->setPosition(vec2.x + getSize.width / 4, vec2.y + getSize.height / 4);
    	this->addChild(labelTTF, 3);
    }
    
  3. 实现角色上下左右移动功能,如下。

    //首先在场景.h文件里进行声明
    class guanScene :public Scene {
    public:
        //...
    	void onClickUp(Ref*, TouchEventType type); //单击监听事件
    	void onClickDown(Ref*, TouchEventType type); //单击监听事件
    	void onClickLeft(Ref*, TouchEventType type); //单击监听事件
    	void onClickRight(Ref*, TouchEventType type); //单击监听事件
    }//再在场景.cpp文件中进行定义
    void guanScene::onClickUp(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    	case ui::TouchEventType::TOUCH_EVENT_BEGAN: //单击事件开始时触发(按下的时候)
    		break;
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x, pos.y + 1));
    		break;
    	case ui::TouchEventType::TOUCH_EVENT_ENDED: //按下之后然后松开之后触发
    		//mysprite->setPosition(Point(pos.x,pos.y+5));
    		break;
    	}
    }
    
    void guanScene::onClickDown(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x, pos.y - 1));
    		break;
    	}
    }
    
    void guanScene::onClickLeft(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x-1, pos.y));
    		break;
    	}
    }
    
    void guanScene::onClickRight(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x+1, pos.y));
    		break;
    	}
    }
    
    //创建按钮显示出来在场景.cpp文件的init函数中实现
    bool guanScene::init()
    {
    	//...
    	//上下左右四个按钮
    	Button* a = Button::create();
    	a->setTitleText("Up");
    	a->setPosition(Point(50, 180));
    	a->addTouchEventListener(this,toucheventselector(guanScene::onClickUp));
    	this->addChild(a,2);
    	Button* b = Button::create();
    	b->setTitleText("Down");
    	b->setPosition(Point(50, 160));
    	b->addTouchEventListener(this, toucheventselector(guanScene::onClickDown));
    	this->addChild(b, 2);
    	Button* c = Button::create();
    	c->setTitleText("Left");
    	c->setPosition(Point(30, 170));
    	c->addTouchEventListener(this, toucheventselector(guanScene::onClickLeft));
    	this->addChild(c, 2);
    	Button* d = Button::create();
    	d->setTitleText("Right");
    	d->setPosition(Point(70, 170));
    	d->addTouchEventListener(this, toucheventselector(guanScene::onClickRight));
    	this->addChild(d, 2);
    	//...
    
    }
    
  4. 效果截图

  5. 完成。

全代码汇总

  1. 就先这样存起来吧。

  2. 项目工程总览。

  3. guanScene.h

    #ifndef _GUANSCENE_H_
    #define _GUANSCENE_H_
    #include "cocos2d.h"
    #include "food.h"
    
    #include "ui/CocosGUI.h"
    
    USING_NS_CC;
    using namespace cocos2d::ui;
    
    
    class zhufoodManager;
    
    class guanScene :public Scene {  //继承Layer层  场景➡层
    public:
    	static cocos2d::Scene* createScene();
    	virtual bool init();
    	CREATE_FUNC(guanScene);  //创建场景回调
    
    	void createJindu(); //创建进度条
    
    	void onClickUp(Ref*, TouchEventType type); //单击监听事件
    	void onClickDown(Ref*, TouchEventType type); //单击监听事件
    	void onClickLeft(Ref*, TouchEventType type); //单击监听事件
    	void onClickRight(Ref*, TouchEventType type); //单击监听事件
    
    private:
    	void initBG(); //初始化关卡背景
    	Sprite* mybgSprite1; //背景精灵1
    	Sprite* mybgSprite2; //背景精灵2
    
    	//Player* myPlayer; //主角
    	virtual void update(float u); //定义一个update函数来实现重写
    
    	/*
    	1. LabelTTF适合于一次性创建文本后不再改变显示信息的情况。
    	2. CCLabelBMFont适合于需要频繁更新的文本内容的情况。
    	3. CCLabelAtlas适合于显示数字信息,如计分板,排行榜。
    	*/
    
    	Sprite* mysprite;
    	void createJump(); //跳跃按钮函数
    
    	void createdirection(); //方向函数
    	void benpaoAciton(); //主角奔跑GIF实现
    
    	void starMenuCallback(cocos2d::Ref* p); //按钮回调
    
    
    
    private:
    	//创建进度条
    	ProgressTimer* progressTimer; //声明进度条指针
    	LabelTTF* labelTTF; //声明标签指针
    	
    };
    
    #endif
    
  4. guanScene.cpp

    #include "guanScene.h"
    #include "zhufoodManager.h"
    
    
    using namespace cocos2d;
    
    Scene* guanScene::createScene()
    {
    	return guanScene::create();
    }
    
    void guanScene::initBG()
    {
    	Size getSize = Director::getInstance()->getVisibleSize();
    
    	mybgSprite1 = Sprite::create("bg.png");
    	mybgSprite1->setPosition(getSize.width / 2, getSize.height / 2);
    	this->addChild(mybgSprite1, 0); //第二个参数表示绘制层次,数值越大对象层次越高(越迟被绘制)
    
    	mybgSprite2 = Sprite::create("bg.png");
    	mybgSprite2->setPosition(getSize.width +getSize.width+260, getSize.height / 2);
    	mybgSprite2->setFlippedX(true); //水平翻转精灵
    	this->addChild(mybgSprite2, 0);
    }
    
    void guanScene::update(float u)
    {
    	int PosX1 = mybgSprite1->getPositionX(); //获取背景1的X坐标
    	int PosX2 = mybgSprite2->getPositionX(); //获取背景2的X坐标
    	
    	int bgspeed = 1; //背景滚动速度
    
    	//两张图片向左滚动,X坐标每次都减1
    	PosX1 -= bgspeed; 
    	PosX2 -= bgspeed;
    
    	//获取背景图片的大小
    	Size bgSize = mybgSprite1->getContentSize();
    
    	//当第一个地图完全离开屏幕时,第二个地图刚好出现在屏幕上,让他们紧贴在一起
    	if (PosX1 <= -bgSize.width / 2) //coco2dx对象描点是图片中间
    	{
    		PosX1 = bgSize.width + bgSize.width / 2;
    	}
    	//当第二个地图完全离开屏幕时,第一个地图刚好出现在屏幕上,让他们紧贴在一起
    	if (PosX2 <= -bgSize.width / 2)
    	{
    		PosX2 = bgSize.width + bgSize.width / 2;
    	}
    
    	mybgSprite1->setPositionX(PosX1);
    	mybgSprite2->setPositionX(PosX2);
    
    	//进度条
    	float c = progressTimer->getPercentage();  //获取当前百分比  
    	c+=0.01f; //给进度条进度每次加0.1%  
    	progressTimer->setPercentage(c);
    	if (c <= 100)    //如果进度小于等于100%  
    	{
    		auto str1 = String::createWithFormat("%.2f%%", c);
    		labelTTF->setString(str1->getCString());  //设置标签显示内容
    	}
    
    }
    
    void guanScene::createJump()
    {
    	Size getSize = Director::getInstance()->getVisibleSize();
    
    	//使用类 MenuItemImage 来创建一个菜单项,第一个参数是按钮没有被单击图片,第二个参数是按钮被单击图片
    	//第三个参数是为按钮的点击事件指定了一个回调函数
    	MenuItemImage* starMenuItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png", this, menu_selector(guanScene::starMenuCallback));
    	
    	//创建一个Menu来包含这个按钮
    	Menu* newMenu = Menu::create(starMenuItem, NULL);
    	newMenu->setPosition(Point(getSize.width-60,getSize.height-230));
    	this->addChild(newMenu, 1);
    }
    
    void guanScene::benpaoAciton() //主角奔跑GIF实现
    {
    	auto myAnimation = Animation::create(); //创建序列帧动画
    	for (int a = 1; a < 7; a++)
    	{
    		char nameSize[66] = { 0 }; //设置主角名称数组的长度
    		sprintf(nameSize, "zhujue/bashen%d.png", a); //利用for循环进行遍历
    		myAnimation->addSpriteFrameWithFile(nameSize); //加入到序列帧动画中
    	}
    	myAnimation->setDelayPerUnit(0.05f); //设置两帧动画之间的间隔时间
    	myAnimation->setLoops(-1); //设置循环次数,-1为无限循环
    	myAnimation->setRestoreOriginalFrame(true); //设置在动画播放结束恢复到第一帧图片
    
    	auto myAnimate = Animate::create(myAnimation); //创建动画播放的对象Animate
    	mysprite->runAction(myAnimate); //执行Animate对象
    }
    
    bool guanScene::init()
    {
    	if (!Scene::init())
    	{
    		return false;
    	}
    
    	Size getSize = Director::getInstance()->getVisibleSize();
    
    	//label
    	auto gametitle = Label::createWithSystemFont("Naruto Ultimate Storm", "Arial", 20);
    	gametitle->setPosition(getSize.width/2, getSize.height-20);
    	gametitle->setColor(Color3B(255,0,0));
    	this->addChild(gametitle, 3);
    
    
    	//创建主角
    	/*
    	myPlayer = Player::create();
    	myPlayer->bangSprite(Sprite::create("zhujue.png"));
    	myPlayer->setPosition(Point(100, getSize.height / 2));
    	this->addChild(myPlayer, 3);
    	*/
    	
    	//使用Animation类创建一个动画效果,每一个动作就是一个Animate对象,借用精灵实现
    	mysprite = Sprite::create("zhujue/bashen1.png"); //创建精灵
    	mysprite->setPosition(Point(getSize.width/2, getSize.height / 2));//Vec2(Point)可以是一个二维坐标点,也可以是一个二维向量。
    	this->addChild(mysprite, 1); //加入层显示,设置为1保证提前绘画
    
    	benpaoAciton(); //奔跑动作
    
    	createJump(); //调用跳跃动作函数
    
    	createJindu(); //创建进度条
    	
    	//上下左右四个按钮
    	Button* a = Button::create();
    	a->setTitleText("Up");
    	a->setPosition(Point(50, 180));
    	a->addTouchEventListener(this,toucheventselector(guanScene::onClickUp));
    	this->addChild(a,2);
    	Button* b = Button::create();
    	b->setTitleText("Down");
    	b->setPosition(Point(50, 160));
    	b->addTouchEventListener(this, toucheventselector(guanScene::onClickDown));
    	this->addChild(b, 2);
    	Button* c = Button::create();
    	c->setTitleText("Left");
    	c->setPosition(Point(30, 170));
    	c->addTouchEventListener(this, toucheventselector(guanScene::onClickLeft));
    	this->addChild(c, 2);
    	Button* d = Button::create();
    	d->setTitleText("Right");
    	d->setPosition(Point(70, 170));
    	d->addTouchEventListener(this, toucheventselector(guanScene::onClickRight));
    	this->addChild(d, 2);
    
    
    	//创建金币管理器
    	zhufoodManager* manager = zhufoodManager::create();
    	this->addChild(manager,4);
    	manager->bangPlayer(mysprite);
    
    
    	//初始化背景图片
    	initBG();
    
    	this->scheduleUpdate(); //启动update函数
    
    	return true;
    
    }
    
    void guanScene::starMenuCallback(Ref* p)
    {
    		//创建跳跃动作
    		auto jump = JumpBy::create(0.5f, Point(0, 0),50, 1);
    
    		//执行动作
    		this->mysprite->runAction(jump);
    }
    
    void guanScene::createJindu()
    {
    	//创建一个进程条和进度条边框
    	Vec2 vec2 = Director::getInstance()->getVisibleOrigin(); //Vec2(原名Point)可二维坐标可维度
    	Size getSize = Director::getInstance()->getVisibleSize();
    	//创建一个进度条精灵边框
    	auto progressbgSp = Sprite::create("bgjindu.png");
    	progressbgSp->setScale(0.8f); //缩小到0.8倍大小
    	progressbgSp->setPosition(Vec2(vec2.x + getSize.width / 4, vec2.y + getSize.height / 4));
    	this->addChild(progressbgSp, 3);
    
    	//创建一个进度条精灵
    	auto progressSp = Sprite::create("jindu.png");
    	progressSp->setScale(0.8f); //缩小到0.8倍大小
    	progressTimer = ProgressTimer::create(progressSp);
    	progressTimer->setType(kCCProgressTimerTypeBar);
    	progressTimer->setPosition(Vec2(vec2.x + getSize.width / 4, vec2.y + getSize.height / 4));
    	//进度动画方向
    	progressTimer->setMidpoint(Vec2(0, 0));
    	//进度条宽高变化
    	progressTimer->setBarChangeRate(Vec2(1, 0));
    	progressTimer->setPercentage(0); //设置进度为0%
    	this->addChild(progressTimer, 3);
    	//创建标签
    	labelTTF = CCLabelTTF::create("0", "Thonburi", 20);
    	labelTTF->setPosition(vec2.x + getSize.width / 4, vec2.y + getSize.height / 4);
    	this->addChild(labelTTF, 3);
    }
    
    void guanScene::onClickUp(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    	case ui::TouchEventType::TOUCH_EVENT_BEGAN: //单击事件开始时触发(按下的时候)
    		break;
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x, pos.y + 1));
    		break;
    	case ui::TouchEventType::TOUCH_EVENT_ENDED: //按下之后然后松开之后触发
    		//mysprite->setPosition(Point(pos.x,pos.y+5));
    		break;
    	}
    }
    
    void guanScene::onClickDown(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x, pos.y - 1));
    		break;
    	}
    }
    
    void guanScene::onClickLeft(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x-1, pos.y));
    		break;
    	}
    }
    
    void guanScene::onClickRight(Ref*, TouchEventType type) //单击监听事件
    {
    	Point pos = mysprite->getPosition();
    	switch (type)
    	{
    
    	case TouchEventType::TOUCH_EVENT_MOVED: //按下之后进行移动操作时触发
    		mysprite->setPosition(Point(pos.x+1, pos.y));
    		break;
    	}
    }
    
  5. food.h

    #ifndef _FOOD_H_
    #define _FOOD_H_
    #include "cocos2d.h"
    USING_NS_CC;
    
    class food :public Node {
    
    public:
    	food();
    	~food();
    	Sprite* getSprite(); //获取精灵
    	void bangSprite(Sprite* a); //绑定精灵
    private:
    	Sprite* mySprite;
    
    };
    
    #endif 
    
  6. food.cpp

    #include "food.h"
    
    food::food()
    {
    	mySprite = NULL;
    }
    
    food::~food()
    {
    }
    
    Sprite* food::getSprite()
    {
    	return this->mySprite;
    }
    
    void food::bangSprite(Sprite* a)
    {
    	this->mySprite = a;
    	this->addChild(mySprite);
    }
    
  7. word.h

    #ifndef __WORD_H__
    #define __WORD_H__
    
    #include "cocos2d.h"
    USING_NS_CC;
    
    class word :public CCNode
    {
    public:
    	word();
    	~word();
    	CREATE_FUNC(word);
    	virtual bool init();
    public:
    	void showWord(const char* text, CCPoint pos);
    	void flowEnd();
    private:
    	CCLabelTTF* mylabeltext;
    };
    
    #endif
    
  8. word.cpp

    #include "word.h"
    
    word::word() {}
    
    word::~word() {}
    
    bool word::init()
    {
    	mylabeltext = CCLabelTTF::create("", "Arial", 30); //使用系统字体
    	mylabeltext->setColor(ccc3(255,0,0)); //设置为红色
    	mylabeltext->setVisible(false); //初始化不显示
    
    	this->addChild(mylabeltext);
    
    	return true;
    }
    
    void word::showWord(const char* str, CCPoint pos)
    {
    	mylabeltext->setVisible(true); //设置可见
    	mylabeltext->setString(str);
    	mylabeltext->setPosition(pos); //设置显示坐标
    	mylabeltext->setAnchorPoint(ccp(1,0));
    
    	//先放大后缩小
    	CCActionInterval* scaleLarge = CCScaleTo::create(0.3f, 2.5f, 2.5f);
    	CCActionInterval* scaleSmall = CCScaleTo::create(0.4f, 0.5f, 0.5f);
    	//回调动作,移除动画效果
    	CCCallFunc* callFunc = CCCallFunc::create(this, callfunc_selector(word::flowEnd));
    	//组合动作
    	CCActionInterval* actions = CCSequence::create(scaleLarge, scaleSmall, callFunc, NULL);
    
    	mylabeltext->runAction(actions);
    }
    
    void word::flowEnd()
    {
    	mylabeltext->setVisible(false);
    	//true:移除节点的动作和回调函数
    	mylabeltext->removeFromParentAndCleanup(true);
    }
    
  9. zhufood.h

    #ifndef _ZHUFOOD_H_
    #define _ZHUFOOD_H_
    #include "food.h" //提供精灵绑定与获取
    #include "word.h"
    #include "guanScene.h"
    
    class zhufood :public food {
    
    public:
    	zhufood();
    	~zhufood();
    	CREATE_FUNC(zhufood);
    	virtual bool zhufoodinit();
    
    	void show(); 
    	void hide(); //隐藏
    	void reboot(); //重置
    	bool isAlive(); //判断是否为活动状态
    
    	bool pengzhuang(Sprite* player); //碰撞检测
    
    	void eat(Sprite* player); //碰撞功能实现
    
    
    private:
    	bool myAlive; //标记金币活动状态
    
    };
    
    #endif
    
  10. zhufood.cpp

    #include "zhufood.h"
    
    zhufood::zhufood()
    {
    	myAlive = false;
    }
    zhufood::~zhufood(){}
    
    bool zhufood::zhufoodinit()
    {
    	return true;
    }
    
    void zhufood::show()
    {
    	if (getSprite()!= NULL)
    	{
    		setVisible(true); //设置为可见
    		myAlive = true;
    	}
    }
    
    void zhufood::hide()
    {
    	if (getSprite()!= NULL)
    	{
    		setVisible(false); //设置为不可见
    		reboot(); //重置
    		myAlive = false;
    	}
    }
    
    void zhufood::reboot()
    {
    	if (getSprite()!= NULL)
    	{
    		//初始化金币坐标, CCRANDOM_0_1随机数
    		setPosition(Point(800 + CCRANDOM_0_1() * 2000, 200 - CCRANDOM_0_1() * 100));
    	}
    }
    
    bool zhufood::isAlive()
    {
    	return myAlive;
    }
    
    bool zhufood::pengzhuang(Sprite* player) //碰撞检测
    {
    	//获取碰撞检查的对象,Node对象或继承了Node的类都拥有一个getBoundingBox()函数,
    	//getBoundingBox()会返回一个矩形,这个矩形就是Node对象的图片外围矩形
    	Rect nowPlayer = player->getBoundingBox();
    	Point getPos = getPosition();
    
    	//判断BoundingBox和金币中心点是否相交
    	return nowPlayer.containsPoint(getPos);
    }
    
    void zhufood::eat(Sprite* player)
    {
    	if (getSprite() == NULL) //判断精灵是否存在
    	{
    		return;
    	}
    
    	//添加不要命显示功能
    	word* myword = word::create();
    	player->addChild(myword);
    	myword->showWord("+100", player->getPosition()/2); //输出显示+100
    
    
    	//创建多种动作
    	auto back = MoveBy::create(0.1f, Point(-15, 0));
    	auto forward = MoveBy::create(0.1f, Point(15, 0));
    	auto backRotate = RotateBy::create(0.1f, -15, 0);
    	auto forwardRotate = RotateBy::create(0.1f, 15, 0);
    	//组合动作,实现后坐力效果
    	auto backend = Spawn::create(back, backRotate, NULL);
    	auto forwardend = Spawn::create(forward, forwardRotate, NULL);
    
    	auto actionend = Sequence::create(backend, forwardend, NULL);
    	//先停止所有的动作及其更新函数
    	player->pauseSchedulerAndActions();
    	//执行动作
    	player->runAction(actionend);
    	//动作恢复,恢复所有动作及其更新函数
    	player->resumeSchedulerAndActions();
    }
    
  11. zhufoodManager.h

    #ifndef _ZHUFOODMANAGER_H_
    #define _ZHUFOODMANAGER_H_
    
    #include "cocos2d.h"
    #include "zhufood.h"
    USING_NS_CC;
    
    #define MAX_ZHUFOOD 10 //最大数量
    
    class zhufoodManager :public Node {
    	
    public:
    	CREATE_FUNC(zhufoodManager);
    	virtual bool init();
    
    	virtual void update(float a); //重写update函数
    
    	void bangPlayer(Sprite* player); //绑定玩家对象
    
    	Sprite* myPlayer; //玩家对象
    	
    
    private:
    	void createZhuFood(); //创建金币对象zhufood
    
    	Vector<zhufood*> myzhufoodlist; //存放zhufood对象的列表
    
    };
    
    #endif
    
  12. zhufoodManager.cpp

    #include "zhufoodManager.h"
    #include "zhufood.h"
    
    bool zhufoodManager::init()
    {
    	createZhuFood(); //创建对象
    	this->scheduleUpdate(); //开启update函数的调用
    	return true;
    }
    
    void zhufoodManager::createZhuFood()
    {
    	zhufood* zhu = NULL;
    	Sprite* sprite = NULL;
    
    	for (int i = 0; i < MAX_ZHUFOOD; i++)
    	{	
    		//创建金币对象zhufood
    		zhu = zhufood::create();
    		zhu->bangSprite(Sprite::create("100yuan.jpg")); //绑定对象,在food.h中声明了
    		zhu->setScale(0.25f); //缩小到0.25倍大小
    		zhu->reboot();
    
    		//添加金币对象
    		this->addChild(zhu);
    
    		//保存金币对象到列表中
    		myzhufoodlist.pushBack(zhu);
    	}
    }
    
    void zhufoodManager::update(float a) 
    {
    	for (auto zhufood : myzhufoodlist) //从存放zhufood对象的列表里取出对象
    	{
    		//如果金币处于活动状态
    		if (zhufood->isAlive())
    		{
    			zhufood->setPositionX(zhufood->getPositionX() - 4);
    			//如果金币X坐标小于0,则超出了屏幕范围,则隐藏起来
    			if (zhufood->getPositionX() < 0)
    				zhufood->hide();
    		}
    		else
    		{
    			//金币处于非活动状态则让金币出场
    			zhufood->show();
    		}	
    		//如果金币X坐标小于0则隐藏金币
    		if (zhufood->getPositionX() < 0)
    			zhufood->hide();
    		else if (zhufood->pengzhuang(myPlayer))
    		{
    			zhufood->eat(myPlayer); //碰撞实现的效果
    			zhufood->hide(); //金币隐藏
    		}
    	}
    }
    
    void zhufoodManager::bangPlayer(Sprite* player)
    {
    	myPlayer = player;
    }
    
  13. 结束。

  14. 记录下功能实现的点点滴滴。

End

总结:多看文档多查资源,一种功能的实现不只一种方法。

~


发布了34 篇原创文章 · 获赞 0 · 访问量 494

猜你喜欢

转载自blog.csdn.net/weixin_44228006/article/details/104095835