summaryrefslogtreecommitdiff
path: root/Scenes/Entities/Player.gd
diff options
context:
space:
mode:
authorDaniel Weipert <code@drogueronin.de>2023-08-10 11:48:05 +0200
committerDaniel Weipert <code@drogueronin.de>2023-08-10 11:48:05 +0200
commit46556d864b9685c3b09a0038f5de83966fe7ff94 (patch)
treec68082eacd35559e14565d1598dd694972fb8e0e /Scenes/Entities/Player.gd
Initial commit
Diffstat (limited to 'Scenes/Entities/Player.gd')
-rw-r--r--Scenes/Entities/Player.gd202
1 files changed, 202 insertions, 0 deletions
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)