天天看點

cocos2dx3.2開發 RPG《Flighting》(六)角色的狀态和控制效果

一、前言

一般來說,我們在做一個稍微有點智能的實體的時候都會用到狀态機。這裡我沒有用到,但是我也為角色設定了幾種狀态。

如果大家看了上一節,也完成了角色的基本移動的話。對比過我一直說的《BattleHeart》之後,你會發現,現在的控制移動操作也太挫了,既沒有那一條拉出來的導航線,也沒有角色被選中的效果。是以接下來我們要對我們的基本控制操作加入一些效果。

二、正文

1、角色的狀态

來來去去我們的角色無非幾種基本狀态 待機、移動、攻擊、受傷、死亡。是以我們定義一個抽象類。聲明了所有的狀态對應的函數。

#ifndef _ROLEPROTOCOL_H_
#define _ROLEPROTOCOL_H_
class RoleProtocol{
public:
	virtual void stand() = 0;
	virtual void move() = 0;
	virtual void attack() = 0;
	virtual void skill() = 0;
	virtual void injured(int effect,int damage=0) = 0;
	virtual void die() = 0;
};
#endif
           

我們的Role類也做出相應的修改,繼承RoleProtocol并且重寫實作這些接口

在Role裡面定義狀态枚舉類,并且增加一個成員變量表示目前角色的狀态

public:
	enum ROLE_STAT{
		ROLE_STAND,
		ROLE_MOVE,
		ROLE_ATTACK,
		ROLE_SKILL,
		ROLE_INJURED,
		ROLE_DIE,
		ROLE_NULL
	};
           
ROLE_STAT en_stat;	//目前狀态
           

記得上一節的最後我們的兩個方法move()和stand(),他們的由來就是上面所說的,下面看他們兩個的實作

void Role::stand(){
	if(m_arm && en_stat!=ROLE_STAND){
		m_arm->getAnimation()->play("stand");
		CCLOG("id=%d:stand",m_id);
		en_stat = ROLE_STAND;
	}
}
void Role::move(){
	if(m_arm && en_stat!=ROLE_MOVE){
		en_stat = ROLE_MOVE;
		m_arm->getAnimation()->play("walk");
	}
}
           

很簡單,就是先判斷是不是已經在播放站立或行走動畫了,如果是,沒必要在播放(不然會定在那裡不動),如果不是,則播放動畫。

現在暫時會用到的就這兩種狀态,其他狀态以後用到的時候會在清楚說明。

2、控制效果

如果按現在的操作,點選選中我們的角色之後,要拉出去到目标點,再放開手(原本BattleHeart就是這樣操作的)。

那麼在視覺上起碼也要有點效果提醒使用者。

1)選中的高亮效果

實作思路:

在Role裡面設定一個屬性m_isHL,還有一個初始不可見的Sprite,m_select_circle

Layer中檢測到Role被點選之後,設定m_isHL為true,Role的update函數會時刻檢測m_isHL,如果為true的話,m_select_circle變得可見。

需要注意的是,還有很多小細節小邏輯需要處理,例如什麼時候m_isHL設定為false,使用者點選空白區域的時候(就是沒有選中Role)怎麼處理等等,不過也很簡單,相信大家自己也能寫出來。

2)拖出去的導航線

實作思路:

當觸摸事件為move的時候,就是已經onTouchBegan選中角色了,滑鼠在移動但是左鍵沒有松開的時候。

在起點(角色的位置)和終點(滑鼠的位置)之間畫一條線。這裡給出我的代碼供大家參考。

bool Role::onTouchBegan(Touch* touch,Event* event){
	if(!m_controlable){
		return false;
	}
	if(m_arm){
		Point point = touch->getLocationInView();
		point = Director::getInstance()->convertToGL(point);
		m_endPoint = point;

		CCLOG("TOUCH POINT PX = %f,PY = %f",point.x,point.y);
		
		Rect heroRect = getBoundingBox();

		if(heroRect.containsPoint(point)){<span style="white-space:pre">		</span>//是這個if
			m_trace = Sprite::create("color.png");		
			m_trace->setAnchorPoint(Point(0,0.5f));
			this->addChild(m_trace,0);
			CCLOG("CLICK MY HERO");
			setHeightLight(true);
			return true;
		}else{
			CCLOG("NOT CONTAIN");
			return false;
		}
	}
	return false;
}
           

onTouchBegan裡面判斷如果點中角色(上面代碼那個if裡面),會建立一個叫m_trace的Sprite。

m_trace開始的時候隻是很小的一塊矩形("color.png"隻是很小的一塊矩形,并不是一條線)。

void Role::onTouchMoved(Touch* touch,Event* event){
	Point point = touch->getLocationInView();
	point = Director::getInstance()->convertToGL(point);
	m_endPoint = point;
	
}
           

明顯,onTouchMoved裡面就是設定m_endPoint而已(m_endPoint就是導航線的終點)

void Role::onTouchEnded(Touch* touch,Event* event){
	if(m_trace){
		m_trace->removeFromParentAndCleanup(true);
		m_trace = nullptr;
		setHeightLight(false);
	}
}
           

onTouchEnded的觸發表明已經松開滑鼠左鍵。m_trace(導航線)應該消失了

關于導航線重要的還是下面的update函數

update中調用update_trace

void Role::update_trace(){
	if(m_trace){
		if(getBoundingBox().containsPoint(m_endPoint)){
			m_endPoint = this->getPosition();
		}
		Point begin(CCDirector::getInstance()->convertToGL(this->getPosition()));
		Point end(CCDirector::getInstance()->convertToGL(m_endPoint));
		m_trace->setRotation(CC_RADIANS_TO_DEGREES(ccpToAngle(end - begin)));    //根據起點和終點,設定旋轉角度
		m_trace->setScaleX(ccpDistance(begin,end)/m_trace->getContentSize().width);<span style="white-space:pre">	</span>//根據起點和終點的距離,設定小方塊的拉伸
	}
}
           

重要的代碼後面已經添加了注釋,應該不難了解。

最後,附上我們優化完的控制效果。

cocos2dx3.2開發 RPG《Flighting》(六)角色的狀态和控制效果

本節結束。

我的csdn位址:http://blog.csdn.net/hezijian22

郵箱位址:[email protected]

如有問題或指教,歡迎與我交流,謝謝。

繼續閱讀