From e8d58944415fe28efe1e57ae0b7b7f372ba3e16d Mon Sep 17 00:00:00 2001 From: Henrique Campos Date: Fri, 26 Apr 2019 05:26:24 -0300 Subject: [PATCH] Add metroidvania (#45) --- metroidvania-prototypes/mercenaries/Coins.gd | 10 + .../mercenaries/DiscoveryAreas.gd | 5 + metroidvania-prototypes/mercenaries/Game.gd | 16 ++ metroidvania-prototypes/mercenaries/Game.tscn | 234 ++++++++++++++++++ metroidvania-prototypes/mercenaries/Void.gd | 5 + .../mercenaries/actors/Capsule.tscn | 17 ++ .../mercenaries/actors/Circle.tscn | 23 ++ .../mercenaries/actors/CrushArea.gd | 35 +++ .../mercenaries/actors/CrushArea.tscn | 19 ++ .../mercenaries/actors/Glide.gd | 14 ++ .../mercenaries/actors/Gravity.gd | 10 + .../mercenaries/actors/Jump.gd | 20 ++ .../mercenaries/actors/KinematicPhysics.gd | 12 + .../mercenaries/actors/KinematicPhysics.tscn | 7 + .../mercenaries/actors/Mercenary.gd | 27 ++ .../mercenaries/actors/Mercenary.tscn | 41 +++ .../mercenaries/actors/Rectangle.tscn | 13 + .../mercenaries/actors/Walk.gd | 22 ++ .../mercenaries/default_env.tres | 8 + .../mercenaries/geometry_2d.gd | 43 ++++ metroidvania-prototypes/mercenaries/icon.png | Bin 0 -> 3433 bytes .../mercenaries/icon.png.import | 34 +++ .../mercenaries/interface/Interface.gd | 32 +++ .../mercenaries/levels/Playground.tscn | 89 +++++++ .../mercenaries/objects/Bank.gd | 17 ++ .../mercenaries/objects/Bank.tscn | 7 + .../mercenaries/objects/Coin.gd | 3 + .../mercenaries/objects/Coin.tscn | 17 ++ .../mercenaries/objects/Contract.gd | 14 ++ .../mercenaries/objects/Contract.tscn | 7 + .../objects/CrushableObstacle.tscn | 17 ++ .../mercenaries/objects/DiscoveryArea.gd | 24 ++ .../mercenaries/objects/DiscoveryArea.tscn | 17 ++ .../mercenaries/objects/MercenaryGuild.gd | 33 +++ .../objects/MercenaryPlaceholder.gd | 16 ++ .../objects/MercenaryPlaceholder.tscn | 7 + .../mercenaries/objects/MercenarySpawner.gd | 16 ++ .../mercenaries/objects/MercenarySpawner.tscn | 7 + .../mercenaries/objects/PickupArea.gd | 14 ++ .../mercenaries/objects/PickupArea.tscn | 17 ++ .../mercenaries/project.godot | 77 ++++++ 41 files changed, 1046 insertions(+) create mode 100644 metroidvania-prototypes/mercenaries/Coins.gd create mode 100644 metroidvania-prototypes/mercenaries/DiscoveryAreas.gd create mode 100644 metroidvania-prototypes/mercenaries/Game.gd create mode 100644 metroidvania-prototypes/mercenaries/Game.tscn create mode 100644 metroidvania-prototypes/mercenaries/Void.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/Capsule.tscn create mode 100644 metroidvania-prototypes/mercenaries/actors/Circle.tscn create mode 100644 metroidvania-prototypes/mercenaries/actors/CrushArea.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/CrushArea.tscn create mode 100644 metroidvania-prototypes/mercenaries/actors/Glide.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/Gravity.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/Jump.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/KinematicPhysics.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/KinematicPhysics.tscn create mode 100644 metroidvania-prototypes/mercenaries/actors/Mercenary.gd create mode 100644 metroidvania-prototypes/mercenaries/actors/Mercenary.tscn create mode 100644 metroidvania-prototypes/mercenaries/actors/Rectangle.tscn create mode 100644 metroidvania-prototypes/mercenaries/actors/Walk.gd create mode 100644 metroidvania-prototypes/mercenaries/default_env.tres create mode 100644 metroidvania-prototypes/mercenaries/geometry_2d.gd create mode 100644 metroidvania-prototypes/mercenaries/icon.png create mode 100644 metroidvania-prototypes/mercenaries/icon.png.import create mode 100644 metroidvania-prototypes/mercenaries/interface/Interface.gd create mode 100644 metroidvania-prototypes/mercenaries/levels/Playground.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/Bank.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/Bank.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/Coin.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/Coin.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/Contract.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/Contract.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/CrushableObstacle.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/DiscoveryArea.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/DiscoveryArea.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/MercenaryGuild.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/MercenarySpawner.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/MercenarySpawner.tscn create mode 100644 metroidvania-prototypes/mercenaries/objects/PickupArea.gd create mode 100644 metroidvania-prototypes/mercenaries/objects/PickupArea.tscn create mode 100644 metroidvania-prototypes/mercenaries/project.godot diff --git a/metroidvania-prototypes/mercenaries/Coins.gd b/metroidvania-prototypes/mercenaries/Coins.gd new file mode 100644 index 0000000..83ff6f5 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/Coins.gd @@ -0,0 +1,10 @@ +extends Node + +signal coin_picked(coin_value) + +func _ready(): + for coin in get_children(): + coin.connect("tree_exiting", self, "_on_Coin_tree_exiting", [coin.value]) + +func _on_Coin_tree_exiting(coin_value: int) -> void: + emit_signal("coin_picked", coin_value) diff --git a/metroidvania-prototypes/mercenaries/DiscoveryAreas.gd b/metroidvania-prototypes/mercenaries/DiscoveryAreas.gd new file mode 100644 index 0000000..9669bad --- /dev/null +++ b/metroidvania-prototypes/mercenaries/DiscoveryAreas.gd @@ -0,0 +1,5 @@ +extends Node2D + +func _ready() -> void: + for discovery_area in get_children(): + discovery_area.connect("discovered", get_parent(), "_on_DiscoveryArea_discored") diff --git a/metroidvania-prototypes/mercenaries/Game.gd b/metroidvania-prototypes/mercenaries/Game.gd new file mode 100644 index 0000000..30a5c61 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/Game.gd @@ -0,0 +1,16 @@ +extends Node + +func _on_Interface_mercenary_selected(mercenary_name): + $MercenaryGuild.hire_mercenary($Bank, mercenary_name) + + +func _on_Bank_money_changed(new_amount: int) -> void: + $InterfaceLayer/Interface.set_money_label_amount(new_amount) + + +func _on_Coins_coin_picked(coin_value): + $Bank.money += coin_value + + +func _on_DiscoveryArea_discored(mercenary_name: String) -> void: + $InterfaceLayer/Interface.enable_mercenary_button(mercenary_name) \ No newline at end of file diff --git a/metroidvania-prototypes/mercenaries/Game.tscn b/metroidvania-prototypes/mercenaries/Game.tscn new file mode 100644 index 0000000..87daec6 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/Game.tscn @@ -0,0 +1,234 @@ +[gd_scene load_steps=16 format=2] + +[ext_resource path="res://Game.gd" type="Script" id=1] +[ext_resource path="res://interface/Interface.gd" type="Script" id=2] +[ext_resource path="res://levels/Playground.tscn" type="PackedScene" id=3] +[ext_resource path="res://objects/Bank.tscn" type="PackedScene" id=4] +[ext_resource path="res://objects/MercenaryGuild.gd" type="Script" id=5] +[ext_resource path="res://objects/Contract.tscn" type="PackedScene" id=6] +[ext_resource path="res://actors/Rectangle.tscn" type="PackedScene" id=7] +[ext_resource path="res://actors/Capsule.tscn" type="PackedScene" id=8] +[ext_resource path="res://actors/Circle.tscn" type="PackedScene" id=9] +[ext_resource path="res://Coins.gd" type="Script" id=10] +[ext_resource path="res://objects/Coin.tscn" type="PackedScene" id=11] +[ext_resource path="res://DiscoveryAreas.gd" type="Script" id=12] +[ext_resource path="res://objects/DiscoveryArea.tscn" type="PackedScene" id=13] +[ext_resource path="res://Void.gd" type="Script" id=14] + +[sub_resource type="LineShape2D" id=1] + +[node name="Game" type="Node"] +script = ExtResource( 1 ) + +[node name="InterfaceLayer" type="CanvasLayer" parent="."] +editor/display_folded = true + +[node name="Interface" type="Button" parent="InterfaceLayer"] +margin_left = 20.0 +margin_top = 20.0 +margin_right = 111.0 +margin_bottom = 40.0 +toggle_mode = true +text = "Mercenaries" +script = ExtResource( 2 ) + +[node name="GridContainer" type="GridContainer" parent="InterfaceLayer/Interface"] +visible = false +margin_left = 50.0 +margin_top = 20.0 +margin_right = 240.0 +margin_bottom = 270.0 +columns = 2 + +[node name="Rectangle" type="Button" parent="InterfaceLayer/Interface/GridContainer"] +margin_right = 93.0 +margin_bottom = 64.0 +rect_min_size = Vector2( 0, 64 ) +size_flags_horizontal = 3 +text = "Rectangle" + +[node name="Capsule" type="Button" parent="InterfaceLayer/Interface/GridContainer"] +visible = false +margin_left = 97.0 +margin_right = 190.0 +margin_bottom = 64.0 +rect_min_size = Vector2( 0, 64 ) +size_flags_horizontal = 3 +text = "Capsule" + +[node name="Circle" type="Button" parent="InterfaceLayer/Interface/GridContainer"] +visible = false +margin_top = 68.0 +margin_right = 93.0 +margin_bottom = 132.0 +rect_min_size = Vector2( 0, 64 ) +size_flags_horizontal = 3 +text = "Circle" + +[node name="MoneyLabel" type="Label" parent="InterfaceLayer/Interface"] +margin_left = 810.0 +margin_right = 900.0 +margin_bottom = 20.0 +text = "Money: 0000" + +[node name="Playground" parent="." instance=ExtResource( 3 )] + +[node name="Bank" parent="." instance=ExtResource( 4 )] + +[node name="MercenaryGuild" type="Node" parent="."] +script = ExtResource( 5 ) + +[node name="Contract" parent="MercenaryGuild" instance=ExtResource( 6 )] +cost = 100 + +[node name="Rectangle" parent="MercenaryGuild" instance=ExtResource( 7 )] +position = Vector2( 350, 540 ) + +[node name="Capsule" parent="MercenaryGuild" instance=ExtResource( 8 )] +position = Vector2( 190, 229 ) + +[node name="Circle" parent="MercenaryGuild" instance=ExtResource( 9 )] +position = Vector2( 1510, 540 ) + +[node name="Coins" type="Node" parent="."] +editor/display_folded = true +script = ExtResource( 10 ) + +[node name="Coin" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 670, 460 ) + +[node name="Coin24" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 670, 320 ) + +[node name="Coin26" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -140, 140 ) + +[node name="Coin31" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -240, 160 ) + +[node name="Coin33" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -340, 190 ) + +[node name="Coin38" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -490, 280 ) + +[node name="Coin16" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -670, 500 ) + +[node name="Coin30" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -560, 360 ) + +[node name="Coin17" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -760, 590 ) + +[node name="Coin37" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -630, 450 ) + +[node name="Coin18" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -850, 690 ) + +[node name="Coin35" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -720, 550 ) + +[node name="Coin19" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -910, 770 ) + +[node name="Coin36" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( -810, 630 ) + +[node name="Coin4" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 520, 500 ) + +[node name="Coin23" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 520, 360 ) + +[node name="Coin5" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 520, 460 ) + +[node name="Coin40" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 520, 320 ) + +[node name="Coin6" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 570, 460 ) + +[node name="Coin41" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 570, 320 ) + +[node name="Coin7" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 570, 500 ) + +[node name="Coin29" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 570, 360 ) + +[node name="Coin8" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 670, 500 ) + +[node name="Coin28" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 670, 360 ) + +[node name="Coin9" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 720, 460 ) + +[node name="Coin39" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 720, 320 ) + +[node name="Coin20" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 720, 500 ) + +[node name="Coin42" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 720, 360 ) + +[node name="Coin21" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 770, 500 ) + +[node name="Coin32" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 770, 360 ) + +[node name="Coin22" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 770, 460 ) + +[node name="Coin27" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 770, 320 ) + +[node name="Coin10" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 620, 500 ) + +[node name="Coin25" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 620, 360 ) + +[node name="Coin11" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 620, 460 ) + +[node name="Coin34" parent="Coins" instance=ExtResource( 11 )] +position = Vector2( 620, 320 ) + +[node name="DiscoveryAreas" type="Node2D" parent="."] +script = ExtResource( 12 ) + +[node name="CapsuleDiscoveryArea" parent="DiscoveryAreas" instance=ExtResource( 13 )] +position = Vector2( 190, 229 ) +discovered_mercenary = 2 + +[node name="CircleDiscoveryArea2" parent="DiscoveryAreas" instance=ExtResource( 13 )] +position = Vector2( 1520, 540 ) +discovered_mercenary = 1 + +[node name="Void" type="Area2D" parent="."] +position = Vector2( -240, 1020 ) +script = ExtResource( 14 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Void"] +shape = SubResource( 1 ) + +[node name="Win" type="Label" parent="."] +margin_left = -1050.0 +margin_top = 760.0 +margin_right = -973.0 +margin_bottom = 774.0 +text = "You won! lol" + +[connection signal="mercenary_selected" from="InterfaceLayer/Interface" to="." method="_on_Interface_mercenary_selected"] +[connection signal="toggled" from="InterfaceLayer/Interface" to="InterfaceLayer/Interface/GridContainer" method="set_visible"] +[connection signal="money_changed" from="Bank" to="." method="_on_Bank_money_changed"] +[connection signal="coin_picked" from="Coins" to="." method="_on_Coins_coin_picked"] +[connection signal="body_entered" from="Void" to="Void" method="_on_body_entered"] diff --git a/metroidvania-prototypes/mercenaries/Void.gd b/metroidvania-prototypes/mercenaries/Void.gd new file mode 100644 index 0000000..3d6ebae --- /dev/null +++ b/metroidvania-prototypes/mercenaries/Void.gd @@ -0,0 +1,5 @@ +extends Area2D + +func _on_body_entered(body): + get_tree().reload_current_scene() + diff --git a/metroidvania-prototypes/mercenaries/actors/Capsule.tscn b/metroidvania-prototypes/mercenaries/actors/Capsule.tscn new file mode 100644 index 0000000..d5af680 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Capsule.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://actors/Mercenary.tscn" type="PackedScene" id=1] +[ext_resource path="res://actors/Glide.gd" type="Script" id=2] + +[sub_resource type="CapsuleShape2D" id=1] +radius = 20.0 + +[node name="Mercenary" instance=ExtResource( 1 )] + +[node name="Geometry2D" parent="." index="0"] +shape = SubResource( 1 ) +color = Color( 0.247059, 0.4, 1, 1 ) + +[node name="Glide" type="Node" parent="." index="4"] +script = ExtResource( 2 ) + diff --git a/metroidvania-prototypes/mercenaries/actors/Circle.tscn b/metroidvania-prototypes/mercenaries/actors/Circle.tscn new file mode 100644 index 0000000..4f10d2e --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Circle.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://actors/Mercenary.tscn" type="PackedScene" id=1] + +[sub_resource type="CircleShape2D" id=1] +radius = 30.0 + +[node name="Circle" instance=ExtResource( 1 )] + +[node name="Geometry2D" parent="." index="0"] +shape = SubResource( 1 ) +color = Color( 1, 0.635294, 0.247059, 1 ) + +[node name="Gravity" parent="." index="1"] +kinematic_body2D_path = NodePath("..") + +[node name="Jump" parent="." index="2"] +kinematic_body2D_path = NodePath("..") +max_jumps = 2 + +[node name="Walk" parent="." index="3"] +kinematic_body2D_path = NodePath("..") + diff --git a/metroidvania-prototypes/mercenaries/actors/CrushArea.gd b/metroidvania-prototypes/mercenaries/actors/CrushArea.gd new file mode 100644 index 0000000..90f7d44 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/CrushArea.gd @@ -0,0 +1,35 @@ +extends Area2D + +signal crush_started +signal crush_finished + +onready var kinematic_body2D: KinematicBody2D = get_node(kinematic_body2D_path) as KinematicBody2D +onready var shape: CollisionPolygon2D = $CollisionPolygon2D as CollisionPolygon2D +onready var timer: Timer = $Timer as Timer + +export (NodePath) var kinematic_body2D_path: NodePath = ".." +export (float) var smash_velocity := 300.0 + +func _unhandled_input(event): + if timer.time_left > 0.0: + return + if event.is_action_pressed("crush"): + crush() + +func crush() -> void: + if not kinematic_body2D.is_on_floor(): + return + + emit_signal("crush_started") + visible = true + shape.disabled = false + timer.start() + yield(timer, "timeout") + + shape.disabled = true + visible = false + emit_signal("crush_finished") + + +func _on_body_entered(body: CollisionObject2D): + body.queue_free() diff --git a/metroidvania-prototypes/mercenaries/actors/CrushArea.tscn b/metroidvania-prototypes/mercenaries/actors/CrushArea.tscn new file mode 100644 index 0000000..af308ce --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/CrushArea.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://actors/CrushArea.gd" type="Script" id=1] + +[node name="CrushArea" type="Area2D"] +visible = false +collision_layer = 0 +collision_mask = 2 +script = ExtResource( 1 ) + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."] +polygon = PoolVector2Array( -90, 0, -90, -40, 90, -40, 90, 0 ) +disabled = true + +[node name="Timer" type="Timer" parent="."] +wait_time = 0.25 +one_shot = true + +[connection signal="body_entered" from="." to="." method="_on_body_entered"] diff --git a/metroidvania-prototypes/mercenaries/actors/Glide.gd b/metroidvania-prototypes/mercenaries/actors/Glide.gd new file mode 100644 index 0000000..beebb13 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Glide.gd @@ -0,0 +1,14 @@ +extends "res://actors/KinematicPhysics.gd" + +export (float) var fall_threshold := 50.0 + +var falling_speed := 0.0 + +func _physics_process(delta: float) -> void: + var is_falling: bool = kinematic_body2D.velocity.y > fall_threshold + if not is_falling: + return + if Input.is_action_just_pressed("glide"): + falling_speed = kinematic_body2D.velocity.y + if Input.is_action_pressed("glide"): + kinematic_body2D.velocity.y = falling_speed diff --git a/metroidvania-prototypes/mercenaries/actors/Gravity.gd b/metroidvania-prototypes/mercenaries/actors/Gravity.gd new file mode 100644 index 0000000..a32756d --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Gravity.gd @@ -0,0 +1,10 @@ +extends "res://actors/KinematicPhysics.gd" + +export (float) var acceleration := 50.0 +export (Vector2) var direction := Vector2(0, 1) + +func _physics_process(delta: float) -> void: + if kinematic_body2D.is_on_floor(): + kinematic_body2D.velocity.y = 0 + return + kinematic_body2D.velocity += acceleration * direction diff --git a/metroidvania-prototypes/mercenaries/actors/Jump.gd b/metroidvania-prototypes/mercenaries/actors/Jump.gd new file mode 100644 index 0000000..be53704 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Jump.gd @@ -0,0 +1,20 @@ +extends "res://actors/KinematicPhysics.gd" + +export (float) var strength := 300.0 +export (int) var max_jumps := 1 + +var _available_jumps: int = 1 + +func _physics_process(delta: float) -> void: + if kinematic_body2D.is_on_floor(): + _available_jumps = max_jumps + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("jump"): + apply() + +func apply() -> void: + if _available_jumps > 0: + kinematic_body2D.velocity.y = -strength + _available_jumps -= 1 + _available_jumps = max(0, _available_jumps) \ No newline at end of file diff --git a/metroidvania-prototypes/mercenaries/actors/KinematicPhysics.gd b/metroidvania-prototypes/mercenaries/actors/KinematicPhysics.gd new file mode 100644 index 0000000..0227386 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/KinematicPhysics.gd @@ -0,0 +1,12 @@ +extends Node + +onready var kinematic_body2D: KinematicBody2D = get_node(kinematic_body2D_path) as KinematicBody2D + +export (NodePath) var kinematic_body2D_path: NodePath = ".." + +func _ready(): + kinematic_body2D.connect("tree_exiting", self, "_on_KinematicBody2D_tree_exiting") + + +func _on_KinematicBody2D_tree_exiting() -> void: + set_physics_process(false) \ No newline at end of file diff --git a/metroidvania-prototypes/mercenaries/actors/KinematicPhysics.tscn b/metroidvania-prototypes/mercenaries/actors/KinematicPhysics.tscn new file mode 100644 index 0000000..9d442ab --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/KinematicPhysics.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://actors/KinematicPhysics.gd" type="Script" id=1] + +[node name="KinematicPhysics" type="Node"] +script = ExtResource( 1 ) + diff --git a/metroidvania-prototypes/mercenaries/actors/Mercenary.gd b/metroidvania-prototypes/mercenaries/actors/Mercenary.gd new file mode 100644 index 0000000..f65a2cc --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Mercenary.gd @@ -0,0 +1,27 @@ +extends KinematicBody2D +class_name Mercenary + +const FLOOR_NORMAL := Vector2(0, -1) +var velocity := Vector2(0, 0) + +var active := false setget set_active + +func _ready() -> void: + set_active(false) + +func _physics_process(delta: float) -> void: + move_and_slide(velocity, FLOOR_NORMAL, true) + +func get_geometry() -> Geometry2D: + return get_node("Geometry2D") as Geometry2D + +func set_active(is_active: bool) -> void: + for child in get_children(): + child.set_process(is_active) + child.set_physics_process(is_active) + child.set_process_unhandled_input(is_active) + + set_physics_process(is_active) + $Camera2D.current = is_active + $PickupArea.set_detection_active(is_active) + active = is_active diff --git a/metroidvania-prototypes/mercenaries/actors/Mercenary.tscn b/metroidvania-prototypes/mercenaries/actors/Mercenary.tscn new file mode 100644 index 0000000..43dcc9e --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Mercenary.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://actors/Mercenary.gd" type="Script" id=1] +[ext_resource path="res://geometry_2d.gd" type="Script" id=2] +[ext_resource path="res://actors/Gravity.gd" type="Script" id=3] +[ext_resource path="res://actors/Jump.gd" type="Script" id=4] +[ext_resource path="res://actors/Walk.gd" type="Script" id=5] +[ext_resource path="res://objects/PickupArea.tscn" type="PackedScene" id=6] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 20, 30 ) + +[node name="Mercenary" type="KinematicBody2D"] +script = ExtResource( 1 ) + +[node name="Geometry2D" type="CollisionShape2D" parent="."] +position = Vector2( 0, -30 ) +shape = SubResource( 1 ) +script = ExtResource( 2 ) + +[node name="Gravity" type="Node" parent="."] +script = ExtResource( 3 ) + +[node name="Jump" type="Node" parent="."] +script = ExtResource( 4 ) +strength = 800.0 + +[node name="Walk" type="Node" parent="."] +script = ExtResource( 5 ) +speed = 400.0 + +[node name="PickupArea" parent="." instance=ExtResource( 6 )] +collision_layer = 4 +collision_mask = 12 + +[node name="Camera2D" type="Camera2D" parent="."] +position = Vector2( 0, -60 ) +current = true +smoothing_enabled = true +editor_draw_drag_margin = true + diff --git a/metroidvania-prototypes/mercenaries/actors/Rectangle.tscn b/metroidvania-prototypes/mercenaries/actors/Rectangle.tscn new file mode 100644 index 0000000..d4b6711 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Rectangle.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://actors/Mercenary.tscn" type="PackedScene" id=1] +[ext_resource path="res://actors/CrushArea.tscn" type="PackedScene" id=2] + +[node name="Mercenary" instance=ExtResource( 1 )] +position = Vector2( 320, 170 ) + +[node name="Geometry2D" parent="." index="0"] +color = Color( 0.0980392, 1, 0.72549, 1 ) + +[node name="CrushArea" parent="." index="4" instance=ExtResource( 2 )] + diff --git a/metroidvania-prototypes/mercenaries/actors/Walk.gd b/metroidvania-prototypes/mercenaries/actors/Walk.gd new file mode 100644 index 0000000..85cfb53 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/actors/Walk.gd @@ -0,0 +1,22 @@ +extends Node + +onready var kinematic_body2D: KinematicBody2D = get_node(kinematic_body2D_path) as KinematicBody2D + +export (NodePath) var kinematic_body2D_path: NodePath = ".." +export (float) var speed := 200.0 + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("walk_left"): + kinematic_body2D.velocity.x = -speed + elif event.is_action_pressed("walk_right"): + kinematic_body2D.velocity.x = speed + + if event.is_action_released("walk_left") and not Input.is_action_pressed("walk_right"): + kinematic_body2D.velocity.x = 0.0 + elif event.is_action_released("walk_right") and not Input.is_action_pressed("walk_left"): + kinematic_body2D.velocity.x = 0.0 + elif event.is_action_released("walk_left") and Input.is_action_pressed("walk_right"): + kinematic_body2D.velocity.x = speed + elif event.is_action_released("walk_right") and Input.is_action_pressed("walk_left"): + kinematic_body2D.velocity.x = -speed + diff --git a/metroidvania-prototypes/mercenaries/default_env.tres b/metroidvania-prototypes/mercenaries/default_env.tres new file mode 100644 index 0000000..bed4799 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/default_env.tres @@ -0,0 +1,8 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) + diff --git a/metroidvania-prototypes/mercenaries/geometry_2d.gd b/metroidvania-prototypes/mercenaries/geometry_2d.gd new file mode 100644 index 0000000..3f60acd --- /dev/null +++ b/metroidvania-prototypes/mercenaries/geometry_2d.gd @@ -0,0 +1,43 @@ +# Geometry2D +# author: Henrique "Pigdev" Campos +""" +Draws a Shape2D using CollisionShape2D's editor plugin's handles +--- +Notes + +Don't use it as direct child of CollisionBody2D classes unless you intent +to use it as its CollisionShape2D. +""" + +tool +extends CollisionShape2D +class_name Geometry2D + +export (Color) var color := Color(1, 1, 1, 1) setget set_color +export (Vector2) var offset_position := Vector2(0, 0) + +func set_color(new_color: Color) -> void: + color = new_color + update() + +func _draw() -> void: + if shape is CircleShape2D: + draw_circle(offset_position, shape.radius, color) + elif shape is RectangleShape2D: + var rect := Rect2(offset_position - shape.extents, shape.extents * 2.0) + draw_rect(rect, color) + elif shape is CapsuleShape2D: + draw_capsule(offset_position, shape.radius, shape.height, color) + +func draw_capsule(capsule_position: Vector2, capsule_radius: float, + capsule_height: float, capsule_color: Color) -> void: + + var upper_circle_position: Vector2 = capsule_position + Vector2(0, capsule_height * 0.5) + draw_circle(upper_circle_position, capsule_radius, capsule_color) + + var lower_circle_position: Vector2 = capsule_position - Vector2(0, capsule_height * 0.5) + draw_circle(lower_circle_position, capsule_radius, capsule_color) + + var rect_position: Vector2 = capsule_position - Vector2(capsule_radius, capsule_height * 0.5) + var rect := Rect2(rect_position, Vector2(capsule_radius * 2, capsule_height)) + draw_rect(rect, capsule_color) diff --git a/metroidvania-prototypes/mercenaries/icon.png b/metroidvania-prototypes/mercenaries/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2b658158b6a2211b656d83fee35e3941e5ad376a GIT binary patch literal 3433 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 LNkvXXu0mjfd922> literal 0 HcmV?d00001 diff --git a/metroidvania-prototypes/mercenaries/icon.png.import b/metroidvania-prototypes/mercenaries/icon.png.import new file mode 100644 index 0000000..96cbf46 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/metroidvania-prototypes/mercenaries/interface/Interface.gd b/metroidvania-prototypes/mercenaries/interface/Interface.gd new file mode 100644 index 0000000..d729c69 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/interface/Interface.gd @@ -0,0 +1,32 @@ +extends Button + +signal mercenary_selected(mercenary_name) + +func _ready() -> void: + for button in $GridContainer.get_children(): + button.connect("button_up", self, "_on_mercenary_selected", [button.text]) + + +func _on_mercenary_selected(mercenary_name: String) -> void: + emit_signal("mercenary_selected", mercenary_name) + release_focus() + pressed = false + emit_signal("toggled", pressed) + + +func set_money_label_amount(amount: int) -> void: + $MoneyLabel.text = "Money: $%s"%[amount] + + +func enable_mercenary_button(mercenary_name: String) -> void: + var button: Button = $GridContainer/Rectangle + match mercenary_name: + "Rectangle": + button = $GridContainer/Rectangle + "Capsule": + button = $GridContainer/Capsule + "Circle": + button = $GridContainer/Circle + + button.visible = true + diff --git a/metroidvania-prototypes/mercenaries/levels/Playground.tscn b/metroidvania-prototypes/mercenaries/levels/Playground.tscn new file mode 100644 index 0000000..d301961 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/levels/Playground.tscn @@ -0,0 +1,89 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://geometry_2d.gd" type="Script" id=1] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 270, 30 ) + +[sub_resource type="RectangleShape2D" id=3] +extents = Vector2( 160, 30 ) + +[sub_resource type="RectangleShape2D" id=2] +extents = Vector2( 10, 50 ) + +[sub_resource type="RectangleShape2D" id=4] +extents = Vector2( 20, 100 ) + +[node name="Playground" type="Node2D"] + +[node name="StaticBody2D" type="StaticBody2D" parent="."] + +[node name="Geometry2D" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2( 270, 570 ) +shape = SubResource( 1 ) +script = ExtResource( 1 ) +color = Color( 0.231373, 0.172549, 0.141176, 1 ) + +[node name="Geometry2D2" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2( 810, 570 ) +shape = SubResource( 1 ) +script = ExtResource( 1 ) +color = Color( 0.231373, 0.172549, 0.141176, 1 ) + +[node name="Geometry2D3" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2( 1350, 570 ) +shape = SubResource( 1 ) +script = ExtResource( 1 ) +color = Color( 0.231373, 0.172549, 0.141176, 1 ) + +[node name="Geometry2D4" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2( 640, 410 ) +shape = SubResource( 3 ) +script = ExtResource( 1 ) +color = Color( 0.231373, 0.172549, 0.141176, 1 ) + +[node name="Geometry2D5" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2( 190, 260 ) +shape = SubResource( 3 ) +script = ExtResource( 1 ) +color = Color( 0.231373, 0.172549, 0.141176, 1 ) + +[node name="Geometry2D6" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2( -1070, 850 ) +shape = SubResource( 3 ) +script = ExtResource( 1 ) +color = Color( 0.231373, 0.172549, 0.141176, 1 ) + +[node name="Obstacles" type="Node2D" parent="."] + +[node name="Wall" type="StaticBody2D" parent="Obstacles"] +position = Vector2( 490, 490 ) +collision_layer = 3 +collision_mask = 0 + +[node name="Geometry2D" type="CollisionShape2D" parent="Obstacles/Wall"] +shape = SubResource( 2 ) +script = ExtResource( 1 ) +color = Color( 0.521569, 0.113725, 0.231373, 1 ) + +[node name="Wall2" type="StaticBody2D" parent="Obstacles"] +position = Vector2( 790, 490 ) +collision_layer = 3 +collision_mask = 0 + +[node name="Geometry2D" type="CollisionShape2D" parent="Obstacles/Wall2"] +shape = SubResource( 2 ) +script = ExtResource( 1 ) +color = Color( 0.521569, 0.113725, 0.231373, 1 ) + +[node name="Wall3" type="StaticBody2D" parent="Obstacles"] +position = Vector2( 1320, 490 ) +collision_layer = 3 +collision_mask = 0 + +[node name="Geometry2D" type="CollisionShape2D" parent="Obstacles/Wall3"] +position = Vector2( 0, -50 ) +shape = SubResource( 4 ) +script = ExtResource( 1 ) +color = Color( 0.521569, 0.113725, 0.231373, 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/Bank.gd b/metroidvania-prototypes/mercenaries/objects/Bank.gd new file mode 100644 index 0000000..d6b8873 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/Bank.gd @@ -0,0 +1,17 @@ +extends Node +class_name Bank + +""" +Manage the player's money +""" +signal money_changed(new_amount) + +var money := 0 setget set_money + +func _ready() -> void: + set_money(money) + + +func set_money(value: int) -> void: + money = value + emit_signal("money_changed", money) diff --git a/metroidvania-prototypes/mercenaries/objects/Bank.tscn b/metroidvania-prototypes/mercenaries/objects/Bank.tscn new file mode 100644 index 0000000..16158f7 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/Bank.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://objects/Bank.gd" type="Script" id=1] + +[node name="Bank" type="Node"] +script = ExtResource( 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/Coin.gd b/metroidvania-prototypes/mercenaries/objects/Coin.gd new file mode 100644 index 0000000..29f7a6c --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/Coin.gd @@ -0,0 +1,3 @@ +extends Area2D + +export (int) var value := 5 \ No newline at end of file diff --git a/metroidvania-prototypes/mercenaries/objects/Coin.tscn b/metroidvania-prototypes/mercenaries/objects/Coin.tscn new file mode 100644 index 0000000..ce1de50 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/Coin.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://objects/Coin.gd" type="Script" id=1] +[ext_resource path="res://geometry_2d.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] + +[node name="Coin" type="Area2D"] +collision_layer = 8 +collision_mask = 0 +script = ExtResource( 1 ) + +[node name="Geometry2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 2 ) +color = Color( 1, 0.796078, 0.188235, 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/Contract.gd b/metroidvania-prototypes/mercenaries/objects/Contract.gd new file mode 100644 index 0000000..9fb6faa --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/Contract.gd @@ -0,0 +1,14 @@ +extends Node + +""" +Manage the costs of a mercenary +""" + +export (int) var cost := 10 + + +func can_contract(available_money: int) -> bool: + var can_contract := false + + can_contract = available_money - cost >= 0 + return can_contract diff --git a/metroidvania-prototypes/mercenaries/objects/Contract.tscn b/metroidvania-prototypes/mercenaries/objects/Contract.tscn new file mode 100644 index 0000000..98639a6 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/Contract.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://objects/Contract.gd" type="Script" id=1] + +[node name="Contract" type="Node"] +script = ExtResource( 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/CrushableObstacle.tscn b/metroidvania-prototypes/mercenaries/objects/CrushableObstacle.tscn new file mode 100644 index 0000000..9f85eae --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/CrushableObstacle.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://geometry_2d.gd" type="Script" id=1] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 30, 130 ) + +[node name="CrushableObstacle" type="StaticBody2D"] +collision_layer = 3 +collision_mask = 0 + +[node name="Geometry2D" type="CollisionShape2D" parent="."] +position = Vector2( 0, -130 ) +shape = SubResource( 1 ) +script = ExtResource( 1 ) +color = Color( 1, 0.223529, 0.423529, 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/DiscoveryArea.gd b/metroidvania-prototypes/mercenaries/objects/DiscoveryArea.gd new file mode 100644 index 0000000..5018423 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/DiscoveryArea.gd @@ -0,0 +1,24 @@ +extends Area2D + +signal discovered(mercenary) + +const RECTANGLE := "Rectangle" +const CIRCLE := "Circle" +const CAPSULE := "Capsule" + +enum Mercenaries{RECTANGLE, CIRCLE, CAPSULE} + +export (Mercenaries) var discovered_mercenary: int = 0 + +func _on_area_entered(area: CollisionObject2D) -> void: + var mercenary_name: = RECTANGLE + match discovered_mercenary: + 0: + mercenary_name = RECTANGLE + 1: + mercenary_name = CIRCLE + 2: + mercenary_name = CAPSULE + emit_signal("discovered", mercenary_name) + + queue_free() diff --git a/metroidvania-prototypes/mercenaries/objects/DiscoveryArea.tscn b/metroidvania-prototypes/mercenaries/objects/DiscoveryArea.tscn new file mode 100644 index 0000000..1fd9eee --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/DiscoveryArea.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://objects/DiscoveryArea.gd" type="Script" id=1] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 100, 80 ) + +[node name="DiscoveryArea" type="Area2D"] +collision_layer = 0 +collision_mask = 4 +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( 0, -80 ) +shape = SubResource( 1 ) + +[connection signal="area_entered" from="." to="." method="_on_area_entered"] diff --git a/metroidvania-prototypes/mercenaries/objects/MercenaryGuild.gd b/metroidvania-prototypes/mercenaries/objects/MercenaryGuild.gd new file mode 100644 index 0000000..3a7839c --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/MercenaryGuild.gd @@ -0,0 +1,33 @@ +extends Node + +""" +Manage the control over a given mercenary +""" + +onready var current_mercenary: Mercenary = $Rectangle + +func _ready(): + current_mercenary.active = true + +func hire_mercenary(bank_account: Bank, mercenary_name: String) -> bool: + var can_hire: bool = $Contract.can_contract(bank_account.money) + + if not can_hire: + return false + + var mercenary: Mercenary + match mercenary_name: + "Rectangle": + mercenary = $Rectangle + "Capsule": + mercenary = $Capsule + "Circle": + mercenary = $Circle + + if not current_mercenary == mercenary: + current_mercenary.active = false + current_mercenary = mercenary + mercenary.active = true + + bank_account.money -= $Contract.cost + return can_hire diff --git a/metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.gd b/metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.gd new file mode 100644 index 0000000..2f07f02 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.gd @@ -0,0 +1,16 @@ +extends Position2D + +""" +A dummy mercenary that shall only replicate a reference mercenary's +appearence +""" + +export (PackedScene) var mercenary_scene: PackedScene = preload("res://actors/Mercenary.tscn") + +func _ready(): + var mercenary: Mercenary = mercenary_scene.instance() + var appearence: Geometry2D = mercenary.get_geometry() + + appearence = appearence.duplicate() + add_child(appearence) + mercenary.queue_free() diff --git a/metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.tscn b/metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.tscn new file mode 100644 index 0000000..245077d --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/MercenaryPlaceholder.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://objects/MercenaryPlaceholder.gd" type="Script" id=1] + +[node name="MercenaryPlaceholder" type="Position2D"] +script = ExtResource( 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/MercenarySpawner.gd b/metroidvania-prototypes/mercenaries/objects/MercenarySpawner.gd new file mode 100644 index 0000000..248766b --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/MercenarySpawner.gd @@ -0,0 +1,16 @@ +extends Node2D + +""" +Creates an instance of a mercenary inside a reference node's hierachy +at the current position of the spawner. +""" + +export (PackedScene) var mercenary_scene: PackedScene = preload("res://actors/Mercenary.tscn") +export (NodePath) var instance_parent: NodePath = ".." + +func spawn() -> Mercenary: + var new_mercenary: Mercenary = mercenary_scene.instance() as Mercenary + new_mercenary.global_position = global_position + + get_node(instance_parent).add_child(new_mercenary) + return new_mercenary as Mercenary diff --git a/metroidvania-prototypes/mercenaries/objects/MercenarySpawner.tscn b/metroidvania-prototypes/mercenaries/objects/MercenarySpawner.tscn new file mode 100644 index 0000000..9310676 --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/MercenarySpawner.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://objects/MercenarySpawner.gd" type="Script" id=1] + +[node name="MercenarySpawner" type="Node2D"] +script = ExtResource( 1 ) + diff --git a/metroidvania-prototypes/mercenaries/objects/PickupArea.gd b/metroidvania-prototypes/mercenaries/objects/PickupArea.gd new file mode 100644 index 0000000..740c6fd --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/PickupArea.gd @@ -0,0 +1,14 @@ +extends Area2D + +onready var shape = $CollisionShape2D + +var detection_active: bool = false setget set_detection_active + +func _ready(): + set_detection_active(detection_active) + +func set_detection_active(active: bool) -> void: + shape.disabled = not active + +func _on_area_entered(area: Area2D): + area.queue_free() diff --git a/metroidvania-prototypes/mercenaries/objects/PickupArea.tscn b/metroidvania-prototypes/mercenaries/objects/PickupArea.tscn new file mode 100644 index 0000000..d03705e --- /dev/null +++ b/metroidvania-prototypes/mercenaries/objects/PickupArea.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://objects/PickupArea.gd" type="Script" id=1] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 30, 40 ) + +[node name="PickupArea" type="Area2D"] +collision_layer = 0 +collision_mask = 4 +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( 0, -40 ) +shape = SubResource( 1 ) + +[connection signal="area_entered" from="." to="." method="_on_area_entered"] diff --git a/metroidvania-prototypes/mercenaries/project.godot b/metroidvania-prototypes/mercenaries/project.godot new file mode 100644 index 0000000..4a6ee0e --- /dev/null +++ b/metroidvania-prototypes/mercenaries/project.godot @@ -0,0 +1,77 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ { +"base": "Node", +"class": "Bank", +"language": "GDScript", +"path": "res://objects/Bank.gd" +}, { +"base": "CollisionShape2D", +"class": "Geometry2D", +"language": "GDScript", +"path": "res://geometry_2d.gd" +}, { +"base": "KinematicBody2D", +"class": "Mercenary", +"language": "GDScript", +"path": "res://actors/Mercenary.gd" +} ] +_global_script_class_icons={ +"Bank": "", +"Geometry2D": "", +"Mercenary": "" +} + +[application] + +config/name="Mercenaries" +config/icon="res://icon.png" + +[input] + +jump={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null) + ] +} +walk_left={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null) + ] +} +walk_right={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null) + ] +} +crush={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"unicode":0,"echo":false,"script":null) + ] +} +glide={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null) + ] +} + +[layer_names] + +2d_physics/layer_2="crushable" + +[rendering] + +environment/default_environment="res://default_env.tres"