shotgun effects (resolves #5)

- animations
- fires 3 pellets
- particles
- bassier and quieter sound
controller-support
HumanoidSandvichDispenser 2023-08-15 17:53:43 -07:00
parent f4be615635
commit 8d20d96059
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
11 changed files with 418 additions and 101 deletions

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://cb5olv6rxm4f1"
path="res://.godot/imported/shotgun-cycle.wav-798600074f1556e6a764fb8979bf11fd.sample"
[deps]
source_file="res://Assets/Sounds/shotgun-cycle.wav"
dest_files=["res://.godot/imported/shotgun-cycle.wav-798600074f1556e6a764fb8979bf11fd.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://25euyff77a4d"
path="res://.godot/imported/shell.png-576f7092ca803877a253aef907e954e9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Sprites/Misc/shell.png"
dest_files=["res://.godot/imported/shell.png-576f7092ca803877a253aef907e954e9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,55 @@
[gd_scene load_steps=9 format=3 uid="uid://da1do2r2pbayb"]
[ext_resource type="Script" path="res://Entities/Projectile.cs" id="1_seunk"]
[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="2_yu7xh"]
[ext_resource type="Shader" path="res://Shaders/SpeedLines.gdshader" id="3_eb2yu"]
[sub_resource type="CircleShape2D" id="CircleShape2D_mwhod"]
radius = 2.0
[sub_resource type="CanvasTexture" id="CanvasTexture_u1hr7"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_5wli7"]
shader = ExtResource("3_eb2yu")
shader_parameter/value_threshold = 0.5
shader_parameter/color_max = Color(1, 1, 1, 1)
shader_parameter/color_min = Color(1, 1, 1, 0)
shader_parameter/speed = 16.0
shader_parameter/stretch_factor = 8.0
shader_parameter/end_alpha_x = 0.0
shader_parameter/end_alpha_y = 0.1
[sub_resource type="FastNoiseLite" id="FastNoiseLite_qk51l"]
seed = 1
frequency = 0.1
fractal_octaves = 2
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_l6snh"]
width = 16
height = 4
noise = SubResource("FastNoiseLite_qk51l")
[node name="ShotgunPellet" type="RigidBody2D" node_paths=PackedStringArray("Hitbox")]
script = ExtResource("1_seunk")
ProjectileName = "Pellet"
Hitbox = NodePath("Hitbox")
[node name="Hitbox" parent="." instance=ExtResource("2_yu7xh")]
Knockback = 64.0
[node name="CollisionShape2D" parent="Hitbox" index="0"]
shape = SubResource("CircleShape2D_mwhod")
[node name="Sprite2D" type="Sprite2D" parent="."]
self_modulate = Color(0.105882, 0.0470588, 0.117647, 1)
scale = Vector2(4, 2)
texture = SubResource("CanvasTexture_u1hr7")
[node name="SpeedLines" type="Sprite2D" parent="."]
texture_repeat = 2
material = SubResource("ShaderMaterial_5wli7")
position = Vector2(-6, 0)
texture = SubResource("NoiseTexture2D_l6snh")
region_rect = Rect2(0, 0, 40.4088, 33.6735)
[editable path="Hitbox"]

View File

@ -7,6 +7,7 @@ public partial class ProjectileSpawner : Ranged
[Export]
public PackedScene Projectile { get; set; }
[ExportGroup("Projectile Overrides")]
[Export]
public bool ShouldOverrideProjectileDamage { get; set; } = true;
@ -16,12 +17,18 @@ public partial class ProjectileSpawner : Ranged
[Export]
public bool ShouldRotate { get; set; } = true;
public override void Attack()
[ExportGroup("Multishot")]
[Export]
public int ProjectileCount { get; set; } = 1;
[Export]
public float ProjectileAngleDeviation { get; set; }
private void SpawnProjectile(Scenes.Map map, Vector2 direction)
{
var map = Utils.World.Instance.CurrentMap;
var projectile = map.SpawnEntity<Entities.Projectile>(Projectile);
projectile.Hitbox.Faction = Character.Faction;
projectile.Direction = Character.Target.Normalized();
projectile.Direction = direction;
projectile.GlobalPosition = GlobalPosition;
if (ShouldOverrideVelocity)
@ -50,6 +57,38 @@ public partial class ProjectileSpawner : Ranged
}
}
}
public override void Attack()
{
Character.Inventory.EmitSignal("UsedItem", this);
var map = Utils.World.Instance.CurrentMap;
Vector2 target = Character.Target.Normalized();
// avoid unnecessary math if only spawning 1 projectile
if (ProjectileCount == 1)
{
SpawnProjectile(map, target);
return;
}
// example: 4 projectiles =
// i = 0 -> 1.5 theta
// i = 1 -> 0.5 theta
// i = 2 -> -0.5 theta
// i = 3 -> -1.5 theta
// i = x -> -x * 0.5 theta + max dev
float theta = Mathf.DegToRad(ProjectileAngleDeviation);
// maaax angle deviation = ((projectile count - 1) / 2) thetas
float maxAngleDeviations = ((ProjectileCount - 1) / 2);
for (int i = 0; i < ProjectileCount; i++)
{
float curDeviation = -i + maxAngleDeviations;
GD.Print(curDeviation);
SpawnProjectile(map, target.Rotated(curDeviation * theta));
}
}
}

View File

@ -1,75 +1,26 @@
[gd_scene load_steps=18 format=3 uid="uid://d1d4vg7we5rjr"]
[gd_scene load_steps=26 format=3 uid="uid://d1d4vg7we5rjr"]
[ext_resource type="Script" path="res://Items/Weapons/ProjectileSpawner.cs" id="1_4xyyt"]
[ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="2_ag6rd"]
[ext_resource type="PackedScene" uid="uid://bqvseo3sbs1aj" path="res://Entities/RailBeam.tscn" id="2_k2n4h"]
[ext_resource type="PackedScene" uid="uid://da1do2r2pbayb" path="res://Entities/ShotgunPellet.tscn" id="2_p3wx2"]
[ext_resource type="Script" path="res://State/Weapon/RangedIdleState.cs" id="3_dd6bh"]
[ext_resource type="Script" path="res://State/Weapon/RangedFireState.cs" id="4_bwqd6"]
[ext_resource type="Texture2D" uid="uid://b1omx2kdb2x1n" path="res://Assets/Sprites/Items/shotgun.png" id="5_g8d45"]
[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="6_va8ee"]
[ext_resource type="AudioStream" uid="uid://5fybh24xashp" path="res://Assets/Sounds/shotgun.wav" id="7_ucxp5"]
[ext_resource type="AudioStream" uid="uid://cb5olv6rxm4f1" path="res://Assets/Sounds/shotgun-cycle.wav" id="8_sfyq7"]
[ext_resource type="Texture2D" uid="uid://coarr28adgo1u" path="res://Assets/Sprites/Particles/point-light.png" id="9_xrus5"]
[ext_resource type="Texture2D" uid="uid://25euyff77a4d" path="res://Assets/Sprites/Misc/shell.png" id="10_vu81g"]
[ext_resource type="Script" path="res://Utils/CloneableParticles.cs" id="10_vx4wq"]
[sub_resource type="Animation" id="Animation_i0e06"]
resource_name = "fire"
[sub_resource type="CanvasTexture" id="CanvasTexture_wvatk"]
[sub_resource type="Animation" id="Animation_vijrc"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [Vector2(-4, 0), Vector2(0, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("GPUParticles2D:emitting")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.2),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
tracks/2/type = "audio"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("AudioStreamPlayer2D")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"clips": [{
"end_offset": 0.0,
"start_offset": 0.0,
"stream": ExtResource("7_ucxp5")
}],
"times": PackedFloat32Array(0)
}
tracks/2/use_blend = true
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite2D:rotation")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0.5, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.0, 6.28319]
}
[sub_resource type="Animation" id="Animation_sqn2o"]
resource_name = "idle"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:position")
tracks/0/path = NodePath("Anchor:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
@ -81,7 +32,7 @@ tracks/0/keys = {
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:rotation")
tracks/1/path = NodePath("Anchor:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
@ -90,13 +41,136 @@ tracks/1/keys = {
"update": 0,
"values": [0.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("PointLight2D:enabled")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_vijrc"]
length = 0.001
[sub_resource type="Animation" id="Animation_i0e06"]
resource_name = "fire"
length = 1.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:position")
tracks/0/path = NodePath("Anchor:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [Vector2(-4, 0), Vector2(0, 0)]
}
tracks/1/type = "audio"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("AudioStreamPlayer2D")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"clips": [{
"end_offset": 1.04,
"start_offset": 0.0,
"stream": ExtResource("7_ucxp5")
}],
"times": PackedFloat32Array(0)
}
tracks/1/use_blend = true
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Anchor:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1, 1.5),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [6.28319, 6.28319, 0.0]
}
tracks/3/type = "audio"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("AudioStreamPlayer2D2")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"clips": [{
"end_offset": 0.15,
"start_offset": 0.0,
"stream": ExtResource("8_sfyq7")
}],
"times": PackedFloat32Array(1)
}
tracks/3/use_blend = true
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("ShellParticles:emitting")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(1.1),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/5/type = "method"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("ShellParticles")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(1),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"restart"
}]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("PointLight2D:enabled")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
tracks/7/type = "method"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("GPUParticles2D")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"EmitOnWorld"
}]
}
[sub_resource type="Animation" id="Animation_sqn2o"]
resource_name = "idle"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Anchor:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
@ -108,24 +182,12 @@ tracks/0/keys = {
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("GPUParticles2D:emitting")
tracks/1/path = NodePath("Anchor:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
@ -138,39 +200,63 @@ _data = {
}
[sub_resource type="Gradient" id="Gradient_uphon"]
colors = PackedColorArray(1, 1, 1, 0.498039, 1, 1, 1, 0)
offsets = PackedFloat32Array(0, 0.237037, 1)
colors = PackedColorArray(2, 1.8, 1.25, 1, 1, 1, 1, 0.498039, 1, 1, 1, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_83h4s"]
gradient = SubResource("Gradient_uphon")
[sub_resource type="Curve" id="Curve_mqgo6"]
_data = [Vector2(0.5, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 2
_data = [Vector2(0, 0.8), 0.0, 0.0, 0, 0, Vector2(0.7, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.9), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_3omj5"]
curve = SubResource("Curve_mqgo6")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_uexo4"]
particle_flag_disable_z = true
direction = Vector3(0, -1, 0)
spread = 90.0
flatness = 1.0
gravity = Vector3(0, -4, 0)
initial_velocity_min = 3.0
initial_velocity_max = 4.0
initial_velocity_min = -8.0
initial_velocity_max = 24.0
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
scale_min = 0.1
scale_max = 0.1
scale_min = 0.75
scale_curve = SubResource("CurveTexture_3omj5")
color_ramp = SubResource("GradientTexture1D_83h4s")
[sub_resource type="Gradient" id="Gradient_jks7f"]
offsets = PackedFloat32Array(0, 0.5, 1)
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_eeskk"]
gradient = SubResource("Gradient_jks7f")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_rta5n"]
particle_flag_disable_z = true
direction = Vector3(-1, -2, 0)
spread = 10.0
gravity = Vector3(0, 64, 0)
initial_velocity_min = 16.0
initial_velocity_max = 32.0
angular_velocity_min = 30.0
angular_velocity_max = 60.0
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
scale_min = 2.0
scale_max = 2.0
color_ramp = SubResource("GradientTexture1D_eeskk")
[node name="Shotgun" type="Node2D" node_paths=PackedStringArray("StateMachine")]
y_sort_enabled = true
script = ExtResource("1_4xyyt")
Projectile = ExtResource("2_k2n4h")
Projectile = ExtResource("2_p3wx2")
ProjectileCount = 3
ProjectileAngleDeviation = 10.0
StateMachine = NodePath("State")
Damage = 20.0
UseTime = 1.0
InitialVelocity = 256.0
Damage = 12.0
UseTime = 1.5
InitialVelocity = 220.0
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
script = ExtResource("2_ag6rd")
@ -190,27 +276,62 @@ IdleState = NodePath("../Idle")
AnimationPlayer = NodePath("../../AnimationPlayer")
AnimationKey = "fire"
[node name="Sprite2D" type="Sprite2D" parent="."]
[node name="Anchor" type="Node2D" parent="."]
y_sort_enabled = true
[node name="Sprite2D" type="Sprite2D" parent="Anchor"]
y_sort_enabled = true
texture_filter = 1
position = Vector2(4.00001, 5.99998)
texture = ExtResource("5_g8d45")
centered = false
offset = Vector2(0, -2)
offset = Vector2(-4, -10)
[node name="Marker2D" type="Marker2D" parent="Anchor"]
[node name="YSortHint" type="Sprite2D" parent="Anchor"]
visible = false
position = Vector2(4.00001, 5.99998)
texture = SubResource("CanvasTexture_wvatk")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_si0kh")
}
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
volume_db = -2.0
max_distance = 256.0
bus = &"Effects"
[node name="AudioStreamPlayer2D2" type="AudioStreamPlayer2D" parent="."]
max_distance = 256.0
bus = &"Effects"
[node name="GPUParticles2D" type="GPUParticles2D" parent="."]
position = Vector2(16, -1)
position = Vector2(17, -3)
emitting = false
amount = 4
process_material = SubResource("ParticleProcessMaterial_uexo4")
texture = ExtResource("6_va8ee")
lifetime = 0.5
lifetime = 3.0
one_shot = true
preprocess = 0.1
explosiveness = 1.0
script = ExtResource("10_vx4wq")
[node name="ShellParticles" type="GPUParticles2D" parent="."]
position = Vector2(3, 0)
emitting = false
amount = 1
process_material = SubResource("ParticleProcessMaterial_rta5n")
texture = ExtResource("10_vu81g")
one_shot = true
explosiveness = 1.0
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
max_distance = 256.0
bus = &"Effects"
[node name="PointLight2D" type="PointLight2D" parent="."]
position = Vector2(8, 8)
enabled = false
color = Color(0.941176, 0.843137, 0.470588, 1)
energy = 0.25
texture = ExtResource("9_xrus5")
texture_scale = 0.25

View File

@ -0,0 +1,23 @@
shader_type canvas_item;
uniform float value_threshold : hint_range(0, 1, 0.1) = 0.5;
uniform vec4 color_max : source_color = vec4(1);
uniform vec4 color_min : source_color = vec4(0);
uniform float speed = 16;
uniform float stretch_factor = 256;
uniform float end_alpha_x = 0;
uniform float end_alpha_y = 0;
void fragment() {
vec4 tex = texture(TEXTURE, vec2((UV.x + TIME * speed) / stretch_factor, UV.y));
//vec4 tex = texture(TEXTURE, UV + vec2(4, 0) * TIME * speed);
vec4 color = tex;
if (tex.r < value_threshold) {
color = vec4(0);
} else {
color = mix(color_min, color_max, tex.r);
color.a = mix(end_alpha_x, color.a, UV.x);
color.a = mix(color.a, end_alpha_y, abs(0.5 - UV.y) * 2.0);
}
COLOR = color;
}

View File

@ -0,0 +1,21 @@
using Godot;
using SupaLidlGame.Extensions;
namespace SupaLidlGame.Utils;
public partial class CloneableParticles : GpuParticles2D
{
public void EmitOnWorld()
{
var world = this.GetWorld();
var entities = world.CurrentMap.Entities;
var clone = Duplicate() as GpuParticles2D;
clone.GlobalTransform = GlobalTransform;
entities.AddChild(clone);
clone.Emitting = true;
GetTree().CreateTimer(Lifetime).Timeout += () =>
{
clone?.QueueFree();
};
}
}