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/Player.gd |
Initial commit
Diffstat (limited to 'Scenes/Entities/Player.gd')
-rw-r--r-- | Scenes/Entities/Player.gd | 202 |
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) |