diff options
author | metamuffin <metamuffin@disroot.org> | 2024-06-22 18:10:07 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-06-23 19:28:39 +0200 |
commit | e366cfdf9133c0da798352c474580d329c6a0f33 (patch) | |
tree | 1cb97c585cd7c457f3205cacc36cdd183883ac5f | |
parent | 512ea1fce397549e2dd2f2b24adde5bc074b4ad2 (diff) | |
download | hurrycurry-e366cfdf9133c0da798352c474580d329c6a0f33.tar hurrycurry-e366cfdf9133c0da798352c474580d329c6a0f33.tar.bz2 hurrycurry-e366cfdf9133c0da798352c474580d329c6a0f33.tar.zst |
player collisions and better movement code
-rw-r--r-- | client/scripts/controllable_player.gd | 122 | ||||
-rw-r--r-- | client/scripts/game.gd | 7 | ||||
-rw-r--r-- | client/scripts/map.gd | 4 | ||||
-rw-r--r-- | client/scripts/multiplayer.gd | 4 | ||||
-rw-r--r-- | client/scripts/player.gd | 14 |
5 files changed, 63 insertions, 88 deletions
diff --git a/client/scripts/controllable_player.gd b/client/scripts/controllable_player.gd index 58ac4401..34ef5859 100644 --- a/client/scripts/controllable_player.gd +++ b/client/scripts/controllable_player.gd @@ -1,11 +1,11 @@ class_name ControllablePlayer extends Player -@export var map: Node3D -@export var camera: FollowCamera + +const PLAYER_SPEED: float = 25.; var facing = Vector2(1, 0) -var velocity = Vector2(0, 0) +var velocity_ = Vector2(0, 0) func _ready(): var timer = Timer.new() @@ -19,89 +19,49 @@ func _ready(): func _process(delta): var input = Vector2(Input.get_axis("left", "right"), Input.get_axis("forward", "backwards")).normalized() - input = input.rotated(-camera.angle_target) - - if input.length() > 0.1: - facing = lerp_vector2_exp(facing, input, delta * 10.) - - self.rotation.y = -facing.angle() - - velocity.x += input.x * delta * SPEED - velocity.y += input.y * delta * SPEED - - position = Vector3( - position.x + (velocity.x * delta), - 0, - position.z + (velocity.y * delta) - ) + input = input.rotated(-game.camera.angle_target) + update(delta, input) + super(delta) - # collide - collide(delta) - velocity = lerp_vector2_exp(velocity, Vector2(0, 0), delta * 5.) +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(_delta: float): - for i in map.get_children(): - if is_instance_of(i, FullTile): - var tile: FullTile = i - var d = aabb_circle_distance( - tile.position.x, - tile.position.z, - tile.position.x + 1, - tile.position.z + 1, - position.x, - position.z - ) +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 not is_instance_of(game.map.tile_by_pos.get(str(tile)), FullTile): 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; - if d > PLAYER_SIZE: - continue - - var h = 0.01 - var d_sample_x = aabb_circle_distance( - tile.position.x, - tile.position.z, - tile.position.x + 1, - tile.position.z + 1, - position.x + h, - position.z - ) - var d_sample_y = aabb_circle_distance( - tile.position.x, - tile.position.z, - tile.position.x + 1, - tile.position.z + 1, - position.x, - position.z + h - ) - var grad_x = (d_sample_x - d) / h - var grad_y = (d_sample_y - d) / h - - position.x += (PLAYER_SIZE - d) * grad_x - position.z += (PLAYER_SIZE - d) * grad_y - - var vdotn = (grad_x * velocity.x) + (grad_y * velocity.y) - - velocity.x -= grad_x * vdotn - velocity.y -= grad_y * vdotn - # TODO: Player collisions - -func lerp_vector2_exp(current: Vector2, target: Vector2, delta: float) -> Vector2: - return Vector2( - target.x + (current.x - target.x) * exp( - delta), - target.y + (current.y - target.y) * exp( - delta) - ) + 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_circle_distance( - min_x: float, - min_y: float, - max_x: float, - max_y: float, - px: float, - py: float -) -> float: - var dx = px - max(min_x, min(max_x, px)) - var dy = py - max(min_y, min(max_y, py)) - return sqrt(dx * dx + dy * dy) +func aabb_point_distance(min: Vector2, max: Vector2, p: Vector2) -> float: + return (p - p.clamp(min, max)).length() func update_position(_new_position: Vector2, _new_rotation: float): pass diff --git a/client/scripts/game.gd b/client/scripts/game.gd index 9e02e7c0..48457f9c 100644 --- a/client/scripts/game.gd +++ b/client/scripts/game.gd @@ -1,3 +1,4 @@ +class_name Game extends Node3D @onready var camera: FollowCamera = $FollowCamera @@ -13,12 +14,10 @@ func _ready(): func(player: int, name: String, pos: Vector2, character: int): var player_instance: Player if player == Multiplayer.player_id: - player_instance = ControllablePlayer.new(player, name, pos, character) - player_instance.camera = camera - player_instance.map = map + player_instance = ControllablePlayer.new(player, name, pos, character, self) camera.target = player_instance else: - player_instance = Player.new(player, name, pos, character) + player_instance = Player.new(player, name, pos, character, self) players[player] = player_instance add_child(player_instance) ) diff --git a/client/scripts/map.gd b/client/scripts/map.gd index 9d9453e4..01c7b66e 100644 --- a/client/scripts/map.gd +++ b/client/scripts/map.gd @@ -1,5 +1,8 @@ +class_name Map extends Node3D +var tile_by_pos: Dictionary = {} + func _ready(): Multiplayer.connect("update_map", update) @@ -48,6 +51,7 @@ func update(pos, tile_name, neighbors): instance = Floor.new(node_name, neighbors) instance.position = Vector3(pos[0], 0, pos[1]) + tile_by_pos[str(Vector2i(pos[0],pos[1]))] = instance add_child(instance) func queue_free_rename(node: Node) -> void: diff --git a/client/scripts/multiplayer.gd b/client/scripts/multiplayer.gd index f3f16387..6ac05699 100644 --- a/client/scripts/multiplayer.gd +++ b/client/scripts/multiplayer.gd @@ -14,6 +14,8 @@ var socket := WebSocketPeer.new() var item_names = [] var tile_names = [] +var tile_collide = [] +var tile_interact = [] var item_idx_from_name: Dictionary = {} var player_id = -1 @@ -53,6 +55,8 @@ func handle_packet(bytes: PackedByteArray): player_id = decoded["id"] item_names = decoded["data"]["item_names"] tile_names = decoded["data"]["tile_names"] + tile_collide = decoded["data"]["tile_collide"] + tile_interact = decoded["data"]["tile_interact"] for i in range(item_names.size()): item_idx_from_name[item_names[i]] = i emit_signal("init", player_id) diff --git a/client/scripts/player.gd b/client/scripts/player.gd index 3ad77322..8f53b790 100644 --- a/client/scripts/player.gd +++ b/client/scripts/player.gd @@ -4,13 +4,21 @@ extends Node3D const PLAYER_SIZE: float = 0.4 const SPEED: float = 25. +var game: Game +var position_ = Vector2(0, 0) + var mesh = preload("res://scenes/player.tscn").instantiate() -func _init(id: int, new_name: String, pos: Vector2, _character: int): +func _init(id: int, new_name: String, pos: Vector2, _character: int, new_game: Game): add_child(mesh) - position = Vector3(pos.x, 0, pos.y) + position_ = pos name = new_name + game = new_game func update_position(new_position: Vector2, new_rotation: float): - position = Vector3(new_position.x, 0, new_position.y) + position_ = new_position rotation.y = new_rotation + +func _process(delta): + position.x = position_.x + position.z = position_.y |