Added shield damage taken indicator to colliding with enemies; added

shaders to experiment with (disabled)
This commit is contained in:
Henry 2025-12-13 10:26:47 +00:00
parent bfe71e4908
commit 3bd16da435
8 changed files with 387 additions and 4 deletions

175
crt.gdshader Normal file
View file

@ -0,0 +1,175 @@
shader_type canvas_item;
// Add required screen texture uniform
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
// Display settings
uniform bool overlay = false;
uniform vec2 resolution = vec2(640.0, 480.0);
uniform float brightness = 1.4;
// Scanline settings
uniform float scanlines_opacity : hint_range(0.0, 1.0) = 0.4;
uniform float scanlines_width : hint_range(0.0, 0.5) = 0.25;
uniform float grille_opacity : hint_range(0.0, 1.0) = 0.3;
// Distortion settings
uniform bool roll = true;
uniform float roll_speed = 8.0;
uniform float roll_size : hint_range(0.0, 100.0) = 15.0;
uniform float roll_variation : hint_range(0.1, 5.0) = 1.8;
uniform float distort_intensity : hint_range(0.0, 0.2) = 0.05;
uniform float aberration : hint_range(-1.0, 1.0) = 0.03;
// Noise settings
uniform float noise_opacity : hint_range(0.0, 1.0) = 0.4;
uniform float noise_speed = 5.0;
uniform float static_noise_intensity : hint_range(0.0, 1.0) = 0.06;
// Additional effects
uniform bool pixelate = true;
uniform bool discolor = true;
uniform float warp_amount : hint_range(0.0, 5.0) = 1.0;
uniform bool clip_warp = false;
uniform float vignette_intensity = 0.4;
uniform float vignette_opacity : hint_range(0.0, 1.0) = 0.5;
// The rest of the shader code remains exactly the same from here...
// (All the functions and fragment shader code remain unchanged)
// Generate random value
vec2 random(vec2 uv) {
uv = vec2(dot(uv, vec2(127.1, 311.7)), dot(uv, vec2(269.5, 183.3)));
return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
}
// Generate noise
float noise(vec2 uv) {
vec2 uv_index = floor(uv);
vec2 uv_fract = fract(uv);
vec2 blur = smoothstep(0.0, 1.0, uv_fract);
return mix(
mix(
dot(random(uv_index + vec2(0.0, 0.0)), uv_fract - vec2(0.0, 0.0)),
dot(random(uv_index + vec2(1.0, 0.0)), uv_fract - vec2(1.0, 0.0)),
blur.x
),
mix(
dot(random(uv_index + vec2(0.0, 1.0)), uv_fract - vec2(0.0, 1.0)),
dot(random(uv_index + vec2(1.0, 1.0)), uv_fract - vec2(1.0, 1.0)),
blur.x
),
blur.y
) * 0.5 + 0.5;
}
// Screen warping
vec2 warp(vec2 uv) {
vec2 delta = uv - 0.5;
float delta2 = dot(delta.xy, delta.xy);
float delta4 = delta2 * delta2;
return uv + delta * (delta4 * warp_amount);
}
// Screen border
float border(vec2 uv) {
float radius = min(warp_amount, 0.08);
radius = max(min(min(abs(radius * 2.0), abs(1.0)), abs(1.0)), 1e-5);
vec2 abs_uv = abs(uv * 2.0 - 1.0) - vec2(1.0, 1.0) + radius;
float dist = length(max(vec2(0.0), abs_uv)) / radius;
return clamp(1.0 - smoothstep(0.96, 1.0, dist), 0.0, 1.0);
}
// Vignette effect
float vignette(vec2 uv) {
uv *= 1.0 - uv.xy;
float vig = uv.x * uv.y * 15.0;
return pow(vig, vignette_intensity * vignette_opacity);
}
void fragment() {
// Get base UV and handle overlay
vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV);
vec2 text_uv = uv;
// Handle pixelation
if (pixelate) {
text_uv = ceil(uv * resolution) / resolution;
}
// Calculate roll effect
float roll_line = 0.0;
vec2 roll_uv = vec2(0.0);
if (roll || noise_opacity > 0.0) {
float time = roll ? TIME : 0.0;
roll_line = smoothstep(0.3, 0.9, sin(uv.y * roll_size - (time * roll_speed)));
roll_line *= roll_line * smoothstep(0.3, 0.9, sin(uv.y * roll_size * roll_variation - (time * roll_speed * roll_variation)));
roll_uv = vec2(roll_line * distort_intensity * (1.0 - UV.x), 0.0);
}
// Sample texture with chromatic aberration
vec4 text;
if (roll) {
text.r = texture(SCREEN_TEXTURE, text_uv + roll_uv * 0.8 + vec2(aberration, 0.0) * 0.1).r;
text.g = texture(SCREEN_TEXTURE, text_uv + roll_uv * 1.2 - vec2(aberration, 0.0) * 0.1).g;
text.b = texture(SCREEN_TEXTURE, text_uv + roll_uv).b;
} else {
text.r = texture(SCREEN_TEXTURE, text_uv + vec2(aberration, 0.0) * 0.1).r;
text.g = texture(SCREEN_TEXTURE, text_uv - vec2(aberration, 0.0) * 0.1).g;
text.b = texture(SCREEN_TEXTURE, text_uv).b;
}
text.a = 1.0;
// Apply CRT grille
if (grille_opacity > 0.0) {
float gr = smoothstep(0.85, 0.95, abs(sin(uv.x * (resolution.x * 3.14159265))));
float gg = smoothstep(0.85, 0.95, abs(sin(1.05 + uv.x * (resolution.x * 3.14159265))));
float gb = smoothstep(0.85, 0.95, abs(sin(2.1 + uv.x * (resolution.x * 3.14159265))));
text.r = mix(text.r, text.r * gr, grille_opacity);
text.g = mix(text.g, text.g * gg, grille_opacity);
text.b = mix(text.b, text.b * gb, grille_opacity);
}
// Apply brightness
text.rgb = clamp(text.rgb * brightness, 0.0, 1.0);
// Apply scanlines
if (scanlines_opacity > 0.0) {
float scan = smoothstep(scanlines_width, scanlines_width + 0.5, abs(sin(uv.y * (resolution.y * 3.14159265))));
text.rgb = mix(text.rgb, text.rgb * vec3(scan), scanlines_opacity);
}
// Apply noise
if (noise_opacity > 0.0) {
float n = smoothstep(0.4, 0.5, noise(uv * vec2(2.0, 200.0) + vec2(10.0, TIME * noise_speed)));
float nl = n * roll_line * clamp(random((ceil(uv * resolution) / resolution) + vec2(TIME * 0.8, 0.0)).x + 0.8, 0.0, 1.0);
text.rgb = clamp(mix(text.rgb, text.rgb + nl, noise_opacity), vec3(0.0), vec3(1.0));
}
// Apply static
if (static_noise_intensity > 0.0) {
text.rgb += clamp(random((ceil(uv * resolution) / resolution) + fract(TIME)).x, 0.0, 1.0) * static_noise_intensity;
}
// Apply border and vignette
text.rgb *= border(uv);
text.rgb *= vignette(uv);
// Handle clip warp
if (clip_warp) {
text.a = border(uv);
}
// Apply VHS discoloration
if (discolor) {
vec3 greyscale = vec3(dot(text.rgb, vec3(0.333)));
text.rgb = mix(text.rgb, greyscale, 0.5);
float midpoint = pow(0.5, 2.2);
text.rgb = (text.rgb - vec3(midpoint)) * 1.2 + midpoint;
}
COLOR = text;
}

1
crt.gdshader.uid Normal file
View file

@ -0,0 +1 @@
uid://c4jtlpwspb778

51
explosion.tscn Normal file
View file

@ -0,0 +1,51 @@
[gd_scene load_steps=5 format=3 uid="uid://4jvu41vu2557"]
[ext_resource type="Texture2D" uid="uid://h04wm5a27u0" path="res://Mini Pixel Pack 3/Effects/Explosion (16 x 16).png" id="1_q7epf"]
[sub_resource type="Animation" id="Animation_vxas0"]
resource_name = "explosion-one-shot"
length = 0.5
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.3, 0.4, 0.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [0, 1, 3, 4, 5]
}
[sub_resource type="Animation" id="Animation_j4sxf"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_m5xho"]
_data = {
&"RESET": SubResource("Animation_j4sxf"),
&"explosion-one-shot": SubResource("Animation_vxas0")
}
[node name="Explosion" type="Sprite2D"]
texture = ExtResource("1_q7epf")
hframes = 6
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_m5xho")
}
autoplay = "explosion-one-shot"

View file

@ -1,12 +1,15 @@
[gd_scene load_steps=10 format=3 uid="uid://cc2dnhuv4qx7m"]
[gd_scene load_steps=13 format=3 uid="uid://cc2dnhuv4qx7m"]
[ext_resource type="Script" uid="uid://c51huloycn5as" path="res://main.gd" id="1_h2yge"]
[ext_resource type="Texture2D" uid="uid://jj8b7vqj3ihx" path="res://Mini Pixel Pack 3/Space_BG (2 frames) (64 x 64).png" id="1_ig7tw"]
[ext_resource type="PackedScene" uid="uid://pyuorpwb7lpe" path="res://player.tscn" id="2_0xm2m"]
[ext_resource type="Shader" uid="uid://c4jtlpwspb778" path="res://crt.gdshader" id="3_272bh"]
[ext_resource type="PackedScene" uid="uid://s6wf3egdqtmh" path="res://ui.tscn" id="4_1bvp3"]
[ext_resource type="Texture2D" uid="uid://bonoqs5pisflo" path="res://Mini Pixel Pack 3/UI objects/START (48 x 8).png" id="5_lquwl"]
[ext_resource type="Texture2D" uid="uid://bubqwoum50gf8" path="res://Mini Pixel Pack 3/UI objects/GAME_OVER (72 x 8).png" id="6_7mycd"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_5vw27"]
[sub_resource type="Animation" id="Animation_1bvp3"]
length = 0.001
tracks/0/type = "value"
@ -45,11 +48,37 @@ _data = {
&"scroll": SubResource("Animation_h2yge")
}
[sub_resource type="ShaderMaterial" id="ShaderMaterial_kek77"]
shader = ExtResource("3_272bh")
shader_parameter/overlay = true
shader_parameter/resolution = Vector2(640, 480)
shader_parameter/brightness = 1.4
shader_parameter/scanlines_opacity = 0.530000025175
shader_parameter/scanlines_width = 0.2370000112575
shader_parameter/grille_opacity = 0.3
shader_parameter/roll = false
shader_parameter/roll_speed = 4.0
shader_parameter/roll_size = 5.0000002375
shader_parameter/roll_variation = 0.90200003958512
shader_parameter/distort_intensity = 0.0
shader_parameter/aberration = 0.03
shader_parameter/noise_opacity = 0.4
shader_parameter/noise_speed = 5.0
shader_parameter/static_noise_intensity = 0.06
shader_parameter/pixelate = true
shader_parameter/discolor = true
shader_parameter/warp_amount = 0.0
shader_parameter/clip_warp = false
shader_parameter/vignette_intensity = 0.4
shader_parameter/vignette_opacity = 0.1750000083125
[node name="Main" type="Node2D"]
script = ExtResource("1_h2yge")
[node name="background" type="Sprite2D" parent="."]
z_index = -4
texture_repeat = 2
material = SubResource("ShaderMaterial_5vw27")
texture = ExtResource("1_ig7tw")
centered = false
region_enabled = true
@ -83,6 +112,12 @@ texture_normal = ExtResource("5_lquwl")
layout_mode = 2
texture = ExtResource("6_7mycd")
[node name="Sprite2D" type="Sprite2D" parent="."]
material = SubResource("ShaderMaterial_kek77")
position = Vector2(120, 161.5)
scale = Vector2(1.859375, 5.015625)
texture = ExtResource("1_ig7tw")
[connection signal="died" from="Player" to="." method="_on_player_died"]
[connection signal="shield_changed" from="Player" to="CanvasLayer/UI" method="update_shield"]
[connection signal="pressed" from="CanvasLayer/CenterContainer/Start" to="." method="_on_start_pressed"]

View file

@ -19,7 +19,8 @@ func _ready():
start()
func start():
show()
set_process(true)
$Ship.show()
shield = max_shield
position = Vector2(screensize.x / 2, screensize.y - 64)
$GunCooldown.wait_time = cooldown
@ -28,7 +29,11 @@ func set_shield(value):
shield = min(max_shield, value)
shield_changed.emit(max_shield, shield)
if shield <= 0:
hide()
set_process(false)
$Ship.hide()
$Explosion.show()
$Explosion/AnimationPlayer.play("explosion-one-shot")
await $Explosion/AnimationPlayer.animation_finished
died.emit()
func shoot():
@ -66,6 +71,7 @@ func _on_area_entered(area):
if area.is_in_group("enemies"):
area.explode()
shield -= max_shield / 2
damage_taken.emit()
if area.is_in_group("enemy_bullets"):
damage_taken.emit()

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=17 format=3 uid="uid://pyuorpwb7lpe"]
[gd_scene load_steps=18 format=3 uid="uid://pyuorpwb7lpe"]
[ext_resource type="Script" uid="uid://dcrnf4r6c5qaw" path="res://player.gd" id="1_sweqy"]
[ext_resource type="PackedScene" uid="uid://bwxxdrdvo3le0" path="res://bullet.tscn" id="2_1jxqw"]
@ -7,6 +7,7 @@
[ext_resource type="Shader" uid="uid://dfywtah53il1m" path="res://player_hit.gdshader" id="3_dw050"]
[ext_resource type="Texture2D" uid="uid://bjdhq42ummgky" path="res://Mini Pixel Pack 3/Player ship/Boosters_left (16 x 16).png" id="4_dw050"]
[ext_resource type="Texture2D" uid="uid://cjv3xbuj65pav" path="res://Mini Pixel Pack 3/Player ship/Boosters_right (16 x 16).png" id="5_b26j0"]
[ext_resource type="PackedScene" uid="uid://4jvu41vu2557" path="res://explosion.tscn" id="8_dw050"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_b26j0"]
shader = ExtResource("3_dw050")
@ -98,6 +99,9 @@ shape = SubResource("RectangleShape2D_op7ga")
[node name="GunCooldown" type="Timer" parent="."]
one_shot = true
[node name="Explosion" parent="." instance=ExtResource("8_dw050")]
visible = false
[connection signal="area_entered" from="." to="." method="_on_area_entered"]
[connection signal="damage_taken" from="." to="." method="_on_damage_taken"]
[connection signal="timeout" from="GunCooldown" to="." method="_on_gun_cool_down_timeout"]

110
starfield.gdshader Normal file
View file

@ -0,0 +1,110 @@
// Starfield shader v5 by Brian Smith (steampunkdemon.itch.io)
// MIT licence
shader_type canvas_item;
// Comment out the following line if you are not applying the shader to a ColorRect:
uniform vec2 dimensions = vec2(1024.0, 600.0); // Resolution of ColorRect in pixels
uniform float small_stars = 50.0; // Number of small stars. Rows for horizontally scrolling stars or columns for vertically scrolling stars.
uniform float small_stars_far_size : hint_range(0.1, 1.0, 0.1) = 0.5;
uniform float small_stars_near_size : hint_range(0.1, 1.0, 0.1) = 1.0;
uniform float large_stars = 8.0; // Number of large stars. Rows for horizontally scrolling stars or columns for vertically scrolling stars.
uniform float large_stars_far_size : hint_range(0.1, 1.0, 0.1) = 0.5;
uniform float large_stars_near_size : hint_range(0.1, 1.0, 0.1) = 1.0;
// Replace the below references to 'source_color' with 'hint_color' if you are using a version of Godot before 4.
uniform vec4 far_stars_color : source_color = vec4(0.50, 0.0, 1.0, 1.0);
uniform vec4 near_stars_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
// Remove the below references to ': source_color, filter_nearest_mipmap' if you are using a version of Godot before 4.
uniform sampler2D small_stars_texture : source_color, filter_nearest_mipmap;
uniform sampler2D large_stars_texture : source_color, filter_nearest_mipmap;
uniform float base_scroll_speed : hint_range(0.0, 1.0, 0.01) = 0.05;
uniform float additional_scroll_speed : hint_range(0.01, 1.0, 0.01) = 0.05;
float greater_than(float x, float y) {
return max(sign(x - y), 0.0);
}
void fragment() {
// The below line will scroll the stars from right to left or from bottom to top.
// To make the stars scroll in the opposite direction change the line to:
// float time = 10000.0 - TIME;
// Alternatively you can comment out the below line and add a new uniform above as:
// uniform float time = 10000.0;
// You can then update the time uniform from your _physics_process function by adding or subtracting delta. You can also pause the scrolling by not changing the time uniform.
float time = 10000.0 + TIME;
// Comment out the following two lines if you are not applying the shader to a TextureRect:
// COLOR = texture(TEXTURE,UV); // This line is only required if you are using a version of Godot before 4.
// vec2 dimensions = 1.0 / TEXTURE_PIXEL_SIZE;
// Horizontal scrolling:
float small_star_rn = fract(sin(floor(UV.y * small_stars)) * dimensions.y);
float large_star_rn = fract(sin(floor(UV.y * large_stars)) * dimensions.y);
vec2 small_star_uv = vec2(fract(UV.x + (base_scroll_speed + small_star_rn * additional_scroll_speed) * time) * small_stars * dimensions.x / dimensions.y, fract(UV.y * small_stars)) * 2.0 - 1.0;
vec2 large_star_uv = vec2(fract(UV.x + (base_scroll_speed + large_star_rn * additional_scroll_speed) * time) * large_stars * dimensions.x / dimensions.y, fract(UV.y * large_stars)) * 2.0 - 1.0;
// Vertical scrolling:
// float small_stars_rn = fract(sin(floor(UV.x * small_stars)) * dimensions.x);
// float large_stars_rn = fract(sin(floor(UV.x * large_stars)) * dimensions.x);
// vec2 small_stars_uv = vec2(fract(UV.x * small_stars), fract(UV.y + (base_scroll_speed + small_stars_rn * additional_scroll_speed) * time) * small_stars * dimensions.y / dimensions.x) * 2.0 - 1.0;
// vec2 large_stars_uv = vec2(fract(UV.x * large_stars), fract(UV.y + (base_scroll_speed + large_stars_rn * additional_scroll_speed) * time) * large_stars * dimensions.y / dimensions.x) * 2.0 - 1.0;
vec4 star_color = mix(far_stars_color, near_stars_color, small_star_rn);
float star_size = small_stars_far_size + (small_stars_near_size - small_stars_far_size) * small_star_rn;
// Render small stars as circles with soft edges:
COLOR.rgb = mix(COLOR.rgb, star_color.rgb, max((star_size - length(small_star_uv)) / star_size, 0.0) * star_color.a);
// Render small stars as circles with hard edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, greater_than(star_size, length(small_star_uv)) * star_color.a);
// Render small stars as crosses with soft edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, max((star_size - length(small_star_uv)) / star_size, 0.0) * (max(greater_than(star_size / 10.0, abs(small_star_uv.x)), greater_than(star_size / 10.0, abs(small_star_uv.y)))) * star_color.a);
// Render small stars as crosses with hard edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, max(greater_than(star_size / 5.0, abs(small_star_uv.x)) * greater_than(star_size, abs(small_star_uv.y)), greater_than(star_size / 5.0, abs(small_star_uv.y)) * greater_than(star_size, abs(small_star_uv.x))) * star_color.a);
// Render small stars as squares:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, greater_than(star_size, abs(small_star_uv.x)) * greater_than(star_size, abs(small_star_uv.y)) * star_color.a);
// Render small stars as diamonds:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, greater_than(star_size, abs(small_star_uv.y) + abs(small_star_uv.x)) * star_color.a);
// Render small stars using the 'small_stars_texture':
// The 'small_stars_texture' must have a border of blank transparent pixels.
// vec4 small_stars_texture_pixel = texture(small_stars_texture, (small_star_uv / (small_stars_far_size + (small_stars_near_size - small_stars_far_size) * small_star_rn) + 1.0) / 2.0) * mix(far_stars_color, near_stars_color, small_star_rn);
// COLOR.rgb = mix(COLOR.rgb, small_stars_texture_pixel.rgb, small_stars_texture_pixel.a);
star_color = mix(far_stars_color, near_stars_color, large_star_rn);
star_size = large_stars_far_size + (large_stars_near_size - large_stars_far_size) * large_star_rn;
// Render large stars as circles with soft edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, max((star_size - length(large_star_uv)) / star_size, 0.0) * star_color.a);
// Render large stars with circles and crosses with smooth edges:
COLOR.rgb = mix(COLOR.rgb, star_color.rgb, (max((star_size / 1.7 - length(large_star_uv)) / star_size, 0.0) + max((star_size - length(large_star_uv)) / star_size / 2.0, 0.0) * (max(greater_than(star_size / 10.0, abs(large_star_uv.x)), greater_than(star_size / 10.0, abs(large_star_uv.y))))) * star_color.a);
// Render large stars as circles with hard edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, greater_than(star_size, length(large_star_uv)) * star_color.a);
// Render large stars as crosses with soft edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, max((star_size - length(large_star_uv)) / star_size, 0.0) * (max(greater_than(star_size / 10.0, abs(large_star_uv.x)), greater_than(star_size / 10.0, abs(large_star_uv.y)))) * star_color.a);
// Render large stars as crosses with hard edges:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, max(greater_than(star_size / 5.0, abs(large_star_uv.x)) * greater_than(star_size, abs(large_star_uv.y)), greater_than(star_size / 5.0, abs(large_star_uv.y)) * greater_than(star_size, abs(large_star_uv.x))) * star_color.a);
// Render large stars as squares:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, greater_than(star_size, abs(large_star_uv.x)) * greater_than(star_size, abs(large_star_uv.y)) * star_color.a);
// Render large stars as diamonds:
// COLOR.rgb = mix(COLOR.rgb, star_color.rgb, greater_than(star_size, abs(large_star_uv.y) + abs(large_star_uv.x)) * star_color.a);
// Render large stars using the 'large_stars_texture':
// The 'large_stars_texture' must have a border of blank transparent pixels.
// vec4 large_stars_texture_pixel = texture(large_stars_texture, (large_star_uv / (large_stars_far_size + (large_stars_near_size - large_stars_far_size) * large_star_rn) + 1.0) / 2.0) * mix(far_stars_color, near_stars_color, large_star_rn);
// COLOR.rgb = mix(COLOR.rgb, large_stars_texture_pixel.rgb, large_stars_texture_pixel.a);
}

1
starfield.gdshader.uid Normal file
View file

@ -0,0 +1 @@
uid://bs8uhiq3os0o6