From 3fe50a6865c61df25edac264997a008fa99717d4 Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Sun, 8 Jan 2023 12:11:09 +0000 Subject: [PATCH] Make olives squishable in the press --- characters/player/Player.gd | 34 +++++- characters/player/Player.tscn | 6 + levels/Level0A.tscn | 15 ++- project.godot | 1 + scenery/facilities/Press.gd | 175 ++++++++++++++++++++++++++++ scenery/facilities/Press.tscn | 45 +++++-- scenery/facilities/Wheelbarrow.gd | 9 ++ scenery/facilities/Wheelbarrow.tscn | 2 +- 8 files changed, 266 insertions(+), 21 deletions(-) create mode 100644 scenery/facilities/Press.gd diff --git a/characters/player/Player.gd b/characters/player/Player.gd index 393ddcd..0ef98f5 100644 --- a/characters/player/Player.gd +++ b/characters/player/Player.gd @@ -1,6 +1,6 @@ extends KinematicBody2D -const SPEED_MULTIPLIER_WHEN_ATTACHED = 0.8 +const SPEED_MULTIPLIER_WHEN_ATTACHED = 0.7 export var speed = 200 # How fast the player will move (pixels/sec). var screen_size # Size of the game window. @@ -30,7 +30,6 @@ func _physics_process(_delta): $InteractionArea.rotation = direction.angle() else: $AnimatedSprite.stop() - func _process(_delta): if Input.is_action_just_pressed("interact"): @@ -53,3 +52,34 @@ func _process(_delta): if body.is_in_group("interactable"): print("interactable!") body.interact(self) + +var press_area_press = null + +func on_press_area_entered(press: Node2D): + press_area_press = press + if press.crushing_needed(): + self._crush_jump() + + +func on_press_area_exited(press: Node2D): + press_area_press = null + + +var is_crush_jumping = false +func _crush_jump(): + if is_crush_jumping: + return + is_crush_jumping = true + $Tween.interpolate_property($AnimatedSprite, "position:y", 0, -72, 0.3, Tween.TRANS_QUAD, Tween.EASE_OUT) + $Tween.interpolate_property($AnimatedSprite, "position:y", -72, 0, 0.3, Tween.TRANS_QUAD, Tween.EASE_IN, 0.3) + $Tween.start() + + +func _on_Tween_tween_all_completed(): + $Tween.remove_all() + if is_crush_jumping: + is_crush_jumping = false + if press_area_press != null: + press_area_press.crush() + if press_area_press.crushing_needed(): + self._crush_jump() diff --git a/characters/player/Player.tscn b/characters/player/Player.tscn index 12bf49c..a13d6ae 100644 --- a/characters/player/Player.tscn +++ b/characters/player/Player.tscn @@ -16,6 +16,8 @@ animations = [ { radius = 23.0217 [node name="Player" type="KinematicBody2D"] +position = Vector2( 0, -14 ) +collision_layer = 9 script = ExtResource( 2 ) __meta__ = { "_edit_horizontal_guides_": [ -111.0 ] @@ -41,3 +43,7 @@ collision_mask = 2 polygon = PoolVector2Array( 0, -21, 20, -8, 20, 12, 0, 24, 0, 35, 52, 21, 52, -20, 0, -32 ) [node name="PlayerAttachmentManager" parent="." instance=ExtResource( 3 )] + +[node name="Tween" type="Tween" parent="."] + +[connection signal="tween_all_completed" from="Tween" to="." method="_on_Tween_tween_all_completed"] diff --git a/levels/Level0A.tscn b/levels/Level0A.tscn index f91764e..5b02f57 100644 --- a/levels/Level0A.tscn +++ b/levels/Level0A.tscn @@ -20,17 +20,20 @@ tile_set = ExtResource( 1 ) format = 1 tile_data = PoolIntArray( 262145, 5, 0, 262146, 1, 0, 262147, 1, 0, 262148, 1, 0, 262149, 1, 0, 262150, 2, 0, 262151, 3, 0, 262152, 1, 0, 262153, 1, 0, 262154, 1, 0, 262155, 1, 0, 262156, 1, 0, 262157, 1, 0, 262158, 6, 0, 327681, 4, 0, 327694, 7, 0, 393217, 4, 0, 393226, 4, 0, 393227, 1, 0, 393228, 9, 0, 393229, 1, 0, 393230, 7, 0, 458753, 4, 0, 458762, 4, 0, 458766, 7, 0, 524289, 3, 0, 524290, 1, 0, 524291, 2, 0, 524292, 3, 0, 524293, 1, 0, 524294, 1, 0, 524295, 1, 0, 524296, 1, 0, 524297, 1, 0, 524298, 1, 0, 524299, 1, 0, 524300, 1, 0, 524301, 1, 0, 524302, 2, 0 ) -[node name="Press" parent="." instance=ExtResource( 5 )] -position = Vector2( 120, 257 ) +[node name="YSort" type="YSort" parent="."] +z_index = 5 -[node name="Player" parent="." instance=ExtResource( 2 )] +[node name="Press" parent="YSort" instance=ExtResource( 5 )] +position = Vector2( 247, 391 ) + +[node name="Player" parent="YSort" instance=ExtResource( 2 )] position = Vector2( 486, 154 ) -[node name="Node2D" parent="." instance=ExtResource( 3 )] +[node name="Node2D" parent="YSort" instance=ExtResource( 3 )] position = Vector2( 701, 189 ) -[node name="Node2D2" parent="." instance=ExtResource( 3 )] +[node name="Node2D2" parent="YSort" instance=ExtResource( 3 )] position = Vector2( 135, 190 ) -[node name="Node2D3" parent="." instance=ExtResource( 4 )] +[node name="Node2D3" parent="YSort" instance=ExtResource( 4 )] position = Vector2( 542, 475 ) diff --git a/project.godot b/project.godot index a752512..8eb54e3 100644 --- a/project.godot +++ b/project.godot @@ -66,6 +66,7 @@ interact={ 2d_physics/layer_1="Collision" 2d_physics/layer_2="Interaction" 2d_physics/layer_3="AutoCollection" +2d_physics/layer_4="PressArea" [physics] diff --git a/scenery/facilities/Press.gd b/scenery/facilities/Press.gd new file mode 100644 index 0000000..f69d3a8 --- /dev/null +++ b/scenery/facilities/Press.gd @@ -0,0 +1,175 @@ +extends StaticBody2D + +var olives_in_crusher = 0 +var crushed_olives_in_reserve = 0 +var oil_level_in_bottle = 0 + +const FRESH_OLIVE_SPRITE = preload("res://items/olive.png") + +var fresh_olive_sprites = [] +var crushed_olive_sprites = [] + +const OLIVE_OIL_W = 32 +# 4 - 37 +const OLIVE_OIL_HEIGHTS = [0, 14, 25, 48] + +var bottles = [] + +func _ready(): + bottles = [$BottleOliveoil, $BottleOliveoil2, $BottleOliveoil3, $BottleOliveoil4, $BottleOliveoil5, $BottleOliveoil6] + _reset_bottle() + for bottle in bottles: + bottle.visible = false + +# The current animation finished, do something if there's something to be done +func _next_step(): + if $Tween.is_active(): + return + + if self._add_label_and_lid(): + return + + if self._new_bottle(): + return + + if not $FillingBottle.visible: + _reset_bottle() + + if self._spray_bottle(): + return + +func _reset_bottle(): + _set_oil_height(OLIVE_OIL_HEIGHTS[0]) + $FillingBottle.visible = true + $FillingBottle/BottleOliveoilLid.visible = false + $FillingBottle/BottleOliveoilLabel.visible = false + +func _add_label_and_lid(): + if $FillingBottle/BottleOliveoilLid.visible or oil_level_in_bottle < 3: + return false + + $FillingBottle/BottleOliveoilLid.visible = true + $FillingBottle/BottleOliveoilLid.modulate.a = 0 + $FillingBottle/BottleOliveoilLabel.visible = true + $FillingBottle/BottleOliveoilLabel.modulate.a = 0 + + $Tween.interpolate_property($FillingBottle/BottleOliveoilLid, "modulate:a", 0.0, 1.0, 0.5, Tween.TRANS_QUAD, Tween.EASE_IN_OUT) + $Tween.interpolate_property($FillingBottle/BottleOliveoilLabel, "modulate:a", 0.0, 1.0, 0.5, Tween.TRANS_QUAD, Tween.EASE_IN_OUT, 0.5) + $Tween.start() + return true + +func _new_bottle(): + if oil_level_in_bottle < 3: + return false + + var any_free_bottles = false + for bottle in bottles: + if not bottle.visible: + any_free_bottles = true + break + + if not any_free_bottles: + return true + + oil_level_in_bottle = 0 + + var positions_in_chain = [ + $FillingBottle.position, + $BottleOliveoil.position, + $BottleOliveoil2.position, + $BottleOliveoil3.position, + $BottleOliveoil4.position, + $BottleOliveoil5.position, + $BottleOliveoil6.position + ] + + var time_to_slide = rand_range(1.5, 2.5) + + for pos in positions_in_chain: + print("PIC ", pos.x) + + var carrying_on = true + for i in range(6): + var next_src_pos = positions_in_chain[i] + var bottle_to_affect = bottles[i] + if not bottle_to_affect.visible: + if not carrying_on: + break + carrying_on = false + bottle_to_affect.set_deferred("visible", true) + + var old_x = bottle_to_affect.position.x + bottle_to_affect.position.x = next_src_pos.x + $Tween.interpolate_property(bottle_to_affect, "position:y", next_src_pos.y, bottle_to_affect.position.y, 0.6, Tween.TRANS_LINEAR, Tween.EASE_IN) + $Tween.interpolate_property(bottle_to_affect, "position:x", next_src_pos.x, old_x, time_to_slide, Tween.TRANS_LINEAR, Tween.EASE_IN, 0.6) + bottle_to_affect.position.y = next_src_pos.y + + $FillingBottle.visible = false + + $Tween.start() + + return true + +func _set_oil_height(new_h: float): + new_h = round(new_h) + $FillingBottle/BottleOliveoilOil.region_rect = Rect2(0, 48 - new_h, 32, new_h) + $FillingBottle/BottleOliveoilOil.offset.y = - new_h + +func _spray_bottle(): + if crushed_olives_in_reserve < 1 or oil_level_in_bottle >= 3: + return false + + crushed_olives_in_reserve -= 1 + crushed_olive_sprites.pop_back().queue_free() + var old_oil_h = OLIVE_OIL_HEIGHTS[oil_level_in_bottle] + oil_level_in_bottle += 1 + var new_oil_h = OLIVE_OIL_HEIGHTS[oil_level_in_bottle] + + $Tween.interpolate_method(self, "_set_oil_height", old_oil_h, new_oil_h, 1.0, Tween.TRANS_QUAD, Tween.EASE_IN_OUT) + $Tween.start() + + return true + + +func _on_Tween_tween_all_completed(): + _next_step() + + +func _on_CollectionArea_body_entered(body: PhysicsBody2D): + if body.has_method("on_press_area_entered"): + body.on_press_area_entered(self) + + +func crushing_needed(): + return olives_in_crusher > 0 + +func crush(): + if olives_in_crusher < 1: + return + olives_in_crusher -= 1 + crushed_olives_in_reserve += 1 + var olive_sprite = fresh_olive_sprites.pop_back() + # give it a 'squished' effect + olive_sprite.scale = Vector2(rand_range(1.5, 2.5), rand_range(0.15, 0.45)) + # make it a bit more yellowy + olive_sprite.modulate = Color(0.5, 1.0, 1.0) + crushed_olive_sprites.push_back(olive_sprite) + _next_step() + +func add_fresh_olives(num: int): + olives_in_crusher += num + + var dist = rand_range(10, 52) + var offs = rand_range(0, 2 * PI) + + for i in range(num): + var angle = PI * i * (2.0 / num) + offs + var new_olive_sprite = Sprite.new() + $PressB.add_child(new_olive_sprite) + new_olive_sprite.texture = FRESH_OLIVE_SPRITE + new_olive_sprite.position = Vector2(0, -52) + Vector2(dist, 0).rotated(angle) + fresh_olive_sprites.push_back(new_olive_sprite) + +func _on_CollectionArea_body_exited(body): + if body.has_method("on_press_area_exited"): + body.on_press_area_exited(self) diff --git a/scenery/facilities/Press.tscn b/scenery/facilities/Press.tscn index 70a32a6..159d39d 100644 --- a/scenery/facilities/Press.tscn +++ b/scenery/facilities/Press.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=2] +[gd_scene load_steps=11 format=2] [ext_resource path="res://items/bottle_oliveoil.png" type="Texture" id=1] [ext_resource path="res://items/bottle_oliveoil_bottle.png" type="Texture" id=2] @@ -7,6 +7,7 @@ [ext_resource path="res://scenery/facilities/press_back.png" type="Texture" id=5] [ext_resource path="res://items/bottle_oliveoil_oil.png" type="Texture" id=6] [ext_resource path="res://items/bottle_oliveoil_lid.png" type="Texture" id=7] +[ext_resource path="res://scenery/facilities/Press.gd" type="Script" id=8] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 29.5128, 2.79108 ) @@ -15,21 +16,26 @@ extents = Vector2( 29.5128, 2.79108 ) extents = Vector2( 104, 10 ) [node name="Press" type="StaticBody2D"] +position = Vector2( 0, -64 ) +script = ExtResource( 8 ) [node name="PressB" type="Sprite" parent="."] +position = Vector2( 0, -7 ) z_index = -1 texture = ExtResource( 5 ) -centered = false [node name="PressF" type="Sprite" parent="."] +position = Vector2( 0, -7 ) texture = ExtResource( 3 ) -centered = false [node name="FillingBottle" type="Node2D" parent="."] -position = Vector2( 32, 136 ) +position = Vector2( -96.6, 1.7 ) [node name="BottleOliveoilOil" type="Sprite" parent="FillingBottle"] +position = Vector2( -16, 25 ) texture = ExtResource( 6 ) +centered = false +offset = Vector2( 0, -48 ) region_enabled = true region_rect = Rect2( 0, 0, 32, 48 ) @@ -43,40 +49,55 @@ texture = ExtResource( 7 ) texture = ExtResource( 4 ) [node name="BottleOliveoil" type="Sprite" parent="."] -position = Vector2( 63, 166 ) +position = Vector2( -65.6, 31.7 ) texture = ExtResource( 1 ) [node name="BottleOliveoil2" type="Sprite" parent="."] -position = Vector2( 92, 166 ) +position = Vector2( -36.6, 31.7 ) texture = ExtResource( 1 ) [node name="BottleOliveoil3" type="Sprite" parent="."] -position = Vector2( 120, 166 ) +position = Vector2( -8.60001, 31.7 ) texture = ExtResource( 1 ) [node name="BottleOliveoil4" type="Sprite" parent="."] -position = Vector2( 147, 166 ) +position = Vector2( 18.4, 31.7 ) texture = ExtResource( 1 ) [node name="BottleOliveoil5" type="Sprite" parent="."] -position = Vector2( 174, 166 ) +position = Vector2( 45.4, 31.7 ) texture = ExtResource( 1 ) [node name="BottleOliveoil6" type="Sprite" parent="."] -position = Vector2( 201, 166 ) +position = Vector2( 72.4, 31.7 ) texture = ExtResource( 1 ) [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."] +position = Vector2( -128.6, -134.3 ) polygon = PoolVector2Array( 208, 27, 160, 7, 106, 7, 60, 24, 60, 48, 84, 32, 120, 26, 158, 26, 190, 39, 208, 56 ) [node name="CollisionPolygon2D2" type="CollisionPolygon2D" parent="."] +position = Vector2( -128.6, -134.3 ) polygon = PoolVector2Array( 60, 47, 60, 136, 90, 151, 122, 155, 157, 155, 185, 146, 208, 129, 208, 125, 184, 143, 158, 151, 123, 151, 92, 147, 62, 134 ) [node name="CollisionShape2D2" type="CollisionShape2D" parent="."] -position = Vector2( 230, 134 ) +position = Vector2( 101.4, -0.300003 ) rotation = 0.628319 shape = SubResource( 1 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2( 118, 173 ) +position = Vector2( -10.6, 38.7 ) shape = SubResource( 2 ) + +[node name="Tween" type="Tween" parent="."] + +[node name="CollectionArea" type="Area2D" parent="."] +collision_layer = 0 +collision_mask = 8 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="CollectionArea"] +polygon = PoolVector2Array( 68, -78, 67, -24, 5, -3, -63, -22, -62, -84, 5, -103 ) + +[connection signal="tween_all_completed" from="Tween" to="." method="_on_Tween_tween_all_completed"] +[connection signal="body_entered" from="CollectionArea" to="." method="_on_CollectionArea_body_entered"] +[connection signal="body_exited" from="CollectionArea" to="." method="_on_CollectionArea_body_exited"] diff --git a/scenery/facilities/Wheelbarrow.gd b/scenery/facilities/Wheelbarrow.gd index 77ad4fb..e9db5e2 100644 --- a/scenery/facilities/Wheelbarrow.gd +++ b/scenery/facilities/Wheelbarrow.gd @@ -30,3 +30,12 @@ func _collect_olive(olive: Area2D, olive_slot: Node2D): func slot_entry_complete(slot: Node2D): used_slots.push_back(slot) slot.visible = true + +func on_press_area_entered(press: PhysicsBody2D): + var num_olives = 0 + for olive in used_slots: + olive.visible = false + free_slots.push_back(olive) + num_olives += 1 + used_slots = [] + press.add_fresh_olives(num_olives) diff --git a/scenery/facilities/Wheelbarrow.tscn b/scenery/facilities/Wheelbarrow.tscn index a743160..4c73791 100644 --- a/scenery/facilities/Wheelbarrow.tscn +++ b/scenery/facilities/Wheelbarrow.tscn @@ -14,7 +14,7 @@ height = 61.25 [node name="Wheelbarrow" type="KinematicBody2D" groups=["attachable"]] position = Vector2( 0, -11 ) -collision_layer = 3 +collision_layer = 11 script = ExtResource( 3 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="."]