最近開(kāi)始學(xué)習(xí)cocos2d-x引擎,用來(lái)做一些2d小游戲。在基本做完一個(gè)飛機(jī)大戰(zhàn)游戲的情況下,感覺(jué)手機(jī)玩沙盒2d游戲需要一個(gè)控制角色移動(dòng)的控制手柄,不然光靠點(diǎn)屏幕是不精確而又費(fèi)勁的體驗(yàn)。于是開(kāi)始寫了一個(gè)角色控制器RoleController,效果如下
項(xiàng)目地址
https://github.com/Ccapton/Cocos2d-x-RoleController
演示程序apk
https://raw.githubusercontent.com/Ccapton/Cocos2d-x-RoleController/master/Fightman-debug.apk
RoleController.h內(nèi)容
#ifndef __ROLE_CONTROLLER_H__
#define __ROLE_CONTROLLER_H__
#include "cocos2d.h"
USING_NS_CC;
#include "string"
class RoleControllerListenr {
public:
// velocity 為控制球相對(duì)于控制中心的偏移量,
// 你可以在具體的實(shí)現(xiàn)方法內(nèi)利用定時(shí)更新函數(shù)對(duì)此結(jié)果進(jìn)行利用,進(jìn)而實(shí)現(xiàn)對(duì)精靈的位置控制
virtual void onControllerTouchBegan(Vec2 velocity) = 0;
virtual void onControllerTouchMoving(Vec2 velocity) = 0;
virtual void onControllerTouchEnded(Vec2 velocity) = 0;
};
class RoleController : public Layer {
private:
RoleController() {}
public:
bool touchIngInside = false;
float radius = 0;
float ball_d_bg = 0;
Vec2 offset;
Color4F bg_color = Color4F(-1.0f,-1.0f,-1.0f,-1.0f);
Color4F ball_color = Color4F(-1.0f, -1.0f, -1.0f, -1.0f);;
Node * tempLayer;
Node * tempLayer2;
std::string bg_resouce_path;
std::string ball_resouce_path;
static RoleController* createController(float radius,const Vec2 offset);
RoleControllerListenr * listener;
virtual bool init();
void createBg();
void createBall();
void setPositioin(Vec2 position);
void setOffset(Vec2 offset);
void setBgResoucePath(std::string path);
void setBallResoucePath(std::string path);
bool touchBeganCallback(Touch* touch, Event* event);
void touchMovedCallback(Touch* touch, Event* event);
void touchEndedCallback(Touch* touch, Event* event);
void setRoleControllerListenr(RoleControllerListenr * listener);
CREATE_FUNC(RoleController);
};
#endif
本來(lái)想把它做完再發(fā)文章的,但是覺(jué)得沒(méi)什么人看我的文章,也就算了,畢竟這個(gè)控制器挺簡(jiǎn)單的。
原理
主要是靠觸摸事件來(lái)判斷手指位置來(lái)判斷是否其在控制器內(nèi),若是則使小圓的位置跟隨觸摸移動(dòng)。若一開(kāi)始觸摸從控制器內(nèi),然后往外移動(dòng)最后離開(kāi)控制器范圍,則小球則會(huì)在控制內(nèi)移動(dòng)然后根據(jù)手指落點(diǎn)的位置而在控制器的圓邊界上移動(dòng)。這個(gè)控制器最復(fù)雜的地方是:
計(jì)算這個(gè)小球在控制器邊界移動(dòng)的坐標(biāo),最后解決了這個(gè)算法,一個(gè)簡(jiǎn)單的控制器變完成了9成。.
通過(guò)高中數(shù)學(xué)的解析幾何知識(shí)
我得到了下面這個(gè)算法:
// 控制器小球在控制器邊界圓上移動(dòng)時(shí),其坐標(biāo)的算法
// targetX,targetY為所求圓邊界上的坐標(biāo) (這是僅有的兩個(gè)未知量)
// centerP.x為控制器中心橫坐標(biāo),centerP.y為控制器中心縱坐標(biāo)
// touchP.x為觸控點(diǎn)橫坐標(biāo),touchP.y為觸控點(diǎn)縱坐標(biāo)
// distance 為觸控點(diǎn)距離控制器中心的距離,radius則是圓形控制器的半徑
float targetX = 0, targetY = 0;
if (touchP.x > centerP.x && touchP.y > centerP.y) {
targetX = centerP.x + radius * (touchP.x - centerP.x) / distance;
targetY = centerP.y + radius * (touchP.y - centerP.y) / distance;
}else if (touchP.x < centerP.x && touchP.y > centerP.y) {
targetX = centerP.x - radius * (centerP.x - touchP.x) / distance;
targetY = centerP.y + radius * (touchP.y - centerP.y) / distance;
}else if (touchP.x < centerP.x && touchP.y < centerP.y) {
targetX = centerP.x - radius * (centerP.x - touchP.x) / distance;
targetY = centerP.y - radius * (centerP.y - touchP.y) / distance;
}else if (touchP.x > centerP.x && touchP.y < centerP.y) {
targetX = centerP.x + radius * (touchP.x - centerP.x) / distance;
targetY = centerP.y - radius * (centerP.y - touchP.y ) / distance;
}
最后便是回調(diào)結(jié)果了,將小球相對(duì)于控制器中心的偏移量Vec2傳遞出去,這里用到了RoleControllerListenr這個(gè)類作為接口,你需要在合適的地方繼承此接口類并實(shí)現(xiàn)其抽象函數(shù)
class RoleControllerListenr {
public:
// velocity 為控制球相對(duì)于控制中心的偏移量,
// 你可以在具體的實(shí)現(xiàn)方法內(nèi)利用定時(shí)更新函數(shù)對(duì)此結(jié)果進(jìn)行利用,進(jìn)而實(shí)現(xiàn)對(duì)精靈的位置控制
virtual void onControllerTouchBegan(Vec2 velocity) = 0; // 開(kāi)始觸摸控制器
virtual void onControllerTouchMoving(Vec2 velocity) = 0; // 控制器小球移動(dòng)中
virtual void onControllerTouchEnded(Vec2 velocity) = 0; // 結(jié)束觸摸控制器
};
后記
很多人估計(jì)看到這一頭霧水,這里很多的代碼是基于cocos2dx這個(gè)游戲開(kāi)發(fā)引擎的,看不懂很正常,對(duì)游戲開(kāi)發(fā)感興趣的朋友可以去官網(wǎng)仔細(xì)閱讀一下文檔。好了,關(guān)于這個(gè)控制器就介紹到這了,希望你們會(huì)喜歡。
別忘了關(guān)注我,給我星星
https://github.com/Ccapton