From 5677971bf040f0198957d40213ff85d317eae076 Mon Sep 17 00:00:00 2001 From: Haze Weathers Date: Fri, 7 Mar 2025 01:58:41 -0500 Subject: [PATCH] portal object improvements :3 --- assets/textures/portal/portal.png | Bin 567 -> 4932 bytes assets/textures/portal/portal_light.png | Bin 0 -> 952 bytes .../textures/portal/portal_light.png.import | 34 ++++++ assets/textures/portal/portal_normal.png | Bin 0 -> 4742 bytes .../textures/portal/portal_normal.png.import | 34 ++++++ maps/purple_portals.tscn | 16 +-- objects/player/player.tscn | 2 +- objects/portal/portal.gd | 79 ++++++++++++-- objects/portal/portal.tscn | 103 +++++++++++++----- 9 files changed, 218 insertions(+), 50 deletions(-) create mode 100644 assets/textures/portal/portal_light.png create mode 100644 assets/textures/portal/portal_light.png.import create mode 100644 assets/textures/portal/portal_normal.png create mode 100644 assets/textures/portal/portal_normal.png.import diff --git a/assets/textures/portal/portal.png b/assets/textures/portal/portal.png index db2cc58ea093baaa9aebb1c4e6a54a123d725072..a7b11af96c77313505b70a00c47da8f6ca9ece9a 100644 GIT binary patch literal 4932 zcmeHLdsGuw8Xq(Y60!IISsyh-+lo5LWb&RSB0`iajL0Qld+N6LH{(du*C-=w|P@dVNBkWNG3`0U-Uj-Wu zZoi7Cu4#pDV)w4IgHaxr0HgDdHGUfUD678l;t$khl+`RQWz>Y^%zU#FkOQxMV z>g)XU)UD&^l+zi_+cU~S->Q?Pe7tLiWs7fv?oc+-BG#9`er0*piR|4cp4^g;p4hPi z98KOLEjG=GSsOIMV@)jH5^SCym%pPH3%D|KGTB>IaNx&qH;=7jCv zf4Y_%cBe3}s$3zd7uQcJYcKp!cVxWe(de`vrWPF;^{2w^-`vT%Ha&xzeDdVqvo5{J zofbc2$hsr=5);W0telR6fj}R5FzeLrp$5AD7MzmKa<#LnOs5=z)MEqcn@>IYKV? zdc88QQs#7J$`yLOUXI~%97mxB>Mn5bqz`qtrwb6>7;(T&xmb>8oeqhBN!pwq-YAvA zbxE&%cFtnygLk-lSb%)UeIzGW$S}FxE+4qV&71NeNRL6kxWjEN;D9^{xSbvs1x)$C z!A~CuA>5`u1i__D*3S8zg5(W4jHdeZIFBpWuR~LEkPGY()D7)Z4ASRWrk|`qwh1eK zcLo{)kL$x9q}}VgUm0pyEJU1>@(72TtV(3`V1*N~=IsdWJ;xltztGlvbz0aYg|&zz-$F zfrv>o8>P4m>z_%?C3(i_vKys~Sck{gzhGtUAekox(iB>iLW!$!y&BVLF)iM&lmc9C zm~aB7zg+rPXo^?>5lNUhtewmRa?X+IUl77VKxZJaq>!f&**_0`A!1#C@vkjJxbcz%I@ zs{2MIgS_rh_b`|BUnPmee<=u(>UP0R<^$SqC&cPrqOwRwCV4yLWL8!riU>3^LJ6BQsazXsY4YuJ&mdu9gf-r7vX(TXcT~^^vu5z z_&>R*?ac}3u|FqzTr|jqve+9`gZw|j-mNg8jzVg>=U{z?vL)rCzqbs=o#Rwem4?Qn@56(I{E(*RS zN7`On80UXgB0tAA6hUbe7r)F6AE4)j7I49NfQFNSyxC$3{9$puI#wC|VP+o;RG^ZDM&*XB{C zIPO5G%$qQ3>gMe?#1AJwZmC)I;ziE+O?!3w8U32cyB57n1PwbbjDpI_@}Bc7b|7T(qWo@qWURyh3;B_@dc$e55ENjINtdUS8hW z*~t;RL+5ivMN1A^YnrkZd#)aA%GQ;|PB5(}FLJv2!$mt!B$c+f{^-Tq5s{+%E2l<^)-@ulTU;e8WbbUb zu0J)iv?gfv-Tb#&Kjs@&XevXJ5*|D;rhK@yF(ZR%FPs+j5*d-c*=787#D>nOF~#G~ zwYJXAn=-k@?TXm&*Qu-TKABrk-G2W*kck^UNx%A4RGn_hm>aDgV)vM&OU+kzf!|jD znF)&IR!qE*2Z?BFBg2=UYd2hK!GCA3+?QXM^x^gy*KU`5WUpjCDu{7tDy<*9j-;oj z-!qgqG&D3%scJxcKHqyy*-zj3yeYf5V*7&kW2Ri_cv5(oCd}iWK6t>C)>Rmyqbu8Q z-+tx7&23LtId51h#I@|9cEjz{*U-@$V_Uy}NS%G|m0G|+77U?`c*5z*){w!hmmciz>oMEFQuNIfc{7i=TaSVrKIiK*$={7S& zon@FdnL!_@XB9~Ce>P>z)Z%5fHWL>4nJ@ErzW#^d=bQh8ZuQ0pzeUNHMZ9FalX# zKr9VqgM6vM$P5-|0@05M2Ej7GDR0T@mb*cn)WDh!N_ z4Hy?dOavp@3Xlx~Oh9v(z$$|*Er2YjE<*zYknGE=-z-ku%Bcb}`#fD7Lo|YQ z{kw$@8*nIXy5fHO=l^=^oa3>6EMIu48dB40UfR@Lnf>;$Xo19ZcCp-D$I|tW-`X~5 z<+fC1RwMD78th3b?afAqmrsA2UKB52B59ezcAsnM`IUN7szuLa!t6Y)CPk@)OlZ`b z9{Vm%#j9MS>F>O{rRQHR{Ze@U`}d%PmcEH{f9h}leIs-0FSA_>n}7dP_KhG{db;|# JtaD0e0s#JspBexF diff --git a/assets/textures/portal/portal_light.png b/assets/textures/portal/portal_light.png new file mode 100644 index 0000000000000000000000000000000000000000..2480336aead98aa46aed27a4f149ae887668b841 GIT binary patch literal 952 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 void: - if body is Player && check_for_bodies: - body.global_position = portal.global_position - body.launch(body.velocity * 1.25) - portal.check_for_bodies = false - +## color the portal is tinted as +@export_color_no_alpha var color: Color = Color.PURPLE: + set(value): + color = value + sprite.modulate = color + if linked_portal and linked_portal.color != color: + linked_portal.color = color + queue_redraw() -func _on_area_2d_body_exited(body: Node2D) -> void: - await get_tree().create_timer(0.1).timeout - check_for_bodies = true +## Other connected portal. The linked +@export var linked_portal: Portal: + set(new_portal): + if new_portal == self: + return + if new_portal == null: + linked_portal = null + return + if linked_portal: + linked_portal.linked_portal = null + linked_portal = new_portal + if linked_portal: + if linked_portal.linked_portal != self: + linked_portal.linked_portal = self + linked_portal.color = color + queue_redraw() + +## Multiplier to the player's velocity when they travel through the portal. +@export var speed_multiplier: float = 1.25 +## Delay in seconds until an exited portal can be re-entered. +@export var teleport_cooldown: float = 0.1 + +@export_group("Internal References") +@export var sprite: Sprite2D + + +var check_for_player: bool = true + + +func _init() -> void: + set_notify_transform(true) + +func _notification(what: int) -> void: + if what == NOTIFICATION_TRANSFORM_CHANGED: + queue_redraw() + if linked_portal: + linked_portal.queue_redraw() + +func _draw() -> void: + if Engine.is_editor_hint(): + if linked_portal: + draw_line(Vector2.ZERO, to_local(linked_portal.global_position), color, 1.5) + + +func _on_player_detector_body_entered(body: Node2D) -> void: + if check_for_player and body is Player and linked_portal: + body.global_position = linked_portal.global_position + body.launch(body.velocity * speed_multiplier) + linked_portal.check_for_player = false + create_tween().tween_property( + linked_portal, ^"check_for_player", true, 0.0 + ).set_delay(teleport_cooldown) + + +func _on_player_detector_body_exited(body: Node2D) -> void: + var tween = create_tween().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) + tween.tween_property(self, ^"check_for_player", true, 0.0).set_delay(teleport_cooldown) diff --git a/objects/portal/portal.tscn b/objects/portal/portal.tscn index a03aeba..233fe53 100644 --- a/objects/portal/portal.tscn +++ b/objects/portal/portal.tscn @@ -1,25 +1,12 @@ -[gd_scene load_steps=7 format=3 uid="uid://cypj35yv5auuc"] +[gd_scene load_steps=10 format=3 uid="uid://cypj35yv5auuc"] [ext_resource type="Script" uid="uid://dbrblyk7xttpj" path="res://objects/portal/portal.gd" id="1_v7atq"] [ext_resource type="Texture2D" uid="uid://dtwp3ohanw2sn" path="res://assets/textures/portal/portal.png" id="2_ah4id"] +[ext_resource type="Texture2D" uid="uid://cv7rv8wlhpbg1" path="res://assets/textures/portal/portal_normal.png" id="3_ah4id"] +[ext_resource type="Texture2D" uid="uid://h45qkvmrh0ey" path="res://assets/textures/portal/portal_light.png" id="4_xxtm7"] -[sub_resource type="Animation" id="Animation_xxtm7"] -resource_name = "spin" -length = 0.5 -loop_mode = 1 -step = 0.25 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Sprite2D:rotation") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 0.5), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [0.0, 6.28319] -} +[sub_resource type="RectangleShape2D" id="RectangleShape2D_v7atq"] +size = Vector2(16, 16) [sub_resource type="Animation" id="Animation_0po8f"] length = 0.001 @@ -35,6 +22,47 @@ tracks/0/keys = { "update": 0, "values": [0.0] } +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("LightPivot:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} + +[sub_resource type="Animation" id="Animation_xxtm7"] +resource_name = "spin" +loop_mode = 1 +step = 0.25 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, 12.5664] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("LightPivot:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, -6.28319] +} [sub_resource type="AnimationLibrary" id="AnimationLibrary_6y8yo"] _data = { @@ -42,14 +70,21 @@ _data = { &"spin": SubResource("Animation_xxtm7") } -[sub_resource type="RectangleShape2D" id="RectangleShape2D_v7atq"] -size = Vector2(16, 16) +[sub_resource type="CanvasTexture" id="CanvasTexture_xxtm7"] +diffuse_texture = ExtResource("2_ah4id") +normal_texture = ExtResource("3_ah4id") -[node name="Portal" type="Node2D"] +[node name="Portal" type="Node2D" node_paths=PackedStringArray("sprite")] script = ExtResource("1_v7atq") +sprite = NodePath("Sprite2D") -[node name="Sprite2D" type="Sprite2D" parent="."] -texture = ExtResource("2_ah4id") +[node name="PlayerDetector" type="Area2D" parent="."] +collision_layer = 0 +collision_mask = 16 +monitorable = false + +[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerDetector"] +shape = SubResource("RectangleShape2D_v7atq") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] libraries = { @@ -57,11 +92,21 @@ libraries = { } autoplay = "spin" -[node name="Area2D" type="Area2D" parent="."] -collision_mask = 16 +[node name="Sprite2D" type="Sprite2D" parent="."] +modulate = Color(0.627451, 0.12549, 0.941176, 1) +self_modulate = Color(1, 1, 1, 0.75) +light_mask = 32 +texture = SubResource("CanvasTexture_xxtm7") -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] -shape = SubResource("RectangleShape2D_v7atq") +[node name="LightPivot" type="Node2D" parent="."] +position = Vector2(-4, 4) -[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] -[connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"] +[node name="PointLight2D" type="PointLight2D" parent="LightPivot"] +position = Vector2(4, 0) +range_item_cull_mask = 32 +texture = ExtResource("4_xxtm7") +texture_scale = 2.0 +height = 4.0 + +[connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_detector_body_entered"] +[connection signal="body_exited" from="PlayerDetector" to="." method="_on_player_detector_body_exited"]