From 9bc7c7d28c730cb5cc1fdc4bbde58700778bcd68 Mon Sep 17 00:00:00 2001 From: chendian <-> Date: Thu, 12 Oct 2023 02:40:37 +0800 Subject: [PATCH] =?UTF-8?q?hit=20box=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../saved_state.json | 10 ++++- config/attack/normal.tres | 14 ++++++ config/character/monster01.tres | 2 +- config/character/monster02.tres | 14 ++++++ config/player_skill/hero01_long_attack01.tres | 4 +- config/player_skill/hero01_long_attack02.tres | 4 +- config/player_skill/hero01_long_attack03.tres | 6 ++- config/player_skill/hero01_long_attack04.tres | 6 ++- config/player_skill/hero01_long_flash.tres | 3 +- config/player_skill/hero01_long_skill01.tres | 6 ++- .../character/monster03_attack.aseprite | Bin 22767 -> 22767 bytes .../animation/character/monster03_attack.png | Bin 15048 -> 8806 bytes .../skill_animation/hero01_long_attack01.tres | 19 +++++++- .../skill_animation/hero01_long_attack02.tres | 2 +- .../skill_animation/hero01_long_attack03.tres | 8 ++-- .../skill_animation/hero01_long_attack04.tres | 8 ++-- .../skill_animation/hero01_long_flash.tres | 22 ++++++--- .../skill_animation/hero01_long_skill01.tres | 6 +-- scene/character/character.tscn | 12 +++-- scene/character/player.tscn | 21 +++++---- scene/launcher.tscn | 4 +- script/_global/enum.gd | 1 + script/character/battle.gd | 42 ++++++++++++++++++ script/character/character.gd | 12 ++++- .../player/{input.gd => player_input.gd} | 3 +- script/character/skill.gd | 5 +++ script/character/status.gd | 9 ++-- script/config/attack_cfg.gd | 17 +++++++ script/config/skill_cfg.gd | 1 + script/manager/character_manager.gd | 19 ++++++-- script/manager/game_manager.gd | 4 +- 31 files changed, 230 insertions(+), 54 deletions(-) create mode 100644 config/attack/normal.tres create mode 100644 config/character/monster02.tres create mode 100644 script/character/battle.gd rename script/character/player/{input.gd => player_input.gd} (95%) create mode 100644 script/config/attack_cfg.gd diff --git a/addons/resources_spreadsheet_view/saved_state.json b/addons/resources_spreadsheet_view/saved_state.json index a4f1e53..b0d0679 100644 --- a/addons/resources_spreadsheet_view/saved_state.json +++ b/addons/resources_spreadsheet_view/saved_state.json @@ -4,6 +4,13 @@ "resource_local_to_scene": true, "resource_name": true }, + "res://config/player_skill/": { + "animation_name": true, + "has_animation": true, + "resource_local_to_scene": true, + "resource_name": true, + "sprite_frams": true + }, "res://example/Items/items/": { "resource_local_to_scene": true, "resource_name": true @@ -11,7 +18,8 @@ }, "recent_paths": [ "res://example/Items/items/", - "res://config/character/" + "res://config/character/", + "res://config/player_skill/" ], "table_functions": { "filter": [ diff --git a/config/attack/normal.tres b/config/attack/normal.tres new file mode 100644 index 0000000..22de861 --- /dev/null +++ b/config/attack/normal.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="AttackCfg" load_steps=2 format=3 uid="uid://bsqk3q6mccllg"] + +[ext_resource type="Script" path="res://script/config/attack_cfg.gd" id="1_wn06b"] + +[resource] +script = ExtResource("1_wn06b") +damage_rate = 1.0 +break_level = 0 +hit_back_speed = 0.0 +hit_back_duration = 0.0 +hit_up_speed = 0.0 +hit_up_duration = 0.0 +pause_time = 0.0 +is_floating = false diff --git a/config/character/monster01.tres b/config/character/monster01.tres index 6120037..3db677d 100644 --- a/config/character/monster01.tres +++ b/config/character/monster01.tres @@ -9,7 +9,7 @@ script = ExtResource("1_4orbu") name = "monster01" type = 1 sprite_frames = ExtResource("2_su3hg") -sprite_harf_height = 26 +sprite_harf_height = 10 sprite_width = 16 move = ExtResource("1_b0lkj") hp_max = 200.0 diff --git a/config/character/monster02.tres b/config/character/monster02.tres new file mode 100644 index 0000000..b523f64 --- /dev/null +++ b/config/character/monster02.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="CharacterCfg" load_steps=3 format=3 uid="uid://dmfh54jffhx28"] + +[ext_resource type="Script" path="res://script/config/character_cfg.gd" id="1_wkjce"] +[ext_resource type="SpriteFrames" uid="uid://criqnimi5dara" path="res://resource/animation/character/monster02_move.aseprite" id="2_h60bf"] + +[resource] +script = ExtResource("1_wkjce") +name = "monster02" +type = 0 +sprite_frames = ExtResource("2_h60bf") +sprite_harf_height = 0 +sprite_width = 0 +hp_max = 0.0 +shield_max = 0.0 diff --git a/config/player_skill/hero01_long_attack01.tres b/config/player_skill/hero01_long_attack01.tres index 4a70b8b..7a5df01 100644 --- a/config/player_skill/hero01_long_attack01.tres +++ b/config/player_skill/hero01_long_attack01.tres @@ -1,5 +1,6 @@ -[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=5 format=3 uid="uid://b6x3jdiqtum6"] +[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=6 format=3 uid="uid://b6x3jdiqtum6"] +[ext_resource type="Resource" uid="uid://bsqk3q6mccllg" path="res://config/attack/normal.tres" id="1_6ven2"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="1_gik08"] [ext_resource type="Animation" uid="uid://daopmieibx3b7" path="res://resource/skill_animation/hero01_long_attack01.tres" id="2_6nbpq"] [ext_resource type="SpriteFrames" uid="uid://7swf8owxd63i" path="res://resource/animation/character/hero01_long_attack.aseprite" id="3_og1bb"] @@ -14,6 +15,7 @@ break_level = 3 action = "attack_light" name = "" skill_animation = ExtResource("2_6nbpq") +attack_list = Array[Resource("res://script/config/attack_cfg.gd")]([ExtResource("1_6ven2")]) has_animation = false sprite_frams = ExtResource("3_og1bb") animation_name = "long_attack01" diff --git a/config/player_skill/hero01_long_attack02.tres b/config/player_skill/hero01_long_attack02.tres index 7020dc2..3615579 100644 --- a/config/player_skill/hero01_long_attack02.tres +++ b/config/player_skill/hero01_long_attack02.tres @@ -1,5 +1,6 @@ -[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=5 format=3 uid="uid://cs32884hwqxd7"] +[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=6 format=3 uid="uid://cs32884hwqxd7"] +[ext_resource type="Resource" uid="uid://bsqk3q6mccllg" path="res://config/attack/normal.tres" id="1_8fm1u"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="1_e0fqi"] [ext_resource type="Animation" uid="uid://bf6jaraltouun" path="res://resource/skill_animation/hero01_long_attack02.tres" id="2_jrgan"] [ext_resource type="SpriteFrames" uid="uid://7swf8owxd63i" path="res://resource/animation/character/hero01_long_attack.aseprite" id="3_jidy7"] @@ -14,6 +15,7 @@ break_level = 3 action = "attack_light" name = "" skill_animation = ExtResource("2_jrgan") +attack_list = Array[Resource("res://script/config/attack_cfg.gd")]([ExtResource("1_8fm1u")]) has_animation = false sprite_frams = ExtResource("3_jidy7") animation_name = "long_attack02" diff --git a/config/player_skill/hero01_long_attack03.tres b/config/player_skill/hero01_long_attack03.tres index b7254c5..9652955 100644 --- a/config/player_skill/hero01_long_attack03.tres +++ b/config/player_skill/hero01_long_attack03.tres @@ -1,5 +1,6 @@ -[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=5 format=3 uid="uid://huxlxrmyulo"] +[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=6 format=3 uid="uid://huxlxrmyulo"] +[ext_resource type="Resource" uid="uid://bsqk3q6mccllg" path="res://config/attack/normal.tres" id="1_4o7bo"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="1_uaib7"] [ext_resource type="Resource" uid="uid://cy3wwalxeyro0" path="res://config/weapon/long.tres" id="2_8uqiw"] [ext_resource type="Animation" uid="uid://c8yueqe7rjn60" path="res://resource/skill_animation/hero01_long_attack03.tres" id="2_ugt3f"] @@ -14,6 +15,7 @@ break_level = 3 action = "attack_light" name = "" skill_animation = ExtResource("2_ugt3f") -has_animation = true +attack_list = Array[Resource("res://script/config/attack_cfg.gd")]([ExtResource("1_4o7bo")]) +has_animation = false sprite_frams = ExtResource("3_sr2og") animation_name = "long_attack03" diff --git a/config/player_skill/hero01_long_attack04.tres b/config/player_skill/hero01_long_attack04.tres index 19e8a38..4e8e4ef 100644 --- a/config/player_skill/hero01_long_attack04.tres +++ b/config/player_skill/hero01_long_attack04.tres @@ -1,5 +1,6 @@ -[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=5 format=3 uid="uid://chuv8k5d44ln4"] +[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=6 format=3 uid="uid://chuv8k5d44ln4"] +[ext_resource type="Resource" uid="uid://bsqk3q6mccllg" path="res://config/attack/normal.tres" id="1_kpxla"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="1_xsxbs"] [ext_resource type="Animation" uid="uid://dk1o3gqhjmuvh" path="res://resource/skill_animation/hero01_long_attack04.tres" id="2_sam6s"] [ext_resource type="SpriteFrames" uid="uid://7swf8owxd63i" path="res://resource/animation/character/hero01_long_attack.aseprite" id="3_w7h1m"] @@ -14,6 +15,7 @@ break_level = 3 action = "attack_light" name = "" skill_animation = ExtResource("2_sam6s") -has_animation = true +attack_list = Array[Resource("res://script/config/attack_cfg.gd")]([ExtResource("1_kpxla")]) +has_animation = false sprite_frams = ExtResource("3_w7h1m") animation_name = "long_attack04" diff --git a/config/player_skill/hero01_long_flash.tres b/config/player_skill/hero01_long_flash.tres index 11535ab..6d37a86 100644 --- a/config/player_skill/hero01_long_flash.tres +++ b/config/player_skill/hero01_long_flash.tres @@ -14,6 +14,7 @@ break_level = 1 action = "flash" name = "" skill_animation = ExtResource("2_bdxlh") -has_animation = true +attack_list = Array[Resource("res://script/config/attack_cfg.gd")]([]) +has_animation = false sprite_frams = ExtResource("2_uof6p") animation_name = "long_flash" diff --git a/config/player_skill/hero01_long_skill01.tres b/config/player_skill/hero01_long_skill01.tres index 00943c9..a83fe43 100644 --- a/config/player_skill/hero01_long_skill01.tres +++ b/config/player_skill/hero01_long_skill01.tres @@ -1,5 +1,6 @@ -[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=5 format=3 uid="uid://bi2ipbximefsr"] +[gd_resource type="Resource" script_class="PlayerSkillCfg" load_steps=6 format=3 uid="uid://bi2ipbximefsr"] +[ext_resource type="Resource" uid="uid://bsqk3q6mccllg" path="res://config/attack/normal.tres" id="1_p5wrw"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="1_ud5ph"] [ext_resource type="Animation" uid="uid://bjnkrte7660pt" path="res://resource/skill_animation/hero01_long_skill01.tres" id="2_ewts2"] [ext_resource type="SpriteFrames" uid="uid://0yuryfn6dc2v" path="res://resource/animation/character/hero01_long_skill01.aseprite" id="3_qwjfl"] @@ -14,6 +15,7 @@ break_level = 3 action = "attack_heavy" name = "" skill_animation = ExtResource("2_ewts2") -has_animation = true +attack_list = Array[Resource("res://script/config/attack_cfg.gd")]([ExtResource("1_p5wrw")]) +has_animation = false sprite_frams = ExtResource("3_qwjfl") animation_name = "long_skill01" diff --git a/resource/animation/character/monster03_attack.aseprite b/resource/animation/character/monster03_attack.aseprite index fc859425be45a975b7a959ccd6fc2ddcf17649e1..bf18d6737e3a54feee4a2c2c5eef9553397735fe 100644 GIT binary patch delta 16 YcmaFAk@5XT#tqw;8JRY3XSN6h078KVsQ>@~ delta 18 acmaFAk@5XT#tqw;Ctqcj*nEyzF%$q;YzQd; diff --git a/resource/animation/character/monster03_attack.png b/resource/animation/character/monster03_attack.png index 1162d6df45c8945506df4f383803b28cf25a3325..1e31303cf2e122d791b9839f47cf2625d63c35e7 100644 GIT binary patch literal 8806 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 pm*b=B4WU=Di-pz>9rZnm<#?{s*%H^56gf literal 15048 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 diff --git a/resource/skill_animation/hero01_long_attack01.tres b/resource/skill_animation/hero01_long_attack01.tres index bc7ea6b..9fa884c 100644 --- a/resource/skill_animation/hero01_long_attack01.tres +++ b/resource/skill_animation/hero01_long_attack01.tres @@ -60,7 +60,7 @@ tracks/4/path = NodePath("Status:speed_up_rate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { -"times": PackedFloat32Array(0.1, 0.3), +"times": PackedFloat32Array(0.2, 0.3), "transitions": PackedFloat32Array(1, 1), "update": 1, "values": [-0.5, -1.0] @@ -77,3 +77,20 @@ tracks/5/keys = { "update": 1, "values": [1.0, 0.0] } +tracks/6/type = "method" +tracks/6/imported = false +tracks/6/enabled = true +tracks/6/path = NodePath("Battle") +tracks/6/interp = 1 +tracks/6/loop_wrap = true +tracks/6/keys = { +"times": PackedFloat32Array(0.2, 0.3), +"transitions": PackedFloat32Array(1, 1), +"values": [{ +"args": [], +"method": &"attack" +}, { +"args": [], +"method": &"attack" +}] +} diff --git a/resource/skill_animation/hero01_long_attack02.tres b/resource/skill_animation/hero01_long_attack02.tres index ab7cfa0..da9a5ef 100644 --- a/resource/skill_animation/hero01_long_attack02.tres +++ b/resource/skill_animation/hero01_long_attack02.tres @@ -60,7 +60,7 @@ tracks/4/path = NodePath("Status:speed_up_rate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { -"times": PackedFloat32Array(0.1, 0.3), +"times": PackedFloat32Array(0.2, 0.3), "transitions": PackedFloat32Array(1, 1), "update": 1, "values": [-0.5, -1.0] diff --git a/resource/skill_animation/hero01_long_attack03.tres b/resource/skill_animation/hero01_long_attack03.tres index 7a13350..d7990ff 100644 --- a/resource/skill_animation/hero01_long_attack03.tres +++ b/resource/skill_animation/hero01_long_attack03.tres @@ -60,7 +60,7 @@ tracks/4/path = NodePath("Status:speed_up_rate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { -"times": PackedFloat32Array(0.1, 0.3), +"times": PackedFloat32Array(0, 0.6), "transitions": PackedFloat32Array(1, 1), "update": 1, "values": [-0.5, -1.0] @@ -72,8 +72,8 @@ tracks/5/path = NodePath("Status:skill_move_speed") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/keys = { -"times": PackedFloat32Array(0.1, 0.3), -"transitions": PackedFloat32Array(1, 1), +"times": PackedFloat32Array(0.1, 0.3, 0.4, 0.5), +"transitions": PackedFloat32Array(1, 1, 1, 1), "update": 1, -"values": [1.0, 0.0] +"values": [1.0, 0.0, 1.0, 0.0] } diff --git a/resource/skill_animation/hero01_long_attack04.tres b/resource/skill_animation/hero01_long_attack04.tres index 9a66994..e5aa613 100644 --- a/resource/skill_animation/hero01_long_attack04.tres +++ b/resource/skill_animation/hero01_long_attack04.tres @@ -60,7 +60,7 @@ tracks/4/path = NodePath("Status:speed_up_rate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { -"times": PackedFloat32Array(0.1, 0.3), +"times": PackedFloat32Array(0.1, 0.4), "transitions": PackedFloat32Array(1, 1), "update": 1, "values": [-0.5, -1.0] @@ -72,8 +72,8 @@ tracks/5/path = NodePath("Status:skill_move_speed") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/keys = { -"times": PackedFloat32Array(0.1, 0.3), -"transitions": PackedFloat32Array(1, 1), +"times": PackedFloat32Array(0.1, 0.5, 0.6), +"transitions": PackedFloat32Array(1, 1, 1), "update": 1, -"values": [1.0, 0.0] +"values": [0.5, 1.0, 0.0] } diff --git a/resource/skill_animation/hero01_long_flash.tres b/resource/skill_animation/hero01_long_flash.tres index 32cb32c..39cccbe 100644 --- a/resource/skill_animation/hero01_long_flash.tres +++ b/resource/skill_animation/hero01_long_flash.tres @@ -44,22 +44,34 @@ tracks/2/keys = { tracks/3/type = "value" tracks/3/imported = false tracks/3/enabled = true -tracks/3/path = NodePath("Status:speed_up_rate") +tracks/3/path = NodePath("Status:break_level") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/keys = { -"times": PackedFloat32Array(0.1, 0.3), -"transitions": PackedFloat32Array(1, 1), +"times": PackedFloat32Array(0, 0.2, 0.3), +"transitions": PackedFloat32Array(1, 1, 1), "update": 1, -"values": [0.0, 0.0] +"values": [0, 3, 4] } tracks/4/type = "value" tracks/4/imported = false tracks/4/enabled = true -tracks/4/path = NodePath("Status:skill_move_speed") +tracks/4/path = NodePath("Status:speed_up_rate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 1, +"values": [0.0, 0.0] +} +tracks/5/type = "value" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("Status:skill_move_speed") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { "times": PackedFloat32Array(0.1, 0.3), "transitions": PackedFloat32Array(1, 1), "update": 1, diff --git a/resource/skill_animation/hero01_long_skill01.tres b/resource/skill_animation/hero01_long_skill01.tres index 3163c25..cdee492 100644 --- a/resource/skill_animation/hero01_long_skill01.tres +++ b/resource/skill_animation/hero01_long_skill01.tres @@ -59,7 +59,7 @@ tracks/4/path = NodePath("Status:speed_up_rate") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { -"times": PackedFloat32Array(0.1, 0.3), +"times": PackedFloat32Array(0.1, 0.5), "transitions": PackedFloat32Array(1, 1), "update": 1, "values": [-0.5, -1.0] @@ -71,8 +71,8 @@ tracks/5/path = NodePath("Status:skill_move_speed") tracks/5/interp = 1 tracks/5/loop_wrap = true tracks/5/keys = { -"times": PackedFloat32Array(0.1, 0.3), +"times": PackedFloat32Array(0.1, 0.4), "transitions": PackedFloat32Array(1, 1), "update": 1, -"values": [1.0, 0.0] +"values": [4.0, 0.0] } diff --git a/scene/character/character.tscn b/scene/character/character.tscn index 667e09e..2becbb6 100644 --- a/scene/character/character.tscn +++ b/scene/character/character.tscn @@ -1,12 +1,13 @@ -[gd_scene load_steps=9 format=3 uid="uid://vnkcr04hevna"] +[gd_scene load_steps=10 format=3 uid="uid://vnkcr04hevna"] [ext_resource type="Script" path="res://script/character/character.gd" id="1_tonbs"] [ext_resource type="Script" path="res://script/character/status.gd" id="2_txdip"] -[ext_resource type="SpriteFrames" uid="uid://7swf8owxd63i" path="res://resource/animation/character/hero01_long_attack.aseprite" id="3_ibonj"] +[ext_resource type="SpriteFrames" uid="uid://7swf8owxd63i" path="res://resource/animation/character/hero01_long_attack.aseprite" id="3_safrr"] [ext_resource type="Script" path="res://script/character/move.gd" id="4_66r53"] [ext_resource type="Script" path="res://script/character/view.gd" id="4_vijjv"] [ext_resource type="Script" path="res://script/character/skill.gd" id="6_h4xqy"] [ext_resource type="AnimationLibrary" uid="uid://croik07a1qko5" path="res://resource/skill_animation_library/animation_library.tres" id="6_pakq5"] +[ext_resource type="Script" path="res://script/character/battle.gd" id="8_w84sf"] [sub_resource type="BoxShape3D" id="BoxShape3D_ty8lx"] @@ -21,13 +22,14 @@ shape = SubResource("BoxShape3D_ty8lx") [node name="Status" type="Node3D" parent="."] unique_name_in_owner = true script = ExtResource("2_txdip") +speed_up_rate = -0.5 [node name="View" type="AnimatedSprite3D" parent="."] unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1.414, 0, 0, 0, 1, 0, 0, 0) alpha_cut = 2 texture_filter = 0 -sprite_frames = ExtResource("3_ibonj") +sprite_frames = ExtResource("3_safrr") animation = &"long_attack01" script = ExtResource("4_vijjv") metadata/_aseprite_wizard_config_ = { @@ -51,5 +53,9 @@ libraries = { } script = ExtResource("6_h4xqy") +[node name="Battle" type="Node3D" parent="."] +unique_name_in_owner = true +script = ExtResource("8_w84sf") + [connection signal="animation_finished" from="View" to="View" method="_on_animation_finished"] [connection signal="animation_finished" from="Skill" to="Skill" method="_on_animation_finished"] diff --git a/scene/character/player.tscn b/scene/character/player.tscn index d233719..3781e03 100644 --- a/scene/character/player.tscn +++ b/scene/character/player.tscn @@ -1,19 +1,18 @@ -[gd_scene load_steps=5 format=3 uid="uid://b85fy0wfgr4gs"] +[gd_scene load_steps=4 format=3 uid="uid://uvv575nd76ji"] [ext_resource type="PackedScene" uid="uid://vnkcr04hevna" path="res://scene/character/character.tscn" id="1_bny0p"] -[ext_resource type="SpriteFrames" uid="uid://0yuryfn6dc2v" path="res://resource/animation/character/hero01_long_skill01.aseprite" id="2_cg8l2"] -[ext_resource type="Script" path="res://script/character/player/input.gd" id="2_qkra8"] -[ext_resource type="Script" path="res://script/character/player/combo.gd" id="4_jsefx"] +[ext_resource type="Script" path="res://script/character/player/combo.gd" id="2_6xb1m"] +[ext_resource type="Script" path="res://script/character/player/player_input.gd" id="2_d5j0i"] [node name="Character" instance=ExtResource("1_bny0p")] -[node name="View" parent="." index="2"] -sprite_frames = ExtResource("2_cg8l2") -animation = &"long_flash" - -[node name="Input" type="Node3D" parent="." index="5"] -script = ExtResource("2_qkra8") +[node name="Status" parent="." index="1"] +speed_up_rate = 0.0 +skill_move_speed = 4.0 [node name="Combo" type="Node3D" parent="." index="6"] unique_name_in_owner = true -script = ExtResource("4_jsefx") +script = ExtResource("2_6xb1m") + +[node name="PlayerInput" type="Node3D" parent="." index="7"] +script = ExtResource("2_d5j0i") diff --git a/scene/launcher.tscn b/scene/launcher.tscn index a6b779a..ed75637 100644 --- a/scene/launcher.tscn +++ b/scene/launcher.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=7 format=3 uid="uid://sl6cgchsyqlo"] +[gd_scene load_steps=8 format=3 uid="uid://sl6cgchsyqlo"] [ext_resource type="Script" path="res://script/manager/game_manager.gd" id="1_q2t80"] [ext_resource type="ArrayMesh" uid="uid://cap7t5iwpjpi2" path="res://resource/level/levelground0000.vox" id="1_u51ir"] [ext_resource type="Resource" uid="uid://bjvrih37ni5nx" path="res://config/character/hero01.tres" id="2_m8pa4"] +[ext_resource type="Resource" uid="uid://b1gf2jimihmc7" path="res://config/character/monster01.tres" id="3_awqf6"] [ext_resource type="Script" path="res://script/manager/character_manager.gd" id="4_oonkb"] [ext_resource type="Script" path="res://script/editor_tool/editor_tool.gd" id="5_n3qhi"] @@ -14,6 +15,7 @@ data = PackedVector3Array(-6.4, 0, -6.4, -3.2, 0, -6.4, -3.2, 0, 6.4, -3.2, 0, 6 [node name="GameManager" type="Node3D" parent="."] script = ExtResource("1_q2t80") player = ExtResource("2_m8pa4") +test_monster = ExtResource("3_awqf6") [node name="LevelManager" type="Node3D" parent="GameManager"] unique_name_in_owner = true diff --git a/script/_global/enum.gd b/script/_global/enum.gd index be93623..1a5a85a 100644 --- a/script/_global/enum.gd +++ b/script/_global/enum.gd @@ -3,6 +3,7 @@ extends Node3D enum EActionType {Pressed, Released} enum ECharacterType {Player, Monster, Bullet} +enum ETeam {Player, Monster} enum EStance { Idle,Ground1,Ground2,Ground3,Ground4,Ground5,Ground6,Ground7, AirIdle = 10,Air1,Air2,Air3, diff --git a/script/character/battle.gd b/script/character/battle.gd new file mode 100644 index 0000000..9491c74 --- /dev/null +++ b/script/character/battle.gd @@ -0,0 +1,42 @@ +extends Node3D +class_name Battle + +@onready var character = (get_owner() as Character) +@onready var status = (%Status as Status) + +class HitInfo: + var form : int + var to : int + var dir : Vector2 + var attack : AttackCfg + +var hit_info_list = [] #命中信息 + +func attack(): + var attack_list = status.skill_cfg.attack_list + if !attack_list: + print("未配置技能攻击",status.skill_cfg) + var attack_index = status.skill_attack_index + if attack_index >= len(attack_list): + attack_index = len(attack_list) - 1 + var attack = attack_list[attack_index] + var enemy_list = character.manager().get_enemy_list(character.id()) + for enemy in enemy_list: + var pos_dir = enemy.pos()-character.pos() + var distance = pos_dir.length() + #test + if (distance < 1): + var hit_info = HitInfo.new() + hit_info.form = character.id() + hit_info.to = enemy.id() + hit_info.dir = status.skill_dir + hit_info.attack = attack + hit_info_list.append(hit_info) + +func _process(delta): + for hit_info in hit_info_list: + settle(hit_info) + hit_info_list.clear() + +func settle(hit_info:HitInfo): + print(hit_info.attack) diff --git a/script/character/character.gd b/script/character/character.gd index 985f930..c355e8d 100644 --- a/script/character/character.gd +++ b/script/character/character.gd @@ -5,8 +5,12 @@ class_name Character @onready var view = (%View as View) @onready var collision = (%Collision) -func init(id:int,cfg:CharacterCfg): +var character_manager : CharacterManager + +func init(mgr:CharacterManager,id:int,cfg:CharacterCfg,team:Enum.ETeam): + character_manager = mgr status.id = id + status.team = team status.cfg = cfg build_view(cfg) build_battle(cfg) @@ -25,3 +29,9 @@ func build_battle(cfg:CharacterCfg): status.hp_max = cfg.hp_max status.shield = cfg.shield_max status.shield_max = cfg.shield_max + +#==getter== +func manager()->CharacterManager:return character_manager +func id()->int:return status.id +func team()->Enum.ETeam:return status.team +func pos()->Vector2:return Vector2(position.x,position.z) diff --git a/script/character/player/input.gd b/script/character/player/player_input.gd similarity index 95% rename from script/character/player/input.gd rename to script/character/player/player_input.gd index c177ec7..7bac0b9 100644 --- a/script/character/player/input.gd +++ b/script/character/player/player_input.gd @@ -1,4 +1,5 @@ -extends Node +extends Node3D +class_name PlayerInput @onready var status = (%Status as Status) @onready var combo = (%Combo as Combo) diff --git a/script/character/skill.gd b/script/character/skill.gd index aadc69c..1ea8ee6 100644 --- a/script/character/skill.gd +++ b/script/character/skill.gd @@ -18,9 +18,12 @@ func cast_skill(cfg:SkillCfg,cast_dir:Vector2): if has_animation(animation_name): status.speed_up_rate = -1 status.is_free_control = false + status.is_free_turn = false status.is_skill_running = true + status.skill_cfg = cfg status.skill_dir = cast_dir status.break_level = Enum.EBreakLevel.None + if cast_dir.x != 0: status.is_right = cast_dir.x > 0 play(animation_name) else: print("技能animation不存在",animation_name) @@ -29,7 +32,9 @@ func cancel_skill(): stop() status.speed_up_rate = 0 status.is_free_control = true + status.is_free_turn = true status.is_skill_running = false + status.skill_cfg = null status.break_level = Enum.EBreakLevel.Walk view.reset() diff --git a/script/character/status.gd b/script/character/status.gd index 8fbb960..4eafaf0 100644 --- a/script/character/status.gd +++ b/script/character/status.gd @@ -2,11 +2,12 @@ extends Node3D class_name Status @export_category("实体属性") -@export var id : int -@export var owner_id : int +@export var id : int #id +@export var owner_id : int #所有者id +@export var team : Enum.ETeam #队伍 @export_category("静态属性") -@export var cfg : CharacterCfg +@export var cfg : CharacterCfg #配置表 @export_category("战斗状态") @export var hp : float #当前血量 @@ -27,9 +28,11 @@ class_name Status @export var is_jumped_check_time : float #是否已跳跃检测时间 避免未起直接判定落地 @export_category("技能状态") +@export var skill_cfg : SkillCfg #当前技能 @export var is_skill_running : bool #技能是否正在释放 @export var skill_dir : Vector2 #技能释放方向 @export var skill_move_speed : float #技能位移速度 +@export var skill_attack_index : int #技能攻击段数 @export_category("玩家技能状态") @export var input_dir : Vector2 #指令方向 diff --git a/script/config/attack_cfg.gd b/script/config/attack_cfg.gd new file mode 100644 index 0000000..6077885 --- /dev/null +++ b/script/config/attack_cfg.gd @@ -0,0 +1,17 @@ +@tool +extends Resource + +class_name AttackCfg + +#命中框信息 + +#数值信息 +@export var damage_rate : float = 1 #伤害系数 +@export var break_level : int #硬直等级 +@export var hit_back_speed : float #击退速度 +@export var hit_back_duration : float #击退持续时间 +@export var hit_up_speed : float #击飞速度 +@export var hit_up_duration : float #击飞持续时间 +@export var pause_time : float #卡帧时间 +@export var is_floating : bool #是否浮空技 + diff --git a/script/config/skill_cfg.gd b/script/config/skill_cfg.gd index f546177..83b4f74 100644 --- a/script/config/skill_cfg.gd +++ b/script/config/skill_cfg.gd @@ -5,6 +5,7 @@ class_name SkillCfg @export var name : String @export var skill_animation : Animation +@export var attack_list : Array[AttackCfg] var _has_animation : bool @export var has_animation : bool : diff --git a/script/manager/character_manager.gd b/script/manager/character_manager.gd index dbe408a..74dd366 100644 --- a/script/manager/character_manager.gd +++ b/script/manager/character_manager.gd @@ -7,7 +7,7 @@ var scene_monster = preload("res://scene/character/monster.tscn") var character_map = {} var character_idx : int = 0 -func create_character(cfg:CharacterCfg): +func create_character(cfg:CharacterCfg,team:Enum.ETeam): var characterNode:Node match cfg.type: Enum.ECharacterType.Player: @@ -19,7 +19,18 @@ func create_character(cfg:CharacterCfg): var character:Character = characterNode as Character character_idx += 1 character_map[character_idx]=character - character.init(character_idx,cfg) + character.init(self,character_idx,cfg,team) -func get_character(id:int): - return character_map[id] +func get_character(id:int) -> Character: + return character_map[id] as Character + +func get_enemy_list(id:int) -> Array[Character]: + var ret:Array[Character] = [] + var target = get_character(id) + if !target: + return ret + for key in character_map: + var character = character_map[key] as Character + if character.team() != target.team(): + ret.append(character) + return ret diff --git a/script/manager/game_manager.gd b/script/manager/game_manager.gd index c4a246e..39d3285 100644 --- a/script/manager/game_manager.gd +++ b/script/manager/game_manager.gd @@ -1,11 +1,13 @@ extends Node3D @export var player:CharacterCfg +@export var test_monster:CharacterCfg @onready var character_manager = (%CharacterManager as CharacterManager) func _ready(): - character_manager.create_character(player) + character_manager.create_character(player,Enum.ETeam.Player) + character_manager.create_character(test_monster,Enum.ETeam.Monster) func _process(delta): pass