源战役客户端
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
14 KiB

  1. --[[@------------------------------------------------------------------
  2. : ,
  3. : deadline
  4. ----------------------------------------------------------------------]]
  5. SourceOperateMove = SourceOperateMove or BaseClass(SourceOperate)
  6. local SourceOperateMove = SourceOperateMove
  7. SourceOperateMove.MoveType =
  8. {
  9. MoveToTarget = 1,
  10. MoveToDirection = 2,
  11. InitedPath = 3,
  12. }
  13. SourceOperateMove.operate_move_id = 0
  14. --沿着两个点的方向寻找离起点最近的一个非障碍点 start_pos,end_pos为真实像素点
  15. function SourceOperateMove.FindNearestPos(start_pos,end_pos,jump_state)
  16. local start_logic_pos = co.TableXY(start_pos.x / SceneObj.LogicRealRatio.x, start_pos.y / SceneObj.LogicRealRatio.y)
  17. local end_logic_pos = co.TableXY(end_pos.x / SceneObj.LogicRealRatio.x, end_pos.y / SceneObj.LogicRealRatio.y)
  18. local tem_dir = co.TableXY(end_logic_pos.x - start_logic_pos.x,end_logic_pos.y - start_logic_pos.y)
  19. local dist = co.NormaliseXYTable(tem_dir)
  20. local r = Scene.Instance:DetectLastUnblockPoint(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(tem_dir.x, tem_dir.y), dist, jump_state) --dist是逻辑坐标系的
  21. if r.z == 1 then
  22. return r.x * SceneObj.LogicRealRatio.x, r.y * SceneObj.LogicRealRatio.y
  23. end
  24. return end_pos.x, end_pos.y
  25. end
  26. --沿着两个点的方向寻找离起点最远的一个非障碍点 start_pos,end_pos为真实像素点
  27. function SourceOperateMove.FindFastestPos(start_pos,end_pos, user_len)
  28. local len = user_len or 20
  29. local tem_dir = nil
  30. local dist = nil
  31. tem_dir = co.TableXY(start_pos.x - end_pos.x,start_pos.y - end_pos.y)
  32. dist = co.NormaliseXYTable(tem_dir)
  33. if not user_len then
  34. len = math.ceil(dist / 60)
  35. end
  36. local x, y = 0, 0
  37. for i = 1,len do
  38. x = end_pos.x + tem_dir.x * i / len * dist
  39. y = end_pos.y + tem_dir.y * i / len * dist
  40. if not SceneManager:getInstance():IsBlockXY(math.floor(x / SceneObj.LogicRealRatio.x), math.floor(y / SceneObj.LogicRealRatio.y)) then
  41. local result = true
  42. if i >= (len - 1) then
  43. result = false
  44. else
  45. --退后一格
  46. --x = x + tem_dir.x * SceneObj.LogicRealRatio.x-- * 0.5
  47. --y = y + tem_dir.y * SceneObj.LogicRealRatio.y-- * 0.5
  48. end
  49. return x, y, result
  50. end
  51. end
  52. return start_pos.x, start_pos.y, false
  53. end
  54. function SourceOperateMove.FindNoBlockPos(now_pos)
  55. now_pos = co.TableXY(math.floor(now_pos.x), math.floor(now_pos.y))
  56. local width = math.floor(Scene.Instance:GetSceneSize().x / SceneObj.LogicRealRatio.x)
  57. local height = math.floor(Scene.Instance:GetSceneSize().y / SceneObj.LogicRealRatio.y)
  58. if now_pos.x < 0 then
  59. now_pos.x = 0
  60. elseif now_pos.x > width then
  61. now_pos.x = width
  62. end
  63. if now_pos.y < 0 then
  64. now_pos.y = 0
  65. elseif now_pos.y > height then
  66. now_pos.y = height
  67. end
  68. local max_offset = math.max(math.ceil(width/2), math.ceil(height/2))
  69. local new_pos = nil
  70. local offset = 0
  71. while offset < max_offset do
  72. offset = offset + 1
  73. for x = now_pos.x - offset, now_pos.x + offset do
  74. --上
  75. local y = now_pos.y - offset
  76. if y >= 0 and not SceneManager:getInstance():IsBlockXY(x, y) then
  77. new_pos = co.TableXY(x, y)
  78. break
  79. end
  80. --下
  81. y = now_pos.y + offset
  82. if y < height and not SceneManager:getInstance():IsBlockXY(x, y) then
  83. new_pos = co.TableXY(x, y)
  84. break
  85. end
  86. end
  87. if new_pos ~= nil then
  88. break
  89. end
  90. for y = now_pos.y - offset + 1, now_pos.y + offset - 1 do
  91. --左
  92. local x = now_pos.x - offset
  93. if x >= 0 and not SceneManager:getInstance():IsBlockXY(x, y) then
  94. new_pos = co.TableXY(x, y)
  95. break
  96. end
  97. --右
  98. x = now_pos.x + offset
  99. if x < width and not SceneManager:getInstance():IsBlockXY(x, y) then
  100. new_pos = co.TableXY(x, y)
  101. break
  102. end
  103. end
  104. if new_pos ~= nil then
  105. break
  106. end
  107. end
  108. if new_pos then
  109. new_pos.x = new_pos.x + 0.5
  110. new_pos.y = new_pos.y + 0.5
  111. end
  112. return new_pos
  113. end
  114. --[[@
  115. :
  116. :
  117. start_logic_pos Game.Vector2
  118. end_logic_pos Game.Vector2
  119. :
  120. :
  121. : zsm
  122. ]]
  123. function SourceOperateMove.FindNoBlockPath(start_logic_pos, end_logic_pos)
  124. local logic_dir = co.SubtractXYTable(end_logic_pos, start_logic_pos)
  125. local max_dist = co.NormaliseXYTable(logic_dir)
  126. local r = Scene.Instance:DetectFirstUnblockPoint(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(logic_dir.x, logic_dir.y), max_dist)
  127. return r
  128. end
  129. --[[@
  130. : A*
  131. :
  132. start_pos Game.Vector2
  133. end_pos Game.Vector2
  134. range () numeric
  135. :
  136. bool
  137. table
  138. :
  139. : deadline
  140. ]]
  141. function SourceOperateMove.FindPathList(obj_type,start_pos, end_pos, range)
  142. local path_info = Scene.Instance:FindWay(Vector2(start_pos.x, start_pos.y), Vector2(end_pos.x, end_pos.y), range)
  143. if not path_info then
  144. return false, {}
  145. end
  146. local is_path_valid = false
  147. local path_list = {}
  148. local total_point = #path_info
  149. if path_info and total_point >= 2 then
  150. is_path_valid = true
  151. --将返回的路径转换为起点终点对的形式,方便使用
  152. local tmp_start_pos = path_info[1]
  153. local now_index = 2
  154. while now_index <= total_point do
  155. local tmp_end_pos = path_info[now_index]
  156. local now_pair = {}
  157. now_pair.start_point = co.TableXY(tmp_start_pos.x, tmp_start_pos.y)
  158. now_pair.end_point = co.TableXY(tmp_end_pos.x, tmp_end_pos.y)
  159. path_list[now_index-1] = now_pair
  160. now_index = now_index + 1
  161. tmp_start_pos = tmp_end_pos
  162. end
  163. end
  164. if not obj_type or obj_type == SceneBaseType.MainRole then
  165. if is_path_valid then
  166. EventSystem.Fire(GlobalEventSystem,EventName.BROADCAST_ROLE_WAY_POINT,path_info)
  167. end
  168. end
  169. return is_path_valid, path_list
  170. end
  171. --[[
  172. * @param startPoint
  173. * @param time
  174. * @return
  175. *
  176. ]]
  177. function SourceOperateMove.findRandomPath(startPoint, time)
  178. local range = time * Scene.Instance.GetMainRole().move_speed
  179. range = range * range
  180. local dis = 0;
  181. --方向加减坐标,2个为一组,分别对应方向1,2,3,4,5,6,7,8,9
  182. local point = {0, 0, -1, 1, 0, 1, 1, 1, -1, 0, 0, 0, 1, 0, -1, -1, 0, -1, 1, -1}
  183. local dirList = {2,1,4,7,8,9,6,3}
  184. local endPoint;
  185. local tx;
  186. local ty;
  187. local flag;
  188. local list = {};
  189. while dis < range do
  190. local dir = math.ceil(math.random() * #dirList)
  191. tx = startPoint.x + point[dirList[dir]*2 + 1]
  192. ty = startPoint.y + point[dirList[dir]*2 + 2]
  193. endPoint = co.TableXY(tx, ty);
  194. if SceneManager:getInstance():IsBlockXY(endPoint.x, endPoint.y) then
  195. table.remove(dirList, dir)
  196. if dirList.length == 0 then
  197. break;
  198. end
  199. else
  200. dirList = {2,1,4,7,8,9,6,3}
  201. local start_real_pos = co.MulXYTable(startPoint, SceneObj.LogicRealRatio)
  202. local end_real_pos = co.MulXYTable(endPoint, SceneObj.LogicRealRatio)
  203. dis = dis + GameMath.GetDistance(start_real_pos.x, start_real_pos.y, end_real_pos.x, end_real_pos.y)
  204. local path_point = {}
  205. path_point.start_point = startPoint
  206. path_point.end_point = endPoint
  207. startPoint = co.TableXY(endPoint.x, endPoint.y)
  208. table.insert(list, path_point)
  209. end
  210. end
  211. if #list == 0 then
  212. return nil;
  213. end
  214. return list;
  215. end
  216. function SourceOperateMove:__init(end_pos, action_func, arg_list)
  217. self.type = OperateManager.SourceOperateType.Move
  218. self.init_time = 0
  219. -- print("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT", type(end_pos))
  220. if type(end_pos)=="table" then
  221. self.end_pos = co.TableXY(end_pos.x, end_pos.y)
  222. end
  223. self.action_func = action_func
  224. self.arg_list = arg_list
  225. self.is_path_valid = false
  226. self.path_list = nil
  227. self.now_use_pair = nil
  228. self.total_pair = nil
  229. self.move_type = SourceOperateMove.MoveType.MoveToTarget
  230. SourceOperateMove.operate_move_id = SourceOperateMove.operate_move_id + 1
  231. self.id = SourceOperateMove.operate_move_id
  232. end
  233. function SourceOperateMove:__delete( )
  234. -- GlobalEventSystem:Fire(SceneEventType.MAIN_ROLE_PATH_FINISHED, self.id)
  235. end
  236. function SourceOperateMove:SetPathList(path)
  237. self.path_list = path
  238. self.total_pair = #(self.path_list)
  239. self.now_use_pair = 1
  240. self.is_path_valid = true
  241. self.move_type = SourceOperateMove.MoveType.InitedPath
  242. self.is_init_finish = true
  243. end
  244. --[[@
  245. :
  246. :
  247. start_pos Game.Vector2
  248. end_pos Game.Vector2
  249. range () numeric
  250. :
  251. bool
  252. :
  253. : deadline
  254. ]]
  255. function SourceOperateMove:RecalcPathInfo( start_pos, end_pos, range )
  256. -- 增加直线的判断
  257. local start_logic_pos = co.TableXY(start_pos.x, start_pos.y)
  258. local end_logic_pos = co.TableXY(end_pos.x, end_pos.y)
  259. local dir = co.TableXY(end_logic_pos.x - start_logic_pos.x, end_logic_pos.y - start_logic_pos.y)
  260. local dist = co.NormaliseXYTable(dir)
  261. --对目标点进行直线探测
  262. local rlt = Scene.Instance:IsStraightLine(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(end_logic_pos.x, end_logic_pos.y))
  263. if rlt then
  264. --直线探测成功
  265. local real_end = end_logic_pos
  266. if dist <= range then
  267. real_end = start_logic_pos
  268. else
  269. real_end = co.TableXY(end_logic_pos.x - dir.x * range, end_logic_pos.y - dir.y * range)
  270. end
  271. local path_point = {}
  272. path_point.start_point = co.TableXY(start_logic_pos.x, start_logic_pos.y)
  273. path_point.end_point = co.TableXY(real_end.x, real_end.y)
  274. table.insert(self.path_list, path_point)
  275. self.total_pair = #self.path_list
  276. self.now_use_pair = 1
  277. self.is_path_valid = true
  278. else
  279. --A*寻路
  280. local is_path_valid, path_list = SourceOperateMove.FindPathList(nil,start_logic_pos, end_logic_pos, range)
  281. if is_path_valid then
  282. --分拆路径
  283. self.path_list = path_list
  284. --设置初始化状态, 当前待执行的路径为第一个小路径
  285. self.total_pair = #self.path_list
  286. self.now_use_pair = 1
  287. self.is_path_valid = true
  288. elseif SceneManager:getInstance():IsBlockXY(end_logic_pos.x, end_logic_pos.y) then
  289. local r = Scene.Instance:DetectLastUnblockPoint(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(dir.x, dir.y), dist) --dist是逻辑坐标系的
  290. if r.z == 1 then
  291. local pair = {}
  292. pair.start_point = co.TableXY(start_logic_pos.x, start_logic_pos.y)
  293. local gv2 = r
  294. pair.end_point = co.TableXY(gv2.x, gv2.y)
  295. self.end_pos = co.TableXY(gv2.x, gv2.y)
  296. table.insert(self.path_list, pair)
  297. self.total_pair = 1
  298. self.now_use_pair = 1
  299. self.is_path_valid = true
  300. end
  301. end
  302. end
  303. if self.is_path_valid then
  304. EventSystem.FireNextFrame(GlobalEventSystem,SceneEventType.CREATE_FINDWAY_POINT, self.path_list)
  305. end
  306. return self.is_path_valid
  307. end
  308. --[[@
  309. : ,
  310. :
  311. :
  312. true表示初始化成功, false表示初始化失败
  313. :
  314. : deadline
  315. ]]
  316. function SourceOperateMove:Init()
  317. self.path_list = {}
  318. local main_role = Scene.Instance:GetMainRole()
  319. if not main_role then
  320. return false
  321. end
  322. local start_logic_pos = co.TableXY(main_role:GetLogicPos())
  323. --如果正在飞行,就直接直线走过去
  324. if main_role:IsFlying() then
  325. local path_point = {}
  326. path_point.start_point = start_logic_pos
  327. path_point.end_point = self.end_pos
  328. table.insert(self.path_list, path_point)
  329. self.total_pair = 1
  330. self.now_use_pair = 1
  331. self.is_path_valid = true
  332. return true
  333. end
  334. --如果当前点在障碍内,就先走出来,再从走出来的点进行寻路
  335. if SceneManager:getInstance():IsBlockXY(start_logic_pos.x, start_logic_pos.y) then
  336. local unblock_pos = SourceOperateMove.FindNoBlockPos(start_logic_pos)
  337. if unblock_pos then
  338. local path_point = {}
  339. path_point.start_point = start_logic_pos
  340. path_point.end_point = unblock_pos
  341. table.insert(self.path_list, path_point)
  342. --把走出来的点作为起始点
  343. start_logic_pos = unblock_pos
  344. end
  345. end
  346. if self.move_type == SourceOperateMove.MoveType.MoveToTarget then
  347. self.init_time = Status.NowTime
  348. if not self.end_pos then
  349. return false
  350. end
  351. local end_logic_pos = self.end_pos
  352. --根据设定的起点终点重置路径信息
  353. local is_get_path_suc = self:RecalcPathInfo(start_logic_pos, end_logic_pos, 0)
  354. -- print("= = = SourceOperateMove:Init:")
  355. -- for i=1,self.total_pair do
  356. -- local pt = self.path_list[i]
  357. -- print(string.format("= = = = [%.2f,%.2f], [%.2f,%.2f]", pt.start_point.x, pt.start_point.y, pt.end_point.x, pt.end_point.y))
  358. -- end
  359. return is_get_path_suc
  360. end
  361. return false
  362. end
  363. function SourceOperateMove:BeforeDelete()
  364. if not self.is_finish and self.now_use_pair and self.total_pair and self.now_use_pair <= self.total_pair then
  365. OperateManager.Instance:CheckJumpAction(self.now_use_pair,self.path_list,self.action_func,self.arg_list)
  366. end
  367. end
  368. --[[@
  369. : SourceOperate中获取一个NowOperate控制角色行为
  370. :
  371. :
  372. NowOperate
  373. :
  374. : deadline
  375. ]]
  376. function SourceOperateMove:GetOperImpl()
  377. local now_oper = nil
  378. local now_time = Status.NowTime
  379. if not self.now_use_pair or not self.total_pair then return end
  380. if self.now_use_pair > self.total_pair then
  381. --行走完成直接执行相关动作
  382. self.is_finish = true
  383. if self.action_func then
  384. self.action_func(unpack(self.arg_list))
  385. --print("self.action_func(unpack(self.arg_list))",self.action_func," ",unpack(self.arg_list))
  386. end
  387. now_oper = self:GenerateNop(0.2)
  388. else
  389. --取出下一个小路径执行
  390. local move_pair = self.path_list[self.now_use_pair]
  391. if move_pair ~= nil then
  392. now_oper = NowOperateMove.New(now_time, move_pair.start_point, move_pair.end_point, self.now_use_pair==self.total_pair)
  393. self.now_use_pair = self.now_use_pair + 1
  394. end
  395. end
  396. return now_oper
  397. end