最近开始学习cocos2d-x引擎,用来做一些2d小游戏。在基本做完一个飞机大战游戏的情况下,感觉手机玩沙盒2d游戏需要一个控制角色移动的控制手柄,不然光靠点屏幕是不精确而又费劲的体验。于是开始写了一个角色控制器RoleController,效果如下
文章图片
项目地址
https://github.com/Ccapton/Cocos2d-x-RoleController
演示程序apk
https://raw.githubusercontent.com/Ccapton/Cocos2d-x-RoleController/master/Fightman-debug.apk
RoleController.h内容
#ifndef __ROLE_CONTROLLER_H__
#define __ROLE_CONTROLLER_H__#include "cocos2d.h"
USING_NS_CC;
#include "string"class RoleControllerListenr {
public:
// velocity 为控制球相对于控制中心的偏移量,
// 你可以在具体的实现方法内利用定时更新函数对此结果进行利用,进而实现对精灵的位置控制
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
本来想把它做完再发文章的,但是觉得没什么人看我的文章,也就算了,毕竟这个控制器挺简单的。
原理
主要是靠触摸事件来判断手指位置来判断是否其在控制器内,若是则使小圆的位置跟随触摸移动。若一开始触摸从控制器内,然后往外移动最后离开控制器范围,则小球则会在控制内移动然后根据手指落点的位置而在控制器的圆边界上移动。这个控制器最复杂的地方是:
计算这个小球在控制器边界移动的坐标,最后解决了这个算法,一个简单的控制器变完成了9成。.
通过高中数学的解析几何知识
文章图片
我得到了下面这个算法:
// 控制器小球在控制器边界圆上移动时,其坐标的算法
// targetX,targetY为所求圆边界上的坐标 (这是仅有的两个未知量)
// centerP.x为控制器中心横坐标,centerP.y为控制器中心纵坐标
// touchP.x为触控点横坐标,touchP.y为触控点纵坐标
// distance 为触控点距离控制器中心的距离,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;
}
【游戏开发|基于cocos2d-x引擎的角色控制器】最后便是回调结果了,将小球相对于控制器中心的偏移量Vec2传递出去,这里用到了RoleControllerListenr这个类作为接口,你需要在合适的地方继承此接口类并实现其抽象函数
class RoleControllerListenr {
public:
// velocity 为控制球相对于控制中心的偏移量,
// 你可以在具体的实现方法内利用定时更新函数对此结果进行利用,进而实现对精灵的位置控制
virtual void onControllerTouchBegan(Vec2 velocity) = 0;
// 开始触摸控制器
virtual void onControllerTouchMoving(Vec2 velocity) = 0;
// 控制器小球移动中
virtual void onControllerTouchEnded(Vec2 velocity) = 0;
// 结束触摸控制器
};
后记
很多人估计看到这一头雾水,这里很多的代码是基于cocos2dx这个游戏开发引擎的,看不懂很正常,对游戏开发感兴趣的朋友可以去官网仔细阅读一下文档。好了,关于这个控制器就介绍到这了,希望你们会喜欢。
别忘了关注我,给我星星
https://github.com/Ccapton