〖cocos2d-x 3.3〗学习笔记之游戏实例 《跑酷》第五步(大功告成)— 加入金币

接下来是第五步(大功告成)— 加入金币。 这里一样要用到和第二步背景循环以及第四部岩石的循环差不多的原理,来设置金币的一个不断循环产生过程,另外要加一个碰撞检测,来检测主角和金币 碰撞之后金币消失,分数加1的一个机制。

这一步一共就新添加了1个类:Runner

加入类:Runner 功能: 1.初始化金币的动作(金币的旋转)以及绑定物理刚体 2.创建帧动画,包装动作

更新PlayScene.cpp中bool PlayScene::onContactBegin()函数如下:
bool PlayScene::onContactBegin(PhysicsContact& contact)
{
	auto body_1 = (Sprite*)contact.getShapeA()->getBody()->getNode();
	auto body_2 = (Sprite*)contact.getShapeB()->getBody()->getNode();

	CCLOG("dssd");

	if ((body_1->getTag() == 3 && body_2->getTag() == 1) ||
		(body_1->getTag() == 1 && body_2->getTag() == 3)){
		GameOver();
	}

	if (body_1->getTag() == 2){
		body_1->setVisible(false);
		score += 1;
		//刷新分数
		this->label->setString(String::createWithFormat("Scores:%d", score)->getCString());
	}

	if (body_2->getTag() == 2){
		body_2->setVisible(false);
		score += 1;
		this->label->setString(String::createWithFormat("Scores:%d", score)->getCString());
	}

	return false;
}
Coin.cpp
#include "Coin.h"
#include "cocos2d.h"

USING_NS_CC;

bool Coin::init(){
	if (!Node::init()){
		return false;
	}

	//缓存池
	auto frameCache = SpriteFrameCache::getInstance();
	frameCache->addSpriteFramesWithFile("parkour.plist", "parkour.png");

	auto sprite = Sprite::createWithSpriteFrameName("coin7.png");

	//绑定
	setSprite(sprite);
	//执行动作
	getSprite()->runAction(createAnimate(frameCache));
	//绑定刚体
	initBody();

	return true;
}

Animate* Coin::createAnimate(SpriteFrameCache* frameCache){


	SpriteFrame* frame = NULL;
	//数组不行 要用vector
	//auto frameArray = Array::create();
	//frameArray->retain();
	Vector<SpriteFrame*>frameArray;

	// 用一个列表保存所有SpriteFrame对象 
	for (int i = 0; i <= 7; i++) {
		/* 从SpriteFrame缓存池中获取CCSpriteFrame对象 */
		frame = frameCache->spriteFrameByName(String::createWithFormat("coin%d.png", i)->getCString());
		frameArray.pushBack(frame);

	}
	/* 使用SpriteFrame列表创建动画对象 */
	auto animation = Animation::createWithSpriteFrames(frameArray);

	animation->setLoops(-1);

	animation->setDelayPerUnit(0.1f);

	/* 将动画包装成一个动作 */
	auto action = Animate::create(animation);

	return action;
}

void Coin::initBody(){
	auto phyBody = PhysicsBody::createBox(getSprite()->getContentSize());
	phyBody->setGravityEnable(false);
	phyBody->setCategoryBitmask(1);
	phyBody->setCollisionBitmask(1);
	phyBody->setContactTestBitmask(1);

	this->setPhysicsBody(phyBody);
}
Coin.h
#ifndef __Coin__H__
#define __Coin__H__

#include "Base.h"
#include "cocos2d.h"

USING_NS_CC;

class Coin : public Base
{
public:
	virtual bool init();
	CREATE_FUNC(Coin);

	//金币动作
	cocos2d::Animate* createAnimate(cocos2d::SpriteFrameCache* frameCache);
	//物理刚体
	void initBody();

private:
};/**/

#endif
另外更新BaseManager.h,加入金币头文件、宏定义以及createCoin()函数:
#ifndef __BaseManager__H__
#define __BaseManager__H__

#include "cocos2d.h"
#include "Coin.h" //新增加
#include "Rock.h"

#define coinNum 4 //新增加
#define coinTag 2 //新增加
#define rockNum 2
#define rockTag 3

class BaseManager : public cocos2d::Node
{
public:
	CREATE_FUNC(BaseManager);
	virtual bool init();
	virtual void update(float dt);

private:
	void createCoin(); //新增加
	cocos2d::Array* m_coinArr; //新增加

	void createRock();
	cocos2d::Array* m_rockArr;
};

#endif
更新BaseManager.cpp文件,加入金币的循环刷新:
#include "BaseManager.h"
#define ground_hight 59

USING_NS_CC;

bool BaseManager::init(){
	if (!Node::init()){
		return false;
	}

	createCoin();
	createRock();
	this->scheduleUpdate();
	return true;
}

void BaseManager::createCoin(){
	m_coinArr = Array::create();
	m_coinArr->retain();

	Coin* coin = NULL;

	for (int i = 1; i <= coinNum; ++i){
		coin = Coin::create();

		coin->setVisible(false);

		coin->setTag(coinTag);

		//记得添加
		this->addChild(coin);

		m_coinArr->addObject(coin);
	}/**/
}

void BaseManager::createRock(){
	m_rockArr = Array::create();
	m_rockArr->retain();

	Rock* rock = NULL;

	float dis = 960;//两岩石的间距

	for (int i = 1; i <= rockNum; ++i){
		rock = Rock::create();

		rock->setTag(rockTag);

		rock->setPosition(dis, ground_hight + rock->getConSize().height / 2);
		dis += 640;

		//记得添加
		this->addChild(rock);

		m_rockArr->addObject(rock);
	}
}

void BaseManager::update(float dt){
	Ref* obj = NULL;
	Coin* coin = NULL;

	//需要重置金币的个数
	int setNum = 0;
	CCARRAY_FOREACH(m_coinArr, obj){
		coin = (Coin*)obj;

		//不在屏幕
		if (coin->getPositionX() < -coin->getConSize().width / 2){
			coin->setVisible(false);
		}

		//要是不可见,要不就是不在屏幕里,要不就是被碰撞了
		if (!coin->isVisible()){
			setNum++;
		}

		//让金币移动
		coin->setPositionX(coin->getPositionX() - 2);
	}

	//4个全部重置
	if (setNum == 4){
		int i = 0;
		float posX = 640 + 50;
		float posY = ground_hight + 15 + CCRANDOM_0_1() * 60;
		CCARRAY_FOREACH(m_coinArr, obj){
			coin = (Coin*)obj;
			//不在屏幕
			if (coin->getPositionX() < -coin->getConSize().width / 2){
				coin->setVisible(false);
			}
			//要是不可见,要不就是不在屏幕里,要不就是被碰撞了
			if (!coin->isVisible()){
				//两个两个一起
				if (i < 2){
					posX += 30;//两个金币同一高度,间隔30
				}
				else{
					//重新重置位置 
					i = -1;
					posY = ground_hight + 15 + CCRANDOM_0_1() * 60;
					posX += 400;
				}
				i++;//重置金币个数记录
				//
				coin->setVisible(true);
				coin->setPosition(posX, posY);
			}
		}
	}



	Ref* rockObj = NULL;
	Rock* rock = NULL;

	CCARRAY_FOREACH(m_rockArr, rockObj){
		rock = (Rock*)rockObj;

		if (rock->getPositionX() < -rock->getConSize().width / 2){
			rock->setVisible(false);
		}
		if (rock->isVisible() == false){
			float posX = 1280;
			float posY = ground_hight + rock->getConSize().height / 2;
			if (CCRANDOM_MINUS1_1() > 0){
				posY += 50;
			}
			rock->setPosition(posX, posY);
			rock->setVisible(true);
		}

		rock->setPositionX(rock->getPositionX() - 2);
	}
}

然后运行如下:

QQ图片20150806115017

如果想去掉精灵周围的红色框框即取消调试,只需要把PlayScene.cpp中的init()函数中的调试注释掉就行了:

//开启调试,将物理世界描绘出来,使得其可见,如果不需要把下面代码注释掉即可 scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

那么到此为止这个跑酷游戏也已经完成了,其中有很多细节需要朋友们自己琢磨,我自己当时也是琢磨了很久,或许刚开始看的时候觉得游戏很简单,内容也没什么复杂的,但是实际操作后会发现,从头到尾自己完成这样一个游戏工程,还是很头疼的,毕竟是新手,因此这款游戏代码很锻炼新手,也很适合新手尝试,所以大家加油吧,有兴趣就努力学习,把好刀用到刀刃上,转眼我就已经大三了(暑假结束就是大三),努力学习只是才是我们的责任和任务啊,不说别的,money这种东西还得靠科技,毕竟科技知识才是第一生产力啊,真是后悔高中初中在干嘛,浪费了大把大把的时间!

游戏需要用到的资源以及源代码:Resources和Classes

标签:   |  
时间: 2015年08月06日下午12:01  |  
作者:
4 COMMENTS
  1. 2016/03/23
    泰动听电台

    做完了给我玩玩

    • 2016/03/23
      那樊笼
      @泰动听电台 其实不好玩,这只是个入门教程
      • 2016/03/27
        泰动听电台
        @那樊笼 晕死,你那个小人怎么弄的。
        • 2016/03/27
          那樊笼
          @泰动听电台 我发过一篇文章,你在我文章里找一下,有教程
LEAVE A REPLY
loading
正在赶回来……