diff --git a/project.godot b/project.godot index 174b355..b373694 100644 --- a/project.godot +++ b/project.godot @@ -18,8 +18,8 @@ config/icon="res://icon.png" [autoload] -Global="*res://src/global.gd" -Window="*res://src/window.gd" +Global="*res://src/scripts/global.gd" +Window="*res://src/scripts/window.gd" EnemyClass="*res://src/scripts/enemy_class.gd" [display] @@ -83,4 +83,5 @@ common/enable_pause_aware_picking=true [rendering] quality/driver/driver_name="GLES2" +environment/default_clear_color=Color( 0, 0, 0, 1 ) environment/default_environment="res://default_env.tres" diff --git a/res/shaders/outline.tres b/res/shaders/outline.tres new file mode 100644 index 0000000..a1aac4e --- /dev/null +++ b/res/shaders/outline.tres @@ -0,0 +1,65 @@ +[gd_resource type="Shader" format=2] + +[resource] +code = "shader_type canvas_item; + +uniform vec4 color : hint_color = vec4(1.0); +uniform float width : hint_range(0, 10) = 1.0; +uniform int pattern : hint_range(0, 2) = 0; // diamond, circle, square +uniform bool inside = false; +uniform bool add_margins = true; // only useful when inside is false + +void vertex() { + if (add_margins) { + VERTEX += (UV * 2.0 - 1.0) * width; + } +} + +bool hasContraryNeighbour(vec2 uv, vec2 texture_pixel_size, sampler2D texture) { + for (float i = -ceil(width); i <= ceil(width); i++) { + float x = abs(i) > width ? width * sign(i) : i; + float offset; + + if (pattern == 0) { + offset = width - abs(x); + } else if (pattern == 1) { + offset = floor(sqrt(pow(width + 0.5, 2) - x * x)); + } else if (pattern == 2) { + offset = width; + } + + for (float j = -ceil(offset); j <= ceil(offset); j++) { + float y = abs(j) > offset ? offset * sign(j) : j; + vec2 xy = uv + texture_pixel_size * vec2(x, y); + + if ((xy != clamp(xy, vec2(0.0), vec2(1.0)) || texture(texture, xy).a == 0.0) == inside) { + return true; + } + } + } + + return false; +} + +void fragment() { + vec2 uv = UV; + + if (add_margins) { + vec2 texture_pixel_size = vec2(1.0) / (vec2(1.0) / TEXTURE_PIXEL_SIZE + vec2(width * 2.0)); + + uv = (uv - texture_pixel_size * width) * TEXTURE_PIXEL_SIZE / texture_pixel_size; + + if (uv != clamp(uv, vec2(0.0), vec2(1.0))) { + COLOR.a = 0.0; + } else { + COLOR = texture(TEXTURE, uv); + } + } else { + COLOR = texture(TEXTURE, uv); + } + + if ((COLOR.a > 0.0) == inside && hasContraryNeighbour(uv, TEXTURE_PIXEL_SIZE, TEXTURE)) { + COLOR.rgb = inside ? mix(COLOR.rgb, color.rgb, color.a) : color.rgb; + COLOR.a += (1.0 - COLOR.a) * color.a; + } +}" diff --git a/src/models/enemies/bat/Bat.tscn b/src/models/enemies/bat/Bat.tscn index aa6ecc7..0d16b9f 100644 --- a/src/models/enemies/bat/Bat.tscn +++ b/src/models/enemies/bat/Bat.tscn @@ -15,6 +15,7 @@ collision_mask = 2 script = ExtResource( 2 ) [node name="Sprite" type="Sprite" parent="."] +use_parent_material = true texture = ExtResource( 1 ) centered = false diff --git a/src/models/enemies/bat/bat.gd b/src/models/enemies/bat/bat.gd index 7ed31af..12114e8 100644 --- a/src/models/enemies/bat/bat.gd +++ b/src/models/enemies/bat/bat.gd @@ -8,9 +8,6 @@ onready var player = $"../../Player" func _ready(): hp = 15 -func _process(_delta): - get_node("Sprite").flip_h = true if player.global_position.x > self.position.x else false - func _physics_process(_delta): var player_position = player.global_position + Vector2(8, 8) var angle = get_angle_to(player_position) diff --git a/src/models/enemies/ghost/Ghost.tscn b/src/models/enemies/ghost/Ghost.tscn index cec8f87..4773bf0 100644 --- a/src/models/enemies/ghost/Ghost.tscn +++ b/src/models/enemies/ghost/Ghost.tscn @@ -11,6 +11,7 @@ z_index = 2 script = ExtResource( 2 ) [node name="Sprite" type="Sprite" parent="."] +use_parent_material = true texture = ExtResource( 1 ) centered = false diff --git a/src/models/player/player.gd b/src/models/player/player.gd index 5bb950b..ad57e33 100644 --- a/src/models/player/player.gd +++ b/src/models/player/player.gd @@ -27,6 +27,9 @@ func _physics_process(_delta): velocity = move_and_slide(velocity * speed_multiplier) choose_target() +const SHADER = preload("res://res/shaders/outline.tres") + + func choose_target(): var least_dist = 4000 var enemy_dist @@ -36,3 +39,4 @@ func choose_target(): if enemy_dist < least_dist: least_dist = enemy_dist target = enemy + #enemy.set_shader_param("width", 0) diff --git a/src/scenes/game/Game.tscn b/src/scenes/game/Game.tscn index fbe842b..bb04902 100644 --- a/src/scenes/game/Game.tscn +++ b/src/scenes/game/Game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=20 format=2] +[gd_scene load_steps=24 format=2] [ext_resource path="res://src/scenes/menu/background/background.png" type="Texture" id=1] [ext_resource path="res://src/scenes/game/sprites/background_houses.png" type="Texture" id=2] @@ -15,6 +15,7 @@ [ext_resource path="res://src/models/enemies/trash_can/TrashCan.tscn" type="PackedScene" id=13] [ext_resource path="res://src/models/enemies/bat/Bat.tscn" type="PackedScene" id=14] [ext_resource path="res://src/models/enemies/ghost/Ghost.tscn" type="PackedScene" id=15] +[ext_resource path="res://res/shaders/outline.tres" type="Shader" id=16] [sub_resource type="RectangleShape2D" id=2] extents = Vector2( 10, 60 ) @@ -22,6 +23,30 @@ extents = Vector2( 10, 60 ) [sub_resource type="RectangleShape2D" id=3] extents = Vector2( 140, 10.125 ) +[sub_resource type="ShaderMaterial" id=5] +shader = ExtResource( 16 ) +shader_param/color = Color( 1, 0.870588, 0, 1 ) +shader_param/width = 1.0 +shader_param/pattern = 0 +shader_param/inside = false +shader_param/add_margins = true + +[sub_resource type="ShaderMaterial" id=6] +shader = ExtResource( 16 ) +shader_param/color = Color( 1, 0.870588, 0, 1 ) +shader_param/width = 1.0 +shader_param/pattern = 0 +shader_param/inside = false +shader_param/add_margins = true + +[sub_resource type="ShaderMaterial" id=7] +shader = ExtResource( 16 ) +shader_param/color = Color( 1, 0.870588, 0, 1 ) +shader_param/width = 1.0 +shader_param/pattern = 0 +shader_param/inside = true +shader_param/add_margins = true + [sub_resource type="DynamicFont" id=1] size = 8 font_data = ExtResource( 4 ) @@ -76,14 +101,17 @@ shape = SubResource( 3 ) [node name="TrashCan" parent="View/Enemies" instance=ExtResource( 13 )] [node name="Bat" parent="View/Enemies" instance=ExtResource( 14 )] +material = SubResource( 5 ) z_index = 1 [node name="Bat2" parent="View/Enemies" instance=ExtResource( 14 )] +material = SubResource( 6 ) position = Vector2( 142, 54 ) z_index = 1 [node name="Ghost" parent="View/Enemies" instance=ExtResource( 15 )] -position = Vector2( 400, 50 ) +material = SubResource( 7 ) +position = Vector2( 509, 100 ) [node name="Player" parent="View" instance=ExtResource( 5 )] position = Vector2( 46, 42 ) diff --git a/src/global.gd b/src/scripts/global.gd similarity index 100% rename from src/global.gd rename to src/scripts/global.gd diff --git a/src/window.gd b/src/scripts/window.gd similarity index 99% rename from src/window.gd rename to src/scripts/window.gd index 70b95f7..5d0d0aa 100644 --- a/src/window.gd +++ b/src/scripts/window.gd @@ -19,4 +19,3 @@ func _input(event): # Input.mouse_mode = Input.MOUSE_MODE_CAPTURED #if event is InputEventKey and event.scancode == 16777240 and event.pressed: #scancode 16777240 == KEY_ALT # Input.mouse_mode = Input.MOUSE_MODE_VISIBLE -