源战役客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

458 行
14 KiB

--[[@------------------------------------------------------------------
说明: 移动源操作包, 用于产生控制角色移动到场景指定位置的操作包
作者: 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