diff --git a/Zennysoft.Game.Ma/src/camera/ShakeCamera.cs b/Zennysoft.Game.Ma/src/camera/ShakeCamera.cs new file mode 100644 index 00000000..98972384 --- /dev/null +++ b/Zennysoft.Game.Ma/src/camera/ShakeCamera.cs @@ -0,0 +1,45 @@ +using Godot; + +public partial class ShakeCamera : Camera3D +{ + [Export] private double _shakeIntensity = 1.0; + + [Export] private double _maxX = 10; + [Export] private double _maxY = 10; + [Export] private double _maxZ = 5; + + [Export] private FastNoiseLite _noise; + [Export] private double _noiseSpeed = 50.0; + + private double _shake = 0.0; + private double _time = 0.0; + + private Vector3 _initialRotation; + + public override void _Ready() + { + _initialRotation = RotationDegrees; + } + + public override void _Process(double delta) + { + _time += delta; + _shake = Mathf.Max(_shake - delta * _shakeIntensity, 0.0); + + RotationDegrees = new Vector3( + (float)(_initialRotation.X + _maxX * Mathf.Pow(_shake, 2) * GetNoiseFromSeed(0)), + (float)(_initialRotation.Y + _maxY * Mathf.Pow(_shake, 2) * GetNoiseFromSeed(1)), + (float)(_initialRotation.Z + _maxZ * Mathf.Pow(_shake, 2) * GetNoiseFromSeed(2))); + } + + public void AddShake(float shakeAmount) + { + _shake = Mathf.Clamp(_shake + shakeAmount, 0.0, 1.0); + } + + private double GetNoiseFromSeed(int seed) + { + _noise.Seed = seed; + return _noise.GetNoise1D((float)(_time * _noiseSpeed)); + } +} diff --git a/Zennysoft.Game.Ma/src/camera/ShakeCamera.cs.uid b/Zennysoft.Game.Ma/src/camera/ShakeCamera.cs.uid new file mode 100644 index 00000000..b53e8ec6 --- /dev/null +++ b/Zennysoft.Game.Ma/src/camera/ShakeCamera.cs.uid @@ -0,0 +1 @@ +uid://bb36q1wpe0tlw diff --git a/Zennysoft.Game.Ma/src/camera/ShakeCamera.tscn b/Zennysoft.Game.Ma/src/camera/ShakeCamera.tscn new file mode 100644 index 00000000..1ef1d901 --- /dev/null +++ b/Zennysoft.Game.Ma/src/camera/ShakeCamera.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://didc6vnf5ftlg"] + +[ext_resource type="Script" uid="uid://bb36q1wpe0tlw" path="res://src/camera/ShakeCamera.cs" id="1_ubmds"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_ubmds"] +frequency = 0.08 +fractal_octaves = 4 + +[node name="Camera3D" type="Camera3D"] +cull_mask = 1048569 +doppler_tracking = 1 +fov = 52.0 +near = 0.01 +far = 9000.0 +script = ExtResource("1_ubmds") +_shakeIntensity = 1.8 +_maxX = 0.0 +_maxY = 5.0 +_noise = SubResource("FastNoiseLite_ubmds") +_noiseSpeed = 40.0 diff --git a/Zennysoft.Game.Ma/src/player/Player.cs b/Zennysoft.Game.Ma/src/player/Player.cs index 8d94ab8f..bde3ae64 100644 --- a/Zennysoft.Game.Ma/src/player/Player.cs +++ b/Zennysoft.Game.Ma/src/player/Player.cs @@ -76,6 +76,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide [Node] private IAnimationPlayer PlayerFXAnimations { get; set; } = default!; + [Node] private IAnimationPlayer TakeDamageAnimationPlayer { get; set; } = default!; + [Node] private Area3D Hitbox { get; set; } = default!; [Node] private Area3D CollisionDetector { get; set; } = default!; @@ -87,6 +89,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide [Node] private AudioStreamPlayer3D WalkSFX { get; set; } = default!; [Node] private CollisionShape3D MainCollision { get; set; } = default!; + + [Node] private ShakeCamera _camera3D { get; set; } = default!; #endregion @@ -168,7 +172,6 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide public void Activate() { - MainCollision.Disabled = false; SetProcessInput(true); SetPhysicsProcess(true); SetHealthTimerStatus(HealthTimerIsActive); @@ -176,7 +179,6 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide public void Deactivate() { - MainCollision.Disabled = true; SetProcessInput(false); SetPhysicsProcess(false); SetHealthTimerStatus(false); @@ -197,6 +199,8 @@ public partial class Player : CharacterBody3D, IPlayer, IProvide public void TakeDamage(AttackData damage) { + _camera3D.AddShake(1.0f); + TakeDamageAnimationPlayer.Play("take_damage"); var damageReceived = DamageCalculator.CalculateDamage(damage, DefenseComponent.CurrentDefense.Value + EquipmentComponent.BonusDefense, EquipmentComponent.ElementalResistance); HealthComponent.Damage(damageReceived); SfxDatabase.Instance.Play(SoundEffect.TakeDamage); diff --git a/Zennysoft.Game.Ma/src/player/Player.tscn b/Zennysoft.Game.Ma/src/player/Player.tscn index ae4da4a5..1a353aef 100644 --- a/Zennysoft.Game.Ma/src/player/Player.tscn +++ b/Zennysoft.Game.Ma/src/player/Player.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=59 format=3 uid="uid://cfecvvav8kkp6"] +[gd_scene load_steps=63 format=3 uid="uid://cfecvvav8kkp6"] [ext_resource type="Script" uid="uid://yxmiqy7i0t7r" path="res://src/player/Player.cs" id="1_xcol5"] +[ext_resource type="PackedScene" uid="uid://didc6vnf5ftlg" path="res://src/camera/ShakeCamera.tscn" id="2_jtmj1"] [ext_resource type="AudioStream" uid="uid://cth2xgoqhdf0m" path="res://src/audio/sfx/player_hit_wall.ogg" id="3_565yv"] [ext_resource type="Texture2D" uid="uid://c4ps26w7h3vpq" path="res://src/minimap/textures/player_map_icon.png" id="4_3ojaj"] [ext_resource type="Shader" uid="uid://dfk3eps71yyyl" path="res://src/player/InvertColors.gdshader" id="4_v5qoq"] @@ -14,7 +15,7 @@ height = 3.07596 [sub_resource type="ShaderMaterial" id="ShaderMaterial_jtmj1"] -[sub_resource type="QuadMesh" id="QuadMesh_v7rlw"] +[sub_resource type="QuadMesh" id="QuadMesh_ebyyx"] material = SubResource("ShaderMaterial_jtmj1") flip_faces = true size = Vector2(2, 2) @@ -353,6 +354,43 @@ _data = { &"normal_attack": SubResource("Animation_v5qoq") } +[sub_resource type="Animation" id="Animation_g183x"] +resource_name = "take_damage" +length = 0.1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("SubViewportContainer/SubViewport/ColorRect:color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.0333333, 0.0666667), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 0.623529), Color(1, 1, 1, 0)] +} + +[sub_resource type="Animation" id="Animation_ojh85"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("SubViewportContainer/SubViewport/ColorRect:color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_ojh85"] +_data = { +&"RESET": SubResource("Animation_ojh85"), +&"take_damage": SubResource("Animation_g183x") +} + [sub_resource type="AtlasTexture" id="AtlasTexture_v5qoq"] atlas = ExtResource("4_v7rlw") region = Rect2(0, 0, 512, 512) @@ -637,17 +675,14 @@ wait_time = 3.0 [node name="Camera" type="Node3D" parent="."] -[node name="Camera3D" type="Camera3D" parent="Camera"] -transform = Transform3D(1, 6.69803e-05, 0.000118449, -6.06525e-05, 0.998614, -0.052638, -0.000121811, 0.052638, 0.998614, 0.003, 1.2, -0.01) -cull_mask = 1048569 -doppler_tracking = 1 -fov = 52.0 -near = 0.01 -far = 9000.0 +[node name="Camera3D" parent="Camera" instance=ExtResource("2_jtmj1")] +unique_name_in_owner = true +transform = Transform3D(1, 6.69803e-05, 0.00011845, -6.06525e-05, 0.998614, -0.052638, -0.000121811, 0.052638, 0.998614, 0.003, 1.2, -0.01) +current = true [node name="MeshInstance3D" type="MeshInstance3D" parent="Camera/Camera3D"] extra_cull_margin = 16384.0 -mesh = SubResource("QuadMesh_v7rlw") +mesh = SubResource("QuadMesh_ebyyx") [node name="player_model" type="Node3D" parent="Camera"] transform = Transform3D(-0.015, 0, -2.26494e-09, 0, 0.015, 0, 2.26494e-09, 0, -0.015, 0, -0.268445, -0.00941753) @@ -741,6 +776,12 @@ libraries = { &"": SubResource("AnimationLibrary_ebyyx") } +[node name="TakeDamageAnimationPlayer" type="AnimationPlayer" parent="ScreenFX"] +unique_name_in_owner = true +libraries = { +&"": SubResource("AnimationLibrary_ojh85") +} + [node name="SubViewportContainer" type="SubViewportContainer" parent="ScreenFX"] custom_minimum_size = Vector2(1440, 1080) anchors_preset = -1 @@ -767,6 +808,14 @@ scale = Vector2(36.5, 36.5) sprite_frames = SubResource("SpriteFrames_ebyyx") animation = &"sample" +[node name="ColorRect" type="ColorRect" parent="ScreenFX/SubViewportContainer/SubViewport"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(1, 1, 1, 0) + [node name="HitWallSound" type="AudioStreamPlayer" parent="."] unique_name_in_owner = true bus = &"SFX"