143 lines
4.9 KiB
GDScript
143 lines
4.9 KiB
GDScript
extends BlockAction
|
||
class_name BlockActionMove
|
||
|
||
|
||
func _init() -> void:
|
||
self.action_name="移动"
|
||
self.need_target=true
|
||
|
||
pass
|
||
#获取动作可以作用于的地块(true or false)二维数组,并建立寻路缓存
|
||
func get_action_could_use_block(_self:UnitBlock,tile_map_area:Rect2i,global_block_data:Dictionary)->Array:
|
||
var astar=AStarGrid2D.new()
|
||
print(global_block_data)
|
||
astar.default_compute_heuristic=AStarGrid2D.HEURISTIC_MANHATTAN
|
||
astar.default_estimate_heuristic=AStarGrid2D.HEURISTIC_MANHATTAN
|
||
astar.diagonal_mode=AStarGrid2D.DIAGONAL_MODE_NEVER
|
||
astar.region=Rect2i(tile_map_area.position,tile_map_area.size+Vector2i(1,1))
|
||
astar.update()
|
||
var right_pos:Vector2i=tile_map_area.position+tile_map_area.size
|
||
for i in range(tile_map_area.position.x,right_pos.x+1):
|
||
var res_in:Array[bool]=[]
|
||
for j in range(tile_map_area.position.y,right_pos.y+1):
|
||
if global_block_data.has(Vector2i(i,j)):
|
||
#计算当前地块是否可通行
|
||
var block_arr:Array=global_block_data[Vector2i(i,j)]
|
||
var walkable:bool=true
|
||
for k in block_arr:
|
||
if k is BaseBlock:
|
||
walkable=walkable and k.walkable
|
||
astar.set_point_solid(Vector2i(i,j),not walkable)
|
||
else:
|
||
#默认可通行
|
||
astar.set_point_solid(Vector2i(i,j),false)
|
||
var res:Array=[]
|
||
block_road_cache=[]
|
||
for i in range(tile_map_area.position.x,right_pos.x+1):
|
||
var res_in:Array[bool]=[]
|
||
var block_in:Array=[]
|
||
for j in range(tile_map_area.position.y,right_pos.y+1):
|
||
var road_find_result=is_move_able(astar,_self.block_pos,Vector2i(i,j),_self.action_num,tile_map_area)
|
||
block_in.append(road_find_result)
|
||
res_in.append(road_find_result[0])
|
||
res.append(res_in)
|
||
block_road_cache.append(block_in)
|
||
pass
|
||
return res
|
||
|
||
|
||
#区域是否可达
|
||
func is_move_able(astar:AStarGrid2D,from:Vector2i,to:Vector2i,move_distance:int,tile_map_area:Rect2i):
|
||
var res=get_walkable_path(astar,from,to,tile_map_area)
|
||
if not res[0]:
|
||
return [false,0,null]
|
||
var distance=res[1]
|
||
if move_distance>=distance:
|
||
return [true,res[1],res[2]]
|
||
else:
|
||
return [false,0,null]
|
||
|
||
|
||
|
||
|
||
#获取两点之间的最短可达路径,返回一个数组,0下标未是否可达,1下标为距离,2下标为途径点数组
|
||
func get_walkable_path(astar:AStarGrid2D,from:Vector2i,to:Vector2i,tile_map_area:Rect2i)->Array:
|
||
var right_pos=tile_map_area.position+tile_map_area.size
|
||
#如果不在要求的tilemap范围内,则返回不可达
|
||
if to.x<tile_map_area.position.x or to.x>right_pos.x or to.y<tile_map_area.position.y or to.y>right_pos.y:
|
||
return [false,0,null]
|
||
var arr=astar.get_id_path(from,to)
|
||
if arr==null or (arr is Array and arr.size()<=0):
|
||
return [false,0,null]
|
||
return [true,arr.size()-1,arr]
|
||
#寻路缓存
|
||
var block_road_cache:Array=[]
|
||
#在_self上使用action动作,返回是否成功
|
||
func block_use_action(_self:UnitBlock,tile_map_area:Rect2i,global_block_data:Dictionary,target=null)->bool:
|
||
if not target is Vector2i:
|
||
return false
|
||
|
||
var astar=AStarGrid2D.new()
|
||
astar.default_compute_heuristic=AStarGrid2D.HEURISTIC_MANHATTAN
|
||
astar.default_estimate_heuristic=AStarGrid2D.HEURISTIC_MANHATTAN
|
||
astar.diagonal_mode=AStarGrid2D.DIAGONAL_MODE_NEVER
|
||
astar.region=Rect2i(tile_map_area.position,tile_map_area.size+Vector2i(1,1))
|
||
astar.update()
|
||
var right_pos:Vector2i=tile_map_area.position+tile_map_area.size
|
||
for i in range(tile_map_area.position.x,right_pos.x+1):
|
||
var res_in:Array[bool]=[]
|
||
for j in range(tile_map_area.position.y,right_pos.y+1):
|
||
if global_block_data.has(Vector2i(i,j)):
|
||
#计算当前地块是否可通行
|
||
var block_arr:Array=global_block_data[Vector2i(i,j)]
|
||
var walkable:bool=true
|
||
for k in block_arr:
|
||
if k is BaseBlock:
|
||
walkable=walkable and k.walkable
|
||
astar.set_point_solid(Vector2i(i,j),not walkable)
|
||
else:
|
||
#默认可通行
|
||
astar.set_point_solid(Vector2i(i,j),false)
|
||
var res=is_move_able(astar,_self.block_pos,target,_self.action_num,tile_map_area)
|
||
if res[0]:
|
||
_self.action_num-=res[1]
|
||
_self.request_move(res[2],global_block_data)
|
||
return true
|
||
return false
|
||
var draw_line
|
||
#展示施法演示
|
||
func draw_action_with_target(_self:UnitBlock,tile_map_area:Rect2i,global_block_data:Dictionary,target:Vector2i,block_add_pos:TileMapLayer):
|
||
var right_pos=tile_map_area.position+tile_map_area.size
|
||
if target.x<tile_map_area.position.x or target.x>right_pos.x or target.y<tile_map_area.position.y or target.y>right_pos.y:
|
||
if draw_line!=null:
|
||
draw_line.queue_free()
|
||
draw_line=null
|
||
return
|
||
var crood=target-tile_map_area.position
|
||
var cache=block_road_cache[crood.x][crood.y]
|
||
if not cache[0]:
|
||
if draw_line!=null:
|
||
draw_line.queue_free()
|
||
draw_line=null
|
||
return
|
||
var point_arr:Array=cache[2]
|
||
if draw_line!=null:
|
||
draw_line.queue_free()
|
||
draw_line=null
|
||
var new_line=Line2D.new()
|
||
block_add_pos.add_child(new_line)
|
||
draw_line=new_line
|
||
draw_line.default_color=Color.RED
|
||
for i in point_arr:
|
||
draw_line.add_point(block_add_pos.map_to_local(i))
|
||
|
||
|
||
pass
|
||
#释放施法演示
|
||
func del_action_with_target():
|
||
block_road_cache.clear()
|
||
if draw_line!=null:
|
||
draw_line.queue_free()
|
||
draw_line=null
|
||
pass
|