首先新建GameLayer类,要在这层实现人物的创建,地图的创建,金币的生成和碰撞检测,GameLayer是很重的层啊

1.生成简单的地图就好了,地图由地面和墙壁构成,分成2个容器,用来存放生成的地面和墙壁精灵,场景的移动采用背景向左移动的策略,那么,地面,墙壁,金币等都要不断向左移动,同时,判断是否移出屏幕(即x坐标是否小于0,注意,判断时不要直接与0判断,稍微向左边偏离几个格子),移除屏幕时,则从容器中清除,并在容器的最后随机生成相应的精灵,实现无穷的跑动且没有重复场景

2.碰撞检测,设置定时器,每帧检测人物的上下右是否发生碰撞,采用矩形和点是否包含的策略,要注意的是有时要判断一个方向的多个点,否则碰撞效果不好;金币与人物的碰撞使用2个矩形是否相交。

3.随机函数,直接使用c++中的srand和rand配合

上代码+注释

#pragma once
#include "cocos2d.h"
#include "Player.h"//角色的加入
#include "Def.h"
#include <vector>
using namespace std;
USING_NS_CC;
class GameLayer :public Layer
{
public:
 bool init();
 CREATE_FUNC(GameLayer);
 bool onTouchBegan(Touch *touch, Event *unused_event);
 Player* player;
 Sprite *wall;
 CCTMXTiledMap *tileMap;//载入地图、废弃
 CCTMXLayer *tileLay;//废弃
 CCTMXObjectGroup *tileObject;//废弃
 void timeCallBcak(float f);//地图物体移动
 void bobCallBcak(float f);//碰撞检测
 void playerCallBcak(float f);//右边有障碍主角移动
 SpriteBatchNode *m_batchNode;//地面砖块缓冲池
 SpriteBatchNode *m_goldBatchNode;//金币缓冲池
 SpriteBatchNode *m_wallBatchNode;//墙壁缓冲池
 vector< Sprite* > m_Vector;//存放地面容器
 vector< Sprite* > m_goldVector;//存放金币容器
 vector< Sprite* > m_wallVector;//存放墙壁容器
 bool IscollWithUp();
 bool IscollWithDown();
 bool IscollWithRight();
 bool IscollWithLeft();
 bool IscollWithGold();
 bool IsDie();
 void DownLogic();
 void UpLogic();
 void RightLogic();
 void LeftLogic();
};
bool GameLayer::init()
{
 if (!Layer::init())
 {
  return false;
 }
 //随机种子的初始化
 srand((unsigned)time(NULL));
 
 auto visibleSize = Director::getInstance()->getVisibleSize();
 auto origin = Director::getInstance()->getVisibleOrigin();


 //添加地面缓冲
 m_batchNode = SpriteBatchNode::create("wall.png",50);
 m_batchNode->setAnchorPoint(Point::ZERO);
 m_batchNode->setPosition(ccp(0, 0));
 this->addChild(m_batchNode);
 //添加金币缓冲
 m_goldBatchNode = SpriteBatchNode::create("gold.png", 50);
 m_goldBatchNode->setAnchorPoint(Point::ZERO);
 m_goldBatchNode->setPosition(Point::ZERO);
 this->addChild(m_goldBatchNode);
 //添加墙壁缓冲
 m_wallBatchNode = SpriteBatchNode::create("wall.png", 50);
 m_wallBatchNode->setAnchorPoint(Point::ZERO);
 m_wallBatchNode->setPosition(Point::ZERO);
 this->addChild(m_wallBatchNode);


 //在地面缓冲中添加精灵,即开始时地面
 for (int i = 0; i < 30; i++)
 {
  auto walls = Sprite::create("wall.png");
  walls->setAnchorPoint(Point::ZERO);
  walls->setPosition(ccp(i * 32, 32));
  m_batchNode->addChild(walls);
  m_Vector.push_back(walls);
 }
  //建立人物 
 player = Player::getInstance();
 player->setAnchorPoint(ccp(0,0)); 
 player->setPosition(ccp(100,160));
 player->setPlayState(STATE_PLAYER_RUN);
 this->addChild(player); 

 //触摸建立
 auto listener = EventListenerTouchOneByOne::create();
 listener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan, this);
 auto dispatcher = Director::getInstance()->getEventDispatcher();
 dispatcher->addEventListenerWithSceneGraphPriority(listener, this);

 //地图定时器
//	this->schedule(schedule_selector(GameLayer::timeCallBcak), 0.1);//更改到mainScene中调用


 //碰撞定时器
 this->schedule(schedule_selector(GameLayer::bobCallBcak), 0.016);
 return true;
}

触摸

bool GameLayer::onTouchBegan(Touch *touch, Event *unused_event)
{
	CCLOG("on touch begin");
	player->setSpeed(DEFLAUT_SPEEDY);
	player->setPlayState(STATE_PLAYER_JUMP);
	return false;
}

地图和物体的移动:

void GameLayer::timeCallBcak(float f)//地图物体的移动
{
	//墙壁的移动
	int n = m_Vector.size();//容器的遍历
	for (int i = 0; i < n; i++)
	{
		m_Vector[i]->setPositionX(m_Vector[i]->getPositionX() - MOVING_GAP);
		if (m_Vector[i]->getPositionX() <= -m_Vector[i]->getContentSize().width)//跑出屏幕左边则清除同时在最左边随机生成
		{
			m_batchNode->removeChild(m_Vector[i], true);
			m_Vector.erase(m_Vector.begin() + i);
			int i = rand() % 10;//清除后添加
			CCLOG("i=%d", i);
			if (i>0)//在最后添加一个地面块
			{
				auto walls = Sprite::create("wall.png");
				walls->setAnchorPoint(Point::ZERO);
				walls->setPosition(ccp((*(m_Vector.end() - 1))->getPositionX() + 32, 32));//加到最后
				m_batchNode->addChild(walls);
				m_Vector.push_back(walls);
			}
			else//空2格再添加地面块(1/10的概率)
			{
				auto walls = Sprite::create("wall.png");
				walls->setAnchorPoint(Point::ZERO);
				walls->setPosition(ccp((*(m_Vector.end() - 1))->getPositionX() + 3 * 32, 32));//加到最后
				m_batchNode->addChild(walls);
				m_Vector.push_back(walls);


			}
			//右边将要出现的物品
			//右边将要产生墙壁
			auto produceWall = rand() % 10;//出现墙壁概率
			auto wallHigh = rand() % 4;//墙壁高度
			if (produceWall == 0)
			{
				for (int j = 0; j < wallHigh; j++)
				{
					auto wall = Sprite::create("wall.png");
					wall->setAnchorPoint(Point::ZERO);
					wall->setPosition(ccp((*(m_Vector.end() - 1))->getPositionX(), 32 * (j + 2)));
					m_wallVector.push_back(wall);
					m_wallBatchNode->addChild(wall);
				}
			}
			// 1.产生金币 1/5的概率
			auto produceGold = rand() % 5;
			if (produceGold == 0)
			{
				auto goldHigh = rand() % 3 + 3;//金币高度
				if (produceWall == 0) goldHigh = wallHigh + 2;//金币在墙壁的上方
				auto gold = Sprite::create("gold.png");
				gold->setAnchorPoint(Point::ZERO);
				gold->setPosition(ccp((*(m_Vector.end() - 1))->getPositionX(), 32 * goldHigh));
				m_goldVector.push_back(gold);
				m_goldBatchNode->addChild(gold);
			}
			


		}
	}
	//金币的移动
		for (auto i = 0; i < m_goldVector.size();)
		{
			m_goldVector[i]->setPositionX(m_goldVector[i]->getPositionX() - MOVING_GAP);
			if (m_goldVector[i]->getPositionX() < -m_goldVector[i]->getContentSize().width)
			{
				m_goldBatchNode->removeChild(m_goldVector[i], true);
				m_goldVector.erase(m_goldVector.begin() + i);
				


			}
			else
			{
				i++;
			}
		}
	//墙壁的移动
		for (auto i = 0; i < m_wallVector.size();)
		{
			m_wallVector[i]->setPositionX(m_wallVector[i]->getPositionX() - MOVING_GAP);
			if (m_wallVector[i]->getPositionX() < -m_wallVector[i]->getContentSize().width)
			{
				m_wallBatchNode->removeChild(m_wallVector[i], true);
				m_wallVector.erase(m_wallVector.begin() + i);
			}
			else i++;
		}
}



void GameLayer::bobCallBcak(float f)//碰撞检测
{
	if (IscollWithDown())//人物和下方有接触
	{
		if (player->getPlayState() == STATE_PLAYER_DOWN)
		{
			Sounder::getInstance()->playTouch();
			player->setPlayState(STATE_PLAYER_RUN);
		}
	}
	else
	{
		if (player->getPlayState()==STATE_PLAYER_RUN)
			player->setPlayState(STATE_PLAYER_DOWN);
	}
	if (IscollWithUp())//人物和上方有接触
	{
		if (player->getPlayState() == STATE_PLAYER_JUMP)player->setPlayState(STATE_PLAYER_RUN);
	}
	if (IscollWithRight())//人物和右边有接触
	{
		this->schedule(schedule_selector(GameLayer::playerCallBcak), 0.1);
	}
	else
	{
		this->unschedule(schedule_selector(GameLayer::playerCallBcak));
	}
	IscollWithLeft();
	
	//IscollWithGold();//移到主界面去了,为了和信息界面交互
}
bool GameLayer::IsDie()//判断人物是否死亡
{
<span style="white-space:pre">	</span>if (player->getPositionX()<0 || player->getPositionY()<0)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return true;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return false;
}
bool GameLayer::IscollWithGold()//是否与金币碰撞
{
	for (int i = 0; i < m_goldVector.size(); )//遍历
	{
		if (m_goldVector[i]->getBoundingBox().intersectsRect(player->getBoundingBox()))
		{
			m_goldBatchNode->removeChild(m_goldVector[i], true);//发生碰撞则移除并返回
			m_goldVector.erase(m_goldVector.begin() + i);
			return true;
		}
		else i++;//无碰撞则往后遍历
	}
	return false;


}
bool GameLayer::IscollWithDown()
{
	Point point;//中间点
	point.x = player->getBoundingBox().getMidX();
	point.y = player->getBoundingBox().getMinY();
	//增加碰厨点
	Point point1;//左边点
	point1.x = player->getBoundingBox().getMinX();
	point1.y = player->getBoundingBox().getMinY();
	Point point2;//右边点
	point2.x = player->getBoundingBox().getMaxX()-10;
	point2.y = player->getBoundingBox().getMinY();

	//是否与地面接触
	for (int i = 0; i < m_Vector.size(); i++)
	{
		if (m_Vector[i]->getBoundingBox().containsPoint(point)
			//|| m_Vector[i]->getBoundingBox().containsPoint(point1)
			|| m_Vector[i]->getBoundingBox().containsPoint(point2))
		{
			return true;
		}
	}
	//是否与wall碰撞
	for (int i = 0; i < m_wallVector.size(); i++)
	{
		if (m_wallVector[i]->getBoundingBox().containsPoint(point)
			//|| m_wallVector[i]->getBoundingBox().containsPoint(point1)
			|| m_wallVector[i]->getBoundingBox().containsPoint(point2))
		{
			return true;
		}
	}
	return false;
}
bool GameLayer::IscollWithUp()
{
	Point point1,point2,point3;
	point1.x = player->getBoundingBox().getMinX();
	point1.y = player->getBoundingBox().getMaxY();
	point2.x = player->getBoundingBox().getMidX();
	point2.y = player->getBoundingBox().getMaxY();
	point3.x = player->getBoundingBox().getMaxX();
	point3.y = player->getBoundingBox().getMaxY();
	for (int i = 0; i < m_Vector.size(); i++)
	{
		if (//m_Vector[i]->getBoundingBox().containsPoint(point1)//头发可以穿过
			 m_Vector[i]->getBoundingBox().containsPoint(point2)
			| m_Vector[i]->getBoundingBox().containsPoint(point3)
			)
		{
			return true;
		}
		else if (m_Vector[i]->getPositionX() > point1.x)
		{
			return false;
		}
	}
	return false;
}
bool GameLayer::IscollWithRight()
{
	Point point;
	point.x = player->getBoundingBox().getMaxX();
	point.y = player->getBoundingBox().getMinY()+10;
	Point point1;
	point1.x = player->getBoundingBox().getMaxX();
	point1.y = player->getBoundingBox().getMidY();
	Point point2;
	point2.x = player->getBoundingBox().getMaxX();
	point2.y = player->getBoundingBox().getMaxY();
	//判断是否与右侧地面碰撞
	for (int i = 0; i < m_Vector.size(); i++)
	{
		if (m_Vector[i]->getBoundingBox().containsPoint(point)//无法在地面上走动,y向上移动一点
			|| m_Vector[i]->getBoundingBox().containsPoint(point1)
			|| m_Vector[i]->getBoundingBox().containsPoint(point2))
		{
			return true;
		}
		/*else if (m_vector[i]->getpositionx() > point.x)//当添加墙壁后应去除
		{
			return false;
		}*/
	}
	//判断是否与右边墙壁碰撞
	for (int i = 0; i < m_wallVector.size(); i++)
	{
		if (m_wallVector[i]->getBoundingBox().containsPoint(point)
			|| m_wallVector[i]->getBoundingBox().containsPoint(point1)
			|| m_wallVector[i]->getBoundingBox().containsPoint(point2))
		{
			return true;
		}
	}
	return false;
}
bool GameLayer::IscollWithLeft()
{
	Point point;
	point.x = player->getBoundingBox().getMinX();
	point.y = player->getBoundingBox().getMidY();
	for (int i = 0; i < m_Vector.size(); i++)
	{
		if (m_Vector[i]->getBoundingBox().containsPoint(point))
		{
			return true;
		}
		else if (m_Vector[i]->getPositionX() > point.x)
		{
			return false;
		}
	}
	return false;
}