diff --git a/project.godot b/project.godot index bd4754a..f7555ed 100644 --- a/project.godot +++ b/project.godot @@ -60,6 +60,11 @@ character_right={ , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null) ] } +flashlight_charge={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"echo":false,"script":null) +] +} [layer_names] diff --git a/scenes/main_scene.tscn b/scenes/main_scene.tscn index b9c6577..dfefed4 100644 --- a/scenes/main_scene.tscn +++ b/scenes/main_scene.tscn @@ -1,17 +1,25 @@ -[gd_scene load_steps=14 format=3 uid="uid://dhn7yt46fyac8"] +[gd_scene load_steps=17 format=3 uid="uid://dhn7yt46fyac8"] [ext_resource type="PackedScene" uid="uid://bhulqhxesd5gc" path="res://prefabs/player.tscn" id="1_65a7v"] [ext_resource type="Texture2D" uid="uid://py6qiu3rm7cu" path="res://sprites/brickwall.png" id="2_edqdh"] [ext_resource type="Texture2D" uid="uid://dlbl6d4yghvht" path="res://sprites/mask.png" id="3_8o315"] [ext_resource type="Script" path="res://scripts/Flashlight.cs" id="3_cylxo"] [ext_resource type="Material" uid="uid://xuvxq5hy1dt" path="res://shaders/light_shader_material.tres" id="4_ro05e"] +[ext_resource type="Shader" path="res://shaders/dithering.gdshader" id="5_64d71"] [ext_resource type="Script" path="res://scripts/GameCamera.cs" id="6_quua3"] [ext_resource type="Script" path="res://scripts/PointLight2DWorkaround.cs" id="6_slohe"] +[sub_resource type="Curve" id="Curve_o5byr"] +_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.0824742, 0.273684), -10.2105, 0.0, 0, 0, Vector2(0.242268, 0.494737), -5.10526, 0.0, 0, 0, Vector2(0.396907, 0.736842), -7.6579, 0.0, 0, 0, Vector2(0.737113, 1), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0] +point_count = 6 + [sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_wg1ao"] light_mode = 2 -[sub_resource type="ViewportTexture" id="ViewportTexture_dwy4p"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_m680d"] +shader = ExtResource("5_64d71") + +[sub_resource type="ViewportTexture" id="ViewportTexture_0u602"] viewport_path = NodePath("FlashlightViewport") [sub_resource type="CircleShape2D" id="CircleShape2D_prnh4"] @@ -31,16 +39,18 @@ y_sort_enabled = true [node name="Player" parent="." instance=ExtResource("1_65a7v")] position = Vector2(19, 4) -[node name="Controller" type="Node" parent="." node_paths=PackedStringArray("Player", "Camera", "Circle", "PlayerCircle", "Polygon", "CollisionCircle", "CollisionPlayerCircle", "CollisionPolygon")] +[node name="Controller" type="Node" parent="." node_paths=PackedStringArray("Player", "Camera", "Circle", "PlayerCircle", "Polygon", "CollisionCircle", "CollisionPlayerCircle", "CollisionPolygon", "FlashlightGroup")] script = ExtResource("3_cylxo") Player = NodePath("../Player") Camera = NodePath("../PlayerCamera") -Circle = NodePath("../FlashlightViewport/Circle") +Circle = NodePath("../FlashlightViewport/CanvasGroup/Circle") PlayerCircle = NodePath("../FlashlightViewport/PlayerCircle") -Polygon = NodePath("../FlashlightViewport/Triangle") +Polygon = NodePath("../FlashlightViewport/CanvasGroup/Triangle") CollisionCircle = NodePath("../PlayerCamera/Area2D/Circle") CollisionPlayerCircle = NodePath("../PlayerCamera/Area2D/PlayerCircle") CollisionPolygon = NodePath("../PlayerCamera/Area2D/CollisionPolygon2D") +FlashlightGroup = NodePath("../FlashlightViewport/CanvasGroup") +BrightnessCurve = SubResource("Curve_o5byr") [node name="TestWall" type="Sprite2D" parent="."] light_mask = 2 @@ -63,15 +73,18 @@ canvas_item_default_texture_filter = 0 size = Vector2i(256, 192) render_target_update_mode = 4 -[node name="Circle" type="Sprite2D" parent="FlashlightViewport"] -texture = ExtResource("3_8o315") - [node name="PlayerCircle" type="Sprite2D" parent="FlashlightViewport"] position = Vector2(13.61, 14.405) scale = Vector2(0.5, 0.5) texture = ExtResource("3_8o315") -[node name="Triangle" type="Polygon2D" parent="FlashlightViewport"] +[node name="CanvasGroup" type="CanvasGroup" parent="FlashlightViewport"] +material = SubResource("ShaderMaterial_m680d") + +[node name="Circle" type="Sprite2D" parent="FlashlightViewport/CanvasGroup"] +texture = ExtResource("3_8o315") + +[node name="Triangle" type="Polygon2D" parent="FlashlightViewport/CanvasGroup"] polygon = PackedVector2Array(-21, -25, 31, 29, -42, 31) [node name="PlayerCamera" type="Camera2D" parent="." node_paths=PackedStringArray("Player")] @@ -82,7 +95,7 @@ CameraBounds = Vector2(30, 20) [node name="PointLight2D" type="PointLight2D" parent="PlayerCamera" node_paths=PackedStringArray("LightViewport")] blend_mode = 2 range_item_cull_mask = 2 -texture = SubResource("ViewportTexture_dwy4p") +texture = SubResource("ViewportTexture_0u602") script = ExtResource("6_slohe") LightViewport = NodePath("../../FlashlightViewport") diff --git a/scripts/Constants.cs b/scripts/Constants.cs index 265fd12..86ad88a 100644 --- a/scripts/Constants.cs +++ b/scripts/Constants.cs @@ -1,12 +1,14 @@ -using Godot; +using Godot; public static class Constants { - public static readonly Vector2 ScreenSize = new(256, 192); - public static readonly Vector2 HalfScreenSize = ScreenSize / 2; + public static readonly Vector2 ScreenSize = new(256, 192); + public static readonly Vector2 HalfScreenSize = ScreenSize / 2; - public const float MaxFlashlightRadius = 32; - public const float MinFlashlightRadius = 8; - public const float MaxFlashlightDistance = 96; - public const float MinFlashlightDistance = 16; -} \ No newline at end of file + public const float MaxFlashlightRadius = 32; + public const float MinFlashlightRadius = 8; + public const float MaxFlashlightDistance = 96; + public const float MinFlashlightDistance = 16; + public const float MaxFlashlightEnergy = 100; + public const float FlashlightEneregyPerCharge = 5; +} diff --git a/scripts/Flashlight.cs b/scripts/Flashlight.cs index e36f3f2..9648f29 100644 --- a/scripts/Flashlight.cs +++ b/scripts/Flashlight.cs @@ -13,9 +13,14 @@ public partial class Flashlight : Node [Export] public CollisionShape2D CollisionCircle; [Export] public CollisionShape2D CollisionPlayerCircle; [Export] public CollisionPolygon2D CollisionPolygon; - + [Export] public CanvasGroup FlashlightGroup; + + [Export] public Curve BrightnessCurve; + private float FlashlightRadius = Constants.MaxFlashlightRadius; - + private float FlashlightEnergy = Constants.MaxFlashlightEnergy; + private float FlashlightChargeTimeout = 1; + public override void _Ready() { base._Ready(); @@ -26,7 +31,7 @@ public partial class Flashlight : Node throw new Exception("Invalid collision shape on the player circle"); } - public override void _Process(double delta) + public override void _PhysicsProcess(double delta) { var playerScreenCenterPosition = Player.Position - Camera.Position; var flashlightScreenCenterPosition = Camera.FlashlightPosition - Camera.Position; @@ -68,5 +73,14 @@ public partial class Flashlight : Node Polygon.Polygon = polygon; CollisionPolygon.Polygon = polygon; } + + FlashlightChargeTimeout = Mathf.Clamp(FlashlightChargeTimeout-(float)delta,0,1); + if (Input.IsActionJustPressed("flashlight_charge") && FlashlightChargeTimeout <= 0){ + FlashlightChargeTimeout = 1; + FlashlightEnergy+=Constants.FlashlightEneregyPerCharge; + } + FlashlightEnergy = Mathf.Clamp(FlashlightEnergy-(float)delta, 0, Constants.MaxFlashlightEnergy); + FlashlightGroup.Modulate = new Color(BrightnessCurve.Sample(FlashlightEnergy/Constants.MaxFlashlightEnergy), 1, 1, 1); + CollisionCircle.Enabled = CollisionPlayerCircle.Enabled = CollisionPolygon.Enabled = FlashlightEnergy >= 10; } } diff --git a/scripts/PointLight2DWorkaround.cs b/scripts/PointLight2DWorkaround.cs index 17b0fc3..f235604 100644 --- a/scripts/PointLight2DWorkaround.cs +++ b/scripts/PointLight2DWorkaround.cs @@ -7,13 +7,13 @@ using System; [Tool] public partial class PointLight2DWorkaround : PointLight2D { - [Export] public Viewport LightViewport; + [Export] public Viewport LightViewport; - public override void _Process(double delta) - { - base._Process(delta); + public override void _Process(double delta) + { + base._Process(delta); - Texture = null; - Texture = LightViewport.GetTexture(); - } + Texture = null; + Texture = LightViewport.GetTexture(); + } } diff --git a/shaders/dithering.gdshader b/shaders/dithering.gdshader new file mode 100644 index 0000000..24f549d --- /dev/null +++ b/shaders/dithering.gdshader @@ -0,0 +1,35 @@ +// My custom shader for implementing dithered alpha +shader_type canvas_item; + +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; + +void fragment() { + // Fancy dithered alpha stuff + vec4 color = texture(screen_texture, SCREEN_UV); + float opacity = color.r; + int x = int(FRAGCOORD.x) % 4; + int y = int(FRAGCOORD.y) % 4; + int index = x + y * 4; + float limit = 0.0; + + if (x < 8) { + if (index == 0) limit = 0.0625; + if (index == 1) limit = 0.5625; + if (index == 2) limit = 0.1875; + if (index == 3) limit = 0.6875; + if (index == 4) limit = 0.8125; + if (index == 5) limit = 0.3125; + if (index == 6) limit = 0.9375; + if (index == 7) limit = 0.4375; + if (index == 8) limit = 0.25; + if (index == 9) limit = 0.75; + if (index == 10) limit = 0.125; + if (index == 11) limit = 0.625; + if (index == 12) limit = 1.0; + if (index == 13) limit = 0.5; + if (index == 14) limit = 0.875; + if (index == 15) limit = 0.375; + } + // Is this pixel below the opacity limit? Skip drawing it + COLOR = mix(vec4(0,0,0,0), vec4(1,1,1,color.a), step(limit, opacity)); +}