Add new cool light beam for the flashlight

Co-authored-by: Евгений Титаренко <frundle@teasanctuary.ru>
This commit is contained in:
Иван Кузьменко 2023-08-16 00:13:37 +03:00
parent 3832a05c1b
commit f307a7ef00
20 changed files with 230 additions and 68 deletions

34
invert.py Normal file
View file

@ -0,0 +1,34 @@
# shout out to FriendlyWithMeat
from PIL import Image
from pathlib import Path
import os
from PIL.ImageOps import invert
import argparse
parser = argparse.ArgumentParser(
prog='invert.py',
description='Took images from INPUT_FOLDER, invert them and save in OUTPUT_FOLDER.')
parser.add_argument('INPUT_FOLDER')
parser.add_argument('OUTPUT_FOLDER')
args = parser.parse_args()
WORK_DIR = Path(args.INPUT_FOLDER)
IMG_EXTS = set((".png",))
OUT_DIR = Path(args.OUTPUT_FOLDER)
OUT_DIR.mkdir(exist_ok=True)
dir_contents = os.listdir(WORK_DIR)
for elem in dir_contents:
img_file = Path(os.path.join(WORK_DIR, elem))
if img_file.suffix in IMG_EXTS:
image = Image.open(img_file)
r, g, b, a = image.convert('RGBA').split()
rgb_image = Image.merge('RGB', (r,g,b))
inv_image = invert(rgb_image)
r, g, b = inv_image.split()
final_img = Image.merge('RGBA', (r,g,b,a))
save_path = Path(os.path.join(OUT_DIR, elem))
final_img.save(save_path)

View file

@ -15,5 +15,4 @@ shape = SubResource("RectangleShape2D_5hhj3")
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
sprite_frames = ExtResource("1_8jl58")
animation = &"up"
frame_progress = 0.975256
animation = &"down"

3
process_sprites.bat Normal file
View file

@ -0,0 +1,3 @@
python invert.py sprites_orig sprites
python invert.py sprites_orig\player sprites\player
pause

View file

@ -37,8 +37,13 @@ project/assembly_name="1bit-game-jam"
textures/canvas_textures/default_texture_filter=0
renderer/rendering_method="mobile"
textures/lossless_compression/force_png=true
textures/default_filters/use_nearest_mipmap_filter=true
textures/default_filters/anisotropic_filtering_level=0
environment/ssao/quality=0
environment/ssil/quality=0
anti_aliasing/screen_space_roughness_limiter/enabled=false
textures/decals/filter=0
textures/light_projectors/filter=0
environment/glow/upscale_mode=0
environment/defaults/default_clear_color=Color(0, 0, 0, 1)
2d/snap/snap_2d_transforms_to_pixel=true

1
requirements.txt Normal file
View file

@ -0,0 +1 @@
Pillow>=10.0.0

View file

@ -1,49 +1,92 @@
[gd_scene load_steps=6 format=3 uid="uid://dhn7yt46fyac8"]
[gd_scene load_steps=11 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="Script" path="res://scripts/GameCamera.cs" id="6_quua3"]
[ext_resource type="Script" path="res://scripts/PointLight2DWorkaround.cs" id="6_slohe"]
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_wg1ao"]
light_mode = 2
[node name="Root" type="Node2D"]
[sub_resource type="ViewportTexture" id="ViewportTexture_nnmvo"]
viewport_path = NodePath("FlashlightViewport")
[node name="Player" parent="." node_paths=PackedStringArray("FlashlightUI", "FlashlightWorld") instance=ExtResource("1_65a7v")]
position = Vector2(19, 4)
FlashlightUI = NodePath("../CanvasLayer/FlashlightUI")
FlashlightWorld = NodePath("../Camera2D/PointLight2D")
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_au1d0"]
light_mode = 2
[node name="Root" type="Node2D"]
[node name="TestWall" type="Sprite2D" parent="."]
light_mask = 2
material = SubResource("CanvasItemMaterial_wg1ao")
position = Vector2(-108, -74)
position = Vector2(58, 37)
texture = ExtResource("2_edqdh")
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="Player" parent="." instance=ExtResource("1_65a7v")]
position = Vector2(19, 4)
[node name="FlashlightUI" type="Sprite2D" parent="CanvasLayer"]
clip_children = 1
[node name="FlashlightViewport" type="SubViewport" parent="."]
transparent_bg = true
snap_2d_transforms_to_pixel = true
snap_2d_vertices_to_pixel = true
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="InvertRect" type="ColorRect" parent="CanvasLayer/FlashlightUI"]
material = ExtResource("4_ro05e")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -32.0
offset_top = -32.0
offset_right = -32.0
offset_bottom = -32.0
grow_horizontal = 2
grow_vertical = 2
metadata/_edit_use_anchors_ = true
[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="Camera2D" type="Camera2D" parent="."]
[node name="Triangle" type="Polygon2D" parent="FlashlightViewport"]
polygon = PackedVector2Array(-21, -25, 31, 29, -42, 31)
[node name="PointLight2D" type="PointLight2D" parent="Camera2D"]
[node name="Controller" type="Node" parent="FlashlightViewport" node_paths=PackedStringArray("Player", "Camera", "Circle", "PlayerCircle", "Polygon")]
script = ExtResource("3_cylxo")
Player = NodePath("../../Player")
Camera = NodePath("../../PlayerCamera")
Circle = NodePath("../Circle")
PlayerCircle = NodePath("../PlayerCircle")
Polygon = NodePath("../Triangle")
[node name="PlayerCamera" type="Camera2D" parent="."]
script = ExtResource("6_quua3")
[node name="PointLight2D" type="PointLight2D" parent="PlayerCamera" node_paths=PackedStringArray("LightViewport")]
energy = 16.0
blend_mode = 2
range_item_cull_mask = 2
script = ExtResource("6_slohe")
LightViewport = NodePath("../../FlashlightViewport")
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="FlashlightUI" type="TextureRect" parent="CanvasLayer"]
clip_children = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("ViewportTexture_nnmvo")
[node name="InvertRect" type="ColorRect" parent="CanvasLayer/FlashlightUI"]
material = ExtResource("4_ro05e")
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Sprite2D" type="Sprite2D" parent="."]
light_mask = 2
material = SubResource("CanvasItemMaterial_au1d0")
position = Vector2(-83, 43)
texture = ExtResource("3_8o315")

9
scripts/Constants.cs Normal file
View file

@ -0,0 +1,9 @@
using Godot;
public static class Constants
{
public static readonly Vector2 ScreenSize = new(256, 192);
public static readonly Vector2 HalfScreenSize = ScreenSize / 2;
public const float MaxFlashlightRadius = 32;
}

48
scripts/Flashlight.cs Normal file
View file

@ -0,0 +1,48 @@
using Godot;
public partial class Flashlight : Node
{
[Export] public Player Player;
[Export] public GameCamera Camera;
[Export] public Node2D Circle;
[Export] public Node2D PlayerCircle;
[Export] public Polygon2D Polygon;
private float FlashlightRadius = Constants.MaxFlashlightRadius;
public override void _Process(double delta)
{
var playerScreenCenterPosition = Player.Position - Camera.Position;
var flashlightScreenCenterPosition = Camera.FlashlightPosition - Camera.Position;
var playerScreenPosition = playerScreenCenterPosition + Constants.HalfScreenSize;
PlayerCircle.Position = playerScreenPosition;
var flashlightScreenPosition = flashlightScreenCenterPosition + Constants.HalfScreenSize;
var flashlightScale = FlashlightRadius / Constants.MaxFlashlightRadius;
Circle.Position = flashlightScreenPosition;
Circle.Scale = new Vector2(flashlightScale, flashlightScale);
var d = Camera.FlashlightPosition.DistanceTo(Player.Position);
if (d <= FlashlightRadius)
Polygon.Visible = false;
else
{
Polygon.Visible = true;
var a = Mathf.Sqrt(d * d - FlashlightRadius * FlashlightRadius);
var xy2 = Camera.FlashlightPosition - Player.Position;
var angle = xy2.Angle();
var arcsinRd = Mathf.Asin(FlashlightRadius / d);
var dslkhjdsflkhjsdfhlkjdfsjlk = angle + arcsinRd;
var xy3 = a * new Vector2(Mathf.Cos(dslkhjdsflkhjsdfhlkjdfsjlk), Mathf.Sin(dslkhjdsflkhjsdfhlkjdfsjlk));
var dslkhjdsflkhjsdfhlkjdfsjlk2 = angle - arcsinRd;
var xy4 = a * new Vector2(Mathf.Cos(dslkhjdsflkhjsdfhlkjdfsjlk2), Mathf.Sin(dslkhjdsflkhjsdfhlkjdfsjlk2));
Polygon.Polygon = new[]
{ playerScreenPosition, playerScreenPosition + xy3, playerScreenPosition + xy4 };
}
}
}

19
scripts/GameCamera.cs Normal file
View file

@ -0,0 +1,19 @@
using Godot;
public partial class GameCamera : Camera2D
{
/// <summary>
/// World position of the flashlight
/// </summary>
public Vector2 FlashlightPosition;
public override void _Input(InputEvent @event)
{
base._Input(@event);
if (@event is InputEventMouseMotion eventMouseMotion)
{
FlashlightPosition = eventMouseMotion.Position - Constants.HalfScreenSize + Position;
}
}
}

View file

@ -1,52 +1,37 @@
using Godot;
using System;
public partial class Player : CharacterBody2D
{
[Export] public Node2D FlashlightUI;
[Export] public Node2D FlashlightWorld;
[Export] public const float Speed = 50.0f;
[Export] public const float Speed = 50.0f;
protected AnimatedSprite2D Sprite;
protected AnimatedSprite2D Sprite;
public override void _Ready()
{
base._Ready();
public override void _Ready()
{
base._Ready();
Sprite = (AnimatedSprite2D)FindChild("AnimatedSprite2D");
}
Sprite = (AnimatedSprite2D)FindChild("AnimatedSprite2D");
}
public override void _PhysicsProcess(double delta)
{
Vector2 velocity = Velocity;
public override void _PhysicsProcess(double delta)
{
Vector2 velocity = Velocity;
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
if (direction != Vector2.Zero)
{
velocity.X = direction.X * Speed;
velocity.Y = direction.Y * Speed;
}
else
{
velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
velocity.Y = Mathf.MoveToward(Velocity.Y, 0, Speed);
}
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
if (direction != Vector2.Zero)
{
velocity.X = direction.X * Speed;
velocity.Y = direction.Y * Speed;
}
else
{
velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
velocity.Y = Mathf.MoveToward(Velocity.Y, 0, Speed);
}
Velocity = velocity;
MoveAndSlide();
}
public override void _Input(InputEvent @event)
{
base._Input(@event);
if (@event is InputEventMouseMotion eventMouseMotion)
{
FlashlightUI.Position = eventMouseMotion.Position;
FlashlightWorld.Position = eventMouseMotion.Position - new Vector2(128F, 96F);
}
}
}
Velocity = velocity;
MoveAndSlide();
}
}

View file

@ -0,0 +1,16 @@
using Godot;
using System;
[Tool]
public partial class PointLight2DWorkaround : PointLight2D
{
[Export] public Viewport LightViewport;
public override void _Process(double delta)
{
base._Process(delta);
Texture = null;
Texture = LightViewport.GetTexture();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 662 B

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 491 B

0
sprites_orig/.gdignore Normal file
View file

BIN
sprites_orig/brickwall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B