Add KnockbackComponent and HazardComponent for enhanced enemy interactions; integrate knockback effects in DamageComponent
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=25 format=3 uid="uid://bockkmyn8il4c"]
|
||||
[gd_scene load_steps=26 format=3 uid="uid://bockkmyn8il4c"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://bs4xvm4qkurpr" path="res://shaders/hit_flash.tres" id="1_hh6y0"]
|
||||
[ext_resource type="Texture2D" uid="uid://duxx56wxmjoxd" path="res://sprites/basic_enemy.png" id="2_laaj3"]
|
||||
@@ -14,6 +14,7 @@
|
||||
[ext_resource type="AudioStream" uid="uid://b3tsqhr06pbrs" path="res://sfx/enemy_hurt.wav" id="14_ndloc"]
|
||||
[ext_resource type="AudioStream" uid="uid://dyev46uqusimi" path="res://sfx/shoot.wav" id="15_cg63s"]
|
||||
[ext_resource type="PackedScene" uid="uid://dx80ivlvuuew4" path="res://objects/fxs/fire_fx.tscn" id="16_jqaq6"]
|
||||
[ext_resource type="Script" uid="uid://cgfynrn68lp12" path="res://scripts/components/KnockbackComponent.cs" id="17_ih01d"]
|
||||
[ext_resource type="PackedScene" uid="uid://ck6nml06tm6ue" path="res://objects/fxs/ice_fx.tscn" id="17_o7qsb"]
|
||||
[ext_resource type="PackedScene" uid="uid://b12tppjkkqpt4" path="res://objects/fxs/hit_particles.tscn" id="18_v861c"]
|
||||
|
||||
@@ -172,3 +173,7 @@ visible = false
|
||||
[node name="HitParticles" parent="." instance=ExtResource("18_v861c")]
|
||||
position = Vector2(0, 1)
|
||||
process_material = SubResource("ParticleProcessMaterial_pxaaa")
|
||||
|
||||
[node name="KnockbackComponent" type="Node" parent="."]
|
||||
script = ExtResource("17_ih01d")
|
||||
metadata/_custom_type_script = "uid://cgfynrn68lp12"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=52 format=3 uid="uid://bqi5s710xb1ju"]
|
||||
[gd_scene load_steps=51 format=3 uid="uid://bqi5s710xb1ju"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://csel4s0e4g5uf" path="res://scripts/components/PlayerController.cs" id="1_yysbb"]
|
||||
[ext_resource type="Shader" uid="uid://bs4xvm4qkurpr" path="res://shaders/hit_flash.tres" id="2_lgb3u"]
|
||||
@@ -21,7 +21,6 @@
|
||||
[ext_resource type="Script" uid="uid://ccqb8kd5m0eh7" path="res://scripts/components/ScoreComponent.cs" id="11_o1ihh"]
|
||||
[ext_resource type="Script" uid="uid://dgb8bqcri7nsj" path="res://scripts/components/HealthComponent.cs" id="12_ur2y5"]
|
||||
[ext_resource type="Script" uid="uid://byw1legrv1ep2" path="res://scripts/components/PlayerDeathComponent.cs" id="13_7til7"]
|
||||
[ext_resource type="Script" uid="uid://cgfynrn68lp12" path="res://scripts/components/KnockbackComponent.cs" id="14_e5pae"]
|
||||
[ext_resource type="Script" uid="uid://cecelixl41t3j" path="res://scripts/components/InvulnerabilityComponent.cs" id="15_xuhvf"]
|
||||
[ext_resource type="Script" uid="uid://dvyd26ricriql" path="res://scripts/components/FlashingComponent.cs" id="16_uno3u"]
|
||||
[ext_resource type="Script" uid="uid://dtg6115je7b5s" path="res://scripts/components/StompDamageComponent.cs" id="17_bl1gx"]
|
||||
@@ -182,11 +181,6 @@ script = ExtResource("13_7til7")
|
||||
DeathSfx = NodePath("../sfx_hurt")
|
||||
HealthComponent = NodePath("../HealthComponent")
|
||||
|
||||
[node name="KnockbackComponent" type="Node" parent="." node_paths=PackedStringArray("HealthComponent")]
|
||||
script = ExtResource("14_e5pae")
|
||||
KnockbackForce = 1250.0
|
||||
HealthComponent = NodePath("../HealthComponent")
|
||||
|
||||
[node name="InvulnerabilityComponent" type="Node" parent="." node_paths=PackedStringArray("FlashingComponent")]
|
||||
script = ExtResource("15_xuhvf")
|
||||
FlashingComponent = NodePath("../FlashingComponent Base")
|
||||
|
41
objects/entities/cactus.tscn
Normal file
41
objects/entities/cactus.tscn
Normal file
@@ -0,0 +1,41 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://un55bdc2cg2q"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_1nndd"]
|
||||
[ext_resource type="Script" uid="uid://cgfynrn68lp12" path="res://scripts/components/KnockbackComponent.cs" id="2_bljtt"]
|
||||
[ext_resource type="Script" uid="uid://nhu2xd8611fk" path="res://scripts/components/HazardComponent.cs" id="3_bljtt"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_14ml2"]
|
||||
size = Vector2(14, 15)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4q8oh"]
|
||||
size = Vector2(16, 16)
|
||||
|
||||
[node name="Cactus" type="StaticBody2D"]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2(0, 0.5)
|
||||
shape = SubResource("RectangleShape2D_14ml2")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
texture = ExtResource("1_1nndd")
|
||||
hframes = 12
|
||||
vframes = 12
|
||||
frame = 71
|
||||
|
||||
[node name="Area2D" type="Area2D" parent="."]
|
||||
collision_mask = 12
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||
position = Vector2(-0.5, 0)
|
||||
shape = SubResource("RectangleShape2D_4q8oh")
|
||||
debug_color = Color(0.285572, 0.422655, 0.118384, 0.42)
|
||||
|
||||
[node name="KnockbackComponent" type="Node" parent="."]
|
||||
script = ExtResource("2_bljtt")
|
||||
metadata/_custom_type_script = "uid://cgfynrn68lp12"
|
||||
|
||||
[node name="HazardComponent" type="Node2D" parent="." node_paths=PackedStringArray("KnockbackComponent", "HazardArea")]
|
||||
script = ExtResource("3_bljtt")
|
||||
KnockbackComponent = NodePath("../KnockbackComponent")
|
||||
HazardArea = NodePath("../Area2D")
|
||||
metadata/_custom_type_script = "uid://nhu2xd8611fk"
|
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=27 format=3 uid="uid://bwdlmualj6xbw"]
|
||||
[gd_scene load_steps=28 format=3 uid="uid://bwdlmualj6xbw"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://bs4xvm4qkurpr" path="res://shaders/hit_flash.tres" id="1_ep4yr"]
|
||||
[ext_resource type="Texture2D" uid="uid://cu72810eyk4dx" path="res://sprites/enemy-robot.png" id="2_hjtwe"]
|
||||
@@ -18,6 +18,7 @@
|
||||
[ext_resource type="PackedScene" uid="uid://dx80ivlvuuew4" path="res://objects/fxs/fire_fx.tscn" id="15_mc6rj"]
|
||||
[ext_resource type="PackedScene" uid="uid://ck6nml06tm6ue" path="res://objects/fxs/ice_fx.tscn" id="16_68hnm"]
|
||||
[ext_resource type="PackedScene" uid="uid://b12tppjkkqpt4" path="res://objects/fxs/hit_particles.tscn" id="18_pxaaa"]
|
||||
[ext_resource type="Script" uid="uid://cgfynrn68lp12" path="res://scripts/components/KnockbackComponent.cs" id="19_xku20"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_pwwji"]
|
||||
size = Vector2(25, 31)
|
||||
@@ -182,3 +183,7 @@ visible = false
|
||||
[node name="HitParticles" parent="." instance=ExtResource("18_pxaaa")]
|
||||
position = Vector2(0, 1)
|
||||
process_material = SubResource("ParticleProcessMaterial_pxaaa")
|
||||
|
||||
[node name="KnockbackComponent" type="Node" parent="."]
|
||||
script = ExtResource("19_xku20")
|
||||
metadata/_custom_type_script = "uid://cgfynrn68lp12"
|
||||
|
@@ -53,15 +53,19 @@ ease = 2
|
||||
|
||||
[node name="Brick Player" parent="." instance=ExtResource("1_lbnsn")]
|
||||
|
||||
[node name="HitParticles" parent="Brick Player" index="26"]
|
||||
[node name="HitParticles" parent="Brick Player" index="24"]
|
||||
process_material = SubResource("ParticleProcessMaterial_lgb3u")
|
||||
|
||||
[node name="WorldEnvironment" parent="." instance=ExtResource("1_hb5r3")]
|
||||
|
||||
[node name="UI Layer" parent="." instance=ExtResource("2_lbnsn")]
|
||||
|
||||
[node name="Marketplace" parent="UI Layer" index="3" node_paths=PackedStringArray("SkillUnlockerComponent")]
|
||||
[node name="HUD" parent="UI Layer" index="0" node_paths=PackedStringArray("Health")]
|
||||
Health = NodePath("../../Brick Player/HealthComponent")
|
||||
|
||||
[node name="Marketplace" parent="UI Layer" index="3" node_paths=PackedStringArray("SkillUnlockerComponent", "ComponentsToDisable")]
|
||||
SkillUnlockerComponent = NodePath("../../Brick Player/SkillUnlockerComponent")
|
||||
ComponentsToDisable = [NodePath("../../Brick Player")]
|
||||
|
||||
[node name="Global Light" parent="." instance=ExtResource("3_3732a")]
|
||||
|
||||
|
@@ -62,10 +62,10 @@ ease = 2
|
||||
z_index = 1
|
||||
position = Vector2(-203, 9)
|
||||
|
||||
[node name="HitParticles" parent="Brick Player" index="25"]
|
||||
[node name="HitParticles" parent="Brick Player" index="24"]
|
||||
process_material = SubResource("ParticleProcessMaterial_lgb3u")
|
||||
|
||||
[node name="VisibleOnScreenNotifier2D" parent="Brick Player" index="28"]
|
||||
[node name="VisibleOnScreenNotifier2D" parent="Brick Player" index="27"]
|
||||
process_mode = 4
|
||||
|
||||
[node name="WorldEnvironment" parent="." instance=ExtResource("2_ot3dy")]
|
||||
|
@@ -12,11 +12,14 @@ public partial class DamageComponent : Node
|
||||
[Export] public Timer DamageTimer { get; set; }
|
||||
|
||||
private Node _currentTarget = null;
|
||||
private KnockbackComponent _knockbackComponent = null;
|
||||
|
||||
[Signal] public delegate void EffectInflictedEventHandler(Node2D target, StatusEffectDataResource effect);
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_knockbackComponent = Owner.GetNodeOrNull<KnockbackComponent>("KnockbackComponent");
|
||||
|
||||
if (Area != null)
|
||||
{
|
||||
Area.BodyEntered += OnAreaBodyEntered;
|
||||
@@ -93,6 +96,11 @@ public partial class DamageComponent : Node
|
||||
|
||||
DealDamage(health);
|
||||
|
||||
if (_knockbackComponent != null && body is CharacterBody2D characterBody && Owner is Node2D source)
|
||||
{
|
||||
_knockbackComponent.ApplyKnockback(characterBody, source);
|
||||
}
|
||||
|
||||
inv?.Activate();
|
||||
}
|
||||
|
||||
|
31
scripts/components/HazardComponent.cs
Normal file
31
scripts/components/HazardComponent.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Godot;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.components;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class HazardComponent : Node2D
|
||||
{
|
||||
[Export] public KnockbackComponent KnockbackComponent { get; set; }
|
||||
[Export] public Area2D HazardArea { get; set; }
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
if (KnockbackComponent == null)
|
||||
{
|
||||
GD.PrintErr("HazardComponent requires a KnockbackComponent to function properly.");
|
||||
SetProcess(false);
|
||||
return;
|
||||
}
|
||||
|
||||
HazardArea.BodyEntered += OnBodyEntered;
|
||||
}
|
||||
|
||||
private void OnBodyEntered(Node2D body)
|
||||
{
|
||||
GD.Print($"Node {body.Name} entered hazard area.");
|
||||
if (body is CharacterBody2D characterBody && Owner is Node2D source)
|
||||
{
|
||||
KnockbackComponent.ApplyKnockback(characterBody, source);
|
||||
}
|
||||
}
|
||||
}
|
1
scripts/components/HazardComponent.cs.uid
Normal file
1
scripts/components/HazardComponent.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://nhu2xd8611fk
|
@@ -5,45 +5,33 @@ namespace Mr.BrickAdventures.scripts.components;
|
||||
[GlobalClass]
|
||||
public partial class KnockbackComponent : Node
|
||||
{
|
||||
[Export] public CharacterBody2D Body { get; set; }
|
||||
[Export] public float KnockbackForce { get; set; } = 25f;
|
||||
[Export] public HealthComponent HealthComponent { get; set; }
|
||||
[Export] public float KnockbackForce { get; set; } = 400f;
|
||||
[Export] public float KnockbackDuration { get; set; } = 0.2f; // Duration in seconds
|
||||
|
||||
private bool _knockbackMode = false;
|
||||
private int _knockbackFrames = 0;
|
||||
|
||||
public override void _Ready()
|
||||
/// <summary>
|
||||
/// Applies a knockback force to a target body, pushing it away from a source.
|
||||
/// </summary>
|
||||
/// <param name="target">The CharacterBody2D to apply the knockback to.</param>
|
||||
/// <param name="source">The Node2D causing the knockback (e.g., the enemy, the cactus).</param>
|
||||
public void ApplyKnockback(CharacterBody2D target, Node2D source)
|
||||
{
|
||||
HealthComponent.HealthChanged += OnHealthChanged;
|
||||
if (target == null || source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
var direction = (target.GlobalPosition - source.GlobalPosition).Normalized();
|
||||
|
||||
if (direction == Vector2.Zero)
|
||||
{
|
||||
if (_knockbackMode) _knockbackFrames++;
|
||||
|
||||
if (_knockbackFrames <= 1) return;
|
||||
|
||||
_knockbackMode = false;
|
||||
_knockbackFrames = 0;
|
||||
direction = Vector2.Up;
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
if (_knockbackMode) ApplyKnockback((float)delta);
|
||||
}
|
||||
target.Velocity = direction * KnockbackForce;
|
||||
|
||||
private void OnHealthChanged(float delta, float totalHealth)
|
||||
{
|
||||
if (totalHealth <= 0f || delta >= 0f) return;
|
||||
|
||||
_knockbackMode = true;
|
||||
}
|
||||
|
||||
private void ApplyKnockback(float delta)
|
||||
{
|
||||
var velocity = Body.Velocity.Normalized();
|
||||
var knockbackDirection = new Vector2(Mathf.Sign(velocity.X), 0.4f);
|
||||
var knockbackVector = -knockbackDirection * KnockbackForce * delta;
|
||||
Body.Velocity += knockbackVector;
|
||||
var tween = CreateTween();
|
||||
tween.TweenProperty(target, "velocity", Vector2.Zero, KnockbackDuration)
|
||||
.SetEase(Tween.EaseType.Out)
|
||||
.SetTrans(Tween.TransitionType.Quad);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user