otherworldly_simulation/scene/test/character.gd

294 lines
6.8 KiB
GDScript3
Raw Normal View History

2024-10-25 15:41:39 +08:00
extends CharacterBody2D
class_name Unit
#这里暂时使用中文键debug方便调试后会更改
var action_emoji:Dictionary={
"生气":"🤯",
"愤怒":"🤬",
"指责":"👈🤯",
"伤害":"😡🔪",
"友好":"🥰",
"被指责":"😟",
"受伤":"😭💔",
"饥饿":"🍽︎",
"好吃":"😋"
}
@export var unit_data:Dictionary={
"unit_id":"default",
"unit_type":"default",
#动画资源
"sprite_frames":"res://res/animation/other_character_default.tres",
#动画偏移
"sprite_offset":Vector2(0,-80),
#动画缩放
"sprite_scale":Vector2(5,5),
#基础属性
"hp_base":100,
"atk_base":10,
"speed_base":1,
#攻击方式
"attack_type":"base",
#下面是临时生成的动态数据
#状态值
#饥饿,疲劳,怒气,紧张,恐慌,压力
"hungry":0,
"fatigue":0,
"rage":0,
"tensity":0,
"panic":0,
#压力
"pressure":0,
"hp_max":100,
"hp":100,
}
#允许的状态队列
var state_value_array:Array=["hungry","fatigue","rage","tensity","panic","pressure","hp_max","hp"]
#设置状态值
func get_state_value(state_value_name:String):
if state_value_name in state_value_array:
return unit_data[state_value_name]
else:
return null
#状态值改变时发出信号
signal state_value_changed(state_value_name:String,value)
#设置状态值
func set_state_value(state_value_name:String,value)->bool:
if state_value_name in state_value_array:
unit_data[state_value_name]=value
state_value_changed.emit(state_value_name,value)
return true
else:
return false
#获取单位ID
func get_unit_id():
return unit_data["unit_id"]
#获取单位类型
func get_unit_type():
return unit_data["unit_type"]
#快捷获取
func get_hungry():
return get_state_value("hungry")
func set_hungry(value):
return set_state_value("hungry",value)
##单位的独特ID
@export var unit_id:String="default"
##单位所属族群
@export var unit_type:String="default"
##每秒触发的timer,用于计算饥饿值积累等
var second_timer:Timer
@export var animation:AnimatedSprite2D
const unit_speed = 300.0
const JUMP_VELOCITY = -400.0
@export var agent: NavigationAgent2D
@export var state_machine: StateMachine
#旋转中心轴
@export var rotate: Node2D
##与其他单位交互的范围,目标进入此范围内才进行交互
@export var touch_area:Area2D
##感知范围
@export var sense_area:Area2D
@export var attack_area:Area2D
#var hungry:float=0:
#set(val):
#hungry=val
#if %hungry!=null:
#%hungry.text="饥饿值:"+str(val)
func _ready() -> void:
Global.set_unit_instance(unit_id,self)
agent.max_speed=unit_speed
agent.velocity_computed.connect(safe_speed)
if animation!=null:
animation.frame_changed.connect(frame_changed)
second_timer=Timer.new()
second_timer.autostart=true
second_timer.one_shot=false
second_timer.wait_time=1
second_timer.timeout.connect(second_timer_time_out)
add_child(second_timer)
var new_sprite_animation:AnimatedSprite2D=AnimatedSprite2D.new()
new_sprite_animation.sprite_frames=load(unit_data["sprite_frames"])
add_child(new_sprite_animation)
new_sprite_animation.position=unit_data["sprite_offset"]
new_sprite_animation.scale=unit_data["sprite_scale"]
animation=new_sprite_animation
#state_machine.launch()
func set_target_pos(target:Vector2):
agent.target_position=target
func _physics_process(delta: float) -> void:
if agent!=null and not is_move_finished():
var current_pos:Vector2=global_position
var next_pos:Vector2=agent.get_next_path_position()
var new_velocity=current_pos.direction_to(next_pos)*unit_speed
if agent.avoidance_enabled:
agent.set_velocity(new_velocity)
rotate.rotation=velocity.angle()
else:
safe_speed(new_velocity)
rotate.rotation=velocity.angle()
if is_move_finished():
velocity=Vector2.ZERO
else:
cache_velicity=velocity
if animation!=null:
if velocity.x>0:
animation.flip_h=false
if velocity.x<0:
animation.flip_h=true
move_and_slide()
func safe_speed(safe_velocity):
velocity=safe_velocity
func stop_move():
set_target_pos(self.global_position)
func is_move_finished():
#return agent.is_target_reached()
return agent.is_navigation_finished()
func sent_message(type:String,value):
state_machine.send_message(type,value)
#判断unit实例在不在交互范围内
func is_unit_instance_in_touch_area(instance:Node):
if touch_area==null:
return false
else:
if instance is PhysicsBody2D:
return instance in touch_area.get_overlapping_bodies()
if instance is Area2D:
return instance in touch_area.get_overlapping_areas()
#指责(口角)
func accuse(unit_id:String):
show_action("指责")
var instance=Global.get_unit_instance(unit_id)
if instance is UnitOther:
instance.accused(self.unit_id)
pass
#被指责,调用
func accused(by_unit_id:String):
show_action("被指责")
Global.set_unit_favour(unit_id,by_unit_id,Global.get_unit_favour(unit_id,by_unit_id)-10)
pass
@export var attack_frames:int=2
#攻击
func attack():
show_action("伤害")
match get_dir():
0:
play_animation("up_attack")
1:
play_animation("down_attack")
2:
play_animation("left_right_attack")
3:
play_animation("left_right_attack")
pass
func frame_changed():
if animation.animation in [&"up_attack",&"down_attack",&"left_right_attack"] and animation.frame==attack_frames:
use_attack_damage()
func is_attack_finished():
if animation.animation in [&"up_attack",&"down_attack",&"left_right_attack"] and not animation.is_playing():
return true
else:
return false
func is_attacking():
return animation.animation in [&"up_attack",&"down_attack",&"left_right_attack"] and animation.is_playing()
#在固定帧使用攻击
func use_attack_damage():
for i in attack_area.get_overlapping_bodies():
if i is Unit and i!=self:
i.attacked(unit_id)
pass
func attacked(by_unit_id:String):
show_action("受伤")
Global.set_unit_favour(unit_id,by_unit_id,Global.get_unit_favour(unit_id,by_unit_id)-20)
pass
func set_target(global_pos:Vector2):
cache_velicity=global_pos-self.global_position
rotate.look_at(global_pos)
if cache_velicity.x>0:
animation.flip_h=false
if cache_velicity.x<0:
animation.flip_h=true
pass
func show_action(type:String):
print(type)
if action_emoji.has(type):
%action_show.text=action_emoji[type]
if %action_animation.is_playing():
%action_animation.stop()
%action_animation.play("show")
pass
func play_animation(animation_name:String):
if animation !=null:
animation.play(animation_name)
pass
var cache_velicity:Vector2=Vector2(1,0)
#0上1下2左,3右
func get_dir()->int:
if abs(cache_velicity.y)>abs(cache_velicity.x):
if cache_velicity.y>0:
return 1
else:
return 0
else:
if cache_velicity.x>0:
return 3
else:
return 2
pass
pass
func second_timer_time_out():
set_hungry(clamp(get_hungry()+10,0,100))
pass
func eat(food:Food):
print("")
show_action("好吃")
set_hungry(clamp(get_hungry()-food.hungry,0,100))
food.eated()
pass