〖cocos2d-x 3.3〗学习笔记之游戏实例 《跑酷》第二步— 进入游戏

接下来是第二步:进入游戏。 就是进入游戏后一些初步初始化,本章就仅仅初始化了一个背景移动的效果,因为人物的跑动一般是有三种实现方法: 第一种:人动,背景不动 第二种:人不动,背景动(人相对于背景就是一直向前走了) 第三种:加入摄像机

我采用的是第二种方法,让背景往后移动,来实现一个人物往前走的效果。

界面定义为:PlayScene 有如下功能: 1.初始化背景1和背景2 2.初始化地板1和地板2 2.初始化一个地板刚体(这就需要用到物理引擎了)

PlayScene.h
#ifndef __PlayScene__H__
#define __PlayScene__H__

#include "cocos2d.h"
#include "cocos-ext.h"

USING_NS_CC_EXT;
USING_NS_CC;

class PlayScene : public cocos2d::Layer
{
public:
	virtual bool init();
	static cocos2d::Scene* createScene();
	CREATE_FUNC(PlayScene);

        //这里两行的作用是:为后面的layer->setPhysicsWorld(scene->getPhysicsWorld());
	cocos2d::PhysicsWorld* m_world;
	void setPhysicsWorld(cocos2d::PhysicsWorld* world){ m_world = world; };
        //初始化背景
	void initBG();
        //用update函数让地图滚动
	virtual void update(float dt);

private:
        //初始化一个地板的物理刚体
	void initPhysicsWorld();
        //背景精灵
	cocos2d::Sprite* bgSprite1;
	cocos2d::Sprite* bgSprite2;
	cocos2d::Sprite* groundSprite1;
	cocos2d::Sprite* groundSprite2;

	Label* label;
};

#endif

头文件应该没什么问题,都是一些声明。

再看一下PlayScene.cpp
#include "PlayScene.h"
#include "SimpleAudioEngine.h"
#include "cocos2d.h"

#define ground_height 59
#define runner_posX 80

USING_NS_CC;
using namespace CocosDenshion;

Scene* PlayScene::createScene()
{
        //创建带有物理的Scene
	auto scene = Scene::createWithPhysics();

        //开启调试,将物理世界描绘出来,使得其可见
	scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

	auto layer = PlayScene::create();
      
        //将Scene中的物理世界传到layer中,使layer获得和scene一样的基本物理规则,方便layer后加一些物理属性
	layer->setPhysicsWorld(scene->getPhysicsWorld());

	scene->addChild(layer);

	return scene;
}

bool PlayScene::init()
{
	if (!Layer::init()){
		return false;
	}
	if (SimpleAudioEngine::getInstance()->isBackgroundMusicPlaying()==false){
		SimpleAudioEngine::getInstance()->playBackgroundMusic("background",true);
	}

	initPhysicsWorld();

	initBG();

        //开启update
	this->scheduleUpdate();

        //这里先加上一个计分板,后面文章会进一步提到怎么用
	auto scoreLabel = Label::create("Score:0", "Arail", 30);
	scoreLabel->setAnchorPoint(Vec2(0,1));
	scoreLabel->setPosition(20,320);
	this->addChild(scoreLabel);
	
	return true;
}

void PlayScene::initPhysicsWorld()
{
	auto visibleSize = Director::getInstance()->getVisibleSize();
	auto origin = Director::getInstance()->getVisibleOrigin();

	//创建一个地板边界 的刚体
	auto boundBody = PhysicsBody::createEdgeSegment(origin,
		ccp(visibleSize.width, 0),
		PHYSICSBODY_MATERIAL_DEFAULT, 1);

        //用一个Node关联物理刚体,否则物理刚体是不显示的,毕竟物理规则是基于物体才有存在意义的。
	auto boundNode = Node::create();
	boundNode->setPhysicsBody(boundBody);
	boundNode->setPosition(0,ground_height);

	this->addChild(boundNode);
}

void PlayScene::initBG()
{
	auto visibleSize = Director::getInstance()->getVisibleSize();

	//背景1
	bgSprite1 = Sprite::create("Map00.png");
	bgSprite1->setPosition(Vec2(bgSprite1->getContentSize().width/2, visibleSize.height / 2));
	this->addChild(bgSprite1);

	//背景2
	bgSprite2 = Sprite::create("Map01.png");
	bgSprite2->setPosition(Vec2(bgSprite1->getContentSize().width + bgSprite1->getContentSize().width / 2, visibleSize.height / 2));
	this->addChild(bgSprite2);

	//地面1
	groundSprite1 = Sprite::create("Ground00.png");
	groundSprite1->setPosition(Vec2(bgSprite1->getContentSize().width/2, groundSprite1->getContentSize().height / 2));
	this->addChild(groundSprite1);

	//地面2
	groundSprite2 = Sprite::create("Ground01.png");
	groundSprite2->setPosition(Vec2(bgSprite1->getContentSize().width + bgSprite1->getContentSize().width / 2, groundSprite1->getContentSize().height / 2));
	this->addChild(groundSprite2);
}

void PlayScene::update(float dt)
{
	int PosX1 = bgSprite1->getPositionX();
	int PosX2 = bgSprite2->getPositionX();

	PosX1 -= 2;
	PosX2 -= 2;

	auto mapSize = bgSprite1->getContentSize();

	if (PosX1< -mapSize.width/2){
		PosX1 = mapSize.width + mapSize.width/2;
		PosX2 = mapSize.width / 2;
	}

	if (PosX2< -mapSize.width/2){
		PosX2 = mapSize.width + mapSize.width / 2;
		PosX1 = mapSize.width / 2;
	}

	bgSprite1 -> setPositionX(PosX1);
	bgSprite2 -> setPositionX(PosX2);
	groundSprite1->setPositionX(PosX1);
	groundSprite2->setPositionX(PosX2);
}

代码注释很详细,估计就算有不懂得,也就是initBG()和update()这两个函数有些疑惑。其实很简单initBG()中背景1和背景2是连在一起的,学过js的都知道,这和轮播图的原理有限类似。这里是把两个背景通过设置position拼接到一块,在update()函数中,背景每一帧向左移动2个像素。当背景1将要完全移除窗口时,进行if语句判断,如果返回true,把背景1的位置瞬间变到第二张背景图的后面,拼接到第二张图后面,然后判断第二张图是否将要移除窗口,如果是那就改变他的位置瞬间把它放到它后面的图后面,也就是此时第一张图的后面,以此类推,实现一个循环。至于地板1和地板2,地板1对应背景1,地板2对应背景2,原理都是一样的。

有什么问题和建议可以在留言板随时反馈给我。游戏的图片和音乐等资源都在游戏第一步文章中给出,详情请看: 第一步:〖cocos2d-x 3.3〗学习笔记之游戏实例 《跑酷》第一步— 开始界面

以上做完后运行就会出现以下界面:

QQ图片20150804102342

游戏需要用到的资源(不放到resourse里运行会报错):Resources

上一步:〖cocos2d-x 3.3〗学习笔记之游戏实例 《跑酷》第一步— 开始界面

下一步:〖cocos2d-x 3.3〗学习笔记之游戏实例 《跑酷》第三步— 加入主角(Runner)

标签:   |  
时间: 2015年08月04日上午10:32  |  
作者:
LEAVE A REPLY
loading
正在赶回来……