mirror of
https://github.com/Steffo99/swear-jar.git
synced 2024-11-22 07:44:17 +00:00
Some Ghost
refactoring
This commit is contained in:
parent
35095a84dd
commit
8845b7a480
12 changed files with 216 additions and 52 deletions
|
@ -1,8 +1,27 @@
|
||||||
extends Area2D
|
extends Area2D
|
||||||
class_name Ghost
|
class_name Ghost
|
||||||
|
|
||||||
## Ghost previewing the instantiation of a scene.
|
## Ghost previewing the instantiation of a scene.
|
||||||
|
|
||||||
|
|
||||||
|
## Color to modulate this with if the body currently isn't overlapping anything.
|
||||||
|
@export var valid_color: Color = Color.WHITE
|
||||||
|
|
||||||
|
## Color to modulate this with if the body currently is overlapping something.
|
||||||
|
@export var invalid_color: Color = Color.RED
|
||||||
|
|
||||||
|
|
||||||
|
## The [Instantiator] to use to spawn the ghosted item.
|
||||||
|
@onready var instantiator: Instantiator = $Instantiator
|
||||||
|
|
||||||
|
## The [OverlapChecker] to use to see if a solid block is overlapping the ghost.
|
||||||
|
@onready var overlap_checker: OverlapChecker = $OverlapChecker
|
||||||
|
|
||||||
|
## The [PlaceableAreaChecker] to use to see if the ghost is currently inside the placeable area.
|
||||||
|
@onready var placeable_area_checker: PlaceableAreaChecker = $PlaceableAreaChecker
|
||||||
|
|
||||||
|
## The [OverlapFreer] to use to delete the [PhysicsBody2D] behind the ghost before instantiation.
|
||||||
|
@onready var overlap_freer: OverlapFreer = $OverlapFreer
|
||||||
|
|
||||||
## The [CollisionShape2D] to use to check for placement checks.
|
## The [CollisionShape2D] to use to check for placement checks.
|
||||||
##
|
##
|
||||||
## MUST consist of a [RectangleShape2D].
|
## MUST consist of a [RectangleShape2D].
|
||||||
|
@ -27,19 +46,6 @@ class_name Ghost
|
||||||
if preview_sprite:
|
if preview_sprite:
|
||||||
preview_sprite.texture = value
|
preview_sprite.texture = value
|
||||||
|
|
||||||
## Whether the ghost can be placed at the current location of the ghost.
|
|
||||||
##
|
|
||||||
## Computed by checking if [placement_shape] overlaps any entity and is inside the [PlacementArea] of the [Bottle].
|
|
||||||
var can_place: bool:
|
|
||||||
get:
|
|
||||||
return can_place
|
|
||||||
set(value):
|
|
||||||
can_place = value
|
|
||||||
if value:
|
|
||||||
preview_sprite.modulate = Color(1.0, 1.0, 1.0, 0.5)
|
|
||||||
else:
|
|
||||||
preview_sprite.modulate = Color(1.0, 0.0, 0.0, 0.5)
|
|
||||||
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
collision_mask = collision_mask_prevent_placement | collision_mask_delete_placement
|
collision_mask = collision_mask_prevent_placement | collision_mask_delete_placement
|
||||||
|
@ -51,37 +57,22 @@ func _physics_process(_delta: float):
|
||||||
update_can_place()
|
update_can_place()
|
||||||
|
|
||||||
|
|
||||||
|
var can_place: bool:
|
||||||
|
get:
|
||||||
|
return can_place
|
||||||
|
set(value):
|
||||||
|
can_place = value
|
||||||
|
modulate = valid_color if value else invalid_color
|
||||||
|
|
||||||
|
|
||||||
## Update the value of [can_place].
|
## Update the value of [can_place].
|
||||||
# DIRTY HACK: Relies on the placeable area being perfectly surrounded by solid bodies.
|
# DIRTY HACK: Relies on the placeable area being perfectly surrounded by solid bodies.
|
||||||
func update_can_place():
|
func update_can_place() -> void:
|
||||||
var no_overlapping_bodies: bool = true
|
can_place = overlap_checker.is_overlapping_with == null and placeable_area_checker.is_overlapping_with != null
|
||||||
var overlapping_bodies = get_overlapping_bodies()
|
|
||||||
for body in overlapping_bodies:
|
|
||||||
if body is TileMap:
|
|
||||||
no_overlapping_bodies = false
|
|
||||||
elif body is PhysicsBody2D:
|
|
||||||
var body_prevents_placement = bool(body.collision_layer & collision_mask_prevent_placement)
|
|
||||||
no_overlapping_bodies = no_overlapping_bodies and not body_prevents_placement
|
|
||||||
|
|
||||||
var is_in_placeable_area: bool = false
|
|
||||||
var overlapping_areas = get_overlapping_areas()
|
|
||||||
for area in overlapping_areas:
|
|
||||||
if area is PlaceableArea:
|
|
||||||
is_in_placeable_area = true
|
|
||||||
|
|
||||||
can_place = no_overlapping_bodies and is_in_placeable_area
|
|
||||||
|
|
||||||
|
|
||||||
## The [PackedScene] that this node should instantiate.
|
|
||||||
@export var scene_to_instantiate: PackedScene
|
|
||||||
|
|
||||||
## The [Node] instatiated scenes should be added as children to.
|
|
||||||
@export var target: Node
|
|
||||||
|
|
||||||
## Emitted when the [materialize] function has finished executing.
|
|
||||||
signal materialized(node: Node)
|
|
||||||
|
|
||||||
func materialize():
|
func materialize():
|
||||||
|
# Compatibility stub for Instantiator
|
||||||
if not can_place:
|
if not can_place:
|
||||||
return null
|
return null
|
||||||
var overlapping_bodies = get_overlapping_bodies()
|
var overlapping_bodies = get_overlapping_bodies()
|
||||||
|
@ -89,9 +80,6 @@ func materialize():
|
||||||
if body is PhysicsBody2D:
|
if body is PhysicsBody2D:
|
||||||
if body.collision_layer & collision_mask_delete_placement:
|
if body.collision_layer & collision_mask_delete_placement:
|
||||||
body.queue_free()
|
body.queue_free()
|
||||||
var instantiated = scene_to_instantiate.instantiate()
|
var inst = instantiator.instantiate()
|
||||||
instantiated.global_position = global_position
|
# TODO: Remove this
|
||||||
instantiated.rotation = rotation
|
return inst
|
||||||
target.add_child(instantiated)
|
|
||||||
materialized.emit(instantiated)
|
|
||||||
return instantiated
|
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
[gd_scene load_steps=4 format=3 uid="uid://qtk4tm6l367w"]
|
[gd_scene load_steps=8 format=3 uid="uid://qtk4tm6l367w"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://interface/ghost/ghost.gd" id="1_1bq64"]
|
[ext_resource type="Script" path="res://interface/ghost/ghost.gd" id="1_1bq64"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c3p0jdf7416ac" path="res://converters/full_converter_shape.tscn" id="2_bo8dp"]
|
[ext_resource type="PackedScene" uid="uid://c3p0jdf7416ac" path="res://converters/full_converter_shape.tscn" id="2_bo8dp"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cgpjm06hleokk" path="res://interface/ghost/precise_placement.tscn" id="3_70ahv"]
|
[ext_resource type="PackedScene" uid="uid://cgpjm06hleokk" path="res://interface/ghost/precise_touch_placer.tscn" id="3_70ahv"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dhrtfpyfsdf3f" path="res://interface/ghost/instantiator.tscn" id="4_f7fmh"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cm3gvvcsh8i7a" path="res://interface/overlap_checker.tscn" id="5_twds7"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bu3alsb2ufaxu" path="res://interface/ghost/overlap_freer.tscn" id="6_y1rxa"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://blk5uc5ta7nwq" path="res://interface/placeable_area_checker.tscn" id="7_wemqm"]
|
||||||
|
|
||||||
[node name="Ghost" type="Area2D"]
|
[node name="Ghost" type="Area2D"]
|
||||||
collision_layer = 0
|
collision_layer = 0
|
||||||
|
@ -19,4 +23,12 @@ scale = Vector2(2.5, 2.5)
|
||||||
modulate = Color(1, 1, 1, 0.5)
|
modulate = Color(1, 1, 1, 0.5)
|
||||||
z_index = 10
|
z_index = 10
|
||||||
|
|
||||||
[node name="PrecisePlacement" parent="." instance=ExtResource("3_70ahv")]
|
[node name="PreciseTouchPlacer" parent="." instance=ExtResource("3_70ahv")]
|
||||||
|
|
||||||
|
[node name="Instantiator" parent="." instance=ExtResource("4_f7fmh")]
|
||||||
|
|
||||||
|
[node name="OverlapChecker" parent="." instance=ExtResource("5_twds7")]
|
||||||
|
|
||||||
|
[node name="OverlapFreer" parent="." instance=ExtResource("6_y1rxa")]
|
||||||
|
|
||||||
|
[node name="PlaceableAreaChecker" parent="." instance=ExtResource("7_wemqm")]
|
||||||
|
|
27
interface/ghost/instantiator.gd
Normal file
27
interface/ghost/instantiator.gd
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
extends Node
|
||||||
|
class_name Instantiator
|
||||||
|
|
||||||
|
|
||||||
|
## The [PackedScene] that this node should instantiate.
|
||||||
|
@export var scene_to_instantiate: PackedScene
|
||||||
|
|
||||||
|
## The [Node] instantiated scenes should be attached to.
|
||||||
|
@export var container: Node
|
||||||
|
|
||||||
|
|
||||||
|
## The [Node2D] instantiated scenes should get properties from.
|
||||||
|
@onready var target: Node2D = get_parent()
|
||||||
|
|
||||||
|
|
||||||
|
func instantiate():
|
||||||
|
var inst = scene_to_instantiate.instantiate()
|
||||||
|
inst.global_position = target.global_position
|
||||||
|
inst.rotation = target.rotation
|
||||||
|
container.add_child(inst)
|
||||||
|
instantiated.emit(inst)
|
||||||
|
# TODO: Remove this
|
||||||
|
return inst
|
||||||
|
|
||||||
|
|
||||||
|
## Emitted when the [instantiate] function has finished executing.
|
||||||
|
signal instantiated(new_scene: Node)
|
6
interface/ghost/instantiator.tscn
Normal file
6
interface/ghost/instantiator.tscn
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dhrtfpyfsdf3f"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://interface/ghost/instantiator.gd" id="1_waf2e"]
|
||||||
|
|
||||||
|
[node name="Instantiator" type="Node"]
|
||||||
|
script = ExtResource("1_waf2e")
|
37
interface/ghost/overlap_freer.gd
Normal file
37
interface/ghost/overlap_freer.gd
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
extends Node
|
||||||
|
class_name OverlapFreer
|
||||||
|
|
||||||
|
|
||||||
|
## Layers to consider when checking overlap with [PhysicBody2D].
|
||||||
|
@export_flags_2d_physics var overlap_mask: int
|
||||||
|
|
||||||
|
## Whether [TileMap]s should be considered in collisions or not.
|
||||||
|
##
|
||||||
|
## Their [collision_layer]s are always ignored.
|
||||||
|
@export var overlap_with_tilemap: bool = false
|
||||||
|
|
||||||
|
|
||||||
|
## The [Area2D] this script should act on.
|
||||||
|
@onready var target: Area2D = get_parent()
|
||||||
|
|
||||||
|
|
||||||
|
## Get all bodies overlapping the [target].
|
||||||
|
func get_all_overlapping_bodies() -> Array[Node2D]:
|
||||||
|
var bodies: Array[Node2D] = []
|
||||||
|
for body in target.get_overlapping_bodies():
|
||||||
|
if body is TileMap:
|
||||||
|
if overlap_with_tilemap:
|
||||||
|
bodies.append(body)
|
||||||
|
elif body is PhysicsBody2D:
|
||||||
|
if body.collision_layer & overlap_mask:
|
||||||
|
bodies.append(body)
|
||||||
|
return bodies
|
||||||
|
|
||||||
|
## Emitted when a body is about to be [queue_free]d.
|
||||||
|
signal body_queueing_free(body: Node2D)
|
||||||
|
|
||||||
|
## Queue free all overlapping bodies.
|
||||||
|
func area_queue_free() -> void:
|
||||||
|
for body in get_all_overlapping_bodies():
|
||||||
|
body_queueing_free.emit(body)
|
||||||
|
body.queue_free()
|
6
interface/ghost/overlap_freer.tscn
Normal file
6
interface/ghost/overlap_freer.tscn
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bu3alsb2ufaxu"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://interface/ghost/overlap_freer.gd" id="1_vr3yj"]
|
||||||
|
|
||||||
|
[node name="OverlapFreer" type="Node"]
|
||||||
|
script = ExtResource("1_vr3yj")
|
|
@ -1,5 +1,5 @@
|
||||||
extends Node
|
extends Node
|
||||||
class_name PrecisePlacement
|
class_name PreciseTouchPlacer
|
||||||
|
|
||||||
|
|
||||||
## The degrees to rotate by when rotation is quantized.
|
## The degrees to rotate by when rotation is quantized.
|
|
@ -1,6 +1,6 @@
|
||||||
[gd_scene load_steps=2 format=3 uid="uid://cgpjm06hleokk"]
|
[gd_scene load_steps=2 format=3 uid="uid://cgpjm06hleokk"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://interface/ghost/precise_placement.gd" id="1_e7b5h"]
|
[ext_resource type="Script" path="res://interface/ghost/precise_touch_placer.gd" id="1_e7b5h"]
|
||||||
|
|
||||||
[node name="PrecisePlacement" type="Node"]
|
[node name="PreciseTouchPlacer" type="Node"]
|
||||||
script = ExtResource("1_e7b5h")
|
script = ExtResource("1_e7b5h")
|
45
interface/overlap_checker.gd
Normal file
45
interface/overlap_checker.gd
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
extends Node
|
||||||
|
class_name OverlapChecker
|
||||||
|
|
||||||
|
|
||||||
|
## Layers to consider when checking overlap with [PhysicBody2D].
|
||||||
|
@export_flags_2d_physics var overlap_mask: int
|
||||||
|
|
||||||
|
## Whether [TileMap]s should be considered in collisions or not.
|
||||||
|
##
|
||||||
|
## Their [collision_layer]s are always ignored.
|
||||||
|
@export var overlap_with_tilemap: bool = true
|
||||||
|
|
||||||
|
|
||||||
|
## The [Area2D] this script should act on.
|
||||||
|
@onready var target: Area2D = get_parent()
|
||||||
|
|
||||||
|
|
||||||
|
## What the [target] object is currently overlapping with.
|
||||||
|
var is_overlapping_with: Node2D = null
|
||||||
|
|
||||||
|
|
||||||
|
## Get the first body overlapping the [target].
|
||||||
|
func get_first_overlapping_body() -> Node2D:
|
||||||
|
for body in target.get_overlapping_bodies():
|
||||||
|
if body is TileMap:
|
||||||
|
if overlap_with_tilemap:
|
||||||
|
return body
|
||||||
|
elif body is PhysicsBody2D:
|
||||||
|
if body.collision_layer & overlap_mask:
|
||||||
|
return body
|
||||||
|
return null
|
||||||
|
|
||||||
|
## Update the [is_overlapping_with] variable.
|
||||||
|
func _update_is_overlapping_with() -> void:
|
||||||
|
var current_overlap = get_first_overlapping_body()
|
||||||
|
if current_overlap != is_overlapping_with:
|
||||||
|
overlap_changing.emit(current_overlap)
|
||||||
|
is_overlapping_with = current_overlap
|
||||||
|
|
||||||
|
## Emitted when the value of [is_overlapping_with] changes because of [_update_is_overlapping_with].
|
||||||
|
signal overlap_changing(to: Node2D)
|
||||||
|
|
||||||
|
## Calculate overlap on every physics frame.
|
||||||
|
func _physics_process(_delta):
|
||||||
|
_update_is_overlapping_with()
|
6
interface/overlap_checker.tscn
Normal file
6
interface/overlap_checker.tscn
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cm3gvvcsh8i7a"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://interface/overlap_checker.gd" id="1_s3ksv"]
|
||||||
|
|
||||||
|
[node name="OverlapChecker" type="Node"]
|
||||||
|
script = ExtResource("1_s3ksv")
|
31
interface/placeable_area_checker.gd
Normal file
31
interface/placeable_area_checker.gd
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
extends Node
|
||||||
|
class_name PlaceableAreaChecker
|
||||||
|
|
||||||
|
|
||||||
|
## The [Area2D] this script should act on.
|
||||||
|
@onready var target: Area2D = get_parent()
|
||||||
|
|
||||||
|
|
||||||
|
## What the [target] object is currently overlapping with.
|
||||||
|
var is_overlapping_with: PlaceableArea = null
|
||||||
|
|
||||||
|
|
||||||
|
## Get the first [PlaceableArea] overlapping the [target].
|
||||||
|
func get_first_overlapping_placeable_area() -> PlaceableArea:
|
||||||
|
for area in target.get_overlapping_areas():
|
||||||
|
if area is PlaceableArea:
|
||||||
|
return area
|
||||||
|
return null
|
||||||
|
|
||||||
|
## Emitted when the value of [is_overlapping_with] changes because of [_update_is_overlapping_with].
|
||||||
|
signal overlap_changing(to: PlaceableArea)
|
||||||
|
|
||||||
|
func _update_is_overlapping_with() -> void:
|
||||||
|
var current_overlap = get_first_overlapping_placeable_area()
|
||||||
|
if current_overlap != is_overlapping_with:
|
||||||
|
overlap_changing.emit(current_overlap)
|
||||||
|
is_overlapping_with = current_overlap
|
||||||
|
|
||||||
|
## Calculate overlap on every physics frame.
|
||||||
|
func _physics_process(_delta):
|
||||||
|
_update_is_overlapping_with()
|
6
interface/placeable_area_checker.tscn
Normal file
6
interface/placeable_area_checker.tscn
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://blk5uc5ta7nwq"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://interface/placeable_area_checker.gd" id="1_yyb05"]
|
||||||
|
|
||||||
|
[node name="PlaceableAreaChecker" type="Node"]
|
||||||
|
script = ExtResource("1_yyb05")
|
Loading…
Reference in a new issue