南锋

南奔万里空,脱死锋镝余

cocos2dx-lua虚拟摇杆方向控制

在游戏开发中,很多时候都需要控制游戏角色的移动,比如王者荣耀中对英雄的控制,我们可以做一个虚拟摇杆来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
--[[

控制层
--]]

local CtrlLayer = class('CtrlLayer', function()
return display.newLayer('CtrlLayer')
end)

--方向按钮的size
local btn_dir_w = 265
local btn_dir_h = 265

--方向按钮位置
local btn_dir_x = display.width - btn_dir_w - 20
local btn_dir_y = 20

--方向按钮的中心点
local btn_dir_cx = btn_dir_x + btn_dir_w/2
local btn_dir_cy = btn_dir_y + btn_dir_h/2

--方向按钮中心圆圈的半径
local btn_dir_center_r = 50

--[[
构造方法
@param linstener 需要接收事件通知的人,需要实现事件列表中的方法
事件列表为:
setDir(dir) : 设置了方向
--]]
function CtrlLayer:ctor(linstener)

self.linstener = linstener

self:pos(0, 0)
self:size(display.width, display.height)


--方向按钮图片
local dirSprite = display.newSprite('dir_btn.jpg')
dirSprite:setAnchorPoint(0, 0)
dirSprite:pos(btn_dir_x, btn_dir_y)
dirSprite:addTo(self)

--添加触屏单点事件
self:setTouchEnabled(true)
--多点触控
--self:setTouchMode(cc.TOUCHES_ALL_AT_ONCE)
--单点触控
self:setTouchMode(cc.TOUCHES_ONE_BY_ONE)
self:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
if event.name == 'began' then
--需要return true才能让事件继续到move/ended等
return true
elseif event.name == 'ended' then
self:onTouchEnded(event)
end
end)

end

--计算某点是否在方向按钮范围
--规定在方向按钮外围构成的矩形为按钮的边界
function CtrlLayer:isInDirBtn(x, y)
if x >= btn_dir_x and x <= (btn_dir_x + btn_dir_w) and y >= btn_dir_y and y <= (btn_dir_y + btn_dir_h) then
return true
else
return false
end
end

--计数某点是否在方向按钮的中心圆圈内
function CtrlLayer:isInDirBtnCenter(x, y)
local tx = math.abs(x-btn_dir_cx)
local ty = math.abs(y-btn_dir_cy)
local tlen = math.sqrt( math.pow(tx, 2) + math.pow(ty, 2) )
return tlen <= btn_dir_center_r
end

--计数某点相对于方向按钮的中心点的方向
--规定方向有up/right/down/left
function CtrlLayer:getDir(x, y)
local dir = ''
local tx = math.abs(x - btn_dir_cx)
local ty = math.abs(y - btn_dir_cy)
if x > btn_dir_cx then
if y > btn_dir_cy then
if tx > ty then
dir = 'right'
else
dir = 'up'
end
else
if tx > ty then
dir = 'right'
else
dir = 'down'
end
end
else
if y > btn_dir_cy then
if tx > ty then
dir = 'left'
else
dir = 'up'
end
else
if tx > ty then
dir = 'left'
else
dir = 'down'
end
end
end
return dir
end


--触屏结束
function CtrlLayer:onTouchEnded(event)
local x, y = event.x, event.y
if self:isInDirBtn(x, y) then
if not self:isInDirBtnCenter(x, y) then
local dir = self:getDir(x, y)
self.linstener:setDir(dir)
end
end
end



return CtrlLayer

效果图如下
在这里插入图片描述

+