說明:這裏是借鑑:曉風殘月 前輩的博客,他是將泰然網的跑酷教程,用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下蹲動作的執行做準備
個人愚昧觀點,歡迎指正與討論