Implement simple hit decals

- Give super soaker custom weapon properties
- Reduce speed at which Spread and recoil recovers
- Use LIFE_TIME and FADE_TIME constants
main
copygirl 4 years ago
parent b14d43b838
commit d66409ebae
  1. BIN
      gfx/hit_decal.png
  2. 34
      gfx/hit_decal.png.import
  3. 182
      scene/HitDecal.tscn
  4. 9
      scene/Player.tscn
  5. 4
      src/Items/Weapon.cs
  6. 22
      src/Objects/Bullet.cs
  7. 38
      src/Objects/HitDecal.cs

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/hit_decal.png-774262fc5a2cc970463c1e1e2886a094.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://gfx/hit_decal.png"
dest_files=[ "res://.import/hit_decal.png-774262fc5a2cc970463c1e1e2886a094.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
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

@ -0,0 +1,182 @@
[gd_scene load_steps=17 format=2]
[ext_resource path="res://gfx/hit_decal.png" type="Texture" id=1]
[ext_resource path="res://src/Objects/HitDecal.cs" type="Script" id=2]
[sub_resource type="VisualShaderNodeInput" id=15]
input_name = "modulate_color"
[sub_resource type="VisualShaderNodeInput" id=16]
input_name = "modulate_alpha"
[sub_resource type="VisualShaderNodeScalarOp" id=17]
operator = 2
[sub_resource type="VisualShaderNodeExpression" id=18]
size = Vector2( 512, 260 )
expression = "vec2 tex_size = vec2(textureSize(mask, 0));
vec2 pix_loc = uv.xy / TEXTURE_PIXEL_SIZE;
mask_uv = vec3((pix_loc + offset.xy) / tex_size, 0);
outside = mask_uv.x >= 0.0 && mask_uv.x <= 1.0 &&
mask_uv.y >= 0.0 && mask_uv.y <= 1.0;"
[sub_resource type="VisualShaderNodeInput" id=19]
input_name = "uv"
[sub_resource type="VisualShaderNodeScalarSwitch" id=20]
[sub_resource type="VisualShaderNodeVectorOp" id=21]
operator = 2
[sub_resource type="VisualShaderNodeTexture" id=22]
source = 5
[sub_resource type="VisualShaderNodeInput" id=23]
input_name = "texture"
[sub_resource type="VisualShaderNodeScalarOp" id=24]
operator = 2
[sub_resource type="VisualShaderNodeVec3Uniform" id=25]
uniform_name = "offset"
[sub_resource type="VisualShaderNodeTextureUniform" id=26]
uniform_name = "mask"
[sub_resource type="VisualShader" id=27]
code = "shader_type canvas_item;
uniform vec3 offset;
uniform sampler2D mask;
void vertex() {
// Output:0
}
void fragment() {
// Input:10
vec3 n_out10p0 = MODULATE.rgb;
// Input:3
// Texture:2
vec3 n_out2p0;
float n_out2p1;
{
vec4 TEXTURE_tex_read = texture(TEXTURE, UV.xy);
n_out2p0 = TEXTURE_tex_read.rgb;
n_out2p1 = TEXTURE_tex_read.a;
}
// VectorOp:18
vec3 n_out18p0 = n_out10p0 * n_out2p0;
// Input:13
float n_out13p0 = MODULATE.a;
// VectorUniform:7
vec3 n_out7p0 = offset;
// Input:16
vec3 n_out16p0 = vec3(UV, 0.0);
// Expression:15
vec3 n_out15p0;
bool n_out15p1;
n_out15p0 = vec3(0.0, 0.0, 0.0);
n_out15p1 = false;
{
vec2 tex_size = vec2(textureSize(mask, 0));
vec2 pix_loc = n_out16p0.xy / TEXTURE_PIXEL_SIZE;
n_out15p0 = vec3((pix_loc + n_out7p0.xy) / tex_size, 0);
n_out15p1 = n_out15p0.x >= 0.0 && n_out15p0.x <= 1.0 &&
n_out15p0.y >= 0.0 && n_out15p0.y <= 1.0;
}
// TextureUniform:8
vec3 n_out8p0;
float n_out8p1;
{
vec4 n_tex_read = texture(mask, n_out15p0.xy);
n_out8p0 = n_tex_read.rgb;
n_out8p1 = n_tex_read.a;
}
// ScalarSwitch:17
float n_in17p2 = 0.00000;
float n_out17p0;
if(n_out15p1)
{
n_out17p0 = n_out8p1;
}
else
{
n_out17p0 = n_in17p2;
}
// ScalarOp:6
float n_out6p0 = n_out2p1 * n_out17p0;
// ScalarOp:14
float n_out14p0 = n_out13p0 * n_out6p0;
// Output:0
COLOR.rgb = n_out18p0;
COLOR.a = n_out14p0;
}
void light() {
// Output:0
}
"
graph_offset = Vector2( 341, -275 )
mode = 1
flags/light_only = false
nodes/fragment/0/position = Vector2( 840, -100 )
nodes/fragment/2/node = SubResource( 22 )
nodes/fragment/2/position = Vector2( 400, -40 )
nodes/fragment/3/node = SubResource( 23 )
nodes/fragment/3/position = Vector2( 220, -40 )
nodes/fragment/6/node = SubResource( 24 )
nodes/fragment/6/position = Vector2( 640, 60 )
nodes/fragment/7/node = SubResource( 25 )
nodes/fragment/7/position = Vector2( -340, 60 )
nodes/fragment/8/node = SubResource( 26 )
nodes/fragment/8/position = Vector2( 400, 100 )
nodes/fragment/10/node = SubResource( 15 )
nodes/fragment/10/position = Vector2( 320, -200 )
nodes/fragment/13/node = SubResource( 16 )
nodes/fragment/13/position = Vector2( 320, -120 )
nodes/fragment/14/node = SubResource( 17 )
nodes/fragment/14/position = Vector2( 640, -60 )
nodes/fragment/15/node = SubResource( 18 )
nodes/fragment/15/position = Vector2( -140, 40 )
nodes/fragment/15/size = Vector2( 512, 260 )
nodes/fragment/15/input_ports = "0,1,offset;1,1,uv;"
nodes/fragment/15/output_ports = "0,1,mask_uv;1,2,outside;"
nodes/fragment/15/expression = "vec2 tex_size = vec2(textureSize(mask, 0));
vec2 pix_loc = uv.xy / TEXTURE_PIXEL_SIZE;
mask_uv = vec3((pix_loc + offset.xy) / tex_size, 0);
outside = mask_uv.x >= 0.0 && mask_uv.x <= 1.0 &&
mask_uv.y >= 0.0 && mask_uv.y <= 1.0;"
nodes/fragment/16/node = SubResource( 19 )
nodes/fragment/16/position = Vector2( -340, 140 )
nodes/fragment/17/node = SubResource( 20 )
nodes/fragment/17/position = Vector2( 620, 180 )
nodes/fragment/18/node = SubResource( 21 )
nodes/fragment/18/position = Vector2( 640, -180 )
nodes/fragment/connections = PoolIntArray( 3, 0, 2, 2, 2, 1, 6, 0, 6, 0, 14, 1, 13, 0, 14, 0, 14, 0, 0, 1, 7, 0, 15, 0, 16, 0, 15, 1, 15, 0, 8, 0, 15, 1, 17, 0, 8, 1, 17, 1, 17, 0, 6, 1, 10, 0, 18, 0, 2, 0, 18, 1, 18, 0, 0, 0 )
[sub_resource type="ShaderMaterial" id=14]
shader = SubResource( 27 )
shader_param/offset = Vector3( 0, 0, 0 )
[node name="HitDecal" type="Sprite"]
material = SubResource( 14 )
texture = ExtResource( 1 )
centered = false
script = ExtResource( 2 )

@ -157,6 +157,15 @@ texture = ExtResource( 10 )
offset = Vector2( 8, 0 ) offset = Vector2( 8, 0 )
script = ExtResource( 8 ) script = ExtResource( 8 )
Automatic = true Automatic = true
RateOfFire = 120
Capacity = 4
ReloadTime = 2.0
Knockback = 60.0
Spread = 3.0
SpreadIncrease = 10.0
BulletVelocity = 640
BulletsPerShot = 16
BulletOpacity = 0.06
[node name="Tip" type="Node2D" parent="Items/Super Soaker"] [node name="Tip" type="Node2D" parent="Items/Super Soaker"]
position = Vector2( 17, 0.5 ) position = Vector2( 17, 0.5 )

@ -66,8 +66,8 @@ public class Weapon : Sprite
public override void _Process(float delta) public override void _Process(float delta)
{ {
var spreadDecrease = Mathf.Max(Mathf.Tau / 300, _currentSpreadInc * 2); var spreadDecrease = Mathf.Max(Mathf.Tau / 200, _currentSpreadInc * 1.5F);
var recoilDecrease = Mathf.Max(Mathf.Tau / 800, _currentRecoil * 2); var recoilDecrease = Mathf.Max(Mathf.Tau / 600, _currentRecoil * 1.5F);
_currentSpreadInc = Mathf.Max(0, _currentSpreadInc - spreadDecrease * delta); _currentSpreadInc = Mathf.Max(0, _currentSpreadInc - spreadDecrease * delta);
_currentRecoil = Mathf.Max(0, _currentRecoil - recoilDecrease * delta); _currentRecoil = Mathf.Max(0, _currentRecoil - recoilDecrease * delta);

@ -3,7 +3,9 @@ using Godot;
public class Bullet : Node2D public class Bullet : Node2D
{ {
private static readonly TimeSpan TRAIL_DURATION = TimeSpan.FromSeconds(0.6); private static readonly TimeSpan LIFE_TIME = TimeSpan.FromSeconds(0.6);
private static readonly TimeSpan FADE_TIME = TimeSpan.FromSeconds(0.6);
private static readonly PackedScene HIT_DECAL = GD.Load<PackedScene>("res://scene/HitDecal.tscn");
public Vector2 Direction { get; } public Vector2 Direction { get; }
public int EffectiveRange { get; } public int EffectiveRange { get; }
@ -12,7 +14,7 @@ public class Bullet : Node2D
public Color Color { get; } public Color Color { get; }
private readonly Vector2 _startPosition; private readonly Vector2 _startPosition;
private TimeSpan _age; private TimeSpan _age = TimeSpan.Zero;
private float _distance; private float _distance;
public Bullet(Vector2 position, Vector2 direction, public Bullet(Vector2 position, Vector2 direction,
@ -26,6 +28,16 @@ public class Bullet : Node2D
Color = color; Color = color;
} }
protected void OnCollide(CollisionObject2D obj, Vector2 hitPosition)
{
var sprite = obj.GetNodeOrNull<Sprite>("Sprite");
if (sprite == null) return;
var hole = HIT_DECAL.Init<HitDecal>();
var color = new Color(Color, (1 + Color.a) / 2);
hole.Add(sprite, hitPosition, color);
}
public override void _Ready() public override void _Ready()
{ if (this.GetGame() is Server) Visible = false; } { if (this.GetGame() is Server) Visible = false; }
@ -33,8 +45,8 @@ public class Bullet : Node2D
{ {
_age += TimeSpan.FromSeconds(delta); _age += TimeSpan.FromSeconds(delta);
if (_age > TRAIL_DURATION) { if (_age > LIFE_TIME) {
Modulate = new Color(Modulate, Modulate.a - delta * 2); Modulate = new Color(Modulate, Modulate.a - delta / (float)FADE_TIME.TotalSeconds);
if (Modulate.a <= 0) this.RemoveFromParent(); if (Modulate.a <= 0) this.RemoveFromParent();
} }
} }
@ -50,6 +62,8 @@ public class Bullet : Node2D
if (collision.Count != 0) { if (collision.Count != 0) {
Position = (Vector2)collision["position"]; Position = (Vector2)collision["position"];
_distance = _startPosition.DistanceTo(Position); _distance = _startPosition.DistanceTo(Position);
var obj = (CollisionObject2D)collision["collider"];
OnCollide(obj, Position - obj.Position);
SetPhysicsProcess(false); SetPhysicsProcess(false);
} }

@ -0,0 +1,38 @@
using System;
using Godot;
// TODO: When spawned, add to multiple nearby sprites.
public class HitDecal : Sprite
{
private static readonly TimeSpan LIFE_TIME = TimeSpan.FromSeconds(5.0);
private static readonly TimeSpan FADE_TIME = TimeSpan.FromSeconds(5.0);
private TimeSpan _age = TimeSpan.Zero;
private float _fadeFactor;
public void Add(Sprite sprite, Vector2 hitVec, Color color)
{
Position = (hitVec - Texture.GetSize() / 2).Round();
var offset = Position + sprite.Texture.GetSize() / 2;
ShaderMaterial material;
Material = material = (ShaderMaterial)Material.Duplicate();
material.SetShaderParam("offset", new Vector3(offset.x, offset.y, 0));
material.SetShaderParam("mask", sprite.Texture);
Modulate = color;
_fadeFactor = color.a;
sprite.AddChild(this);
}
public override void _Process(float delta)
{
_age += TimeSpan.FromSeconds(delta);
if (_age > LIFE_TIME) {
var dec = delta / (float)FADE_TIME.TotalSeconds * _fadeFactor;
Modulate = new Color(Modulate, Modulate.a - dec);
if (Modulate.a <= 0) this.RemoveFromParent();
}
}
}
Loading…
Cancel
Save