From d5c81d658737a38b5d24af126f55efea0b7669e3 Mon Sep 17 00:00:00 2001 From: Zenny Date: Wed, 18 Sep 2024 16:45:00 -0700 Subject: [PATCH] Knockback tag implementation --- src/enemy/Enemy.cs | 19 ++++++++++++----- src/enemy/enemy_types/michael/Michael.tscn | 2 +- src/enemy/enemy_types/sproingy/Sproingy.tscn | 4 +++- src/enemy/state/EnemyLogic.Output.cs | 2 +- .../states/EnemyLogic.State.FollowPlayer.cs | 8 +++---- .../state/states/EnemyLogic.State.Idle.cs | 9 ++++---- src/items/throwable/Dissolve.gdshader | 21 ------------------- src/items/throwable/ThrowableItem.cs | 2 +- .../ThrownGeometricDice.tscn} | 16 +++++--------- src/items/{throwable => thrown}/ThrownItem.cs | 1 - src/map/dungeon/floors/Floor01.tscn | 1 + 11 files changed, 34 insertions(+), 51 deletions(-) delete mode 100644 src/items/throwable/Dissolve.gdshader rename src/items/{throwable/ThrownItem.tscn => thrown/ThrownGeometricDice.tscn} (66%) rename src/items/{throwable => thrown}/ThrownItem.cs (96%) diff --git a/src/enemy/Enemy.cs b/src/enemy/Enemy.cs index 02326b9f..d93ee028 100644 --- a/src/enemy/Enemy.cs +++ b/src/enemy/Enemy.cs @@ -6,7 +6,7 @@ using Godot; namespace GameJamDungeon; -public interface IEnemy : ICharacterBody3D +public interface IEnemy : IRigidBody3D { public IEnemyLogic EnemyLogic { get; } @@ -22,7 +22,7 @@ public interface IEnemy : ICharacterBody3D } [Meta(typeof(IAutoNode))] -public partial class Enemy : CharacterBody3D, IEnemy, IProvide +public partial class Enemy : RigidBody3D, IEnemy, IProvide { public override void _Notification(int what) => this.Notify(what); @@ -69,6 +69,9 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide private const string ATTACK_FORWARD = "attack"; + private float _knockbackStrength = 0.0f; + private Vector3 _knockbackDirection = Vector3.Zero; + public void Setup() { EnemyLogic = new EnemyLogic(); @@ -128,7 +131,8 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide .Handle((in EnemyLogic.Output.MovementComputed output) => { RotateEnemy(-GameRepo.PlayerGlobalTransform.Value.Basis.Z); - MoveAndSlide(); + _knockbackStrength = _knockbackStrength * 0.9f; + MoveAndCollide(output.LinearVelocity + (_knockbackDirection * _knockbackStrength)); }) .Handle((in EnemyLogic.Output.HitByPlayer output) => { @@ -138,6 +142,11 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide // TODO: Make this an event to notify game that player hit someone if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.SelfDamage)) GameRepo.PlayerData.SetCurrentHP(GameRepo.PlayerData.CurrentHP.Value - 5); + if (GameRepo.PlayerData.Inventory.EquippedWeapon.Value.WeaponStats.WeaponTags.Contains(WeaponTag.Knockback)) + { + _knockbackDirection = -GameRepo.PlayerGlobalTransform.Value.Basis.Z.Normalized(); + _knockbackStrength = 0.3f; + } }) .Handle((in EnemyLogic.Output.Attack _) => { @@ -265,9 +274,9 @@ public partial class Enemy : CharacterBody3D, IEnemy, IProvide AnimationTree.Get("parameters/playback").As().Travel("idle_back_walk"); else { - // If the dot product of the perpendicular dot product is positive (up to 1), the enemy is facing to the left (since it's mirrored). + // If the dot product of the perpendicular direction is positive (up to 1), the enemy is facing to the left (since it's mirrored). AnimatedSprite.FlipH = leftDotProduct > 0; - // Check is side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning. + // Check if side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning. if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold) AnimationTree.Get("parameters/playback").As().Travel("idle_left_walk"); } diff --git a/src/enemy/enemy_types/michael/Michael.tscn b/src/enemy/enemy_types/michael/Michael.tscn index 52f82db9..eb445fd3 100644 --- a/src/enemy/enemy_types/michael/Michael.tscn +++ b/src/enemy/enemy_types/michael/Michael.tscn @@ -576,7 +576,7 @@ states/idle_left_walk/position = Vector2(331, 196.947) transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")] graph_offset = Vector2(-190, -62.0526) -[node name="Michael" type="CharacterBody3D"] +[node name="Michael" type="RigidBody3D"] process_mode = 1 collision_layer = 10 collision_mask = 11 diff --git a/src/enemy/enemy_types/sproingy/Sproingy.tscn b/src/enemy/enemy_types/sproingy/Sproingy.tscn index 947e73e2..1ff8ca4d 100644 --- a/src/enemy/enemy_types/sproingy/Sproingy.tscn +++ b/src/enemy/enemy_types/sproingy/Sproingy.tscn @@ -524,12 +524,14 @@ states/idle_left_walk/position = Vector2(331, 196.947) transitions = ["Start", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_vljb2"), "idle_front_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_3xv6a"), "idle_left_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_0h1op"), "idle_front_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_361b7"), "idle_back_walk", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_wftla"), "idle_back_walk", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_gqqkl"), "idle_left_walk", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_5cj36"), "idle_front_walk", "attack", SubResource("AnimationNodeStateMachineTransition_4t05h"), "attack", "idle_front_walk", SubResource("AnimationNodeStateMachineTransition_8hgxu"), "attack", "idle_back_walk", SubResource("AnimationNodeStateMachineTransition_fq2yw"), "attack", "idle_left_walk", SubResource("AnimationNodeStateMachineTransition_yqm0k"), "idle_back_walk", "attack", SubResource("AnimationNodeStateMachineTransition_bmy1k"), "idle_left_walk", "attack", SubResource("AnimationNodeStateMachineTransition_mxl7w")] graph_offset = Vector2(-190, -62.0526) -[node name="Sproingy" type="CharacterBody3D"] +[node name="Sproingy" type="RigidBody3D"] process_mode = 1 collision_layer = 10 collision_mask = 11 axis_lock_linear_y = true axis_lock_angular_x = true +contact_monitor = true +max_contacts_reported = 1 script = ExtResource("1_7tinp") EnemyStatResource = SubResource("Resource_rxw8v") diff --git a/src/enemy/state/EnemyLogic.Output.cs b/src/enemy/state/EnemyLogic.Output.cs index 32a388af..ca46ccd6 100644 --- a/src/enemy/state/EnemyLogic.Output.cs +++ b/src/enemy/state/EnemyLogic.Output.cs @@ -8,7 +8,7 @@ namespace GameJamDungeon { public readonly record struct MoveTowardsPlayer(Vector3 TargetPosition); - public readonly record struct MovementComputed(); + public readonly record struct MovementComputed(Vector3 LinearVelocity); public readonly record struct HitByPlayer(double CurrentHP); diff --git a/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs b/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs index 0c0d935f..3dbed5b8 100644 --- a/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs +++ b/src/enemy/state/states/EnemyLogic.State.FollowPlayer.cs @@ -19,13 +19,13 @@ namespace GameJamDungeon enemy.NavAgent.TargetPosition = target; var targetPosition = enemy.NavAgent.GetNextPathPosition(); - enemy.Velocity = (targetPosition - enemy.GlobalTransform.Origin).Normalized() * 2f; - var lookAtDir = enemy.GlobalTransform.Origin - enemy.Velocity; + var velocity = (targetPosition - enemy.GlobalTransform.Origin).Normalized() * 2f * (float)delta; + var lookAtDir = enemy.GlobalTransform.Origin - velocity; var lookAtPosition = new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z); - if (!enemy.Velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition)) + if (!velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition)) enemy.LookAt(lookAtPosition); - Output(new Output.MovementComputed()); + Output(new Output.MovementComputed(velocity)); return ToSelf(); } diff --git a/src/enemy/state/states/EnemyLogic.State.Idle.cs b/src/enemy/state/states/EnemyLogic.State.Idle.cs index 6cfafa6a..5656edb0 100644 --- a/src/enemy/state/states/EnemyLogic.State.Idle.cs +++ b/src/enemy/state/states/EnemyLogic.State.Idle.cs @@ -20,15 +20,14 @@ public partial class EnemyLogic var delta = input.Delta; var enemy = Get(); var targetPosition = enemy.NavAgent.GetNextPathPosition(); - var velocity = (targetPosition - enemy.GlobalPosition).Normalized() * 1.0f; - enemy.Velocity = velocity; - var lookAtDir = enemy.GlobalTransform.Origin - enemy.Velocity; + var velocity = (targetPosition - enemy.GlobalPosition).Normalized() * 1.0f * (float)delta; + var lookAtDir = enemy.GlobalTransform.Origin - velocity; var lookAtPosition = new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z); - if (!enemy.Velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition)) + if (!velocity.IsEqualApprox(Vector3.Zero) && !enemy.GlobalPosition.IsEqualApprox(lookAtPosition)) enemy.LookAt(new Vector3(lookAtDir.X, enemy.GlobalPosition.Y, lookAtDir.Z)); - Output(new Output.MovementComputed()); + Output(new Output.MovementComputed(velocity)); return ToSelf(); } diff --git a/src/items/throwable/Dissolve.gdshader b/src/items/throwable/Dissolve.gdshader deleted file mode 100644 index 3a00f3c8..00000000 --- a/src/items/throwable/Dissolve.gdshader +++ /dev/null @@ -1,21 +0,0 @@ -shader_type canvas_item; - -float random(vec2 uv) { - return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 438.5453); -} - -uniform float sensitivity : hint_range(0.0, 1.0) = .5; - -void fragment() { - // Get size of texture in pixels - float size_x = float(textureSize(TEXTURE, 0).x); - float size_y = float(textureSize(TEXTURE, 0).y); - // - vec4 pixelColor = texture(TEXTURE, UV); - // Create a new "UV" which remaps every UV value to a snapped pixel value - vec2 UVr = vec2(floor(UV.x*size_x)/size_x, floor(UV.y*size_y)/size_y); - // Determine whether pixel should be visible or not - float visible = step(sensitivity, random(UVr)); - // Draw the pixel, or not depending on if it is visible or not - COLOR = vec4(pixelColor.r, pixelColor.g, pixelColor.b, min(visible, pixelColor.a)); -} \ No newline at end of file diff --git a/src/items/throwable/ThrowableItem.cs b/src/items/throwable/ThrowableItem.cs index 67149034..fd9b2a72 100644 --- a/src/items/throwable/ThrowableItem.cs +++ b/src/items/throwable/ThrowableItem.cs @@ -34,7 +34,7 @@ public partial class ThrowableItem : Node3D, IInventoryItem public void Throw(ThrowableItemStats throwableItemStats) { - var throwableScene = GD.Load("res://src/items/throwable/ThrownItem.tscn"); + var throwableScene = GD.Load("res://src/items/thrown/ThrownGeometricDice.tscn"); var throwable = throwableScene.Instantiate(); Game.AddChild(throwable); throwable.Throw(throwableItemStats); diff --git a/src/items/throwable/ThrownItem.tscn b/src/items/thrown/ThrownGeometricDice.tscn similarity index 66% rename from src/items/throwable/ThrownItem.tscn rename to src/items/thrown/ThrownGeometricDice.tscn index fb12d132..bb6e4924 100644 --- a/src/items/throwable/ThrownItem.tscn +++ b/src/items/thrown/ThrownGeometricDice.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=7 format=3 uid="uid://b1twcuneob5kt"] +[gd_scene load_steps=5 format=3 uid="uid://b1twcuneob5kt"] -[ext_resource type="Script" path="res://src/items/throwable/ThrownItem.cs" id="1_l0mpw"] -[ext_resource type="Shader" path="res://src/items/throwable/Dissolve.gdshader" id="2_lukp6"] -[ext_resource type="Texture2D" uid="uid://mi70lolgtf3n" path="res://src/items/throwable/textures/GEOMANCER-DICE.png" id="2_oyhi4"] +[ext_resource type="Script" path="res://src/items/thrown/ThrownItem.cs" id="1_ig3yn"] +[ext_resource type="Texture2D" uid="uid://mi70lolgtf3n" path="res://src/items/throwable/textures/GEOMANCER-DICE.png" id="2_ia1qk"] [sub_resource type="BoxShape3D" id="BoxShape3D_s4ym5"] size = Vector3(0.288967, 0.302734, 0.28064) @@ -10,10 +9,6 @@ size = Vector3(0.288967, 0.302734, 0.28064) [sub_resource type="ViewportTexture" id="ViewportTexture_vebu3"] viewport_path = NodePath("Sprite3D/SubViewport") -[sub_resource type="ShaderMaterial" id="ShaderMaterial_vnlpn"] -shader = ExtResource("2_lukp6") -shader_parameter/sensitivity = 0.0 - [node name="Hitbox" type="RigidBody3D"] collision_layer = 17 collision_mask = 16 @@ -21,7 +16,7 @@ mass = 0.001 gravity_scale = 0.0 contact_monitor = true max_contacts_reported = 1 -script = ExtResource("1_l0mpw") +script = ExtResource("1_ig3yn") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00739601, 0.0986328, 0.137878) @@ -41,8 +36,7 @@ size = Vector2i(100, 100) [node name="Sprite" type="Sprite2D" parent="Sprite3D/SubViewport"] unique_name_in_owner = true z_index = 100 -material = SubResource("ShaderMaterial_vnlpn") scale = Vector2(0.1, 0.1) -texture = ExtResource("2_oyhi4") +texture = ExtResource("2_ia1qk") centered = false flip_h = true diff --git a/src/items/throwable/ThrownItem.cs b/src/items/thrown/ThrownItem.cs similarity index 96% rename from src/items/throwable/ThrownItem.cs rename to src/items/thrown/ThrownItem.cs index b7e69c65..3c7cfe79 100644 --- a/src/items/throwable/ThrownItem.cs +++ b/src/items/thrown/ThrownItem.cs @@ -1,5 +1,4 @@ using Chickensoft.AutoInject; -using Chickensoft.GodotNodeInterfaces; using Chickensoft.Introspection; using GameJamDungeon; using Godot; diff --git a/src/map/dungeon/floors/Floor01.tscn b/src/map/dungeon/floors/Floor01.tscn index ebc00a43..00d0dcfd 100644 --- a/src/map/dungeon/floors/Floor01.tscn +++ b/src/map/dungeon/floors/Floor01.tscn @@ -30,3 +30,4 @@ corridor_room_scene = ExtResource("4_gni6i") dungeon_size = Vector3i(50, 1, 50) voxel_scale = Vector3(4, 4, 4) generate_on_ready = false +place_even_if_fail = true