# Undercooked - a game about cooking # Copyright 2024 nokoe # Copyright 2024 metamuffin # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, version 3 of the License only. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # class_name ControllablePlayer extends Player const PLAYER_SPEED: float = 25.; var facing = Vector2(1, 0) var velocity_ = Vector2(0, 0) var target: Vector2i = Vector2i(0, 0) func _ready(): var timer = Timer.new() timer.one_shot = false timer.wait_time = 1. / 25. add_child(timer) timer.start() timer.connect("timeout", func(): Multiplayer.send_position(Vector2(position.x, position.z), rotation.y) ) func _process(delta): var input = Vector2(Input.get_axis("left", "right"), Input.get_axis("forward", "backwards")).normalized() input = input.rotated(-game.camera.angle_target) position_anim = position_ rotation_anim = rotation_ if Input.is_action_pressed("interact") or Input.is_action_just_released("interact"): input *= 0 else: target = Vector2i( int(floor(position.x + sin(rotation.y))), int(floor(position.z + cos(rotation.y))) ) interact() update(delta, input) super(delta) func update(dt: float, input: Vector2): var direction = input.limit_length(1.); rotation.y = atan2(self.facing.x, self.facing.y); if direction.length() > 0.1: self.facing = direction + (self.facing - direction) * exp(-dt * 10.); self.velocity_ += direction * dt * PLAYER_SPEED; self.position_ += self.velocity_ * dt; self.velocity_ = self.velocity_ * exp(-dt * 5.); collide(dt); func collide(dt: float): for xo in range(-1,2): for yo in range(-1,2): var tile = Vector2i(xo, yo) + Vector2i(self.position_); if !Multiplayer.get_tile_collision(tile): continue tile = Vector2(tile) var d = aabb_point_distance(tile, tile + Vector2.ONE, self.position_); if d > PLAYER_SIZE: continue var h = 0.01; var d_sample_x = aabb_point_distance(tile, tile + Vector2.ONE, self.position_ + Vector2(h, 0)); var d_sample_y = aabb_point_distance(tile, tile + Vector2.ONE, self.position_ + Vector2(0, h)); var grad = (Vector2(d_sample_x - d, d_sample_y - d)) / h; self.position_ += (PLAYER_SIZE - d) * grad; self.velocity_ -= grad * grad.dot(self.velocity_) for player: Player in game.players.values(): var diff = self.position_ - player.position_ var d = diff.length() if d < 0.01: continue if d >= PLAYER_SIZE * 2: continue var norm = diff.normalized(); var f = 100 / (1 + d) self.velocity_.x += norm.x * f * dt self.velocity_.y += norm.y * f * dt func aabb_point_distance(mi: Vector2, ma: Vector2, p: Vector2) -> float: return (p - p.clamp(mi, ma)).length() func update_position(new_position: Vector2, _new_rotation: float): if (new_position - position_).length() > 3.: position_ = new_position func interact(): var tile_idx = str(target) var t: Floor = game.map.tile_by_pos.get(tile_idx) if t != null: game.marker.set_interactive(Multiplayer.get_tile_interactive(target)) game.marker.visible = true game.marker_target = t.item_base.global_position if Input.is_action_just_pressed("interact"): Multiplayer.send_interact(target, true) t.interact() elif Input.is_action_just_released("interact"): Multiplayer.send_interact(target, false) else: game.marker.visible = false