1-6 player splitscreen multiplayer addon
-rw-r--r--.github/image.pngbin198833 -> 389176 bytes
-rw-r--r--Main.tscn27
-rw-r--r--addons/splitter/package.json4
-rw-r--r--addons/splitter/screen.gd53
-rw-r--r--addons/splitter/viewport.gd26
-rw-r--r--test.gd15
6 files changed, 84 insertions, 41 deletions
diff --git a/.github/image.png b/.github/image.png
index 9dfe9d7..b869c0b 100644
--- a/.github/image.png
+++ b/.github/image.png
Binary files differ
diff --git a/Main.tscn b/Main.tscn
index d3383a1..0c9ecc7 100644
--- a/Main.tscn
+++ b/Main.tscn
@@ -1,9 +1,29 @@
-[gd_scene load_steps=2 format=3 uid="uid://862orftxq81e"]
+[gd_scene load_steps=5 format=3 uid="uid://862orftxq81e"]
[ext_resource type="Script" path="res://test.gd" id="1_ncs1l"]
+[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_25hwq"]
+sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
+ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
+
+[sub_resource type="Sky" id="Sky_1r4oi"]
+sky_material = SubResource("ProceduralSkyMaterial_25hwq")
+
+[sub_resource type="Environment" id="Environment_lkkby"]
+background_mode = 2
+sky = SubResource("Sky_1r4oi")
+tonemap_mode = 2
+glow_enabled = true
+
[node name="Main" type="Node3D"]
+[node name="env" type="WorldEnvironment" parent="."]
+environment = SubResource("Environment_lkkby")
+
+[node name="sun" type="DirectionalLight3D" parent="."]
+transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
+shadow_enabled = true
+
[node name="CSGBox3D" type="CSGBox3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.86143, 0, -5.02182)
@@ -21,8 +41,3 @@ transform = Transform3D(0.337242, 0.185292, -0.923003, -0.678851, -0.631421, -0.
[node name="Node" type="Node" parent="."]
script = ExtResource("1_ncs1l")
-
-[node name="OmniLight3D" type="OmniLight3D" parent="."]
-transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5.78558, 0)
-light_energy = 16.0
-omni_range = 13.704
diff --git a/addons/splitter/package.json b/addons/splitter/package.json
index b4e57dd..5b1a652 100644
--- a/addons/splitter/package.json
+++ b/addons/splitter/package.json
@@ -1,6 +1,6 @@
{
"name": "@bendn/splitter",
- "version": "1.0.3",
+ "version": "1.0.4",
"description": "small addon for splitscreen multiplayer",
"main": "screen.gd",
"scripts": {
@@ -22,4 +22,4 @@
"url": "https://github.com/bend-n/splitter/issues"
},
"homepage": "https://github.com/bend-n/splitter#readme"
-} \ No newline at end of file
+}
diff --git a/addons/splitter/screen.gd b/addons/splitter/screen.gd
index 07a514d..ed6a02a 100644
--- a/addons/splitter/screen.gd
+++ b/addons/splitter/screen.gd
@@ -4,34 +4,37 @@ class_name Splitscreen
var players: Array[PlayerViewport] = []
func _ready() -> void:
- get_window().size_changed.connect(resize_players)
+ set_process(false)
+ get_window().size_changed.connect(set_process.bind(true))
+
+func _process(_delta: float) -> void:
+ resize_players()
+ set_process(false)
func resize_players():
- # plan:
- #┌----┐
- #├────┤
- #└────┘
- var size := Vector2(get_window().size) if len(players) == 1 else Vector2(get_window().size.x, get_window().size.y / 2.0)
- for p in players:
- p.player_count = len(players)
- p.size_port(size)
+ # plan:
+ #┌----┐
+ #├────┤
+ #└────┘
+ for p in players:
+ p.player_count = len(players)
+ p.resize_port(get_window().size)
func join() -> PlayerViewport:
- if len(players) > 1:
- push_error("no slots")
- return
-
- var player := PlayerViewport.new(len(players) + 1)
- player.name = "player %d" % (len(players) + 1)
- players.append(player)
- add_child(player)
- resize_players()
- return player
+ if len(players) > 3:
+ push_error("no slots")
+ return
+ var player := PlayerViewport.new(len(players) + 1)
+ player.name = "player %d" % (len(players) + 1)
+ players.append(player)
+ add_child(player)
+ set_process(true)
+ return player
func leave(id: int) -> void:
- var p := players.pop_at(id)
- if p == null:
- push_error("no player")
- return
- p.kill()
- resize_players()
+ var p := players.pop_at(4 - id)
+ if p == null:
+ push_error("no player")
+ return
+ p.kill()
+ set_process(true)
diff --git a/addons/splitter/viewport.gd b/addons/splitter/viewport.gd
index 6e73d4c..adad49e 100644
--- a/addons/splitter/viewport.gd
+++ b/addons/splitter/viewport.gd
@@ -12,11 +12,31 @@ func _init(_id: int) -> void:
id = _id
player_count = _id # id should be count + 1
-func size_port(to: Vector2) -> void:
+## size this viewport
+func _size(to: Vector2) -> void:
viewport.size = to
size = to
- global_position = Vector2.ZERO if id == 1 else Vector2(0, size.y)
+
+## resize this viewport to fit over [param area], while calculating the best positions.
+func resize_port(area: Vector2) -> void:
+ match player_count:
+ 1: _size(area)
+ 2: _size(Vector2(area.x, area.y / 2)) # split vertically instead of horizontally
+ 3: _size(Vector2(area.x, area.y / 2) if id == 3 else area / 2)
+ 4: _size(area / 2)
+ if id == 1:
+ global_position = Vector2.ZERO
+ else:
+ match player_count:
+ 3: match id:
+ 2: global_position = Vector2(area.x / 2, 0)
+ 3: global_position = Vector2(0, size.y)
+ _: match id:
+ 2: global_position = Vector2(0, size.y)
+ 3: global_position = Vector2(area.x / 2, 0)
+ 4: global_position = size
+
func kill() -> void:
viewport.queue_free()
- queue_free() \ No newline at end of file
+ queue_free()
diff --git a/test.gd b/test.gd
index c00de5a..744dab8 100644
--- a/test.gd
+++ b/test.gd
@@ -2,8 +2,13 @@ extends Splitscreen
func _ready() -> void:
super()
- var cam := Camera3D.new()
- join().add_child(cam)
- await get_tree().create_timer(1).timeout
- cam = Camera3D.new()
- join().add_child(cam) \ No newline at end of file
+ for i in 4:
+ await get_tree().create_timer(1).timeout
+ var cam := Camera3D.new()
+ var p := join()
+ p.viewport.add_child(cam)
+ var l := Label.new(); l.position += Vector2.ONE * 10; l.add_theme_font_size_override("font_size", 80); l.text = str(p.id)
+ p.add_child(l)
+ for i in 4:
+ await get_tree().create_timer(2).timeout
+ leave(i + 1)