diff options
author | nokoe <nokoe@mailbox.org> | 2024-06-21 15:20:17 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-06-23 19:27:04 +0200 |
commit | d6a0899e9641c68b96463669bd655629eb430311 (patch) | |
tree | f51fbedad2a303035a414d446b4222b1d997fa6d | |
parent | 68a671883983252edcc28fced0279eb37e6ba297 (diff) | |
download | hurrycurry-d6a0899e9641c68b96463669bd655629eb430311.tar hurrycurry-d6a0899e9641c68b96463669bd655629eb430311.tar.bz2 hurrycurry-d6a0899e9641c68b96463669bd655629eb430311.tar.zst |
multiplayer movement
-rw-r--r-- | client/scenes/game.tscn | 11 | ||||
-rw-r--r-- | client/scenes/player.tscn | 5 | ||||
-rw-r--r-- | client/scripts/controllable_player.gd | 107 | ||||
-rw-r--r-- | client/scripts/game.gd | 32 | ||||
-rw-r--r-- | client/scripts/multiplayer.gd | 18 | ||||
-rw-r--r-- | client/scripts/player.gd | 98 |
6 files changed, 168 insertions, 103 deletions
diff --git a/client/scenes/game.tscn b/client/scenes/game.tscn index bf93d4d7..998329cb 100644 --- a/client/scenes/game.tscn +++ b/client/scenes/game.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=7 format=3 uid="uid://clsylbmw7jc0s"] +[ext_resource type="Script" path="res://scripts/game.gd" id="1_qnslj"] [ext_resource type="PackedScene" uid="uid://bnqujofthaa4h" path="res://scenes/map.tscn" id="1_qt88a"] -[ext_resource type="PackedScene" uid="uid://d30bj2cp1m7gd" path="res://scenes/player.tscn" id="2_cdwnc"] [ext_resource type="PackedScene" uid="uid://b31mlnao6ybt8" path="res://scenes/follow_camera.tscn" id="3_6ot70"] [sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_ko0bu"] @@ -19,6 +19,7 @@ sdfgi_enabled = true glow_enabled = true [node name="Game" type="Node3D"] +script = ExtResource("1_qnslj") [node name="Map" parent="." instance=ExtResource("1_qt88a")] @@ -29,10 +30,6 @@ shadow_enabled = true [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_h880f") -[node name="Player" parent="." node_paths=PackedStringArray("map", "camera") instance=ExtResource("2_cdwnc")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 2) -map = NodePath("../Map") -camera = NodePath("../FollowCamera") - [node name="FollowCamera" parent="." node_paths=PackedStringArray("target") instance=ExtResource("3_6ot70")] -target = NodePath("../Player") +transform = Transform3D(0.894934, 0.084374, -0.438148, 0, 0.981959, 0.189095, 0.446198, -0.169228, 0.878789, 0, 3.65756, 11.0189) +target = NodePath("../Map") diff --git a/client/scenes/player.tscn b/client/scenes/player.tscn index f746e0ec..d0ebfa75 100644 --- a/client/scenes/player.tscn +++ b/client/scenes/player.tscn @@ -1,11 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://d30bj2cp1m7gd"] - -[ext_resource type="Script" path="res://scripts/player.gd" id="1_yh3ku"] +[gd_scene load_steps=2 format=3 uid="uid://d30bj2cp1m7gd"] [sub_resource type="CapsuleMesh" id="CapsuleMesh_4w71x"] [node name="Player" type="Node3D"] -script = ExtResource("1_yh3ku") [node name="MeshInstance3D" type="MeshInstance3D" parent="."] transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0.5, 0) diff --git a/client/scripts/controllable_player.gd b/client/scripts/controllable_player.gd new file mode 100644 index 00000000..adf3f2c0 --- /dev/null +++ b/client/scripts/controllable_player.gd @@ -0,0 +1,107 @@ +class_name ControllablePlayer +extends Player + +@export var map: Node3D +@export var camera: FollowCamera + +var facing = Vector2(1, 0) +var velocity = Vector2(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 + .5 * PI) + ) + +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) + ) + + # collide + collide(delta) + + velocity = lerp_vector2_exp(velocity, Vector2(0, 0), delta * 5.) + +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 + ) + + 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) + ) + +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 update_position(_new_position: Vector2, _new_rotation: float): + pass diff --git a/client/scripts/game.gd b/client/scripts/game.gd new file mode 100644 index 00000000..7c9b4bc2 --- /dev/null +++ b/client/scripts/game.gd @@ -0,0 +1,32 @@ +extends Node3D + +@onready var camera: FollowCamera = $FollowCamera +@onready var map: Node3D = $Map + +var players := {} +# Called when the node enters the scene tree for the first time. +func _ready(): + await Multiplayer.init + if Multiplayer.player_id == -1: + push_error("multiplayer has not been initialized") + Multiplayer.connect("add_player", + 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 + camera.target = player_instance + else: + player_instance = Player.new(player, name, pos, character) + players[player] = player_instance + add_child(player_instance) + ) + + Multiplayer.connect("position", + func(player: int, position: Vector2, rotation: float): + var player_instance: Player = players[player] + player_instance.update_position(position, rotation) + ) + + Multiplayer.send_join("Blub", 1) diff --git a/client/scripts/multiplayer.gd b/client/scripts/multiplayer.gd index d7dd9d1b..79c5df76 100644 --- a/client/scripts/multiplayer.gd +++ b/client/scripts/multiplayer.gd @@ -1,9 +1,13 @@ extends Node +signal init(player_id: int) signal update_map(tile: int, pos: Array, neighbors: Array) signal clear_message(player: int) signal text_message(player: int, text: String) signal item_message(player: int, item: int) +signal add_player(player: int, name: String, pos: Vector2, character: int) +signal remove_player(player: int) +signal position(player: int, position: Vector2, rotation: float) var connected := false var socket := WebSocketPeer.new() @@ -48,20 +52,24 @@ func handle_packet(bytes: PackedByteArray): player_id = decoded["id"] item_names = decoded["data"]["item_names"] tile_names = decoded["data"]["tile_names"] + emit_signal("init", player_id) "add_player": var id = decoded["id"] var player_name = decoded["name"] - #var item = decoded["item"] var pos = decoded["position"] var char = decoded["character"] + other_players[id] = [player_name, char] + emit_signal("add_player", id, player_name, pos_to_vec2(pos), char) "remove_player": var id = decoded["id"] other_players.erase(id) + emit_signal("remove_player", id) "position": var id = decoded["player"] var pos = decoded["pos"] var rot = decoded["rot"] + emit_signal("position", id, pos_to_vec2(pos), rot) "take_item": var tile = decoded["tile"] var player_id = decoded["player"] @@ -94,10 +102,11 @@ func handle_packet(bytes: PackedByteArray): _: push_error("Unrecognized packet type: %s" % packet_type) -func send_join(player_name: String): +func send_join(player_name: String, character: int): send_packet({ "type": "join", - "name": player_name + "name": player_name, + "character": character }) func send_position(pos: Vector2, rotation: float): @@ -127,3 +136,6 @@ func decode_packet(bytes: PackedByteArray): else: print("Decode of packet failed: %s in %s" % [json.get_error_message(), in_str]) return null + +func pos_to_vec2(pos: Array) -> Vector2: + return Vector2(pos[0], pos[1]) diff --git a/client/scripts/player.gd b/client/scripts/player.gd index c4cec300..3ad77322 100644 --- a/client/scripts/player.gd +++ b/client/scripts/player.gd @@ -1,96 +1,16 @@ +class_name Player extends Node3D const PLAYER_SIZE: float = 0.4 const SPEED: float = 25. -@export var map: Node3D -@export var camera: FollowCamera +var mesh = preload("res://scenes/player.tscn").instantiate() -var facing = Vector2(1, 0) -var velocity = Vector2(0, 0) +func _init(id: int, new_name: String, pos: Vector2, _character: int): + add_child(mesh) + position = Vector3(pos.x, 0, pos.y) + name = new_name -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 * 0.5 - velocity.y += input.y * delta * 0.5 - - position = Vector3( - position.x + (velocity.x * delta * SPEED), - 0, - position.z + (velocity.y * delta * SPEED) - ) - - # collide - collide(delta) - - velocity = lerp_vector2_exp(velocity, Vector2(0, 0), delta * 5.) - -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 - ) - - 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) - ) - -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 update_position(new_position: Vector2, new_rotation: float): + position = Vector3(new_position.x, 0, new_position.y) + rotation.y = new_rotation |