--[[@------------------------------------------------------------------
|
|
说明: 移动源操作包, 用于产生控制角色移动到场景指定位置的操作包
|
|
作者: deadline
|
|
----------------------------------------------------------------------]]
|
|
SourceOperateMove = SourceOperateMove or BaseClass(SourceOperate)
|
|
local SourceOperateMove = SourceOperateMove
|
|
SourceOperateMove.MoveType =
|
|
{
|
|
MoveToTarget = 1,
|
|
MoveToDirection = 2,
|
|
InitedPath = 3,
|
|
}
|
|
SourceOperateMove.operate_move_id = 0
|
|
|
|
--沿着两个点的方向寻找离起点最近的一个非障碍点 start_pos,end_pos为真实像素点
|
|
function SourceOperateMove.FindNearestPos(start_pos,end_pos,jump_state)
|
|
local start_logic_pos = co.TableXY(start_pos.x / SceneObj.LogicRealRatio.x, start_pos.y / SceneObj.LogicRealRatio.y)
|
|
local end_logic_pos = co.TableXY(end_pos.x / SceneObj.LogicRealRatio.x, end_pos.y / SceneObj.LogicRealRatio.y)
|
|
local tem_dir = co.TableXY(end_logic_pos.x - start_logic_pos.x,end_logic_pos.y - start_logic_pos.y)
|
|
local dist = co.NormaliseXYTable(tem_dir)
|
|
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是逻辑坐标系的
|
|
if r.z == 1 then
|
|
return r.x * SceneObj.LogicRealRatio.x, r.y * SceneObj.LogicRealRatio.y
|
|
end
|
|
return end_pos.x, end_pos.y
|
|
end
|
|
|
|
|
|
--沿着两个点的方向寻找离起点最远的一个非障碍点 start_pos,end_pos为真实像素点
|
|
function SourceOperateMove.FindFastestPos(start_pos,end_pos, user_len)
|
|
local len = user_len or 20
|
|
local tem_dir = nil
|
|
local dist = nil
|
|
tem_dir = co.TableXY(start_pos.x - end_pos.x,start_pos.y - end_pos.y)
|
|
dist = co.NormaliseXYTable(tem_dir)
|
|
if not user_len then
|
|
len = math.ceil(dist / 60)
|
|
end
|
|
local x, y = 0, 0
|
|
for i = 1,len do
|
|
x = end_pos.x + tem_dir.x * i / len * dist
|
|
y = end_pos.y + tem_dir.y * i / len * dist
|
|
if not SceneManager:getInstance():IsBlockXY(math.floor(x / SceneObj.LogicRealRatio.x), math.floor(y / SceneObj.LogicRealRatio.y)) then
|
|
local result = true
|
|
if i >= (len - 1) then
|
|
result = false
|
|
else
|
|
--退后一格
|
|
--x = x + tem_dir.x * SceneObj.LogicRealRatio.x-- * 0.5
|
|
--y = y + tem_dir.y * SceneObj.LogicRealRatio.y-- * 0.5
|
|
end
|
|
return x, y, result
|
|
end
|
|
end
|
|
return start_pos.x, start_pos.y, false
|
|
end
|
|
|
|
function SourceOperateMove.FindNoBlockPos(now_pos)
|
|
now_pos = co.TableXY(math.floor(now_pos.x), math.floor(now_pos.y))
|
|
local width = math.floor(Scene.Instance:GetSceneSize().x / SceneObj.LogicRealRatio.x)
|
|
local height = math.floor(Scene.Instance:GetSceneSize().y / SceneObj.LogicRealRatio.y)
|
|
if now_pos.x < 0 then
|
|
now_pos.x = 0
|
|
elseif now_pos.x > width then
|
|
now_pos.x = width
|
|
end
|
|
if now_pos.y < 0 then
|
|
now_pos.y = 0
|
|
elseif now_pos.y > height then
|
|
now_pos.y = height
|
|
end
|
|
local max_offset = math.max(math.ceil(width/2), math.ceil(height/2))
|
|
local new_pos = nil
|
|
local offset = 0
|
|
while offset < max_offset do
|
|
offset = offset + 1
|
|
for x = now_pos.x - offset, now_pos.x + offset do
|
|
--上
|
|
local y = now_pos.y - offset
|
|
if y >= 0 and not SceneManager:getInstance():IsBlockXY(x, y) then
|
|
new_pos = co.TableXY(x, y)
|
|
break
|
|
end
|
|
--下
|
|
y = now_pos.y + offset
|
|
if y < height and not SceneManager:getInstance():IsBlockXY(x, y) then
|
|
new_pos = co.TableXY(x, y)
|
|
break
|
|
end
|
|
end
|
|
|
|
if new_pos ~= nil then
|
|
break
|
|
end
|
|
|
|
for y = now_pos.y - offset + 1, now_pos.y + offset - 1 do
|
|
--左
|
|
local x = now_pos.x - offset
|
|
if x >= 0 and not SceneManager:getInstance():IsBlockXY(x, y) then
|
|
new_pos = co.TableXY(x, y)
|
|
break
|
|
end
|
|
--右
|
|
x = now_pos.x + offset
|
|
if x < width and not SceneManager:getInstance():IsBlockXY(x, y) then
|
|
new_pos = co.TableXY(x, y)
|
|
break
|
|
end
|
|
end
|
|
|
|
if new_pos ~= nil then
|
|
break
|
|
end
|
|
end
|
|
if new_pos then
|
|
new_pos.x = new_pos.x + 0.5
|
|
new_pos.y = new_pos.y + 0.5
|
|
end
|
|
return new_pos
|
|
end
|
|
|
|
--[[@
|
|
功能: 从起始点到结束点之间找到没有障碍的点
|
|
参数:
|
|
start_logic_pos 长路径起始位置 Game.Vector2
|
|
end_logic_pos 终点位置 Game.Vector2
|
|
返回值:
|
|
无
|
|
其它: 无
|
|
作者: zsm
|
|
]]
|
|
function SourceOperateMove.FindNoBlockPath(start_logic_pos, end_logic_pos)
|
|
local logic_dir = co.SubtractXYTable(end_logic_pos, start_logic_pos)
|
|
local max_dist = co.NormaliseXYTable(logic_dir)
|
|
|
|
local r = Scene.Instance:DetectFirstUnblockPoint(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(logic_dir.x, logic_dir.y), max_dist)
|
|
return r
|
|
end
|
|
|
|
--[[@
|
|
功能: A*寻路
|
|
参数:
|
|
start_pos 起点逻辑坐标 Game.Vector2
|
|
end_pos 终点逻辑坐标 Game.Vector2
|
|
range 离终点的修正距离(到达离终点的该范围内算作寻路完成) numeric
|
|
返回值:
|
|
寻路是否成功 bool
|
|
返回的路径 table
|
|
其它: 无
|
|
作者: deadline
|
|
]]
|
|
function SourceOperateMove.FindPathList(obj_type,start_pos, end_pos, range)
|
|
local path_info = Scene.Instance:FindWay(Vector2(start_pos.x, start_pos.y), Vector2(end_pos.x, end_pos.y), range)
|
|
if not path_info then
|
|
return false, {}
|
|
end
|
|
local is_path_valid = false
|
|
local path_list = {}
|
|
local total_point = #path_info
|
|
if path_info and total_point >= 2 then
|
|
is_path_valid = true
|
|
|
|
--将返回的路径转换为起点终点对的形式,方便使用
|
|
local tmp_start_pos = path_info[1]
|
|
local now_index = 2
|
|
while now_index <= total_point do
|
|
local tmp_end_pos = path_info[now_index]
|
|
local now_pair = {}
|
|
now_pair.start_point = co.TableXY(tmp_start_pos.x, tmp_start_pos.y)
|
|
now_pair.end_point = co.TableXY(tmp_end_pos.x, tmp_end_pos.y)
|
|
|
|
path_list[now_index-1] = now_pair
|
|
|
|
now_index = now_index + 1
|
|
tmp_start_pos = tmp_end_pos
|
|
|
|
end
|
|
end
|
|
if not obj_type or obj_type == SceneBaseType.MainRole then
|
|
if is_path_valid then
|
|
EventSystem.Fire(GlobalEventSystem,EventName.BROADCAST_ROLE_WAY_POINT,path_info)
|
|
end
|
|
end
|
|
|
|
return is_path_valid, path_list
|
|
end
|
|
|
|
--[[
|
|
|
|
* @param startPoint 起始点
|
|
* @param time 秒
|
|
* @return
|
|
*
|
|
]]
|
|
function SourceOperateMove.findRandomPath(startPoint, time)
|
|
local range = time * Scene.Instance.GetMainRole().move_speed
|
|
range = range * range
|
|
local dis = 0;
|
|
--方向加减坐标,2个为一组,分别对应方向1,2,3,4,5,6,7,8,9
|
|
local point = {0, 0, -1, 1, 0, 1, 1, 1, -1, 0, 0, 0, 1, 0, -1, -1, 0, -1, 1, -1}
|
|
local dirList = {2,1,4,7,8,9,6,3}
|
|
local endPoint;
|
|
local tx;
|
|
local ty;
|
|
local flag;
|
|
local list = {};
|
|
while dis < range do
|
|
local dir = math.ceil(math.random() * #dirList)
|
|
tx = startPoint.x + point[dirList[dir]*2 + 1]
|
|
ty = startPoint.y + point[dirList[dir]*2 + 2]
|
|
endPoint = co.TableXY(tx, ty);
|
|
if SceneManager:getInstance():IsBlockXY(endPoint.x, endPoint.y) then
|
|
table.remove(dirList, dir)
|
|
if dirList.length == 0 then
|
|
break;
|
|
end
|
|
else
|
|
dirList = {2,1,4,7,8,9,6,3}
|
|
local start_real_pos = co.MulXYTable(startPoint, SceneObj.LogicRealRatio)
|
|
local end_real_pos = co.MulXYTable(endPoint, SceneObj.LogicRealRatio)
|
|
dis = dis + GameMath.GetDistance(start_real_pos.x, start_real_pos.y, end_real_pos.x, end_real_pos.y)
|
|
local path_point = {}
|
|
path_point.start_point = startPoint
|
|
path_point.end_point = endPoint
|
|
startPoint = co.TableXY(endPoint.x, endPoint.y)
|
|
table.insert(list, path_point)
|
|
end
|
|
end
|
|
if #list == 0 then
|
|
return nil;
|
|
end
|
|
return list;
|
|
end
|
|
|
|
|
|
|
|
function SourceOperateMove:__init(end_pos, action_func, arg_list)
|
|
self.type = OperateManager.SourceOperateType.Move
|
|
|
|
self.init_time = 0
|
|
-- print("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT", type(end_pos))
|
|
if type(end_pos)=="table" then
|
|
self.end_pos = co.TableXY(end_pos.x, end_pos.y)
|
|
end
|
|
|
|
self.action_func = action_func
|
|
self.arg_list = arg_list
|
|
|
|
self.is_path_valid = false
|
|
self.path_list = nil
|
|
|
|
self.now_use_pair = nil
|
|
self.total_pair = nil
|
|
|
|
self.move_type = SourceOperateMove.MoveType.MoveToTarget
|
|
|
|
SourceOperateMove.operate_move_id = SourceOperateMove.operate_move_id + 1
|
|
self.id = SourceOperateMove.operate_move_id
|
|
|
|
end
|
|
|
|
function SourceOperateMove:__delete( )
|
|
-- GlobalEventSystem:Fire(SceneEventType.MAIN_ROLE_PATH_FINISHED, self.id)
|
|
end
|
|
|
|
function SourceOperateMove:SetPathList(path)
|
|
self.path_list = path
|
|
self.total_pair = #(self.path_list)
|
|
self.now_use_pair = 1
|
|
self.is_path_valid = true
|
|
self.move_type = SourceOperateMove.MoveType.InitedPath
|
|
self.is_init_finish = true
|
|
end
|
|
|
|
|
|
|
|
--[[@
|
|
功能: 重新根据设定的起始值和终点值计算路径信息
|
|
参数:
|
|
start_pos 起点逻辑坐标 Game.Vector2
|
|
end_pos 终点逻辑坐标 Game.Vector2
|
|
range 离终点的修正距离(到达离终点的该范围内算作寻路完成) numeric
|
|
返回值:
|
|
是否成功生成路径信息 bool
|
|
其它: 无
|
|
作者: deadline
|
|
]]
|
|
function SourceOperateMove:RecalcPathInfo( start_pos, end_pos, range )
|
|
-- 增加直线的判断
|
|
local start_logic_pos = co.TableXY(start_pos.x, start_pos.y)
|
|
local end_logic_pos = co.TableXY(end_pos.x, end_pos.y)
|
|
local dir = co.TableXY(end_logic_pos.x - start_logic_pos.x, end_logic_pos.y - start_logic_pos.y)
|
|
local dist = co.NormaliseXYTable(dir)
|
|
|
|
--对目标点进行直线探测
|
|
local rlt = Scene.Instance:IsStraightLine(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(end_logic_pos.x, end_logic_pos.y))
|
|
if rlt then
|
|
--直线探测成功
|
|
local real_end = end_logic_pos
|
|
|
|
if dist <= range then
|
|
real_end = start_logic_pos
|
|
else
|
|
|
|
real_end = co.TableXY(end_logic_pos.x - dir.x * range, end_logic_pos.y - dir.y * range)
|
|
end
|
|
|
|
local path_point = {}
|
|
path_point.start_point = co.TableXY(start_logic_pos.x, start_logic_pos.y)
|
|
path_point.end_point = co.TableXY(real_end.x, real_end.y)
|
|
table.insert(self.path_list, path_point)
|
|
|
|
self.total_pair = #self.path_list
|
|
self.now_use_pair = 1
|
|
self.is_path_valid = true
|
|
else
|
|
--A*寻路
|
|
local is_path_valid, path_list = SourceOperateMove.FindPathList(nil,start_logic_pos, end_logic_pos, range)
|
|
if is_path_valid then
|
|
--分拆路径
|
|
self.path_list = path_list
|
|
|
|
--设置初始化状态, 当前待执行的路径为第一个小路径
|
|
self.total_pair = #self.path_list
|
|
self.now_use_pair = 1
|
|
self.is_path_valid = true
|
|
elseif SceneManager:getInstance():IsBlockXY(end_logic_pos.x, end_logic_pos.y) then
|
|
local r = Scene.Instance:DetectLastUnblockPoint(Vector2(start_logic_pos.x, start_logic_pos.y), Vector2(dir.x, dir.y), dist) --dist是逻辑坐标系的
|
|
if r.z == 1 then
|
|
local pair = {}
|
|
pair.start_point = co.TableXY(start_logic_pos.x, start_logic_pos.y)
|
|
local gv2 = r
|
|
pair.end_point = co.TableXY(gv2.x, gv2.y)
|
|
self.end_pos = co.TableXY(gv2.x, gv2.y)
|
|
table.insert(self.path_list, pair)
|
|
self.total_pair = 1
|
|
self.now_use_pair = 1
|
|
self.is_path_valid = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.is_path_valid then
|
|
EventSystem.FireNextFrame(GlobalEventSystem,SceneEventType.CREATE_FINDWAY_POINT, self.path_list)
|
|
end
|
|
|
|
return self.is_path_valid
|
|
end
|
|
|
|
--[[@
|
|
功能: 执行初始化操作, 产生一些基准数据
|
|
参数:
|
|
无
|
|
返回值:
|
|
为true表示初始化成功, 为false表示初始化失败
|
|
其它: 无
|
|
作者: deadline
|
|
]]
|
|
function SourceOperateMove:Init()
|
|
self.path_list = {}
|
|
|
|
local main_role = Scene.Instance:GetMainRole()
|
|
if not main_role then
|
|
return false
|
|
end
|
|
|
|
local start_logic_pos = co.TableXY(main_role:GetLogicPos())
|
|
|
|
--如果正在飞行,就直接直线走过去
|
|
if main_role:IsFlying() then
|
|
local path_point = {}
|
|
path_point.start_point = start_logic_pos
|
|
path_point.end_point = self.end_pos
|
|
table.insert(self.path_list, path_point)
|
|
|
|
self.total_pair = 1
|
|
self.now_use_pair = 1
|
|
self.is_path_valid = true
|
|
return true
|
|
end
|
|
|
|
--如果当前点在障碍内,就先走出来,再从走出来的点进行寻路
|
|
if SceneManager:getInstance():IsBlockXY(start_logic_pos.x, start_logic_pos.y) then
|
|
local unblock_pos = SourceOperateMove.FindNoBlockPos(start_logic_pos)
|
|
if unblock_pos then
|
|
local path_point = {}
|
|
path_point.start_point = start_logic_pos
|
|
path_point.end_point = unblock_pos
|
|
table.insert(self.path_list, path_point)
|
|
|
|
--把走出来的点作为起始点
|
|
start_logic_pos = unblock_pos
|
|
end
|
|
end
|
|
|
|
if self.move_type == SourceOperateMove.MoveType.MoveToTarget then
|
|
self.init_time = Status.NowTime
|
|
if not self.end_pos then
|
|
return false
|
|
end
|
|
|
|
local end_logic_pos = self.end_pos
|
|
--根据设定的起点终点重置路径信息
|
|
local is_get_path_suc = self:RecalcPathInfo(start_logic_pos, end_logic_pos, 0)
|
|
|
|
-- print("= = = SourceOperateMove:Init:")
|
|
-- for i=1,self.total_pair do
|
|
-- local pt = self.path_list[i]
|
|
-- print(string.format("= = = = [%.2f,%.2f], [%.2f,%.2f]", pt.start_point.x, pt.start_point.y, pt.end_point.x, pt.end_point.y))
|
|
-- end
|
|
return is_get_path_suc
|
|
end
|
|
return false
|
|
end
|
|
|
|
function SourceOperateMove:BeforeDelete()
|
|
if not self.is_finish and self.now_use_pair and self.total_pair and self.now_use_pair <= self.total_pair then
|
|
OperateManager.Instance:CheckJumpAction(self.now_use_pair,self.path_list,self.action_func,self.arg_list)
|
|
end
|
|
end
|
|
|
|
--[[@
|
|
功能: 用于从SourceOperate中获取一个NowOperate控制角色行为
|
|
参数:
|
|
无
|
|
返回值:
|
|
当前操作包 NowOperate
|
|
其它: 无
|
|
作者: deadline
|
|
]]
|
|
function SourceOperateMove:GetOperImpl()
|
|
local now_oper = nil
|
|
local now_time = Status.NowTime
|
|
if not self.now_use_pair or not self.total_pair then return end
|
|
if self.now_use_pair > self.total_pair then
|
|
--行走完成直接执行相关动作
|
|
self.is_finish = true
|
|
if self.action_func then
|
|
self.action_func(unpack(self.arg_list))
|
|
--print("self.action_func(unpack(self.arg_list))",self.action_func," ",unpack(self.arg_list))
|
|
end
|
|
now_oper = self:GenerateNop(0.2)
|
|
else
|
|
--取出下一个小路径执行
|
|
local move_pair = self.path_list[self.now_use_pair]
|
|
if move_pair ~= nil then
|
|
now_oper = NowOperateMove.New(now_time, move_pair.start_point, move_pair.end_point, self.now_use_pair==self.total_pair)
|
|
|
|
self.now_use_pair = self.now_use_pair + 1
|
|
end
|
|
end
|
|
|
|
return now_oper
|
|
end
|
|
|
|
|
|
|
|
|