challenge-editor/scene/_2d_fight/2d_fight.gd
2024-12-12 19:09:32 +08:00

424 lines
12 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Node2D
class_name Fight2D
const BLOCK_TAG_LABEL = preload("res://scene/_2d_fight/block_tag_label.tscn")
const _2D_ACTION_CHOICE = preload("res://scene/_2d_fight/2d_action_choice.tscn")
#网格寻路系统
var astar:AStarGrid2D=AStarGrid2D.new()
##当前使用的tilemap的范围开始
@export var tile_map_area_from:Vector2i
##当前使用的tilemap的范围结束
@export var tile_map_area_to:Vector2i
##color block的颜色指示
enum ColorBlockSetColor{
BLACK=0,
BLUE=1,
GREEN=2,
RED=3,
WHITE=4,
YELLOW=5
}
#镜头部分
#镜头速度
var camera_speed:float=1000
#镜头模式
enum CameraMode{
#wsad自由移动
FREE=0,
#镜头放大,并且进行一个平滑位移
FOCUS=1
}
##相机模式
@export var camera_mode:CameraMode=CameraMode.FREE
##相机基础缩放乘数
@export var camera_base_zoom_scale:Vector2
##当前聚焦的相机对象
@export var camera_focusmode_focus_target:Node2D:
set(val):
if camera_mode==CameraMode.FOCUS and val!=camera_focusmode_focus_target:
if camera_focus_mode_focus_tween!=null:
camera_focus_mode_focus_tween.kill()
camera_focus_mode_focus_tween=create_tween()
camera_focus_mode_focus_tween.tween_property(%main_camera,"global_position",val.global_position,camera_focus_mode_focus_time)
camera_focus_mode_focus_tween.set_parallel()
camera_focus_mode_focus_tween.tween_property(%main_camera,"zoom",camera_base_zoom_scale*camera_focus_mode_focus_scale,camera_focus_mode_focus_time)
camera_focusmode_focus_target=val
pass
#聚焦模式下相机的tween补间动画
var camera_focus_mode_focus_tween
#相机聚焦所用时间
var camera_focus_mode_focus_time:float=0.2
#相机聚焦倍率
var camera_focus_mode_focus_scale:float=1.5
##地块Block部分
#全局地块数据引用
#Vector2i:Array[BaseBlock]
var global_block_data:Dictionary={
}
#友方单位(需要自己做出行动选择的)
var friendly_side:Array[UnitBlock]=[]
#敌方单位(自动进行行动选择的)
var enermy_side:Array[UnitBlock]=[]
var now_use_block:UnitBlock
var now_use_action:int=-1:
set(val):
if now_use_action!=val:
match val:
-1:
%color_block.clear()
%select.clear()
%panel_container.change_open(true)
var block_action:BlockAction=now_use_block.could_use_action[now_use_action]
block_action.del_action_with_target()
_:
print("尝试进行行动")
var block_action:BlockAction=now_use_block.could_use_action[val]
print(block_action.need_target)
if block_action.need_target:
var res=block_action.get_action_could_use_block(now_use_block,Rect2i(tile_map_area_from,tile_map_area_to-tile_map_area_from),global_block_data)
print(res)
show_color_block(res)
%panel_container.change_open(false)
pass
now_use_action=val
pass
var now_index:int=0
func turn():
now_index=-1
for i in global_block_data.keys():
var arr=global_block_data[i]
for j in arr:
if j is BaseBlock:
j.turn()
next()
pass
var character_block_tween
func next():
if %left_character_drawer.is_open:
close_left_character()
for i in %choice_add_pos.get_children():
i.queue_free()
now_index+=1
now_use_action=-1
if now_index>=friendly_side.size():
turn()
return
var now_block:UnitBlock=friendly_side[now_index]
now_use_block=now_block
if character_block_tween!=null:
character_block_tween.kill()
character_block_tween=create_tween()
character_block_tween.tween_property(%main_camera,"global_position",now_block.position,0.2)
show_left_character({})
var choice_arr=now_block.get_all_choice()
for i in range(choice_arr.size()):
var new_btn=_2D_ACTION_CHOICE.instantiate()
new_btn.pressed.connect(select_choice.bind(i))
new_btn.text=choice_arr[i]
%choice_add_pos.add_child(new_btn)
%action.modulate.a=0
%action.show()
var tween=create_tween()
tween.tween_property(%action,"modulate:a",1,0.2)
pass
func select_choice(index:int):
print(index)
now_use_action=index
pass
func _ready() -> void:
Global.now_2d_fight_scene=self
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_from,tile_map_area_to-tile_map_area_from)
astar.update()
update_astar_from_walkable_map()
for i in range(10):
add_block(Vector2i(i,i),Database.get_block("wall"),2)
for i in range(10):
add_block(Vector2i(i,i+1),Database.get_block("test_character"),0)
#for i in range(10):
#add_block(Vector2i(i,i+2),Database.get_block("test_character"),1)
turn()
#从可行走tilemap图中同步到astar寻路中
func update_astar_from_walkable_map():
for i in range(tile_map_area_from.x,tile_map_area_to.x):
for j in range(tile_map_area_from.y,tile_map_area_to.y):
var crood=Vector2i(i,j)
var tile_data=%walkable.get_cell_tile_data(crood)
if tile_data !=null and tile_data.get_custom_data("walkable"):
astar.set_point_solid(crood,false)
else:
astar.set_point_solid(crood,true)
astar.update()
#获取两点之间的最短可达路径返回一个数组0下标未是否可达1下标为距离2下标为途径点数组
func get_walkable_path(from:Vector2i,to:Vector2i)->Array:
#如果不在要求的tilemap范围内则返回不可达
if to.x<tile_map_area_from.x or to.x>tile_map_area_to.x or to.y<tile_map_area_from.y or to.y>tile_map_area_to.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 before_mouse_block:Vector2i=Vector2i.ZERO
func _process(delta: float) -> void:
match camera_mode:
CameraMode.FREE:
var input=Input.get_vector("a","d","w","s").normalized()
%main_camera.position+=input*delta*camera_speed
CameraMode.FOCUS:
pass
#测试角色移动
if Input.is_action_just_pressed("mouse_left"):
print("click")
if now_use_action!=-1:
var crood=%block_add_pos.local_to_map(get_global_mouse_position())
var now_action:BlockAction=now_use_block.could_use_action[now_use_action]
var res=now_action.block_use_action(now_use_block,Rect2i(tile_map_area_from,tile_map_area_to-tile_map_area_from),global_block_data,crood)
if res:
now_use_action=-1
else:
var crood=%block_add_pos.local_to_map(get_global_mouse_position())
if crood!=before_crood:
before_index=0
if global_block_data.has(crood):
var arr=global_block_data[crood]
if arr.size()==0:
close_block_mes()
else:
var block:BaseBlock=arr[before_index]
pop_up_block_mes(block.block_name,block.block_attribute)
else:
close_block_mes()
pass
if Input.is_action_just_pressed("esc"):
now_use_action=-1
#上一次展示的block信息
var before_crood:Vector2i=Vector2i.ZERO
#上一次弹出地块信息的层级
var before_index:int=0
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
var mouse_pos=get_global_mouse_position()
var crood=%mouse_block.local_to_map(mouse_pos)
update_mouse_block(crood)
if before_mouse_block!=crood:
before_mouse_block=crood
draw_action(crood)
func draw_action(target:Vector2i):
if now_use_action==-1:
return
if not now_use_block is UnitBlock:
return
var block_action:BlockAction=now_use_block.could_use_action[now_use_action]
print(block_action.need_target)
if block_action.need_target:
block_action.draw_action_with_target(now_use_block,Rect2i(tile_map_area_from,tile_map_area_to-tile_map_area_from),global_block_data,target,%block_add_pos)
#更新鼠标显示
func update_mouse_block(pos:Vector2i,area:Rect2i=Rect2i(0,0,0,0)):
%mouse_block.clear()
var area_right=area.position+area.size
for i in range(area.position.x,area_right.x+1):
for j in range(area.position.y,area_right.y+1):
var offset=Vector2i(i,j)
%mouse_block.set_cell(pos+offset,0,Vector2i(0,0))
pass
func add_block(pos:Vector2i,scene:PackedScene,queue):
var instance:BaseBlock=scene.instantiate()
instance.block_pos=pos
instance.request_block_move.connect(move_block.bind(instance))
%block_add_pos.add_child(instance)
match queue:
0:
friendly_side.append(instance)
1:
enermy_side.append(instance)
add_block_to_data(instance,pos)
#移动block实例到指定位置
func move_block(from_pos:Vector2i,to_pos:Vector2i,block_instance:BaseBlock):
if not global_block_data.has(from_pos):
return
var arr:Array=global_block_data[from_pos]
if not block_instance in arr:
return
arr.pop_at(arr.find(block_instance))
if not global_block_data.has(to_pos):
global_block_data[to_pos]=[block_instance]
else:
global_block_data[to_pos].append(block_instance)
pass
#将block的引用添加到全局字典中
func add_block_to_data(block:BaseBlock,pos:Vector2i):
if not global_block_data.has(pos):
global_block_data[pos]=[block]
else:
global_block_data[pos].append(block)
pass
pass
func show_color_block(arr:Array):
var veci_arr:Array[Vector2i]=[]
%select.clear()
for i in range((tile_map_area_to-tile_map_area_from).x+1):
for j in range((tile_map_area_to-tile_map_area_from).y+1):
var offset=Vector2i(i,j)
var real_pos=tile_map_area_from+offset
if arr[i][j]:
%color_block.set_cell(tile_map_area_from+offset,ColorBlockSetColor.GREEN,Vector2i(0,0))
veci_arr.append(Vector2i(real_pos.x,real_pos.y))
else:
%color_block.set_cell(tile_map_area_from+offset,ColorBlockSetColor.RED,Vector2i(0,0))
%select.set_cells_terrain_connect(veci_arr,0,0)
pass
func _on_next_pressed() -> void:
next()
pass # Replace with function body.
func _on_pop_1_pressed() -> void:
%block_drawer.change_open(true)
pass # Replace with function body.
func _on_pop_2_pressed() -> void:
%left_character_drawer.change_open(true)
pass # Replace with function body.
func _on_pop_3_pressed() -> void:
%right_character_drawer.change_open(true)
pass # Replace with function body.
func _on_pop_4_pressed() -> void:
%alert_drawer.change_open(true)
%alert_timer.start()
pass # Replace with function body.
func _on_alert_timer_timeout() -> void:
%alert_drawer.change_open(false)
pass # Replace with function body.
#弹出地块信息,attribute字典应为String:bool
func pop_up_block_mes(_name:String,attribute:Dictionary):
%block_name.text=_name
for i in %block_label_add_pos.get_children():
i.queue_free()
for i in attribute.keys():
var new_tag=BLOCK_TAG_LABEL.instantiate()
%block_label_add_pos.add_child(new_tag)
new_tag.set_mes(i,attribute[i])
%block_drawer.change_open(true)
#收起地块信息
func close_block_mes():
if %block_drawer.is_open:
%block_drawer.change_open(false)
pass
func pop_up_choice(text:String,acc_callback:Callable,ref_callback:Callable):
%choice.modulate.a=0
%choice_text.text=text
ac_cal=acc_callback
re_cal=ref_callback
%choice.show()
var tween=create_tween()
tween.tween_property(%choice,"modulate:a",1,0.2)
pass
var ac_cal
var re_cal
func _on_action_close_pressed() -> void:
%action.hide()
pop_up_choice("是否结束本角色回合?",next,%action.show)
pass # Replace with function body.
func _on_choice_accept_pressed() -> void:
if ac_cal is Callable:
if ac_cal.is_valid():
ac_cal.call()
%choice.hide()
pass # Replace with function body.
func _on_choice_refuse_pressed() -> void:
if re_cal is Callable:
if re_cal.is_valid():
re_cal.call()
%choice.hide()
pass # Replace with function body.
#展示左边的角色信息
func show_left_character(data:Dictionary):
%left_character_drawer.change_open(true)
pass
#展示右边的角色信息
func show_right_character(data:Dictionary):
%right_character_drawer.change_open(true)
pass
#关闭左边的角色信息
func close_left_character():
if %left_character_drawer.is_open:
%left_character_drawer.change_open(false)
pass
#关闭右边的角色信息
func close_right_character():
if %right_character_drawer.is_open:
%right_character_drawer.change_open(false)
pass