From 702080af59834492c554650e9765fe4907ee41b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Wed, 20 Aug 2025 04:35:40 +0200 Subject: [PATCH] game: add magnet pickup --- global_const.gd | 1 + project.godot | 2 ++ scenes/main.tscn | 7 +++++- scenes/pickups/pickup_base.gd | 28 ++++++++++++++++++++++ scenes/pickups/pickup_base.gd.uid | 1 + scenes/pickups/pickup_base.tscn | 24 +++++++++++++++++++ scenes/pickups/pickup_magnet.gd | 36 +++++++++++++++++++++++++++++ scenes/pickups/pickup_magnet.gd.uid | 1 + scenes/pickups/pickup_magnet.tscn | 12 ++++++++++ scenes/player.gd | 4 +++- scenes/player.tscn | 2 +- scenes/xp_orb.gd | 4 +++- scenes/xp_orb.tscn | 2 +- 13 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 scenes/pickups/pickup_base.gd create mode 100644 scenes/pickups/pickup_base.gd.uid create mode 100644 scenes/pickups/pickup_base.tscn create mode 100644 scenes/pickups/pickup_magnet.gd create mode 100644 scenes/pickups/pickup_magnet.gd.uid create mode 100644 scenes/pickups/pickup_magnet.tscn diff --git a/global_const.gd b/global_const.gd index f8d06f5..eae8037 100644 --- a/global_const.gd +++ b/global_const.gd @@ -15,6 +15,7 @@ const GROUP_ENEMY = "enemy" const GROUP_DAMAGEABLE = "damagable" const GROUP_PLAYER = "player" const GROUP_XP_ORB = "xp_orb" +const GROUP_PICKUP = "pickup" enum ModRarity { LEGENDARY, EPIC, RARE, NORMAL } diff --git a/project.godot b/project.godot index 18b5716..ce843c5 100644 --- a/project.godot +++ b/project.godot @@ -32,6 +32,7 @@ player="Group containing current player" enemy="Group containing all enemies" damagable="Can be damaged using take_damage" xp_orb="Experience orbs" +pickup="Items that can be picked up" [input] @@ -72,6 +73,7 @@ click={ 2d_physics/layer_2="Enemies" 2d_physics/layer_3="Player" 2d_physics/layer_4="XP" +2d_physics/layer_5="Pickups" [rendering] diff --git a/scenes/main.tscn b/scenes/main.tscn index b2e4b3d..294e96f 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=6 format=3 uid="uid://bjg50n7aab3ng"] +[gd_scene load_steps=7 format=3 uid="uid://bjg50n7aab3ng"] [ext_resource type="Script" uid="uid://brb4ssksmtq8k" path="res://scenes/main.gd" id="1_jyhfs"] [ext_resource type="PackedScene" uid="uid://4xha2nhf8fya" path="res://scenes/test_level.tscn" id="1_o5qli"] [ext_resource type="PackedScene" uid="uid://ca2so8fm3q8fe" path="res://scenes/player.tscn" id="2_0wfyh"] [ext_resource type="PackedScene" uid="uid://b18uib08hvdpq" path="res://scenes/managers/ui/main_ui.tscn" id="3_sugp2"] [ext_resource type="PackedScene" uid="uid://dy73qrxcgrwg3" path="res://scenes/managers/enemy_manager.tscn" id="5_tbgi4"] +[ext_resource type="PackedScene" uid="uid://bbev8m5g0p3a3" path="res://scenes/pickups/pickup_magnet.tscn" id="6_tefeu"] [node name="Main" type="Node2D"] script = ExtResource("1_jyhfs") @@ -24,3 +25,7 @@ main_ui = NodePath("../MainUI") [node name="EnemyManager" parent="." node_paths=PackedStringArray("target") instance=ExtResource("5_tbgi4")] target = NodePath("../Player") + +[node name="PickupMagnet" parent="." instance=ExtResource("6_tefeu")] +position = Vector2(1697, 414) +duration = 15.0 diff --git a/scenes/pickups/pickup_base.gd b/scenes/pickups/pickup_base.gd new file mode 100644 index 0000000..6bd1461 --- /dev/null +++ b/scenes/pickups/pickup_base.gd @@ -0,0 +1,28 @@ +class_name PickupBase +extends Node2D + +@export var value: float +@export var max_speed: float = 100.0 +@export var min_speed: float = 10.0 + +var player: Player + +func _ready() -> void: + player = get_tree().get_first_node_in_group(GlobalConst.GROUP_PLAYER) + +func _physics_process(delta: float) -> void: + if not player: + return + + var to_player = player.global_position - global_position + var dist = to_player.length() + var attract_radius = player.player_stats.get_final("pickup_radius", player.modifiers) + if dist < 4: + return + if dist < attract_radius: + var dir = to_player.normalized() + var speed = lerp(min_speed, max_speed, (attract_radius - dist) / attract_radius) + global_position += dir * speed * delta + +func pickup() -> void: + push_error("%s did not implement pickup()" % self) diff --git a/scenes/pickups/pickup_base.gd.uid b/scenes/pickups/pickup_base.gd.uid new file mode 100644 index 0000000..e7b46a2 --- /dev/null +++ b/scenes/pickups/pickup_base.gd.uid @@ -0,0 +1 @@ +uid://bo2oowrbsp2k8 diff --git a/scenes/pickups/pickup_base.tscn b/scenes/pickups/pickup_base.tscn new file mode 100644 index 0000000..a871e4d --- /dev/null +++ b/scenes/pickups/pickup_base.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://dr80h4envloce"] + +[ext_resource type="Script" uid="uid://bo2oowrbsp2k8" path="res://scenes/pickups/pickup_base.gd" id="1_oto2a"] + +[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_rs1tx"] +size = Vector2(10, 10) + +[sub_resource type="CircleShape2D" id="CircleShape2D_oto2a"] +radius = 3.16228 + +[node name="PickupBase" type="Node2D" groups=["pickup"]] +script = ExtResource("1_oto2a") + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(-1, 1) +texture = SubResource("PlaceholderTexture2D_rs1tx") + +[node name="Area2D" type="Area2D" parent="."] +collision_layer = 16 +collision_mask = 0 +monitoring = false + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +shape = SubResource("CircleShape2D_oto2a") diff --git a/scenes/pickups/pickup_magnet.gd b/scenes/pickups/pickup_magnet.gd new file mode 100644 index 0000000..163d176 --- /dev/null +++ b/scenes/pickups/pickup_magnet.gd @@ -0,0 +1,36 @@ +class_name PickupMagnet +extends PickupBase + +@export var duration: float = 15.0 + +@onready var collision_shape_2d: CollisionShape2D = $Area2D/CollisionShape2D + +func pickup() -> void: + if not player: + push_error("pickup called on %s without player set" % self) + return + + var mod: PlayerStatsModifier = PlayerStatsModifier.new() + mod.description = "Magnet massively increases pickup range for a limited amout of time" + mod.title = "Magnet" + mod.tex = GlobalConst.placeholder_tex + mod.internal_name = "magnet" + mod.rarity = GlobalConst.ModRarity.RARE + mod.stat_name = "pickup_radius" + mod.value = 5000.0 + mod.type = PlayerStatsModifier.ModifierType.ABSOLUTE + player.modifiers.append(mod) + + # Hide, and stop processing until timeout + visible = false + set_process(false) + set_physics_process(false) + collision_shape_2d.disabled = true + + await get_tree().create_timer(duration).timeout + if is_instance_valid(player): + for i in range(player.modifiers.size()): + if player.modifiers[i].internal_name == mod.internal_name: + player.modifiers.remove_at(i) + break + queue_free() diff --git a/scenes/pickups/pickup_magnet.gd.uid b/scenes/pickups/pickup_magnet.gd.uid new file mode 100644 index 0000000..adafcbb --- /dev/null +++ b/scenes/pickups/pickup_magnet.gd.uid @@ -0,0 +1 @@ +uid://54b8m2gk20ji diff --git a/scenes/pickups/pickup_magnet.tscn b/scenes/pickups/pickup_magnet.tscn new file mode 100644 index 0000000..e8fd903 --- /dev/null +++ b/scenes/pickups/pickup_magnet.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=4 format=3 uid="uid://bbev8m5g0p3a3"] + +[ext_resource type="PackedScene" uid="uid://dr80h4envloce" path="res://scenes/pickups/pickup_base.tscn" id="1_hm4ld"] +[ext_resource type="Script" uid="uid://54b8m2gk20ji" path="res://scenes/pickups/pickup_magnet.gd" id="2_00la4"] +[ext_resource type="Texture2D" uid="uid://c80xxb85fehng" path="res://assets/sprites/magnet.png" id="2_yx0vp"] + +[node name="PickupMagnet" instance=ExtResource("1_hm4ld")] +script = ExtResource("2_00la4") +duration = 15.0 + +[node name="Sprite2D" parent="." index="0"] +texture = ExtResource("2_yx0vp") diff --git a/scenes/player.gd b/scenes/player.gd index a9a95bc..ff9b092 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -111,8 +111,10 @@ func _trigger_level_up() -> void: main_ui.level_up_ui.visible = true func _on_pickup_area_area_entered(area: Area2D) -> void: - var body: XPOrb = area.get_parent() + var body: Node2D = area.get_parent() if body.is_in_group(GlobalConst.GROUP_XP_ORB): add_xp(body.value) GlobalConst.sig_debug_stats_set.emit("player_xp", "%s" % player_stats.current_xp) body.queue_free() + elif body.is_in_group(GlobalConst.GROUP_PICKUP): + body.pickup() diff --git a/scenes/player.tscn b/scenes/player.tscn index 9489c7b..0493cf5 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -27,7 +27,7 @@ player = NodePath("..") [node name="PickupArea" type="Area2D" parent="."] collision_layer = 0 -collision_mask = 8 +collision_mask = 24 monitorable = false [node name="CollisionShape2D" type="CollisionShape2D" parent="PickupArea"] diff --git a/scenes/xp_orb.gd b/scenes/xp_orb.gd index 5c08e6a..265d23b 100644 --- a/scenes/xp_orb.gd +++ b/scenes/xp_orb.gd @@ -17,9 +17,11 @@ func _physics_process(delta: float) -> void: var to_player = player.global_position - global_position var dist = to_player.length() var attract_radius = player.player_stats.get_final("pickup_radius", player.modifiers) + var adjusted_max_speed = clampf((attract_radius / 50.0) * max_speed, min_speed, max_speed * 5) + var adjusted_min_speed = clampf((attract_radius / 50.0) * min_speed, min_speed, min_speed * 5) if dist < 4: return if dist < attract_radius: var dir = to_player.normalized() - var speed = lerp(min_speed, max_speed, (attract_radius - dist) / attract_radius) + var speed = lerp(adjusted_min_speed, adjusted_max_speed, (attract_radius - dist) / attract_radius) global_position += dir * speed * delta diff --git a/scenes/xp_orb.tscn b/scenes/xp_orb.tscn index ccbfb01..d809d3f 100644 --- a/scenes/xp_orb.tscn +++ b/scenes/xp_orb.tscn @@ -6,7 +6,7 @@ [sub_resource type="CircleShape2D" id="CircleShape2D_me6n8"] radius = 5.0 -[node name="XPOrb" type="Node2D" groups=["xp_orb"]] +[node name="XPOrb" type="Node2D" groups=["pickup", "xp_orb"]] script = ExtResource("1_me6n8") [node name="Sprite2D" type="Sprite2D" parent="."]