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

接下来是第三步:加入主角Runner。 这一步就是写帧动画,然后初始化一下主角的物理属性,其次还有加入两个按钮控制主角的跳跃和蹲下。

在runner类里面要加一些判断,判断主角的状态,从而实现一个跳跃的连贯动作以及蹲下。毕竟你跳起来的时候是不能蹲下的!

加入类:Runner 有如下功能: 1.建立主角跳跃、跑步、蹲下等帧动画 2.加入两个按钮控制主角的动作 3.主角的动作判定以及动画的切换

Runner.h
#ifndef __Runner__H__
#define __Runner__H__

#include "cocos2d.h"
//枚举主角的各个状态
enum runnerState{
	running,
	jumpUp,//往上跳
	jumpDown,//跳完落下
	crouch
};

class Runner : public cocos2d::Node{
public:
	virtual bool init();
	CREATE_FUNC(Runner);

	//初始化 action 集合
	void initActionSet(cocos2d::SpriteFrameCache* frameCache);

	//根据动作名称执行动作
	void doAction(const char* actionName);

	void initBody();

	runnerState getState(){ return m_state; };
        //获得跑步时主角的大小 
	cocos2d::Size getRunJumpSize(){ return run_jumpSize; };
        //获得蹲下时主角的大小
	cocos2d::Size getCrouchSize() { return crouchSize; };

	void Run();//跑步

	void Jump();//跳跃

	void Crouch();//蹲下

	virtual void update(float dt);

private:
	//  需要一个主要的精灵执行动作
	cocos2d::Sprite* m_runner;

	// 不同的动作需要不同的刚体大小
	cocos2d::Size run_jumpSize;//跑和跳的大小一样
	cocos2d::Size crouchSize;//蹲下来的大小

	runnerState m_state;
};

#endif
Runner.cpp
#include "Runner.h"
#include "GameOver.h"

USING_NS_CC;

bool Runner::init(){
	//加载图片到缓存池
	auto frameCache = SpriteFrameCache::getInstance();
	frameCache->addSpriteFramesWithFile("parkour.plist", "parkour.png");

	m_runner = Sprite::createWithSpriteFrameName("runner0.png");

	run_jumpSize = m_runner->getContentSize();
	crouchSize = Sprite::createWithSpriteFrameName("runnerCrouch0.png")->getContentSize();

	this->addChild(m_runner);

	initActionSet(frameCache);//初始化动作集合

	initBody();

	this->scheduleUpdate();

	this->setTag(1);

	return true;
}

void Runner::initActionSet(SpriteFrameCache* frameCache){
	SpriteFrame* frame = NULL;
	//3.0中改用vector 而不是用Array
	Vector<SpriteFrame*>frameVector;

	/* 1.----------------加载跑动的Animation-----------------*/
	for (int i = 0; i <= 7; i++) {
		//从缓存池中加载精灵到Vector
		frame = frameCache->spriteFrameByName(String::createWithFormat("runner%d.png", i)->getCString());
		frameVector.pushBack(frame);
	}

	//用vector里面的SpriteFrame列表创建Animation  以及设置一些参数
	auto run_animation = Animation::createWithSpriteFrames(frameVector, 0.1f, -1);
	//将跑动的 Animation 取名为 running 
	AnimationCache::getInstance()->addAnimation(run_animation, "running");

	/* 2.----------------加载跳起的Animation-----------------*/
	frameVector.clear();
	for (int i = 0; i <= 3; i++){
		frame = frameCache->spriteFrameByName(String::createWithFormat("runnerJumpUp%d.png", i)->getCString());
		frameVector.pushBack(frame);
	}
	auto jumpUp_animation = Animation::createWithSpriteFrames(frameVector, 0.2);//不设置无限循环
	AnimationCache::getInstance()->addAnimation(jumpUp_animation, "jumpUp");

	/* 3.----------------加载跳起后落下的Animation-----------------*/	
        frameVector.clear();
	for (int i = 0; i <= 1; i++){
		frame = frameCache->spriteFrameByName(String::createWithFormat("runnerJumpDown%d.png", i)->getCString());
		frameVector.pushBack(frame);
	}
	auto jumpDown_animation = Animation::createWithSpriteFrames(frameVector, 0.3);
	AnimationCache::getInstance()->addAnimation(jumpDown_animation, "jumpDown");

	/* 4.----------------加载蹲下的Animation(蹲下就一个动作)-----------------*/
	frameVector.clear();
	frame = frameCache->spriteFrameByName("runnerCrouch0.png");
	frameVector.pushBack(frame);
	auto crouch_animation = Animation::createWithSpriteFrames(frameVector, 0.3);//不设置无限循环
	AnimationCache::getInstance()->addAnimation(crouch_animation, "crouch");

}

void Runner::doAction(const char* actionName){
	auto animation = AnimationCache::getInstance()->animationByName(actionName);
	auto action = Animate::create(animation);
	m_runner->runAction(action);
}

void Runner::initBody(){
	//根据不同状态设置不同刚体大小
	Size bodySize;
	if (m_state == crouch){
		bodySize = crouchSize;
	}
	else{
		bodySize = run_jumpSize;
	}

	//创建runner的刚体
	auto runnerBody = PhysicsBody::createBox(bodySize, PHYSICSBODY_MATERIAL_DEFAULT);

	//设置可以碰撞检测
	runnerBody->setCategoryBitmask(1);
	runnerBody->setCollisionBitmask(1);
	runnerBody->setContactTestBitmask(1);
        //设置禁止旋转,这个必须有,否则跑的过程中主角可能会旋转
	runnerBody->setRotationEnable(false);
	//绑定刚体
	this->setPhysicsBody(runnerBody);
}

void Runner::Run(){
	m_state = running;
	initBody();
	doAction("running");
}

/**/
void Runner::Jump(){
	//只有在跑动时才能起跳
	if (m_state == running){
		m_state = jumpUp;

		auto mass = this->getPhysicsBody()->getMass() * 140;

		//控制刚体:g给他一个向上的力
		this->getPhysicsBody()->applyImpulse(Vect(0, mass));

		m_runner->stopAllActions();

		doAction("jumpUp");
	}
}

void Runner::update(float dt){
	auto vel = this->getPhysicsBody()->getVelocity();
	if (m_state == jumpUp){
		if (vel.y < 0.1){
			m_state = jumpDown;
			m_runner->stopAllActions();
			doAction("jumpDown");
		}
	}

	if (m_state == jumpDown){
		CCLOG("%f", vel.y);
		//不应该是 等于 0
		if (vel.y > 0){
			m_state = running;
			m_runner->stopAllActions();
			doAction("running");
		}
	}
}

void Runner::Crouch(){
	//只能在跑动的时候蹲下
	if (m_state == running){
		m_state = crouch;
		m_runner->stopAllActions();
		initBody();
		doAction("crouch");
	}
}

其中Runner::initBody()中的runnerBody->setRotationEnable(false);的设置是很有必要的,否则就会出现下面的情况:

QQ图片20150804102342

当然PlayScene.cpp中的init()也要加入Runner,这样才能显示主角。相对于第一步的PlayScene.cpp,加入了 createJumpButton()、jumpEvent()、createCrouchButton()、crouchDown()、crouchUp()函数,当然PlayScene.h 中也要做一下声明。

在PlayScene.cpp的init()方法中加入下面第一个框内的代码(加入主角和按钮)。并在开头加入宏定义 #define ground_height 59 和 #define runner_posX 80
m_runner = Runner::create();
	m_runner->setPosition(runner_posX, ground_height + m_runner->getRunJumpSize().height / 2);
	m_runner->Run();
	this->addChild(m_runner);

	createJumpButton();
	createCrouchButton();
并在PlayScene.cpp最下面加入新增加的函数定义,如下:
void PlayScene::createJumpButton(){
	auto visibleSize = Director::getInstance()->getVisibleSize();

	auto jumpLabel = Label::create("Jump", "Arail", 30);
	auto norBtn = Scale9Sprite::create("norBtn.png");
	auto lightBtn = Scale9Sprite::create("lightBtn.png");

	auto jumpBtn = ControlButton::create(jumpLabel, norBtn);
	jumpBtn->setPosition(visibleSize.width - 80, 130);
	jumpBtn->setBackgroundSpriteForState(lightBtn, Control::State::HIGH_LIGHTED);

	jumpBtn->addTargetWithActionForControlEvents(
		this,
		cccontrol_selector(PlayScene::jumpEvent),
		Control::EventType::TOUCH_DOWN);

	this->addChild(jumpBtn);
}
void PlayScene::jumpEvent(Ref* pSender, Control::EventType event){
	SimpleAudioEngine::sharedEngine()->playEffect("jump.mp3");
	m_runner->Jump();
}

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

	auto crouchLabel = Label::create("Crouch", "Arail", 30);
	auto norBtn = Scale9Sprite::create("norBtn.png");
	auto lightBtn = Scale9Sprite::create("lightBtn.png");

	auto crouchBtn = ControlButton::create(crouchLabel, norBtn);
	crouchBtn->setPosition(visibleSize.width - 100, 80);
	crouchBtn->setBackgroundSpriteForState(lightBtn, Control::State::HIGH_LIGHTED);

	//
	crouchBtn->addTargetWithActionForControlEvents(
		this,
		cccontrol_selector(PlayScene::crouchDown),
		Control::EventType::TOUCH_DOWN);

	//
	crouchBtn->addTargetWithActionForControlEvents(
		this,
		cccontrol_selector(PlayScene::crouchUp),
		Control::EventType::TOUCH_UP_INSIDE);

	this->addChild(crouchBtn);
}

void PlayScene::crouchDown(Ref* pSender, Control::EventType event){
	//添加判断
	if (m_runner->getState() == running){
		m_runner->Crouch();
		m_runner->setPosition(runner_posX, ground_height + m_runner->getCrouchSize().height / 2);
	}
	SimpleAudioEngine::sharedEngine()->playEffect("crouch.mp3");
}
void PlayScene::crouchUp(Ref* pSender, Control::EventType event){
	//否则,在跳起来的时候,点击crouch 松开之后,状态就会变成running
	if (m_runner->getState() == crouch){
		m_runner->stopAllActions();
		m_runner->Run();
		m_runner->setPosition(runner_posX, ground_height + m_runner->getRunJumpSize().height / 2);
	}
}

关于ControlButton和Scale9Sprite(九妹图)的使用,我在别的文章也提到过,详情请看: 《cocos2d-x v3.3中 关于ControlButton的认识》

以上做完后运行就会出现以下界面(Jump控制跳、Crouch控制蹲下):

QQ图片20150804102342

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

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

下一步:〖cocos2d-x 3.3〗学习笔记之游戏实例 《跑酷》第四步— 加入岩石障碍物和游戏结束界面

标签:   |  
时间: 2015年08月05日下午16:50  |  
作者:
LEAVE A REPLY
loading
正在赶回来……