Add track minimap to GUI

pull/2/head
Ensar Sarajčić 2022-01-21 13:50:50 +01:00
parent fbc01a296e
commit 5b05771bb3
12 changed files with 289 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/player_icon.png-97b071f9d92f0abba7d34c4aae551713.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/player_icon.png"
dest_files=[ "res://.import/player_icon.png-97b071f9d92f0abba7d34c4aae551713.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View File

@ -1,5 +1,7 @@
extends Node extends Node
signal peers_updated
const GUI_SCENE = "res://player/gui.tscn" const GUI_SCENE = "res://player/gui.tscn"
var enet_peer = NetworkedMultiplayerENet.new() var enet_peer = NetworkedMultiplayerENet.new()
@ -9,31 +11,42 @@ var current_track: Node = null
var current_track_path: String var current_track_path: String
var current_vehicle: String var current_vehicle: String
var colors = [
Color.blue, Color.yellow, Color.green, Color.violet, Color.brown, Color.cyan, Color.orange
]
class PeerInfo: class PeerInfo:
var id: int var id: int
var vehicle: String var vehicle: String
var name: String var name: String
var spawned: bool var spawned: bool
var color: Color
static func new_peer( static func new_peer(
new_id: int, new_vehicle: String = "", new_name: String = "", new_spawned: bool = false new_id: int,
new_vehicle: String = "",
new_name: String = "",
new_spawned: bool = false,
new_color: Color = Color(1, 1, 1)
) -> PeerInfo: ) -> PeerInfo:
var new_instance = PeerInfo.new() var new_instance = PeerInfo.new()
new_instance.id = new_id new_instance.id = new_id
new_instance.vehicle = new_vehicle new_instance.vehicle = new_vehicle
new_instance.name = new_name new_instance.name = new_name
new_instance.spawned = new_spawned new_instance.spawned = new_spawned
new_instance.color = new_color
return new_instance return new_instance
func to_array() -> Array: func to_array() -> Array:
return [id, vehicle, name, spawned] return [id, vehicle, name, spawned, color]
func from_array(data: Array) -> void: func from_array(data: Array) -> void:
self.id = data[0] self.id = data[0]
self.vehicle = data[1] self.vehicle = data[1]
self.name = data[2] self.name = data[2]
self.spawned = data[3] self.spawned = data[3]
self.color = data[4]
func _ready(): func _ready():
@ -57,9 +70,12 @@ func create_server(port, track, vehicle):
current_vehicle = vehicle current_vehicle = vehicle
enet_peer.create_server(port, 2) enet_peer.create_server(port, 2)
get_tree().network_peer = enet_peer get_tree().network_peer = enet_peer
peers[1] = PeerInfo.new_peer(1, vehicle, GlobalSettings.multiplayer_name, true) peers[1] = PeerInfo.new_peer(
1, vehicle, GlobalSettings.multiplayer_name, true, get_next_color(1)
)
create_player(1, vehicle) create_player(1, vehicle)
get_tree().root.call_deferred("add_child", current_track) get_tree().root.call_deferred("add_child", current_track)
emit_signal("peers_updated")
func create_client(address, port, vehicle): func create_client(address, port, vehicle):
@ -67,18 +83,24 @@ func create_client(address, port, vehicle):
enet_peer.create_client(address, port) enet_peer.create_client(address, port)
get_tree().network_peer = enet_peer get_tree().network_peer = enet_peer
peers[get_tree().get_network_unique_id()] = PeerInfo.new_peer( peers[get_tree().get_network_unique_id()] = PeerInfo.new_peer(
get_tree().get_network_unique_id(), vehicle, GlobalSettings.multiplayer_name, true get_tree().get_network_unique_id(),
vehicle,
GlobalSettings.multiplayer_name,
true,
get_next_color(1)
) )
emit_signal("peers_updated")
func _peer_connected(peer_id): func _peer_connected(peer_id):
peers[peer_id] = PeerInfo.new_peer(peer_id, "", "", false) peers[peer_id] = PeerInfo.new_peer(peer_id, "", "", false, get_next_color(peer_id))
rpc_id( rpc_id(
peer_id, peer_id,
"add_player", "add_player",
get_tree().get_network_unique_id(), get_tree().get_network_unique_id(),
peers[get_tree().get_network_unique_id()].to_array() peers[get_tree().get_network_unique_id()].to_array()
) )
emit_signal("peers_updated")
if get_tree().get_network_unique_id() == 1: if get_tree().get_network_unique_id() == 1:
rpc_id(peer_id, "select_track", current_track_path) rpc_id(peer_id, "select_track", current_track_path)
@ -135,12 +157,12 @@ func quit():
remote func add_player(peer_id, peer_info: Array): remote func add_player(peer_id, peer_info: Array):
if peers[peer_id] == null: if peers[peer_id] == null:
peers[peer_id] = PeerInfo.new_peer(peer_id, "", "", false) peers[peer_id] = PeerInfo.new_peer(peer_id, "", "", false, get_next_color(peer_id))
if peers[peer_id].spawned == false: if peers[peer_id].spawned == false:
peers[peer_id].from_array(peer_info) peers[peer_id].from_array(peer_info)
# Check for duplicate names on server side # Check for duplicate names on server side and update colors
if get_tree().get_network_unique_id() == 1: if get_tree().get_network_unique_id() == 1:
var names = [] var names = []
for peer in peers: for peer in peers:
@ -151,11 +173,15 @@ remote func add_player(peer_id, peer_info: Array):
peers[peer_id].name = peers[peer_id].name + ("(%s)" % peer_id) peers[peer_id].name = peers[peer_id].name + ("(%s)" % peer_id)
rpc("update_name", peer_id, peers[peer_id].name) rpc("update_name", peer_id, peers[peer_id].name)
peers[peer_id].color = get_next_color(peer_id)
rpc("update_color", peer_id, peers[peer_id].color)
if current_track != null: if current_track != null:
peers[peer_id].spawned = true peers[peer_id].spawned = true
create_player(peer_id, peers[peer_id].vehicle) create_player(peer_id, peers[peer_id].vehicle)
else: else:
peers[peer_id].spawned = false peers[peer_id].spawned = false
emit_signal("peers_updated")
remote func select_track(track_path): remote func select_track(track_path):
@ -166,7 +192,21 @@ remote func select_track(track_path):
if peers[peer].spawned == false: if peers[peer].spawned == false:
peers[peer].spawned = true peers[peer].spawned = true
create_player(peer, peers[peer].vehicle) create_player(peer, peers[peer].vehicle)
emit_signal("peers_updated")
remote func update_name(peer_id, name: String): remote func update_name(peer_id, name: String):
peers[peer_id].name = name peers[peer_id].name = name
emit_signal("peers_updated")
remote func update_color(peer_id, color: Color):
peers[peer_id].color = color
emit_signal("peers_updated")
func get_next_color(peer_id: int) -> Color:
if peers.size() >= colors.size():
return Color(peer_id)
else:
return colors[peers.size()]

View File

@ -27,6 +27,7 @@ func spawn_player(player_node: BuggedVehicle, gui: Node) -> void:
func spawn_vehicle(vehicle: BuggedVehicle) -> void: func spawn_vehicle(vehicle: BuggedVehicle) -> void:
vehicle.connect("position_updated", track, "_on_player_position_updated")
reset_player_to(track.get_furthest_checkpoint(), vehicle) reset_player_to(track.get_furthest_checkpoint(), vehicle)
add_child(vehicle) add_child(vehicle)
@ -47,6 +48,7 @@ func reset_player_to(node_to_reset_to: Node, player_node: BuggedVehicle) -> void
func _spawn_in_player(): func _spawn_in_player():
reset_player_to(track.get_furthest_checkpoint(), player_node) reset_player_to(track.get_furthest_checkpoint(), player_node)
player_node.connect("position_updated", track, "_on_player_position_updated")
add_child(player_node) add_child(player_node)
add_child(gui) add_child(gui)
player_controller = PLAYER_CONTROLLER.new() player_controller = PLAYER_CONTROLLER.new()

View File

@ -0,0 +1,12 @@
extends Node2D
export(Curve2D) var curve
export(Color) var color = Color.red
export(float) var width = 2.0
func _draw() -> void:
if curve == null:
return
draw_polyline(curve.get_baked_points(), color, width)

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://scenes/components/curved_line_2d.gd" type="Script" id=1]
[node name="CurvedLine2d" type="Node2D"]
script = ExtResource( 1 )

View File

@ -0,0 +1,90 @@
extends Node2D
export(Vector2) var size = Vector2(200, 200)
export(Texture) var player_icon
onready var scaling_helper = $ScalingHelper
onready var track_path = $ScalingHelper/TrackPath
onready var track_line = $ScalingHelper/TrackLine
onready var start_line = $ScalingHelper/TrackPath/StartLine
onready var players_container = $ScalingHelper/Players
func _ready() -> void:
scaling_helper.position.x = size.x / 2
scaling_helper.position.y = size.y / 2
MultiplayerController.connect("peers_updated", self, "_on_peers_updated")
func set_curve(curve: Curve3D) -> void:
var curve2d = Curve2D.new()
var point_count = curve.get_point_count()
for point in range(point_count):
var point3d = curve.get_point_position(point)
var point_in = curve.get_point_in(point)
var point_out = curve.get_point_out(point)
curve2d.add_point(
Vector2(point3d.x, point3d.z),
Vector2(point_in.x, point_in.z),
Vector2(point_out.x, point_out.z)
)
var max_x = curve2d.get_baked_points()[0].x
var max_y = curve2d.get_baked_points()[0].y
var min_x = curve2d.get_baked_points()[0].x
var min_y = curve2d.get_baked_points()[0].y
for point in curve2d.get_baked_points():
if point.x > max_x:
max_x = point.x
if point.x < min_x:
min_x = point.x
if point.y > max_y:
max_y = point.y
if point.y < min_y:
min_y = point.y
var center_x = (max_x + min_x) / 2
var center_y = (max_y + min_y) / 2
var width = max_x - min_x
var height = max_y - min_y
var max_dim = max(width, height)
var scale_factor = size.x / (max_dim + track_line.width)
var new_center_x = scaling_helper.position.x - (center_x * scale_factor)
var new_center_y = scaling_helper.position.y - (center_y * scale_factor)
scaling_helper.scale.x = scale_factor
scaling_helper.scale.y = scale_factor
scaling_helper.position.x = new_center_x
scaling_helper.position.y = new_center_y
track_path.curve = curve2d
track_line.curve = curve2d
start_line.offset = 0.01
func on_player_position_updated(player_id: int, position: Transform) -> void:
var existing_node: Sprite = players_container.get_node_or_null(String(player_id))
if existing_node == null:
var player_color
if MultiplayerController.is_online():
player_color = MultiplayerController.peers[player_id].color
else:
player_color = Color(1, 1, 1)
existing_node = Sprite.new()
existing_node.name = String(player_id)
existing_node.texture = player_icon
existing_node.modulate = player_color
players_container.add_child(existing_node)
existing_node.position.x = position.origin.x
existing_node.position.y = position.origin.z
existing_node.rotation = position.basis.x.signed_angle_to(Vector3.LEFT, Vector3.UP)
func _on_peers_updated() -> void:
for peer in MultiplayerController.peers:
var existing_node: Sprite = players_container.get_node_or_null(String(peer))
if existing_node != null:
var player_color = MultiplayerController.peers[peer].color
existing_node.modulate = player_color
for child in players_container.get_children():
if not MultiplayerController.peers.has(int(float(child.name))):
child.queue_free()

View File

@ -0,0 +1,37 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://assets/player_icon.png" type="Texture" id=1]
[ext_resource path="res://scenes/track_minimap.gd" type="Script" id=2]
[ext_resource path="res://scenes/components/curved_line_2d.tscn" type="PackedScene" id=3]
[sub_resource type="Gradient" id=1]
offsets = PoolRealArray( 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 )
colors = PoolColorArray( 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1 )
[sub_resource type="GradientTexture" id=2]
gradient = SubResource( 1 )
width = 50
[node name="TrackMinimap" type="Node2D"]
script = ExtResource( 2 )
player_icon = ExtResource( 1 )
[node name="ScalingHelper" type="Node2D" parent="."]
[node name="TrackPath" type="Path2D" parent="ScalingHelper"]
curve = null
[node name="StartLine" type="PathFollow2D" parent="ScalingHelper/TrackPath"]
position = Vector2( -99.1171, -154.856 )
rotation = -0.742965
[node name="Sprite" type="Sprite" parent="ScalingHelper/TrackPath/StartLine"]
rotation = 1.5708
scale = Vector2( 1, 5 )
texture = SubResource( 2 )
[node name="TrackLine" parent="ScalingHelper" instance=ExtResource( 3 )]
color = Color( 0.482353, 0, 0, 1 )
width = 10.0
[node name="Players" type="Node2D" parent="ScalingHelper"]

View File

@ -8,6 +8,7 @@ onready var best_time_value = $VBoxContainer/HBoxContainer/BestTimeValue
onready var wrong_way_label = $CenterContainer/WrongWayLabel onready var wrong_way_label = $CenterContainer/WrongWayLabel
onready var leaderboards = $VBoxContainer/LeaderboardsLine onready var leaderboards = $VBoxContainer/LeaderboardsLine
onready var leaderboards_list = $VBoxContainer/LeaderboardsLine/VBoxContainer/Leaderboards onready var leaderboards_list = $VBoxContainer/LeaderboardsLine/VBoxContainer/Leaderboards
onready var track_minimap = $VBoxContainer2/HBoxContainer/ViewportContainer/TrackRadar/TrackMinimap
func _ready() -> void: func _ready() -> void:
@ -15,6 +16,7 @@ func _ready() -> void:
best_time_value.text = "NaN" best_time_value.text = "NaN"
if MultiplayerController.is_online(): if MultiplayerController.is_online():
leaderboards.visible = true leaderboards.visible = true
MultiplayerController.connect("peers_updated", self, "_on_peers_updated")
else: else:
leaderboards.visible = false leaderboards.visible = false
@ -47,7 +49,10 @@ func _format_time(time: float) -> String:
remote func update_leaderboard_time(peer_id: String, lap_time: float): remote func update_leaderboard_time(peer_id: String, lap_time: float):
leaderboards_data[peer_id] = lap_time leaderboards_data[peer_id] = lap_time
_refresh_leaderboard()
func _refresh_leaderboard():
var leaderboards_sorted = [] var leaderboards_sorted = []
for peer in leaderboards_data: for peer in leaderboards_data:
leaderboards_sorted.append([peer, leaderboards_data[peer]]) leaderboards_sorted.append([peer, leaderboards_data[peer]])
@ -67,3 +72,19 @@ remote func update_leaderboard_time(peer_id: String, lap_time: float):
func _leaderbords_comparison(left: Array, right: Array) -> bool: func _leaderbords_comparison(left: Array, right: Array) -> bool:
return left[1] < right[1] return left[1] < right[1]
func set_curve(curve: Curve3D) -> void:
track_minimap.set_curve(curve)
func on_player_position_updated(player_id: int, position: Transform) -> void:
track_minimap.on_player_position_updated(player_id, position)
func _on_peers_updated() -> void:
for peer in leaderboards_data.keys():
if not MultiplayerController.peers.has(peer):
leaderboards_data.erase(peer)
_refresh_leaderboard()

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=5 format=2] [gd_scene load_steps=6 format=2]
[ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1] [ext_resource path="res://assets/fonts/kenney-future-narrow.ttf" type="DynamicFontData" id=1]
[ext_resource path="res://scenes/trackgui.gd" type="Script" id=2] [ext_resource path="res://scenes/trackgui.gd" type="Script" id=2]
[ext_resource path="res://scenes/track_minimap.tscn" type="PackedScene" id=3]
[sub_resource type="DynamicFont" id=1] [sub_resource type="DynamicFont" id=1]
size = 36 size = 36
@ -125,3 +126,30 @@ align = 1
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[node name="VBoxContainer2" type="VBoxContainer" parent="."]
margin_right = 984.0
margin_bottom = 560.0
alignment = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer2"]
margin_top = 360.0
margin_right = 984.0
margin_bottom = 560.0
alignment = 2
[node name="ViewportContainer" type="ViewportContainer" parent="VBoxContainer2/HBoxContainer"]
margin_left = 784.0
margin_right = 984.0
margin_bottom = 200.0
[node name="TrackRadar" type="Viewport" parent="VBoxContainer2/HBoxContainer/ViewportContainer"]
size = Vector2( 200, 200 )
transparent_bg = true
handle_input_locally = false
disable_3d = true
usage = 0
render_target_update_mode = 3
gui_disable_input = true
[node name="TrackMinimap" parent="VBoxContainer2/HBoxContainer/ViewportContainer/TrackRadar" instance=ExtResource( 3 )]

View File

@ -24,6 +24,7 @@ var current_time = 0
var lap_done = false var lap_done = false
onready var checkpoints = $Checkpoints onready var checkpoints = $Checkpoints
onready var track_gui = $TrackGUI
onready var path: Path = get_node(track_path) onready var path: Path = get_node(track_path)
@ -51,6 +52,7 @@ func _ready() -> void:
gate.scale = gate_size gate.scale = gate_size
checkpoints.get_child(0).add_child(gate) checkpoints.get_child(0).add_child(gate)
checkpoints.global_transform.origin = path.global_transform.origin checkpoints.global_transform.origin = path.global_transform.origin
track_gui.set_curve(path.curve)
func _process(_delta: float) -> void: func _process(_delta: float) -> void:
@ -96,3 +98,7 @@ func _build_checkpoint_collision():
func _update_time(): func _update_time():
current_time = OS.get_ticks_msec() - start_time current_time = OS.get_ticks_msec() - start_time
emit_signal("time_updated", current_time) emit_signal("time_updated", current_time)
func _on_player_position_updated(player_id: int, position: Transform) -> void:
track_gui.on_player_position_updated(player_id, position)

View File

@ -8,6 +8,7 @@ signal brake_updated(brake_percent)
signal clutch_updated(clutch_percent) signal clutch_updated(clutch_percent)
signal gear_updated(gear) signal gear_updated(gear)
signal steering_updated(steering_angle, steering_percent) signal steering_updated(steering_angle, steering_percent)
signal position_updated(player_id, position)
enum GearRequest { NONE, UP, DOWN } enum GearRequest { NONE, UP, DOWN }
@ -256,6 +257,8 @@ func _physics_process(delta: float):
steering = steering_input * lerp(max_steer_angle_rad, speed_steer_angle_rad, steer_speed_factor) steering = steering_input * lerp(max_steer_angle_rad, speed_steer_angle_rad, steer_speed_factor)
emit_signal("steering_updated", steering, steering / max_steer_angle_rad) emit_signal("steering_updated", steering, steering / max_steer_angle_rad)
emit_signal("position_updated", get_network_master(), global_transform)
if MultiplayerController.is_online(): if MultiplayerController.is_online():
if get_network_master() == get_tree().get_network_unique_id(): if get_network_master() == get_tree().get_network_unique_id():
_synchronize() _synchronize()
@ -288,6 +291,7 @@ func _synchronize():
remote func sync_position(position: Transform): remote func sync_position(position: Transform):
reset_transform = position reset_transform = position
emit_signal("position_updated", get_network_master(), global_transform)
remote func sync_inputs(remote_inputs): remote func sync_inputs(remote_inputs):