mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-06 07:50:22 +01:00
Port Multiplayer bomber to replication system.
This commit is contained in:
@@ -5,17 +5,18 @@ var from_player
|
||||
|
||||
# Called from the animation.
|
||||
func explode():
|
||||
if not is_network_master():
|
||||
# Explode only on master.
|
||||
if not is_multiplayer_authority():
|
||||
# Explode only on authority.
|
||||
return
|
||||
for p in in_area:
|
||||
if p.has_method("exploded"):
|
||||
# Exploded has a master keyword, so it will only be received by the master.
|
||||
p.rpc("exploded", from_player)
|
||||
# Exploded can only be called by the authority, but will also be called locally.
|
||||
p.rpc(&"exploded", from_player)
|
||||
|
||||
|
||||
func done():
|
||||
queue_free()
|
||||
if is_multiplayer_authority():
|
||||
queue_free()
|
||||
|
||||
|
||||
func _on_bomb_body_enter(body):
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
[gd_scene load_steps=10 format=3 uid="uid://enwoaqi0rnei"]
|
||||
|
||||
[ext_resource path="res://bomb.gd" type="Script" id=1]
|
||||
[ext_resource path="res://brickfloor.png" type="Texture2D" id=2]
|
||||
[ext_resource path="res://explosion.png" type="Texture2D" id=3]
|
||||
[ext_resource type="Script" path="res://bomb.gd" id="1"]
|
||||
[ext_resource type="Texture2D" uid="uid://bdomqql6y50po" path="res://brickfloor.png" id="2"]
|
||||
[ext_resource type="Texture2D" uid="uid://drfbkdqmj0gu2" path="res://explosion.png" id="3"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2(8, 96)
|
||||
[sub_resource type="RectangleShape2D" id="1"]
|
||||
size = Vector2(16, 192)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=2]
|
||||
extents = Vector2(96, 8)
|
||||
[sub_resource type="RectangleShape2D" id="2"]
|
||||
size = Vector2(192, 16)
|
||||
|
||||
[sub_resource type="Curve" id=3]
|
||||
[sub_resource type="Curve" id="3"]
|
||||
max_value = 2.0
|
||||
_data = [Vector2(0.00150494, 0.398437), 0.0, 0.0, 0, 0, Vector2(0.0152287, 1.42969), 0.0, 0.0, 0, 0, Vector2(0.478607, 1.30078), 0.0, 0.0, 0, 0, Vector2(1, 0.291016), 0.0, 0.0, 0, 0]
|
||||
|
||||
[sub_resource type="Animation" id=4]
|
||||
[sub_resource type="CurveTexture" id="4"]
|
||||
curve = SubResource( "3" )
|
||||
|
||||
[sub_resource type="ParticlesMaterial" id="5"]
|
||||
emission_shape = 2
|
||||
emission_sphere_radius = 1.0
|
||||
gravity = Vector3(0, 0, 0)
|
||||
scale_curve = SubResource( "4" )
|
||||
|
||||
[sub_resource type="Animation" id="6"]
|
||||
length = 4.0
|
||||
tracks/0/type = "value"
|
||||
tracks/0/path = NodePath("Sprite2D:self_modulate")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Sprite:self_modulate")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.4, 0.6, 0.8, 1.1, 1.3, 1.5, 1.8, 1.9, 2, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
|
||||
@@ -29,28 +38,28 @@ tracks/0/keys = {
|
||||
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(8, 8, 8, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(8, 8, 8, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(8, 8, 8, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(8, 8, 8, 1), Color(1, 1, 1, 1), Color(8, 8, 8, 1), Color(1, 1, 1, 1), Color(8, 8, 8, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
|
||||
}
|
||||
tracks/1/type = "method"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath(".")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(2.8, 3.4),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"values": [{
|
||||
"args": [],
|
||||
"method": "explode"
|
||||
"method": &"explode"
|
||||
}, {
|
||||
"args": [],
|
||||
"method": "done"
|
||||
"method": &"done"
|
||||
}]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("Explosion1:emitting")
|
||||
tracks/2/interp = 1
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 2.8),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
@@ -58,11 +67,11 @@ tracks/2/keys = {
|
||||
"values": [false, true]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/path = NodePath("Explosion2:emitting")
|
||||
tracks/3/interp = 1
|
||||
tracks/3/loop_wrap = true
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0, 2.8),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
@@ -71,52 +80,40 @@ tracks/3/keys = {
|
||||
}
|
||||
|
||||
[node name="Bomb" type="Area2D"]
|
||||
script = ExtResource( 1 )
|
||||
monitorable = false
|
||||
script = ExtResource( "1" )
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
[node name="Sprite" type="Sprite2D" parent="."]
|
||||
position = Vector2(-2.92606, -2.92606)
|
||||
texture = ExtResource( 2 )
|
||||
texture = ExtResource( "2" )
|
||||
region_enabled = true
|
||||
region_rect = Rect2(144, 0, 48, 48)
|
||||
|
||||
[node name="Shape1" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
shape = SubResource( "1" )
|
||||
|
||||
[node name="Shape2" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 2 )
|
||||
shape = SubResource( "2" )
|
||||
|
||||
[node name="Explosion1" type="CPUParticles2D" parent="."]
|
||||
[node name="Explosion1" type="GPUParticles2D" parent="."]
|
||||
emitting = false
|
||||
lifetime = 0.5
|
||||
one_shot = true
|
||||
explosiveness = 0.95
|
||||
texture = ExtResource( 3 )
|
||||
emission_shape = 2
|
||||
emission_rect_extents = Vector2(80, 1)
|
||||
gravity = Vector2(0, 0)
|
||||
initial_velocity = 1.0
|
||||
angular_velocity = 187.85
|
||||
angular_velocity_random = 1.0
|
||||
scale_amount_curve = SubResource( 3 )
|
||||
process_material = SubResource( "5" )
|
||||
texture = ExtResource( "3" )
|
||||
|
||||
[node name="Explosion2" type="CPUParticles2D" parent="."]
|
||||
[node name="Explosion2" type="GPUParticles2D" parent="."]
|
||||
rotation = 1.57162
|
||||
scale = Vector2(1, 1)
|
||||
emitting = false
|
||||
one_shot = true
|
||||
explosiveness = 0.95
|
||||
texture = ExtResource( 3 )
|
||||
emission_shape = 2
|
||||
emission_rect_extents = Vector2(80, 1)
|
||||
gravity = Vector2(0, 0)
|
||||
initial_velocity = 1.0
|
||||
angular_velocity = 187.85
|
||||
angular_velocity_random = 1.0
|
||||
scale_amount_curve = SubResource( 3 )
|
||||
process_material = SubResource( "5" )
|
||||
texture = ExtResource( "3" )
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
autoplay = "anim"
|
||||
anims/anim = SubResource( 4 )
|
||||
anims/anim = SubResource( "6" )
|
||||
|
||||
[connection signal="body_entered" from="." to="." method="_on_bomb_body_enter"]
|
||||
[connection signal="body_exited" from="." to="." method="_on_bomb_body_exit"]
|
||||
|
||||
9
networking/multiplayer_bomber/bomb_spawner.gd
Normal file
9
networking/multiplayer_bomber/bomb_spawner.gd
Normal file
@@ -0,0 +1,9 @@
|
||||
extends MultiplayerSpawner
|
||||
|
||||
func _spawn_custom(data):
|
||||
if data.size() != 2 or typeof(data[0]) != TYPE_VECTOR2 or typeof(data[1]) != TYPE_INT:
|
||||
return null
|
||||
var bomb = preload("res://bomb.tscn").instantiate()
|
||||
bomb.position = data[0]
|
||||
bomb.from_player = data[1]
|
||||
return bomb
|
||||
@@ -1,8 +1,9 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture2D"
|
||||
path="res://.godot/imported/brickfloor.png-bab1cbace80ab627972eea565951db9e.stex"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bdomqql6y50po"
|
||||
path="res://.godot/imported/brickfloor.png-bab1cbace80ab627972eea565951db9e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -10,26 +11,23 @@ metadata={
|
||||
[deps]
|
||||
|
||||
source_file="res://brickfloor.png"
|
||||
dest_files=["res://.godot/imported/brickfloor.png-bab1cbace80ab627972eea565951db9e.stex"]
|
||||
dest_files=["res://.godot/imported/brickfloor.png-bab1cbace80ab627972eea565951db9e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/hdr_compression=1
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
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
|
||||
process/hdr_as_srgb=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture2D"
|
||||
path="res://.godot/imported/charwalk.png-a9f067962a6454cc2f52a6e82832cbc5.stex"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bsqovikudjr0q"
|
||||
path="res://.godot/imported/charwalk.png-a9f067962a6454cc2f52a6e82832cbc5.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -10,26 +11,23 @@ metadata={
|
||||
[deps]
|
||||
|
||||
source_file="res://charwalk.png"
|
||||
dest_files=["res://.godot/imported/charwalk.png-a9f067962a6454cc2f52a6e82832cbc5.stex"]
|
||||
dest_files=["res://.godot/imported/charwalk.png-a9f067962a6454cc2f52a6e82832cbc5.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/hdr_compression=1
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
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
|
||||
process/hdr_as_srgb=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture2D"
|
||||
path="res://.godot/imported/explosion.png-730076d88b39dbfd5c22ad71f1135b01.stex"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://drfbkdqmj0gu2"
|
||||
path="res://.godot/imported/explosion.png-730076d88b39dbfd5c22ad71f1135b01.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -10,26 +11,23 @@ metadata={
|
||||
[deps]
|
||||
|
||||
source_file="res://explosion.png"
|
||||
dest_files=["res://.godot/imported/explosion.png-730076d88b39dbfd5c22ad71f1135b01.stex"]
|
||||
dest_files=["res://.godot/imported/explosion.png-730076d88b39dbfd5c22ad71f1135b01.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/hdr_compression=1
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
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
|
||||
process/hdr_as_srgb=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
||||
@@ -27,14 +27,14 @@ signal game_error(what)
|
||||
# Callback from SceneTree.
|
||||
func _player_connected(id):
|
||||
# Registration of a client beings here, tell the connected player that we are here.
|
||||
rpc_id(id, "register_player", player_name)
|
||||
rpc_id(id, StringName("register_player"), player_name)
|
||||
|
||||
|
||||
# Callback from SceneTree.
|
||||
func _player_disconnected(id):
|
||||
if has_node("/root/World3D"): # Game is in progress.
|
||||
if get_tree().is_network_server():
|
||||
emit_signal("game_error", "Player " + players[id] + " disconnected")
|
||||
if has_node("/root/World"): # Game is in progress.
|
||||
if multiplayer.is_server():
|
||||
game_error.emit("Player " + players[id] + " disconnected")
|
||||
end_game()
|
||||
else: # Game is not in progress.
|
||||
# Unregister this player.
|
||||
@@ -44,101 +44,60 @@ func _player_disconnected(id):
|
||||
# Callback from SceneTree, only for clients (not server).
|
||||
func _connected_ok():
|
||||
# We just connected to a server
|
||||
emit_signal("connection_succeeded")
|
||||
connection_succeeded.emit()
|
||||
|
||||
|
||||
# Callback from SceneTree, only for clients (not server).
|
||||
func _server_disconnected():
|
||||
emit_signal("game_error", "Server disconnected")
|
||||
game_error.emit("Server disconnected")
|
||||
end_game()
|
||||
|
||||
|
||||
# Callback from SceneTree, only for clients (not server).
|
||||
func _connected_fail():
|
||||
get_tree().set_network_peer(null) # Remove peer
|
||||
emit_signal("connection_failed")
|
||||
multiplayer.set_network_peer(null) # Remove peer
|
||||
connection_failed.emit()
|
||||
|
||||
|
||||
# Lobby management functions.
|
||||
|
||||
remote func register_player(new_player_name):
|
||||
var id = get_tree().get_rpc_sender_id()
|
||||
print(id)
|
||||
@rpc(any_peer)
|
||||
func register_player(new_player_name):
|
||||
var id = multiplayer.get_remote_sender_id()
|
||||
players[id] = new_player_name
|
||||
emit_signal("player_list_changed")
|
||||
player_list_changed.emit()
|
||||
|
||||
|
||||
func unregister_player(id):
|
||||
players.erase(id)
|
||||
emit_signal("player_list_changed")
|
||||
player_list_changed.emit()
|
||||
|
||||
|
||||
remote func pre_start_game(spawn_points):
|
||||
@rpc(call_local)
|
||||
func load_world():
|
||||
# Change scene.
|
||||
var world = load("res://world.tscn").instantiate()
|
||||
get_tree().get_root().add_child(world)
|
||||
|
||||
get_tree().get_root().get_node(^"Lobby").hide()
|
||||
|
||||
var player_scene = load("res://player.tscn")
|
||||
|
||||
for p_id in spawn_points:
|
||||
var spawn_pos = world.get_node(^"SpawnPoints/" + str(spawn_points[p_id])).position
|
||||
var player = player_scene.instantiate()
|
||||
|
||||
player.set_name(str(p_id)) # Use unique ID as node name.
|
||||
player.position=spawn_pos
|
||||
player.set_network_master(p_id) #set unique id as master.
|
||||
|
||||
if p_id == get_tree().get_network_unique_id():
|
||||
# If node for this peer id, set name.
|
||||
player.set_player_name(player_name)
|
||||
else:
|
||||
# Otherwise set name from peer.
|
||||
player.set_player_name(players[p_id])
|
||||
|
||||
world.get_node(^"Players").add_child(player)
|
||||
get_tree().get_root().get_node("Lobby").hide()
|
||||
|
||||
# Set up score.
|
||||
world.get_node(^"Score").add_player(get_tree().get_network_unique_id(), player_name)
|
||||
world.get_node("Score").add_player(multiplayer.get_unique_id(), player_name)
|
||||
for pn in players:
|
||||
world.get_node(^"Score").add_player(pn, players[pn])
|
||||
|
||||
if not get_tree().is_network_server():
|
||||
# Tell server we are ready to start.
|
||||
rpc_id(1, "ready_to_start", get_tree().get_network_unique_id())
|
||||
elif players.size() == 0:
|
||||
post_start_game()
|
||||
|
||||
|
||||
remote func post_start_game():
|
||||
world.get_node("Score").add_player(pn, players[pn])
|
||||
get_tree().set_pause(false) # Unpause and unleash the game!
|
||||
|
||||
|
||||
remote func ready_to_start(id):
|
||||
assert(get_tree().is_network_server())
|
||||
|
||||
if not id in players_ready:
|
||||
players_ready.append(id)
|
||||
|
||||
if players_ready.size() == players.size():
|
||||
for p in players:
|
||||
rpc_id(p, "post_start_game")
|
||||
post_start_game()
|
||||
|
||||
|
||||
func host_game(new_player_name):
|
||||
player_name = new_player_name
|
||||
peer = NetworkedMultiplayerENet.new()
|
||||
peer = ENetMultiplayerPeer.new()
|
||||
peer.create_server(DEFAULT_PORT, MAX_PEERS)
|
||||
get_tree().set_network_peer(peer)
|
||||
multiplayer.set_multiplayer_peer(peer)
|
||||
|
||||
|
||||
func join_game(ip, new_player_name):
|
||||
player_name = new_player_name
|
||||
peer = NetworkedMultiplayerENet.new()
|
||||
peer = ENetMultiplayerPeer.new()
|
||||
peer.create_client(ip, DEFAULT_PORT)
|
||||
get_tree().set_network_peer(peer)
|
||||
multiplayer.set_multiplayer_peer(peer)
|
||||
|
||||
|
||||
func get_player_list():
|
||||
@@ -150,7 +109,11 @@ func get_player_name():
|
||||
|
||||
|
||||
func begin_game():
|
||||
assert(get_tree().is_network_server())
|
||||
assert(multiplayer.is_server())
|
||||
load_world.rpc()
|
||||
|
||||
var world = get_tree().get_root().get_node("World")
|
||||
var player_scene = load("res://player.tscn")
|
||||
|
||||
# Create a dictionary with peer id and respective spawn points, could be improved by randomizing.
|
||||
var spawn_points = {}
|
||||
@@ -159,25 +122,28 @@ func begin_game():
|
||||
for p in players:
|
||||
spawn_points[p] = spawn_point_idx
|
||||
spawn_point_idx += 1
|
||||
# Call to pre-start game with the spawn points.
|
||||
for p in players:
|
||||
rpc_id(p, "pre_start_game", spawn_points)
|
||||
|
||||
pre_start_game(spawn_points)
|
||||
for p_id in spawn_points:
|
||||
var spawn_pos = world.get_node("SpawnPoints/" + str(spawn_points[p_id])).position
|
||||
var player = player_scene.instantiate()
|
||||
player.synced_position = spawn_pos
|
||||
player.name = str(p_id)
|
||||
player.set_player_name(player_name if p_id == multiplayer.get_unique_id() else players[p_id])
|
||||
world.get_node("Players").add_child(player)
|
||||
|
||||
|
||||
func end_game():
|
||||
if has_node("/root/World3D"): # Game is in progress.
|
||||
if has_node("/root/World"): # Game is in progress.
|
||||
# End it
|
||||
get_node(^"/root/World3D").queue_free()
|
||||
get_node("/root/World").queue_free()
|
||||
|
||||
emit_signal("game_ended")
|
||||
game_ended.emit()
|
||||
players.clear()
|
||||
|
||||
|
||||
func _ready():
|
||||
get_tree().connect(&"network_peer_connected", self._player_connected)
|
||||
get_tree().connect("network_peer_disconnected", self,"_player_disconnected")
|
||||
get_tree().connect(&"connected_to_server", self._connected_ok)
|
||||
get_tree().connect(&"connection_failed", self._connected_fail)
|
||||
get_tree().connect(&"server_disconnected", self._server_disconnected)
|
||||
multiplayer.peer_connected.connect(_player_connected)
|
||||
multiplayer.peer_disconnected.connect(_player_disconnected)
|
||||
multiplayer.connected_to_server.connect(_connected_ok)
|
||||
multiplayer.connection_failed.connect(_connected_fail)
|
||||
multiplayer.server_disconnected.connect(_server_disconnected)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture2D"
|
||||
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cbby50724oj4c"
|
||||
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -10,26 +11,23 @@ metadata={
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"]
|
||||
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/hdr_compression=1
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
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
|
||||
process/hdr_as_srgb=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
||||
@@ -2,11 +2,11 @@ extends Control
|
||||
|
||||
func _ready():
|
||||
# Called every time the node is added to the scene.
|
||||
gamestate.connect(&"connection_failed", self._on_connection_failed)
|
||||
gamestate.connect(&"connection_succeeded", self._on_connection_success)
|
||||
gamestate.connect(&"player_list_changed", self.refresh_lobby)
|
||||
gamestate.connect(&"game_ended", self._on_game_ended)
|
||||
gamestate.connect(&"game_error", self._on_game_error)
|
||||
gamestate.connection_failed.connect(_on_connection_failed)
|
||||
gamestate.connection_succeeded.connect(_on_connection_success)
|
||||
gamestate.player_list_changed.connect(refresh_lobby)
|
||||
gamestate.game_ended.connect(_on_game_ended)
|
||||
gamestate.game_error.connect(_on_game_error)
|
||||
# Set the player name according to the system username. Fallback to the path.
|
||||
if OS.has_environment("USERNAME"):
|
||||
$Connect/Name.text = OS.get_environment("USERNAME")
|
||||
@@ -68,7 +68,7 @@ func _on_game_ended():
|
||||
|
||||
func _on_game_error(errtxt):
|
||||
$ErrorDialog.dialog_text = errtxt
|
||||
$ErrorDialog.popup_centered_clamped()
|
||||
$ErrorDialog.popup_centered()
|
||||
$Connect/Host.disabled = false
|
||||
$Connect/Join.disabled = false
|
||||
|
||||
@@ -81,7 +81,7 @@ func refresh_lobby():
|
||||
for p in players:
|
||||
$Players/List.add_item(p)
|
||||
|
||||
$Players/Start.disabled = not get_tree().is_network_server()
|
||||
$Players/Start.disabled = not multiplayer.is_server()
|
||||
|
||||
|
||||
func _on_start_pressed():
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
[gd_scene load_steps=2 format=3 uid="uid://jhdlqsokif5o"]
|
||||
|
||||
[ext_resource path="res://lobby.gd" type="Script" id=1]
|
||||
[ext_resource type="Script" path="res://lobby.gd" id="1"]
|
||||
|
||||
[node name="Lobby" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
script = ExtResource( "1" )
|
||||
|
||||
[node name="Players" type="Panel" parent="."]
|
||||
visible = false
|
||||
@@ -56,11 +53,10 @@ offset_left = -124.0
|
||||
offset_top = 375.0
|
||||
offset_right = 128.0
|
||||
offset_bottom = 429.0
|
||||
custom_constants/line_spacing = 6
|
||||
theme_override_constants/line_spacing = 6
|
||||
text = "If you want non-LAN clients to connect,
|
||||
make sure the port 10567 in UDP
|
||||
is forwarded on your router."
|
||||
align = 1
|
||||
|
||||
[node name="FindPublicIP" type="LinkButton" parent="Players"]
|
||||
offset_left = 168.0
|
||||
@@ -106,6 +102,7 @@ offset_right = 57.0
|
||||
offset_bottom = 80.0
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 0
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "IP:"
|
||||
|
||||
[node name="IPAddress" type="LineEdit" parent="Connect"]
|
||||
@@ -142,14 +139,9 @@ offset_right = 257.0
|
||||
offset_bottom = 139.0
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 0
|
||||
custom_colors/font_color = Color(0.820312, 0.291595, 0.291595, 1)
|
||||
align = 1
|
||||
theme_override_colors/font_color = Color(0.820312, 0.291595, 0.291595, 1)
|
||||
|
||||
[node name="ErrorDialog" type="AcceptDialog" parent="."]
|
||||
offset_right = 55.0
|
||||
offset_bottom = 58.0
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 2
|
||||
|
||||
[connection signal="pressed" from="Players/Start" to="." method="_on_start_pressed"]
|
||||
[connection signal="pressed" from="Players/FindPublicIP" to="." method="_on_find_public_ip_pressed"]
|
||||
|
||||
33
networking/multiplayer_bomber/montserrat.otf.import
Normal file
33
networking/multiplayer_bomber/montserrat.otf.import
Normal file
@@ -0,0 +1,33 @@
|
||||
[remap]
|
||||
|
||||
importer="font_data_dynamic"
|
||||
type="FontData"
|
||||
uid="uid://dksjmw4cy83s4"
|
||||
path="res://.godot/imported/montserrat.otf-0d875bde8933edfaf65407b0d9da84e5.fontdata"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://montserrat.otf"
|
||||
dest_files=["res://.godot/imported/montserrat.otf-0d875bde8933edfaf65407b0d9da84e5.fontdata"]
|
||||
|
||||
[params]
|
||||
|
||||
antialiased=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
force_autohinter=false
|
||||
hinting=1
|
||||
subpixel_positioning=1
|
||||
embolden=0.0
|
||||
transform=Transform2D(1, 0, 0, 1, 0, 0)
|
||||
oversampling=0.0
|
||||
compress=true
|
||||
opentype_feature_overrides={}
|
||||
preload/char_ranges=PackedStringArray()
|
||||
preload/glyph_ranges=PackedStringArray()
|
||||
preload/configurations=PackedStringArray()
|
||||
support_overrides/language_enabled=PackedStringArray()
|
||||
support_overrides/language_disabled=PackedStringArray()
|
||||
support_overrides/script_enabled=PackedStringArray()
|
||||
support_overrides/script_disabled=PackedStringArray()
|
||||
@@ -1,66 +1,58 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
const MOTION_SPEED = 90.0
|
||||
const BOMB_RATE = 0.5
|
||||
|
||||
puppet var puppet_pos = Vector2()
|
||||
puppet var puppet_motion = Vector2()
|
||||
@export
|
||||
var synced_position := Vector2()
|
||||
|
||||
@export var stunned = false
|
||||
|
||||
# Use sync because it will be called everywhere
|
||||
remotesync func setup_bomb(bomb_name, pos, by_who):
|
||||
var bomb = preload("res://bomb.tscn").instantiate()
|
||||
bomb.set_name(bomb_name) # Ensure unique name for the bomb
|
||||
bomb.position = pos
|
||||
bomb.from_player = by_who
|
||||
# No need to set network master to bomb, will be owned by server by default
|
||||
get_node(^"../..").add_child(bomb)
|
||||
@export
|
||||
var stunned = false
|
||||
|
||||
@onready
|
||||
var inputs = $Inputs
|
||||
var last_bomb_time = BOMB_RATE
|
||||
var current_anim = ""
|
||||
var prev_bombing = false
|
||||
var bomb_index = 0
|
||||
|
||||
func _ready():
|
||||
stunned = false
|
||||
position = synced_position
|
||||
if str(name).is_valid_int():
|
||||
get_node("Inputs/InputsSync").set_multiplayer_authority(str(name).to_int())
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
var motion = Vector2()
|
||||
func _physics_process(delta):
|
||||
if multiplayer.multiplayer_peer == null or str(multiplayer.get_unique_id()) == str(name):
|
||||
# The client which this player represent will update the controls state, and notify it to everyone.
|
||||
inputs.update()
|
||||
|
||||
if is_network_master():
|
||||
if Input.is_action_pressed(&"move_left"):
|
||||
motion += Vector2(-1, 0)
|
||||
if Input.is_action_pressed(&"move_right"):
|
||||
motion += Vector2(1, 0)
|
||||
if Input.is_action_pressed(&"move_up"):
|
||||
motion += Vector2(0, -1)
|
||||
if Input.is_action_pressed(&"move_down"):
|
||||
motion += Vector2(0, 1)
|
||||
|
||||
var bombing = Input.is_action_pressed(&"set_bomb")
|
||||
|
||||
if stunned:
|
||||
bombing = false
|
||||
motion = Vector2()
|
||||
|
||||
if bombing and not prev_bombing:
|
||||
var bomb_name = String(get_name()) + str(bomb_index)
|
||||
var bomb_pos = position
|
||||
rpc("setup_bomb", bomb_name, bomb_pos, get_tree().get_network_unique_id())
|
||||
|
||||
prev_bombing = bombing
|
||||
|
||||
rset("puppet_motion", motion)
|
||||
rset("puppet_pos", position)
|
||||
if multiplayer.multiplayer_peer == null or is_multiplayer_authority():
|
||||
# The server updates the position that will be notified to the clients.
|
||||
synced_position = position
|
||||
# And increase the bomb cooldown spawning one if the client wants to.
|
||||
last_bomb_time += delta
|
||||
if not stunned and is_multiplayer_authority() and inputs.bombing and last_bomb_time >= BOMB_RATE:
|
||||
last_bomb_time = 0.0
|
||||
get_node("../../BombSpawner").spawn([position, str(name).to_int()])
|
||||
else:
|
||||
position = puppet_pos
|
||||
motion = puppet_motion
|
||||
# The client simply updates the position to the last known one.
|
||||
position = synced_position
|
||||
|
||||
if not stunned:
|
||||
# Everybody runs physics. I.e. clients tries to predict where they will be during the next frame.
|
||||
velocity = inputs.motion * MOTION_SPEED
|
||||
move_and_slide()
|
||||
|
||||
# Also update the animation based on the last known player input state
|
||||
var new_anim = "standing"
|
||||
if motion.y < 0:
|
||||
|
||||
if inputs.motion.y < 0:
|
||||
new_anim = "walk_up"
|
||||
elif motion.y > 0:
|
||||
elif inputs.motion.y > 0:
|
||||
new_anim = "walk_down"
|
||||
elif motion.x < 0:
|
||||
elif inputs.motion.x < 0:
|
||||
new_anim = "walk_left"
|
||||
elif motion.x > 0:
|
||||
elif inputs.motion.x > 0:
|
||||
new_anim = "walk_right"
|
||||
|
||||
if stunned:
|
||||
@@ -68,30 +60,16 @@ func _physics_process(_delta):
|
||||
|
||||
if new_anim != current_anim:
|
||||
current_anim = new_anim
|
||||
get_node(^"anim").play(current_anim)
|
||||
|
||||
# TODO: This information should be set to the CharacterBody properties instead of arguments.
|
||||
# FIXME: Use move_and_slide
|
||||
move_and_slide(motion * MOTION_SPEED)
|
||||
if not is_network_master():
|
||||
puppet_pos = position # To avoid jitter
|
||||
get_node("anim").play(current_anim)
|
||||
|
||||
|
||||
puppet func stun():
|
||||
stunned = true
|
||||
func set_player_name(value):
|
||||
get_node("label").text = value
|
||||
|
||||
|
||||
master func exploded(_by_who):
|
||||
@rpc(call_local)
|
||||
func exploded(_by_who):
|
||||
if stunned:
|
||||
return
|
||||
rpc("stun") # Stun puppets
|
||||
stun() # Stun master - could use sync to do both at once
|
||||
|
||||
|
||||
func set_player_name(new_name):
|
||||
get_node(^"label").set_text(new_name)
|
||||
|
||||
|
||||
func _ready():
|
||||
stunned = false
|
||||
puppet_pos = position
|
||||
stunned = true
|
||||
get_node("anim").play("stunned")
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
[gd_scene load_steps=12 format=2]
|
||||
[gd_scene load_steps=15 format=3 uid="uid://dviwgv2ty8v6u"]
|
||||
|
||||
[ext_resource path="res://player.gd" type="Script" id=1]
|
||||
[ext_resource path="res://charwalk.png" type="Texture2D" id=2]
|
||||
[ext_resource path="res://montserrat.otf" type="FontData" id=3]
|
||||
[ext_resource type="Script" path="res://player.gd" id="1"]
|
||||
[ext_resource type="Texture2D" uid="uid://bsqovikudjr0q" path="res://charwalk.png" id="2"]
|
||||
[ext_resource type="FontData" uid="uid://dksjmw4cy83s4" path="res://montserrat.otf" id="3"]
|
||||
[ext_resource type="Script" path="res://player_controls.gd" id="4_k1vfr"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
[sub_resource type="CircleShape2D" id="1"]
|
||||
radius = 20.0
|
||||
|
||||
[sub_resource type="Animation" id=2]
|
||||
[sub_resource type="Animation" id="2"]
|
||||
resource_name = "standing"
|
||||
length = 0.8
|
||||
loop = true
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("sprite:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1),
|
||||
@@ -24,15 +25,15 @@ tracks/0/keys = {
|
||||
"values": [0, 4, 8, 12]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id=3]
|
||||
[sub_resource type="Animation" id="3"]
|
||||
resource_name = "stunned"
|
||||
length = 1.2
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("sprite:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
@@ -40,39 +41,39 @@ tracks/0/keys = {
|
||||
"values": [0]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/path = NodePath("sprite:rotation_degrees")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath(".:stunned")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 1, 1.1),
|
||||
"transitions": PackedFloat32Array(1, 0, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 720.0, 0.0]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/path = NodePath(".:stunned")
|
||||
tracks/2/interp = 1
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(1),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 1,
|
||||
"values": [false]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("sprite:rotation")
|
||||
tracks/2/interp = 1
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [-6.28319, 0.0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id=4]
|
||||
[sub_resource type="Animation" id="4"]
|
||||
length = 0.8
|
||||
loop = true
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("sprite:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1),
|
||||
@@ -80,16 +81,16 @@ tracks/0/keys = {
|
||||
"values": [0, 4, 8, 12]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id=5]
|
||||
[sub_resource type="Animation" id="5"]
|
||||
length = 0.8
|
||||
loop = true
|
||||
loop_mode = 1
|
||||
step = 0.2
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("sprite:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1),
|
||||
@@ -97,16 +98,16 @@ tracks/0/keys = {
|
||||
"values": [1, 5, 9, 13]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id=6]
|
||||
[sub_resource type="Animation" id="6"]
|
||||
length = 0.8
|
||||
loop = true
|
||||
loop_mode = 1
|
||||
step = 0.2
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("sprite:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1),
|
||||
@@ -114,16 +115,16 @@ tracks/0/keys = {
|
||||
"values": [3, 7, 11, 15]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id=7]
|
||||
[sub_resource type="Animation" id="7"]
|
||||
length = 0.8
|
||||
loop = true
|
||||
loop_mode = 1
|
||||
step = 0.2
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("sprite:frame")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1),
|
||||
@@ -131,30 +132,47 @@ tracks/0/keys = {
|
||||
"values": [2, 6, 10, 14]
|
||||
}
|
||||
|
||||
[sub_resource type="Font" id=8]
|
||||
size = 14
|
||||
font_data = ExtResource( 3 )
|
||||
[sub_resource type="Font" id="8"]
|
||||
data/0 = ExtResource( "3" )
|
||||
|
||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_xm6wv"]
|
||||
properties/0/path = NodePath(".:synced_position")
|
||||
properties/0/spawn = true
|
||||
properties/0/sync = true
|
||||
properties/1/path = NodePath("label:text")
|
||||
properties/1/spawn = true
|
||||
properties/1/sync = false
|
||||
|
||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_kkxsa"]
|
||||
properties/0/path = NodePath(".:motion")
|
||||
properties/0/spawn = true
|
||||
properties/0/sync = true
|
||||
properties/1/path = NodePath(".:bombing")
|
||||
properties/1/spawn = true
|
||||
properties/1/sync = true
|
||||
|
||||
[node name="player" type="CharacterBody2D"]
|
||||
script = ExtResource( 1 )
|
||||
motion_mode = 1
|
||||
script = ExtResource( "1" )
|
||||
|
||||
[node name="sprite" type="Sprite2D" parent="."]
|
||||
position = Vector2(0.0750351, 6.23615)
|
||||
texture = ExtResource( 2 )
|
||||
rotation = -6.28319
|
||||
texture = ExtResource( "2" )
|
||||
offset = Vector2(-0.0750351, -6.23615)
|
||||
hframes = 4
|
||||
vframes = 4
|
||||
|
||||
[node name="shape" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
shape = SubResource( "1" )
|
||||
|
||||
[node name="anim" type="AnimationPlayer" parent="."]
|
||||
anims/standing = SubResource( 2 )
|
||||
anims/stunned = SubResource( 3 )
|
||||
anims/walk_down = SubResource( 4 )
|
||||
anims/walk_left = SubResource( 5 )
|
||||
anims/walk_right = SubResource( 6 )
|
||||
anims/walk_up = SubResource( 7 )
|
||||
anims/standing = SubResource( "2" )
|
||||
anims/stunned = SubResource( "3" )
|
||||
anims/walk_down = SubResource( "4" )
|
||||
anims/walk_left = SubResource( "5" )
|
||||
anims/walk_right = SubResource( "6" )
|
||||
anims/walk_up = SubResource( "7" )
|
||||
|
||||
[node name="label" type="Label" parent="."]
|
||||
offset_left = -82.0
|
||||
@@ -163,6 +181,18 @@ offset_right = 85.0
|
||||
offset_bottom = -14.0
|
||||
size_flags_horizontal = 2
|
||||
size_flags_vertical = 0
|
||||
custom_fonts/font = SubResource( 8 )
|
||||
theme_override_fonts/font = SubResource( "8" )
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Player 1"
|
||||
align = 1
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||
root_path = NodePath("..")
|
||||
resource = SubResource( "SceneReplicationConfig_xm6wv" )
|
||||
|
||||
[node name="Inputs" type="Node" parent="."]
|
||||
script = ExtResource( "4_k1vfr" )
|
||||
|
||||
[node name="InputsSync" type="MultiplayerSynchronizer" parent="Inputs"]
|
||||
root_path = NodePath("..")
|
||||
resource = SubResource( "SceneReplicationConfig_kkxsa" )
|
||||
|
||||
24
networking/multiplayer_bomber/player_controls.gd
Normal file
24
networking/multiplayer_bomber/player_controls.gd
Normal file
@@ -0,0 +1,24 @@
|
||||
extends Node
|
||||
|
||||
@export
|
||||
var motion = Vector2() :
|
||||
set(value):
|
||||
# This will be sent by players, make sure values are within limits.
|
||||
motion = clamp(value, Vector2(-1, -1), Vector2(1, 1))
|
||||
|
||||
@export
|
||||
var bombing = false
|
||||
|
||||
func update():
|
||||
var m = Vector2()
|
||||
if Input.is_action_pressed("move_left"):
|
||||
m += Vector2(-1, 0)
|
||||
if Input.is_action_pressed("move_right"):
|
||||
m += Vector2(1, 0)
|
||||
if Input.is_action_pressed("move_up"):
|
||||
m += Vector2(0, -1)
|
||||
if Input.is_action_pressed("move_down"):
|
||||
m += Vector2(0, 1)
|
||||
|
||||
motion = m
|
||||
bombing = Input.is_action_pressed("set_bomb")
|
||||
@@ -6,7 +6,7 @@
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=4
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
@@ -16,6 +16,7 @@ One of the players should press 'host', while the other
|
||||
should type in his address and press 'play'."
|
||||
run/main_scene="res://lobby.tscn"
|
||||
config/icon="res://icon.png"
|
||||
config/features=PackedStringArray("4.0")
|
||||
|
||||
[autoload]
|
||||
|
||||
@@ -27,10 +28,13 @@ gdscript/warnings/return_value_discarded=false
|
||||
|
||||
[display]
|
||||
|
||||
window/dpi/allow_hidpi=true
|
||||
window/vsync/use_vsync=false
|
||||
window/stretch/mode="2d"
|
||||
window/stretch/aspect="expand"
|
||||
window/vsync/use_vsync=false
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray()
|
||||
|
||||
[gdnative]
|
||||
|
||||
@@ -45,32 +49,32 @@ gen_mipmaps=false
|
||||
|
||||
move_down={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777234,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777234,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_up={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"store_command":true,"alt_pressed":false,"shift_pressed":false,"meta_pressed":false,"command_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
@@ -87,3 +91,15 @@ set_bomb={
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
|
||||
[replication]
|
||||
|
||||
config={
|
||||
"uid://dviwgv2ty8v6u": {
|
||||
"replicated": true,
|
||||
"spawn_properties": [],
|
||||
"sync_interval": 16,
|
||||
"sync_properties": [&":stunned", &"sprite:hframes", &"sprite:vframes", &":server_position", &"label:text"],
|
||||
"synced": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
# Sent to everyone else
|
||||
puppet func do_explosion():
|
||||
@rpc(call_local)
|
||||
func exploded(by_who):
|
||||
$"../../Score".increase_score(by_who)
|
||||
$"AnimationPlayer".play("explode")
|
||||
|
||||
|
||||
# Received by owner of the rock
|
||||
master func exploded(by_who):
|
||||
rpc("do_explosion") # Re-sent to puppet rocks
|
||||
$"../../Score".rpc("increase_score", by_who)
|
||||
do_explosion()
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
[gd_scene load_steps=5 format=2]
|
||||
[gd_scene load_steps=5 format=3 uid="uid://bao3yernlglws"]
|
||||
|
||||
[ext_resource path="res://rock.gd" type="Script" id=1]
|
||||
[ext_resource path="res://brickfloor.png" type="Texture2D" id=2]
|
||||
[ext_resource type="Script" path="res://rock.gd" id="1"]
|
||||
[ext_resource type="Texture2D" uid="uid://bdomqql6y50po" path="res://brickfloor.png" id="2"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2(24, 24)
|
||||
[sub_resource type="RectangleShape2D" id="1"]
|
||||
size = Vector2(48, 48)
|
||||
|
||||
[sub_resource type="Animation" id=2]
|
||||
[sub_resource type="Animation" id="2"]
|
||||
resource_name = "explode"
|
||||
tracks/0/type = "method"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(1),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"values": [{
|
||||
"args": [],
|
||||
"method": "queue_free"
|
||||
"method": &"queue_free"
|
||||
}]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/path = NodePath("Sprite2D:visible")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("Sprite:visible")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
@@ -36,15 +36,16 @@ tracks/1/keys = {
|
||||
}
|
||||
|
||||
[node name="Rock" type="CharacterBody2D"]
|
||||
script = ExtResource( 1 )
|
||||
motion_mode = 1
|
||||
script = ExtResource( "1" )
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
texture = ExtResource( 2 )
|
||||
[node name="Sprite" type="Sprite2D" parent="."]
|
||||
texture = ExtResource( "2" )
|
||||
region_enabled = true
|
||||
region_rect = Rect2(96, 0, 48, 48)
|
||||
|
||||
[node name="Shape3D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
[node name="Shape" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( "1" )
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
anims/explode = SubResource( 2 )
|
||||
anims/explode = SubResource( "2" )
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture2D"
|
||||
path="res://.godot/imported/rock_bit.png-cd30ec3dce7edf848ee632b29d4d0c95.stex"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bh4gbjcayios1"
|
||||
path="res://.godot/imported/rock_bit.png-cd30ec3dce7edf848ee632b29d4d0c95.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
@@ -10,26 +11,23 @@ metadata={
|
||||
[deps]
|
||||
|
||||
source_file="res://rock_bit.png"
|
||||
dest_files=["res://.godot/imported/rock_bit.png-cd30ec3dce7edf848ee632b29d4d0c95.stex"]
|
||||
dest_files=["res://.godot/imported/rock_bit.png-cd30ec3dce7edf848ee632b29d4d0c95.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/hdr_compression=1
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
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
|
||||
process/hdr_as_srgb=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
||||
@@ -16,7 +16,7 @@ func _process(_delta):
|
||||
$"../Winner".show()
|
||||
|
||||
|
||||
remotesync func increase_score(for_who):
|
||||
func increase_score(for_who):
|
||||
assert(for_who in player_labels)
|
||||
var pl = player_labels[for_who]
|
||||
pl.score += 1
|
||||
@@ -25,13 +25,13 @@ remotesync func increase_score(for_who):
|
||||
|
||||
func add_player(id, new_player_name):
|
||||
var l = Label.new()
|
||||
l.set_align(Label.ALIGN_CENTER)
|
||||
l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
l.set_text(new_player_name + "\n" + "0")
|
||||
l.set_h_size_flags(SIZE_EXPAND_FILL)
|
||||
var font = Font.new()
|
||||
font.set_size(18)
|
||||
font.set_font_data(preload("res://montserrat.otf"))
|
||||
l.add_font_override("font", font)
|
||||
font.add_data(preload("res://montserrat.otf"))
|
||||
l.set("custom_fonts/font", font)
|
||||
l.set("custom_font_size/font_size", 18)
|
||||
add_child(l)
|
||||
|
||||
player_labels[id] = { name = new_player_name, label = l, score = 0 }
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
[gd_scene load_steps=3 format=3 uid="uid://c5m3rogpaglk1"]
|
||||
|
||||
[ext_resource path="res://brickfloor.png" type="Texture2D" id=1]
|
||||
[ext_resource type="Texture2D" uid="uid://bdomqql6y50po" path="res://brickfloor.png" id="1"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2(24, 24)
|
||||
[sub_resource type="RectangleShape2D" id="1"]
|
||||
size = Vector2(48, 48)
|
||||
|
||||
[node name="TileScene" type="Node2D"]
|
||||
|
||||
[node name="Wall" type="Sprite2D" parent="."]
|
||||
position = Vector2(24, 24)
|
||||
texture = ExtResource( 1 )
|
||||
texture = ExtResource( "1" )
|
||||
region_rect = Rect2(0, 0, 48, 48)
|
||||
|
||||
[node name="StaticBody2D" type="StaticBody2D" parent="Wall"]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Wall/StaticBody2D"]
|
||||
shape = SubResource( 1 )
|
||||
shape = SubResource( "1" )
|
||||
|
||||
[node name="Floor" type="Sprite2D" parent="."]
|
||||
position = Vector2(72, 24)
|
||||
texture = ExtResource( 1 )
|
||||
texture = ExtResource( "1" )
|
||||
region_rect = Rect2(48, 0, 48, 48)
|
||||
|
||||
@@ -1,43 +1,19 @@
|
||||
[gd_resource type="TileSet" load_steps=3 format=2]
|
||||
[gd_resource type="TileSet" load_steps=3 format=3 uid="uid://do2l6lpuotti8"]
|
||||
|
||||
[ext_resource path="res://brickfloor.png" type="Texture2D" id=1]
|
||||
[ext_resource type="Texture2D" uid="uid://bdomqql6y50po" path="res://brickfloor.png" id="1"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 24, 24 )
|
||||
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_qhkfp"]
|
||||
texture = ExtResource( "1" )
|
||||
texture_region_size = Vector2i(48, 48)
|
||||
0:0/0 = 0
|
||||
0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
|
||||
0:0/0/physics_layer_0/angular_velocity = 0.0
|
||||
0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-24, -24, 24, -24, 24, 24, -24, 24)
|
||||
1:0/0 = 0
|
||||
1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
|
||||
1:0/0/physics_layer_0/angular_velocity = 0.0
|
||||
|
||||
[resource]
|
||||
0/name = "wall"
|
||||
0/texture = ExtResource( 1 )
|
||||
0/tex_offset = Vector2( 0, 0 )
|
||||
0/modulate = Color( 1, 1, 1, 1 )
|
||||
0/region = Rect2( 0, 0, 48, 48 )
|
||||
0/tile_mode = 0
|
||||
0/occluder_offset = Vector2( 24, 24 )
|
||||
0/navigation_offset = Vector2( 24, 24 )
|
||||
0/shape_offset = Vector2( 24, 24 )
|
||||
0/shape_transform = Transform2D( 1, 0, 0, 1, 24, 24 )
|
||||
0/shape = SubResource( 1 )
|
||||
0/shape_one_way = false
|
||||
0/shape_one_way_margin = 1.0
|
||||
0/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 1 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 24, 24 )
|
||||
} ]
|
||||
0/z_index = 0
|
||||
1/name = "floor"
|
||||
1/texture = ExtResource( 1 )
|
||||
1/tex_offset = Vector2( 0, 0 )
|
||||
1/modulate = Color( 1, 1, 1, 1 )
|
||||
1/region = Rect2( 48, 0, 48, 48 )
|
||||
1/tile_mode = 0
|
||||
1/occluder_offset = Vector2( 24, 24 )
|
||||
1/navigation_offset = Vector2( 24, 24 )
|
||||
1/shape_offset = Vector2( 0, 0 )
|
||||
1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
1/shape_one_way = false
|
||||
1/shape_one_way_margin = 0.0
|
||||
1/shapes = [ ]
|
||||
1/z_index = 0
|
||||
tile_size = Vector2i(48, 48)
|
||||
physics_layer_0/collision_layer = 1
|
||||
sources/0 = SubResource( "TileSetAtlasSource_qhkfp" )
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user