cocos2d-x 3.0遊戲實例學習筆記 《跑酷》 第三步---主角開跑&同時帶着剛體

說明:這裏是借鑑:曉風殘月 前輩的博客,他是將泰然網的跑酷教程,用cocos2d-x 2.X 版本重寫的,目前我正在學習cocos2d-X3.0 於是就用cocos2d-X 3.0重寫,並做相關筆記

在這一步,我們主要是把主角加入到遊戲場景中來,並且讓它跑動,這裏的跑動,實際上也就是執行一組動畫,讓其看起來像是在跑動,而且相對屏幕的位置也不會改變

我們會定義一個主角類: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;};//獲取不同時候的SIze
	cocos2d::Size getCrouchSize() { return crouchSize;};

	void Run();
private:
	//  需要一個主要的精靈執行動作
	cocos2d::Sprite* m_runner;

	// 不同的動作需要不同的剛體大小
	cocos2d::Size run_jumpSize;//跑和跳的大小一樣
	cocos2d::Size crouchSize;//蹲下來的大小

	runnerState m_state;
};/**/

#endif

這裏的剛體Size只有兩個,因爲跑的時候和跳起來的時候的精靈大小是差不多的,那麼處於這兩個狀態的的剛體綁定大小可以一樣,然後下蹲的時候的Size就不同

Runner.cpp

#include "Runner.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);//初始化動作集合

	m_state = running;

	initBody();

	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");
	
}

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 runerBody = PhysicsBody::createBox(bodySize,PHYSICSBODY_MATERIAL_DEFAULT);

	//綁定剛體
	this->setPhysicsBody(runerBody);
}

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

init 函數裏面我們做了一些事:

1.先把圖片加載到緩存池,初始化主精靈,和兩個Size,以及當前狀態

這裏的圖片實際上是一張整合了很多小圖片的集合,不同的圖片有不同紋理,那麼集合到同一圖片中紋理就相同的,那麼同一紋理的圖片,我們就可以減少渲染批次,3.0中的渲染好像是自動處理的,看了一篇文章,說是不推薦使用那個SpriteBachNode啦,然後說得也比較抽象,我這裏也不特別解釋,有好的教程麻煩推薦,謝謝

2.我們初始化了動作集合,這一步當中,我們只初始化跑動的幀動畫

initActionSet函數當中,我都有詳細註釋

doAction函數中,我們可以根據傳入的參數動作名稱來執行動作,也就是在initActionSet 當中給動作取名字的那裏

initBody函數當中,根據不同的狀態,我們就給主角綁定不同大小的剛體,關於重複setPhysicsBody,你可能會有疑問,本來有一個剛體,換了一個狀態,又設定一個剛體可以嗎?答案是可以的,我們可以查看源碼

void Node::setPhysicsBody(PhysicsBody* body)
{
    /*省略*/
    
    if (_physicsBody != nullptr)
    {
        PhysicsWorld* world = _physicsBody->getWorld();
        _physicsBody->removeFromWorld();
        _physicsBody->_node = nullptr;
        _physicsBody->release();
        
        if (world != nullptr && body != nullptr)
        {
            world->addBody(body);
        }
    }
    
    _physicsBody = body;
    if (body != nullptr)
    {
        Node* parent = getParent();
        Point pos = parent != nullptr ? parent->convertToWorldSpace(getPosition()) : getPosition();
        _physicsBody->setPosition(pos);
        _physicsBody->setRotation(getRotation());
    }
}
這裏我們可以看到,它會判斷_physicsBody(也就是Node的剛體)是不是爲空,如有已有剛體,會先刪除,然後重新綁定


好啦,到這裏主角類以及初步設置完啦,我們在PlayScene.h 中加入一個成員變量  Runner* m_runner;

然後在PlayScene.cpp 的init函數中對 m_runner初始化:

m_runner = Runner::create();
m_runner->setPosition(runner_posX,ground_hight+m_runner->getRunJumpSize().height/2);
m_runner->Run();
this->addChild(m_runner);

那麼這裏的runner_posX 就是在 ground_hight  下面定義的一個宏,也就是主角的X座標位置,我這裏定義 80

OK運行測試如圖:


如果你把那些資源都放在Resouce 文件下了,還能聽到背景音樂

這裏我也有一個問題,就是有的人可以插入動態的那種圖片,比較好的演示了運行結果,用QQ好像不能對這個屏幕進行截取動態圖,求方法推薦可憐

下面我們就加入PlayScene的背景,以及地圖無限滾動,讓主角看起來更像是跑動 ,同時也爲主角的Jump跳躍動作以及Crouch下蹲動作的執行做準備


個人愚昧觀點,歡迎指正與討論大笑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章