diff options
author | Daniel Weipert <code@drogueronin.de> | 2023-08-10 11:48:05 +0200 |
---|---|---|
committer | Daniel Weipert <code@drogueronin.de> | 2023-08-10 11:48:05 +0200 |
commit | 46556d864b9685c3b09a0038f5de83966fe7ff94 (patch) | |
tree | c68082eacd35559e14565d1598dd694972fb8e0e /Scenes/Entities |
Initial commit
Diffstat (limited to 'Scenes/Entities')
-rw-r--r-- | Scenes/Entities/Bombs/Bomb.gd | 165 | ||||
-rw-r--r-- | Scenes/Entities/Bombs/Bomb__Breakables.gd | 4 | ||||
-rw-r--r-- | Scenes/Entities/Bombs/Bomb__Breakables.tscn | 50 | ||||
-rw-r--r-- | Scenes/Entities/Bombs/Bomb__Normal.gd | 1 | ||||
-rw-r--r-- | Scenes/Entities/Bombs/Bomb__Normal.tscn | 49 | ||||
-rw-r--r-- | Scenes/Entities/Bombs/Explosion.gd | 11 | ||||
-rw-r--r-- | Scenes/Entities/Bombs/Explosion.tscn | 63 | ||||
-rw-r--r-- | Scenes/Entities/Enemies/Enemy.gd | 81 | ||||
-rw-r--r-- | Scenes/Entities/Enemies/Enemy.tscn | 91 | ||||
-rw-r--r-- | Scenes/Entities/Objects/Box.gd | 28 | ||||
-rw-r--r-- | Scenes/Entities/Objects/Box.tscn | 106 | ||||
-rw-r--r-- | Scenes/Entities/Objects/Coin.gd | 16 | ||||
-rw-r--r-- | Scenes/Entities/Objects/Coin.tscn | 21 | ||||
-rw-r--r-- | Scenes/Entities/Player.gd | 202 | ||||
-rw-r--r-- | Scenes/Entities/Player.tscn | 118 |
15 files changed, 1006 insertions, 0 deletions
diff --git a/Scenes/Entities/Bombs/Bomb.gd b/Scenes/Entities/Bombs/Bomb.gd new file mode 100644 index 0000000..96a5e62 --- /dev/null +++ b/Scenes/Entities/Bombs/Bomb.gd @@ -0,0 +1,165 @@ +extends CharacterBody2D + +class_name Bomb + + +signal body_exited +signal exploded + + +var Explosion = preload("res://Scenes/Entities/Bombs/Explosion.tscn") +var power = 2 + + +func _ready(): + add_to_group("bombs") + + var collision_area = Utilities.Collision.Area.new(self, $CollisionShape2D) + collision_area.connect("collided", Callable(self, "_collide")) + collision_area.connect("body_exited", Callable(self, "_body_exited")) + add_child(collision_area) + + $AnimatedSprite2D.play() + + +func _process(delta): + var collision = move_and_collide(velocity * delta) + if collision: + velocity = Vector2(0, 0) + + +func explode(): + $CollisionShape2D.disabled = true + + # explode on the spot + var explosion = self.spawn_explosion(self.global_position) + + # explode in all directions + var directions = [ + Vector2.UP, + Vector2.RIGHT, + Vector2.DOWN, + Vector2.LEFT, + ] + + for j in range(directions.size()): + var direction = directions[j] + + for i in range(self.get_power()): + var to = Utilities.from_grid_to_position( + Utilities.from_position_to_grid(self.global_position) + (direction * (i + 1)) + ) + + var query = PhysicsPointQueryParameters2D.new() + query.set_position(to) + query.set_collision_mask(explosion.collision_mask) + + var explosion_intersection = get_world_2d().direct_space_state.intersect_point(query) + if explosion_intersection: + var collider = explosion_intersection[0].collider + + # call collision function and get collision type + var collision_type + if collider.is_in_group("player"): + collision_type = self._on_collide_group_player() + elif collider.is_in_group("enemies"): + collision_type = self._on_collide_group_enemies() + elif collider.is_in_group("explosions"): + collision_type = self._on_collide_group_explosions() + elif collider.is_in_group("bombs"): + collision_type = self._on_collide_group_bombs() + elif collider.is_in_group("breakables"): + collision_type = self._on_collide_group_breakables() + else: + collision_type = self._on_collide_group_else() + + # progress loop based on collision type + if collision_type == EXPLOSION_COLLISION_TYPE.STOP: + break + if collision_type == EXPLOSION_COLLISION_TYPE.SPAWN_AND_STOP: + self.spawn_explosion(to) + break + elif collision_type == EXPLOSION_COLLISION_TYPE.SKIP: + continue + elif collision_type == EXPLOSION_COLLISION_TYPE.CONTINUE: + pass + elif collision_type == EXPLOSION_COLLISION_TYPE.HIT_STOP: + if collider.has_method("hit_by_explosion"): + collider.hit_by_explosion() + break + elif collision_type == EXPLOSION_COLLISION_TYPE.HIT_CONTINUE: + if collider.has_method("hit_by_explosion"): + collider.hit_by_explosion() + continue + + self.spawn_explosion(to) + + emit_signal("exploded", self) + + queue_free() + + +func get_power(): + return self.power + + +func spawn_explosion(spawn_position: Vector2): + var explosion = Explosion.instantiate() + explosion.position = spawn_position + get_tree().get_current_scene().add_child(explosion) + + return explosion + + +func hit_by_explosion(): + call_deferred("explode") + + +func _collide(area: Area2D): + if area.is_in_group("explosions"): + call_deferred("explode") + + +func _on_Timer_timeout(): + self.explode() + + +func _body_exited(body): + emit_signal("body_exited", body) + + +### Explosion Collision ### + + +enum EXPLOSION_COLLISION_TYPE { + STOP, + SKIP, + CONTINUE, + SPAWN_AND_STOP, + HIT_STOP, + HIT_CONTINUE, +} + + +func _on_collide_group_player(): + return EXPLOSION_COLLISION_TYPE.CONTINUE + + +func _on_collide_group_enemies(): + return EXPLOSION_COLLISION_TYPE.CONTINUE + + +func _on_collide_group_explosions(): + return EXPLOSION_COLLISION_TYPE.SKIP + + +func _on_collide_group_bombs(): + return EXPLOSION_COLLISION_TYPE.HIT_STOP + + +func _on_collide_group_breakables(): + return EXPLOSION_COLLISION_TYPE.HIT_STOP + + +func _on_collide_group_else(): + return EXPLOSION_COLLISION_TYPE.STOP diff --git a/Scenes/Entities/Bombs/Bomb__Breakables.gd b/Scenes/Entities/Bombs/Bomb__Breakables.gd new file mode 100644 index 0000000..177d86e --- /dev/null +++ b/Scenes/Entities/Bombs/Bomb__Breakables.gd @@ -0,0 +1,4 @@ +extends "res://Scenes/Entities/Bombs/Bomb.gd" + +func _on_collide_group_breakables(): + return EXPLOSION_COLLISION_TYPE.HIT_CONTINUE diff --git a/Scenes/Entities/Bombs/Bomb__Breakables.tscn b/Scenes/Entities/Bombs/Bomb__Breakables.tscn new file mode 100644 index 0000000..a4bb192 --- /dev/null +++ b/Scenes/Entities/Bombs/Bomb__Breakables.tscn @@ -0,0 +1,50 @@ +[gd_scene load_steps=7 format=3 uid="uid://bcdo4xwalfyw2"] + +[ext_resource type="Script" path="res://Scenes/Entities/Bombs/Bomb__Breakables.gd" id="1_53dqw"] +[ext_resource type="Texture2D" uid="uid://tb10jfeilqxk" path="res://Assets/16_bit_animated_bomb/16_bit_bomb3.png" id="2_xuubc"] +[ext_resource type="Texture2D" uid="uid://ptkpqpfgcoug" path="res://Assets/16_bit_animated_bomb/16bit_bomb1.png" id="3_3gndm"] +[ext_resource type="Texture2D" uid="uid://dsomaiq14ajhf" path="res://Assets/16_bit_animated_bomb/16_bit_bomb2.png" id="4_u38sl"] + +[sub_resource type="CircleShape2D" id="1"] +radius = 7.9 + +[sub_resource type="SpriteFrames" id="2"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_xuubc") +}, { +"duration": 1.0, +"texture": ExtResource("3_3gndm") +}, { +"duration": 1.0, +"texture": ExtResource("4_u38sl") +}, { +"duration": 1.0, +"texture": ExtResource("2_xuubc") +}], +"loop": false, +"name": &"default", +"speed": 1.0 +}] + +[node name="Bomb__Breakables" type="CharacterBody2D"] +collision_layer = 4 +collision_mask = 62 +script = ExtResource("1_53dqw") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("1") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +modulate = Color(1, 0, 0, 1) +position = Vector2(1, -1) +scale = Vector2(1.23978, 1.23978) +sprite_frames = SubResource("2") + +[node name="Timer" type="Timer" parent="."] +wait_time = 4.0 +one_shot = true +autostart = true + +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] diff --git a/Scenes/Entities/Bombs/Bomb__Normal.gd b/Scenes/Entities/Bombs/Bomb__Normal.gd new file mode 100644 index 0000000..2c89be6 --- /dev/null +++ b/Scenes/Entities/Bombs/Bomb__Normal.gd @@ -0,0 +1 @@ +extends "res://Scenes/Entities/Bombs/Bomb.gd" diff --git a/Scenes/Entities/Bombs/Bomb__Normal.tscn b/Scenes/Entities/Bombs/Bomb__Normal.tscn new file mode 100644 index 0000000..011c298 --- /dev/null +++ b/Scenes/Entities/Bombs/Bomb__Normal.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=7 format=3 uid="uid://elsifewesoyx"] + +[ext_resource type="Script" path="res://Scenes/Entities/Bombs/Bomb__Normal.gd" id="1_3o4t3"] +[ext_resource type="Texture2D" uid="uid://tb10jfeilqxk" path="res://Assets/16_bit_animated_bomb/16_bit_bomb3.png" id="2_qio5f"] +[ext_resource type="Texture2D" uid="uid://ptkpqpfgcoug" path="res://Assets/16_bit_animated_bomb/16bit_bomb1.png" id="3_nom56"] +[ext_resource type="Texture2D" uid="uid://dsomaiq14ajhf" path="res://Assets/16_bit_animated_bomb/16_bit_bomb2.png" id="4_xndnu"] + +[sub_resource type="CircleShape2D" id="1"] +radius = 7.9 + +[sub_resource type="SpriteFrames" id="2"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2_qio5f") +}, { +"duration": 1.0, +"texture": ExtResource("3_nom56") +}, { +"duration": 1.0, +"texture": ExtResource("4_xndnu") +}, { +"duration": 1.0, +"texture": ExtResource("2_qio5f") +}], +"loop": false, +"name": &"default", +"speed": 1.0 +}] + +[node name="Bomb__Normal" type="CharacterBody2D"] +collision_layer = 4 +collision_mask = 62 +script = ExtResource("1_3o4t3") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("1") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +position = Vector2(1, -1) +scale = Vector2(1.23978, 1.23978) +sprite_frames = SubResource("2") + +[node name="Timer" type="Timer" parent="."] +wait_time = 4.0 +one_shot = true +autostart = true + +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] diff --git a/Scenes/Entities/Bombs/Explosion.gd b/Scenes/Entities/Bombs/Explosion.gd new file mode 100644 index 0000000..eba8b29 --- /dev/null +++ b/Scenes/Entities/Bombs/Explosion.gd @@ -0,0 +1,11 @@ +extends Area2D + + +func _ready(): + add_to_group("explosions") + + $AnimatedSprite2D.play() + + +func _on_AnimatedSprite_animation_finished(): + queue_free() diff --git a/Scenes/Entities/Bombs/Explosion.tscn b/Scenes/Entities/Bombs/Explosion.tscn new file mode 100644 index 0000000..2521dfb --- /dev/null +++ b/Scenes/Entities/Bombs/Explosion.tscn @@ -0,0 +1,63 @@ +[gd_scene load_steps=8 format=3 uid="uid://c8cg25hagp4lj"] + +[ext_resource type="Texture2D" uid="uid://5dk0c1kpvdgs" path="res://Assets/bomb_party_v4.png" id="1"] +[ext_resource type="Script" path="res://Scenes/Entities/Bombs/Explosion.gd" id="2"] + +[sub_resource type="AtlasTexture" id="3"] +atlas = ExtResource("1") +region = Rect2(224, 288, 16, 16) + +[sub_resource type="AtlasTexture" id="4"] +atlas = ExtResource("1") +region = Rect2(224, 272, 16, 16) + +[sub_resource type="AtlasTexture" id="5"] +atlas = ExtResource("1") +region = Rect2(224, 256, 16, 16) + +[sub_resource type="SpriteFrames" id="1"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("3") +}, { +"duration": 1.0, +"texture": SubResource("3") +}, { +"duration": 1.0, +"texture": SubResource("4") +}, { +"duration": 1.0, +"texture": SubResource("4") +}, { +"duration": 1.0, +"texture": SubResource("4") +}, { +"duration": 1.0, +"texture": SubResource("5") +}, { +"duration": 1.0, +"texture": SubResource("5") +}], +"loop": false, +"name": &"default", +"speed": 60.0 +}] + +[sub_resource type="CircleShape2D" id="2"] +radius = 7.5 + +[node name="Explosion" type="Area2D"] +collision_layer = 32 +collision_mask = 62 +script = ExtResource("2") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +position = Vector2(-2.98023e-08, -2.98023e-08) +scale = Vector2(0.913346, 0.913346) +sprite_frames = SubResource("1") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("2") + +[connection signal="animation_finished" from="AnimatedSprite2D" to="." method="_on_AnimatedSprite_animation_finished"] diff --git a/Scenes/Entities/Enemies/Enemy.gd b/Scenes/Entities/Enemies/Enemy.gd new file mode 100644 index 0000000..5b72c04 --- /dev/null +++ b/Scenes/Entities/Enemies/Enemy.gd @@ -0,0 +1,81 @@ +extends CharacterBody2D + + +const SPEED = 30 + +const DIRECTIONS = [Vector2.UP, Vector2.RIGHT, Vector2.DOWN, Vector2.LEFT] +var CURRENT_DIRECTION = Vector2.UP + +@export var health: int = 4 + +var is_invincible = false + + +func _ready(): + add_to_group("enemies") + + var collision_area = Utilities.Collision.Area.new(self, $CollisionShape2D) + collision_area.connect("collided", Callable(self, "_collide")) + add_child(collision_area) + + $Label.text = str(self.health) + + +func _physics_process(delta): + if CURRENT_DIRECTION == Vector2.UP: + velocity.y -= SPEED + $AnimatedSprite2D.play("up") + elif CURRENT_DIRECTION == Vector2.DOWN: + velocity.y += SPEED + $AnimatedSprite2D.play("down") + elif CURRENT_DIRECTION == Vector2.LEFT: + velocity.x -= SPEED + $AnimatedSprite2D.flip_h = true + $AnimatedSprite2D.play("left") + elif CURRENT_DIRECTION == Vector2.RIGHT: + velocity.x += SPEED + $AnimatedSprite2D.flip_h = false + $AnimatedSprite2D.play("right") + + move_and_collide(velocity * delta) + velocity = velocity.lerp(Vector2(0, 0), 1) + + +func take_damage(amount): + if self.is_invincible: + return + + self.set_invincibility() + + self.health -= amount + + if self.health == 0: + queue_free() + + $Label.text = str(self.health) + + +func _collide(area: Area2D): + if area.is_in_group("explosions"): + self.take_damage(4) + + +func _on_movement_timer_timeout(): + var directions = self.DIRECTIONS.duplicate() + + directions.remove_at(directions.find(CURRENT_DIRECTION)) + directions.shuffle() + + CURRENT_DIRECTION = directions[0] + + $MovementTimer.start() + + +func set_invincibility(): + $InvincibilityTimer.start() + $AnimatedSprite2D.set_modulate(Color(10, 1, 1, 1)) + self.is_invincible = true + +func _on_invincibility_timer_timeout(): + $AnimatedSprite2D.set_modulate(Color(1, 1, 1, 1)) + self.is_invincible = false diff --git a/Scenes/Entities/Enemies/Enemy.tscn b/Scenes/Entities/Enemies/Enemy.tscn new file mode 100644 index 0000000..f78d0e5 --- /dev/null +++ b/Scenes/Entities/Enemies/Enemy.tscn @@ -0,0 +1,91 @@ +[gd_scene load_steps=9 format=3 uid="uid://dgyk1sged38ct"] + +[ext_resource type="Script" path="res://Scenes/Entities/Enemies/Enemy.gd" id="1_k16kd"] +[ext_resource type="Texture2D" uid="uid://5dk0c1kpvdgs" path="res://Assets/bomb_party_v4.png" id="2_cjc2s"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_gw5gm"] +size = Vector2(11, 11.5) + +[sub_resource type="AtlasTexture" id="AtlasTexture_t7fm8"] +atlas = ExtResource("2_cjc2s") +region = Rect2(16, 224, 16, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_pyhot"] +atlas = ExtResource("2_cjc2s") +region = Rect2(64, 224, 16, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_aj58r"] +atlas = ExtResource("2_cjc2s") +region = Rect2(64, 224, 16, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_spvfr"] +atlas = ExtResource("2_cjc2s") +region = Rect2(0, 224, 16, 16) + +[sub_resource type="SpriteFrames" id="SpriteFrames_t5cld"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_t7fm8") +}], +"loop": true, +"name": &"down", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_pyhot") +}], +"loop": true, +"name": &"left", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_aj58r") +}], +"loop": true, +"name": &"right", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_spvfr") +}], +"loop": true, +"name": &"up", +"speed": 5.0 +}] + +[node name="Enemy" type="CharacterBody2D"] +collision_layer = 16 +collision_mask = 62 +script = ExtResource("1_k16kd") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(0.5, -0.25) +shape = SubResource("RectangleShape2D_gw5gm") +metadata/_edit_lock_ = true + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +sprite_frames = SubResource("SpriteFrames_t5cld") +animation = &"down" + +[node name="Label" type="Label" parent="."] +offset_left = -5.0 +offset_top = -20.0 +offset_right = 16.0 +offset_bottom = 6.0 +scale = Vector2(0.5, 0.5) +text = "hp" + +[node name="MovementTimer" type="Timer" parent="."] +wait_time = 3.0 +autostart = true + +[node name="InvincibilityTimer" type="Timer" parent="."] +wait_time = 1.5 +one_shot = true + +[connection signal="timeout" from="MovementTimer" to="." method="_on_movement_timer_timeout"] +[connection signal="timeout" from="InvincibilityTimer" to="." method="_on_invincibility_timer_timeout"] diff --git a/Scenes/Entities/Objects/Box.gd b/Scenes/Entities/Objects/Box.gd new file mode 100644 index 0000000..c7b7d4e --- /dev/null +++ b/Scenes/Entities/Objects/Box.gd @@ -0,0 +1,28 @@ +extends StaticBody2D + + +func _ready(): + var collision_area = Utilities.Collision.Area.new(self, $CollisionShape2D, false) + collision_area.connect("collided", Callable(self, "_collide")) + add_child(collision_area) + + +func hit_by_explosion(): + $AnimationPlayer.play("breaking") + await $AnimationPlayer.animation_finished + + if randi_range(1, 3) == 1: + call_deferred("spawn_coin") + + queue_free() + + +func spawn_coin(): + var coin = preload("res://Scenes/Entities/Objects/Coin.tscn").instantiate() + coin.position = self.position + get_tree().get_current_scene().add_child(coin) + + +func _collide(area: Area2D): + if area.is_in_group("explosions"): + self.hit_by_explosion() diff --git a/Scenes/Entities/Objects/Box.tscn b/Scenes/Entities/Objects/Box.tscn new file mode 100644 index 0000000..6acb93f --- /dev/null +++ b/Scenes/Entities/Objects/Box.tscn @@ -0,0 +1,106 @@ +[gd_scene load_steps=7 format=3 uid="uid://bugyo0c505kdw"] + +[ext_resource type="Script" path="res://Scenes/Entities/Objects/Box.gd" id="1_owgyi"] +[ext_resource type="Texture2D" uid="uid://5dk0c1kpvdgs" path="res://Assets/bomb_party_v4.png" id="1_yqw0v"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_rwppg"] +size = Vector2(16, 16) + +[sub_resource type="Animation" id="Animation_ihbs5"] +resource_name = "breaking" +length = 0.2 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(1, 1, 0, 1), Color(1, 0, 0, 1)] +} + +[sub_resource type="Animation" id="Animation_5u23n"] +length = 0.001 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:modulate:r") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:modulate:g") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/2/type = "bezier" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Sprite2D:modulate:b") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/3/type = "bezier" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Sprite2D:modulate:a") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("Sprite2D:modulate") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 0, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_cqvgo"] +_data = { +"RESET": SubResource("Animation_5u23n"), +"breaking": SubResource("Animation_ihbs5") +} + +[node name="Box" type="StaticBody2D" groups=["breakables"]] +collision_layer = 8 +collision_mask = 32 +script = ExtResource("1_owgyi") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_rwppg") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_yqw0v") +region_enabled = true +region_rect = Rect2(144.052, 208.08, 16, 16) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_cqvgo") +} diff --git a/Scenes/Entities/Objects/Coin.gd b/Scenes/Entities/Objects/Coin.gd new file mode 100644 index 0000000..77fc6c2 --- /dev/null +++ b/Scenes/Entities/Objects/Coin.gd @@ -0,0 +1,16 @@ +extends StaticBody2D + + +func _ready(): + var collision_area = Utilities.Collision.Area.new(self, $CollisionShape2D, false) + collision_area.connect("collided", Callable(self, "_collide")) + add_child(collision_area) + + +func hit_by_explosion(): + queue_free() + + +func _collide(area: Area2D): + if area.is_in_group("player"): + queue_free() diff --git a/Scenes/Entities/Objects/Coin.tscn b/Scenes/Entities/Objects/Coin.tscn new file mode 100644 index 0000000..aacb70b --- /dev/null +++ b/Scenes/Entities/Objects/Coin.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=4 format=3 uid="uid://cl7jri45a43t0"] + +[ext_resource type="Script" path="res://Scenes/Entities/Objects/Coin.gd" id="1_kjrye"] +[ext_resource type="Texture2D" uid="uid://5dk0c1kpvdgs" path="res://Assets/bomb_party_v4.png" id="2_0mghm"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_rwppg"] +size = Vector2(16, 16) + +[node name="Coin" type="StaticBody2D" groups=["breakables"]] +collision_layer = 8 +collision_mask = 34 +script = ExtResource("1_kjrye") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("RectangleShape2D_rwppg") + +[node name="Sprite2D" type="Sprite2D" parent="."] +self_modulate = Color(1, 0, 1, 1) +texture = ExtResource("2_0mghm") +region_enabled = true +region_rect = Rect2(48.8626, 208.456, 15.1374, 15.5442) diff --git a/Scenes/Entities/Player.gd b/Scenes/Entities/Player.gd new file mode 100644 index 0000000..a578bbb --- /dev/null +++ b/Scenes/Entities/Player.gd @@ -0,0 +1,202 @@ +extends CharacterBody2D + +class_name Player + + +signal damaged + + +const SPEED = 60 +const KICK_SPEED = 300 +const THROW_DISTANCE = 3 + +@export var Bomb: PackedScene = preload("res://Scenes/Entities/Bombs/Bomb__Normal.tscn") +@export var bomb_power: int = 2 + +@export var maxHealth: int = 12 +@export var health: int = self.maxHealth +@export var extraHealth: int = 5 + +var is_invincible = false + +var held_bomb: Bomb + +var DIRECTION = Vector2.DOWN + +var collision_area: Area2D + + + +func _ready(): + add_to_group("player") + set_up_direction(Vector2.UP) + motion_mode = CharacterBody2D.MOTION_MODE_FLOATING + + collision_area = Utilities.Collision.Area.new(self, $CollisionShape2D) + collision_area.connect("collided", Callable(self, "_collide")) + add_child(collision_area) + + +func _process(delta): + if Input.is_action_pressed("ui_left"): + velocity.x -= SPEED + $AnimatedSprite2D.play("left") + self.DIRECTION = Vector2.LEFT + if Input.is_action_pressed("ui_right"): + velocity.x += SPEED + $AnimatedSprite2D.play("right") + self.DIRECTION = Vector2.RIGHT + if Input.is_action_pressed("ui_up"): + velocity.y -= SPEED + $AnimatedSprite2D.play("up") + self.DIRECTION = Vector2.UP + if Input.is_action_pressed("ui_down"): + velocity.y += SPEED + $AnimatedSprite2D.play("down") + self.DIRECTION = Vector2.DOWN + + if velocity.x < 0 && velocity.y < 0: + $AnimatedSprite2D.play("tl") + elif velocity.x > 0 && velocity.y < 0: + $AnimatedSprite2D.play("tr") + elif velocity.x < 0 && velocity.y > 0: + $AnimatedSprite2D.play("bl") + elif velocity.x > 0 && velocity.y > 0: + $AnimatedSprite2D.play("br") + + if Input.is_action_just_pressed("ui_accept"): + if self.held_bomb: + self.throw_bomb() + else: + var interacted = false + var areas = $InteractionArea.get_overlapping_areas() + for area in areas: + if area.is_in_group("bombs"): + var bomb = area.get_parent() + self.pick_up_bomb(bomb) + + interacted = true + break + + if not interacted: + self.plant_bomb() + + self.collide(move_and_collide(velocity * delta)) + velocity = velocity.lerp(Vector2(0, 0), 1) + + +func plant_bomb(): + var bomb = Bomb.instantiate() + bomb.position = Utilities.get_level_position_grid(self) + bomb.power = self.bomb_power + + self.add_collision_exception_with(bomb) + bomb.connect("body_exited", func(body): + if body.is_in_group("player") and not self.held_bomb: + self.remove_collision_exception_with(bomb) + ) + + get_tree().get_current_scene().add_child(bomb) + + +func pick_up_bomb(bomb: Bomb): + get_tree().get_current_scene().remove_child(bomb) + bomb.position = Vector2(0, 0) + bomb.set_collision_layer_value(Utilities.Collision.Layer.BOMB, false) + self.add_collision_exception_with(bomb) + self.add_child(bomb) + + self.held_bomb = bomb + bomb.connect("exploded", func(bomb): + if self.held_bomb == bomb: + self.held_bomb = null + ) + + +func throw_bomb(): + var bomb = self.held_bomb + + self.remove_child(bomb) + + var target_position = null + var target_intersection = true + var additional_distance = 0 + while target_intersection: + target_position = Utilities.from_grid_to_position( + Utilities.from_position_to_grid(self.position) + ((self.THROW_DISTANCE + additional_distance) * self.DIRECTION) + ) + + var query = PhysicsPointQueryParameters2D.new() + query.set_position(target_position) + target_intersection = get_world_2d().direct_space_state.intersect_point(query) + + additional_distance += 1 + + bomb.position = target_position + + get_tree().get_current_scene().add_child(bomb) + + bomb.set_collision_layer_value(Utilities.Collision.Layer.BOMB, true) + (func(): self.remove_collision_exception_with(bomb)).call_deferred() + + self.held_bomb = null + + +func collide(collision: KinematicCollision2D): + if not collision: + return + + var collider = collision.get_collider() + + if collider.is_in_group("bombs"): + self.kick_bomb(collider) + + +func kick_bomb(bomb): + var diff = Utilities.get_level_position(self) - Utilities.get_level_position(bomb) + if diff.x > 0: + bomb.velocity.x -= KICK_SPEED + elif diff.x < 0: + bomb.velocity.x += KICK_SPEED + elif diff.y > 0: + bomb.velocity.y -= KICK_SPEED + elif diff.y < 0: + bomb.velocity.y += KICK_SPEED + + +func take_damage(amount): + if self.held_bomb: + self.held_bomb.call_deferred("explode") + + if self.is_invincible: + return + + self.set_invincibility() + + if self.extraHealth > 0: + if amount > self.extraHealth: + self.health -= amount - self.extraHealth + self.extraHealth = 0 + else: + self.extraHealth -= amount + else: + self.health -= amount + + self.emit_signal("damaged", self.health) + + +func set_invincibility(): + $Invincibility.start() + $AnimatedSprite2D.set_modulate(Color(10, 10, 10, 1)) + self.is_invincible = true + +func _on_invincibility_timeout(): + $AnimatedSprite2D.set_modulate(Color(1, 1, 1, 1)) + self.is_invincible = false + + +func _collide(area: Area2D): + if area.is_in_group("explosions"): + self.take_damage(2) + elif area.is_in_group("enemies"): + self.take_damage(1) diff --git a/Scenes/Entities/Player.tscn b/Scenes/Entities/Player.tscn new file mode 100644 index 0000000..f4ef6ab --- /dev/null +++ b/Scenes/Entities/Player.tscn @@ -0,0 +1,118 @@ +[gd_scene load_steps=13 format=3 uid="uid://b1xhgqwrw4pgs"] + +[ext_resource type="Texture2D" uid="uid://dtvvpqc7i2dm6" path="res://Assets/tux/signal-2021-05-05-214118_001.png" id="1"] +[ext_resource type="Script" path="res://Scenes/Entities/Player.gd" id="1_2xulf"] +[ext_resource type="Texture2D" uid="uid://o7x47dkwao04" path="res://Assets/tux/signal-2021-05-05-214118_002.png" id="2"] +[ext_resource type="Texture2D" uid="uid://4lhw1rn7w1ye" path="res://Assets/tux/signal-2021-05-05-214118_003.png" id="3"] +[ext_resource type="Texture2D" uid="uid://d354aghbycxto" path="res://Assets/tux/signal-2021-05-05-214118_004.png" id="4"] +[ext_resource type="Texture2D" uid="uid://3jnv1c847c3" path="res://Assets/tux/signal-2021-05-06-203546_001.png" id="5"] +[ext_resource type="Texture2D" uid="uid://c3o4wky2ywpng" path="res://Assets/tux/signal-2021-05-06-203546_004.png" id="6"] +[ext_resource type="Texture2D" uid="uid://b5v0jg6lwnij2" path="res://Assets/tux/signal-2021-05-06-203546_003.png" id="7"] +[ext_resource type="Texture2D" uid="uid://cnxxo0qivbv4c" path="res://Assets/tux/signal-2021-05-06-203546_002.png" id="7_bxbay"] + +[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_xsiww"] +radius = 5.0 +height = 14.0 + +[sub_resource type="SpriteFrames" id="2"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("7") +}], +"loop": true, +"name": &"bl", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("6") +}], +"loop": true, +"name": &"br", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("3") +}], +"loop": true, +"name": &"down", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("4") +}], +"loop": true, +"name": &"left", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("1") +}], +"loop": true, +"name": &"right", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("7_bxbay") +}], +"loop": true, +"name": &"tl", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("5") +}], +"loop": true, +"name": &"tr", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("2") +}], +"loop": true, +"name": &"up", +"speed": 5.0 +}] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_c6666"] +size = Vector2(14, 14) + +[node name="Player" type="CharacterBody2D"] +collision_layer = 2 +collision_mask = 60 +script = ExtResource("1_2xulf") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CapsuleShape2D_xsiww") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +position = Vector2(5.96046e-08, 5.96046e-08) +scale = Vector2(0.405234, 0.405234) +sprite_frames = SubResource("2") +animation = &"down" +metadata/_edit_lock_ = true + +[node name="Camera2D" type="Camera2D" parent="."] +drag_horizontal_enabled = true +drag_vertical_enabled = true + +[node name="InteractionArea" type="Area2D" parent="."] +collision_layer = 0 +collision_mask = 4 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="InteractionArea"] +position = Vector2(0, 1) +shape = SubResource("RectangleShape2D_c6666") + +[node name="Invincibility" type="Timer" parent="."] +wait_time = 1.5 +one_shot = true + +[connection signal="timeout" from="Invincibility" to="." method="_on_invincibility_timeout"] |