diff --git a/DungeonShooting_Art/effect/KnifeHit1.aseprite b/DungeonShooting_Art/effect/KnifeHit1.aseprite new file mode 100644 index 0000000..b13a3d7 --- /dev/null +++ b/DungeonShooting_Art/effect/KnifeHit1.aseprite Binary files differ diff --git a/DungeonShooting_Godot/prefab/FanCollisionShape.tscn b/DungeonShooting_Godot/prefab/FanCollisionShape.tscn new file mode 100644 index 0000000..b810a3e --- /dev/null +++ b/DungeonShooting_Godot/prefab/FanCollisionShape.tscn @@ -0,0 +1,4 @@ +[gd_scene format=2] + +[node name="FanCollisionShape" type="CollisionPolygon2D"] +polygon = PoolVector2Array( 0, -10, 5, -9, 9, -5, 10, 0, 9, 5, 5, 9, 0, 10 ) diff --git a/DungeonShooting_Godot/prefab/effect/Hit.tscn b/DungeonShooting_Godot/prefab/effect/Hit.tscn index 1549fc4..26e0459 100644 --- a/DungeonShooting_Godot/prefab/effect/Hit.tscn +++ b/DungeonShooting_Godot/prefab/effect/Hit.tscn @@ -1,23 +1,11 @@ -[gd_scene load_steps=8 format=2] +[gd_scene load_steps=3 format=2] -[ext_resource path="res://resource/sprite/effect/hit/hit2.png" type="Texture" id=1] -[ext_resource path="res://resource/sprite/effect/hit/hit1.png" type="Texture" id=2] -[ext_resource path="res://resource/sprite/effect/hit/hit4.png" type="Texture" id=3] -[ext_resource path="res://resource/sprite/effect/hit/hit0.png" type="Texture" id=4] -[ext_resource path="res://resource/sprite/effect/hit/hit3.png" type="Texture" id=5] +[ext_resource path="res://resource/effects/Hit.tres" type="SpriteFrames" id=1] [ext_resource path="res://src/game/effect/Hit.cs" type="Script" id=6] -[sub_resource type="SpriteFrames" id=1] -animations = [ { -"frames": [ ExtResource( 4 ), ExtResource( 2 ), ExtResource( 1 ), ExtResource( 5 ), ExtResource( 3 ) ], -"loop": true, -"name": "Hit", -"speed": 20.0 -} ] - [node name="Hit" type="AnimatedSprite"] z_index = 5 -frames = SubResource( 1 ) +frames = ExtResource( 1 ) animation = "Hit" offset = Vector2( 1, 11 ) script = ExtResource( 6 ) diff --git a/DungeonShooting_Godot/prefab/role/Enemy.tscn b/DungeonShooting_Godot/prefab/role/Enemy.tscn index c4fd32f..b24c830 100644 --- a/DungeonShooting_Godot/prefab/role/Enemy.tscn +++ b/DungeonShooting_Godot/prefab/role/Enemy.tscn @@ -23,7 +23,7 @@ [node name="AnimatedSprite" parent="." index="2"] material = SubResource( 2 ) -frame = 0 +frame = 2 [node name="ViewRay" type="RayCast2D" parent="." index="7"] position = Vector2( 0, -8 ) diff --git a/DungeonShooting_Godot/prefab/weapon/Knife.tscn b/DungeonShooting_Godot/prefab/weapon/Knife.tscn index 5e94459..d5628c3 100644 --- a/DungeonShooting_Godot/prefab/weapon/Knife.tscn +++ b/DungeonShooting_Godot/prefab/weapon/Knife.tscn @@ -1,7 +1,9 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=8 format=2] [ext_resource path="res://prefab/weapon/Weapon.tscn" type="PackedScene" id=1] +[ext_resource path="res://resource/sprite/gun/knife1.png" type="Texture" id=2] [ext_resource path="res://resource/materlal/Blend.gdshader" type="Shader" id=3] +[ext_resource path="res://prefab/FanCollisionShape.tscn" type="PackedScene" id=4] [sub_resource type="ShaderMaterial" id=2] resource_local_to_scene = true @@ -15,6 +17,14 @@ shader_param/shadowColor = Color( 1, 1, 1, 1 ) shader_param/schedule = 0.0 +[sub_resource type="SpriteFrames" id=4] +animations = [ { +"frames": [ ExtResource( 2 ) ], +"loop": true, +"name": "default", +"speed": 5.0 +} ] + [node name="Knife" instance=ExtResource( 1 )] [node name="ShadowSprite" parent="." index="0"] @@ -23,3 +33,14 @@ [node name="AnimatedSprite" parent="." index="1"] material = SubResource( 3 ) position = Vector2( 0, 0 ) +frames = SubResource( 4 ) + +[node name="HitArea" type="Area2D" parent="." index="4"] +collision_layer = 0 +collision_mask = 0 +monitoring = false +monitorable = false + +[node name="FanCollisionShape" parent="HitArea" index="0" instance=ExtResource( 4 )] +rotation = -1.5708 +scale = Vector2( 3, 3 ) diff --git a/DungeonShooting_Godot/resource/effects/KnifeHit1.tres b/DungeonShooting_Godot/resource/effects/KnifeHit1.tres new file mode 100644 index 0000000..70f5cf8 --- /dev/null +++ b/DungeonShooting_Godot/resource/effects/KnifeHit1.tres @@ -0,0 +1,35 @@ +[gd_resource type="SpriteFrames" load_steps=8 format=2] + +[ext_resource path="res://resource/sprite/effect/KnifeHit1.png" type="Texture" id=1] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 0, 0, 64, 68 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 64, 0, 64, 68 ) + +[sub_resource type="AtlasTexture" id=3] +atlas = ExtResource( 1 ) +region = Rect2( 128, 0, 64, 68 ) + +[sub_resource type="AtlasTexture" id=4] +atlas = ExtResource( 1 ) +region = Rect2( 192, 0, 64, 68 ) + +[sub_resource type="AtlasTexture" id=5] +atlas = ExtResource( 1 ) +region = Rect2( 256, 0, 64, 68 ) + +[sub_resource type="AtlasTexture" id=6] +atlas = ExtResource( 1 ) +region = Rect2( 320, 0, 64, 68 ) + +[resource] +animations = [ { +"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 4 ), SubResource( 5 ), SubResource( 6 ) ], +"loop": true, +"name": "default", +"speed": 30.0 +} ] diff --git a/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.aseprite b/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.aseprite new file mode 100644 index 0000000..8a8a0e3 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.aseprite Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.png b/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.png new file mode 100644 index 0000000..0c07004 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.png.import b/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.png.import new file mode 100644 index 0000000..626d1a0 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/effect/KnifeHit1.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/KnifeHit1.png-8ec1b83e3e29bcb0e825de1a30fc9c75.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/effect/KnifeHit1.png" +dest_files=[ "res://.import/KnifeHit1.png-8ec1b83e3e29bcb0e825de1a30fc9c75.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0 diff --git a/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs index 438910a..5ef38fb 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/Weapon.cs @@ -117,9 +117,7 @@ /// public bool IsActive => Master != null && Master.Holster.ActiveWeapon == this; - - - + //-------------------------------------------------------------------------------------------- //是否按下 @@ -629,6 +627,15 @@ } /// + /// 获取武器攻击的目标层级 + /// + /// + public uint GetAttackLayer() + { + return Master != null ? Master.AttackLayer : Role.DefaultAttackLayer; + } + + /// /// 返回弹药是否到达上限 /// public bool IsFullAmmo() diff --git a/DungeonShooting_Godot/src/game/item/weapon/bullet/Bullet.cs b/DungeonShooting_Godot/src/game/item/weapon/bullet/Bullet.cs index 048e65d..22e46ae 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/bullet/Bullet.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/bullet/Bullet.cs @@ -55,7 +55,7 @@ { if (other is Role role) { - role.Hit(1); + role.Hurt(1); } //播放受击动画 diff --git a/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs b/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs index c0eecc8..7a394ca 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/gun/Gun.cs @@ -120,7 +120,7 @@ Utils.RandRange(Attribute.MinDistance, Attribute.MaxDistance), FirePoint.GlobalPosition, fireRotation, - Master != null ? Master.AttackLayer : Role.DefaultAttackLayer + GetAttackLayer() ); bullet.PutDown(); } diff --git a/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs b/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs index e571048..4763747 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/gun/Shotgun.cs @@ -88,7 +88,7 @@ Utils.RandRange(Attribute.MinDistance, Attribute.MaxDistance), FirePoint.GlobalPosition, fireRotation + Utils.RandRange(-20 / 180f * Mathf.Pi, 20 / 180f * Mathf.Pi), - Master != null ? Master.AttackLayer : Role.DefaultAttackLayer + GetAttackLayer() ); bullet.PutDown(); } diff --git a/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs b/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs index 23c9ba2..72f0e7e 100644 --- a/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs +++ b/DungeonShooting_Godot/src/game/item/weapon/knife/Knife.cs @@ -26,26 +26,68 @@ MaxBacklash = -8; MinBacklash = -8; BacklashRegressionSpeed = 24; - UpliftAngle = -90; + UpliftAngle = -95; } } + + private Area2D _hitArea; + + private int _attackIndex = 0; public Knife(string id, WeaponAttribute attribute) : base(id, attribute) { - + _hitArea = GetNode("HitArea"); + _hitArea.Monitoring = false; + _hitArea.Monitorable = false; + + _hitArea.Connect("body_entered", this, nameof(OnBodyEntered)); } - + + public override void _Process(float delta) + { + base._Process(delta); + + if (IsActive) + { + //让碰撞节点与武器挂载节点位置保持一致, 而不跟着武器走 + _hitArea.GlobalPosition = Master.MountPoint.GlobalPosition; + } + } + + public override void _PhysicsProcess(float delta) + { + base._PhysicsProcess(delta); + + //过去两个物理帧后就能关闭碰撞了 + if (++_attackIndex >= 2) + { + _hitArea.Monitoring = false; + } + } + protected override void OnStartCharge() { + //开始蓄力时武器角度上抬120度 RotationDegrees = -120; } protected override void OnFire() { GD.Print("近战武器攻击! 蓄力时长: " + GetTriggerChargeTime() + ", 扳机按下时长: " + GetTriggerDownTime()); + //更新碰撞层级 + _hitArea.CollisionMask = GetAttackLayer(); + //启用碰撞 + _hitArea.Monitoring = true; + _attackIndex = 0; + + if (IsActive) //被使用 + { + //播放挥刀特效 + SpecialEffectManager.Play(ResourcePath.resource_effects_KnifeHit1_tres, "default", + Master.MountPoint.GlobalPosition, GlobalRotation + Mathf.Pi * 0.5f, new Vector2(0.8f * (int)Master.Face, 0.8f), new Vector2(17, 4), 1); + } - //这里写播放挥刀特效和碰撞检测代码 - + if (Master == GameApplication.Instance.Room.Player) { //创建抖动 @@ -63,4 +105,17 @@ //这里要做判断, 如果没有碰到敌人, 则不消耗弹药 (耐久) return 0; } + + private void OnBodyEntered(Node2D body) + { + GD.Print("碰到物体: " + body.Name); + var activityObject = body.AsActivityObject(); + if (activityObject != null) + { + if (activityObject is Role role) + { + role.Hurt(1); + } + } + } } diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs index 02d93ff..893d355 100644 --- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs +++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs @@ -10,6 +10,7 @@ public const string editor_prefabs_CodeHintPanel_tscn = "res://editor/prefabs/CodeHintPanel.tscn"; public const string editor_prefabs_CodePanel_tscn = "res://editor/prefabs/CodePanel.tscn"; public const string editor_prefabs_Editor_tscn = "res://editor/prefabs/Editor.tscn"; + public const string prefab_FanCollisionShape_tscn = "res://prefab/FanCollisionShape.tscn"; public const string prefab_effect_FirePart_tscn = "res://prefab/effect/FirePart.tscn"; public const string prefab_effect_Hit_tscn = "res://prefab/effect/Hit.tscn"; public const string prefab_role_CPlusPlus_tscn = "res://prefab/role/CPlusPlus.tscn"; @@ -26,6 +27,7 @@ public const string prefab_weapon_bullet_Bullet_tscn = "res://prefab/weapon/bullet/Bullet.tscn"; public const string prefab_weapon_shell_ShellCase_tscn = "res://prefab/weapon/shell/ShellCase.tscn"; public const string resource_effects_Hit_tres = "res://resource/effects/Hit.tres"; + public const string resource_effects_KnifeHit1_tres = "res://resource/effects/KnifeHit1.tres"; public const string resource_font_cn_font_12_tres = "res://resource/font/cn_font_12.tres"; public const string resource_font_cn_font_18_tres = "res://resource/font/cn_font_18.tres"; public const string resource_font_cn_font_35_tres = "res://resource/font/cn_font_35.tres"; @@ -38,6 +40,7 @@ public const string resource_sprite_bullet_arrow_png = "res://resource/sprite/bullet/arrow.png"; public const string resource_sprite_bullet_bullet_png = "res://resource/sprite/bullet/bullet.png"; public const string resource_sprite_bullet_bullet2_png = "res://resource/sprite/bullet/bullet2.png"; + public const string resource_sprite_effect_KnifeHit1_png = "res://resource/sprite/effect/KnifeHit1.png"; public const string resource_sprite_effect_Trajectory_png = "res://resource/sprite/effect/Trajectory.png"; public const string resource_sprite_effect_hit_hit0_png = "res://resource/sprite/effect/hit/hit0.png"; public const string resource_sprite_effect_hit_hit1_png = "res://resource/sprite/effect/hit/hit1.png"; diff --git a/DungeonShooting_Godot/src/game/manager/SpecialEffectManager.cs b/DungeonShooting_Godot/src/game/manager/SpecialEffectManager.cs index f71a6a7..0f58ee7 100644 --- a/DungeonShooting_Godot/src/game/manager/SpecialEffectManager.cs +++ b/DungeonShooting_Godot/src/game/manager/SpecialEffectManager.cs @@ -42,7 +42,7 @@ } /// - /// 在场景指定位置播放一个特效 + /// 在场景指定位置播放一个特效, 特效必须是 SpriteFrames 类型 /// /// 特效SpriteFrames资源路径 /// 动画名称 @@ -53,7 +53,7 @@ /// 层级 /// 播放速度 /// 循环次数, 到达该次数特效停止播放 - public static void Play(string path, string animName, Vector2 pos, float rotation, Vector2 scale, Vector2 offset, int zIndex, float speed = 1, int loopCount = 1) + public static void Play(string path, string animName, Vector2 pos, float rotation, Vector2 scale, Vector2 offset, int zIndex = 0, float speed = 1, int loopCount = 1) { var spriteFrames = ResourceManager.Load(path); diff --git a/DungeonShooting_Godot/src/game/role/FaceDirection.cs b/DungeonShooting_Godot/src/game/role/FaceDirection.cs index b6f34a7..0ed5025 100644 --- a/DungeonShooting_Godot/src/game/role/FaceDirection.cs +++ b/DungeonShooting_Godot/src/game/role/FaceDirection.cs @@ -3,6 +3,6 @@ /// public enum FaceDirection { - Left, - Right, + Left = -1, + Right = 1, } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/role/Role.cs b/DungeonShooting_Godot/src/game/role/Role.cs index 1cb7309..9336219 100644 --- a/DungeonShooting_Godot/src/game/role/Role.cs +++ b/DungeonShooting_Godot/src/game/role/Role.cs @@ -419,7 +419,7 @@ /// 受到伤害 /// /// 伤害的量 - public virtual void Hit(int damage) + public virtual void Hurt(int damage) { Hp -= damage; AnimationPlayer.Stop();