From dad9aa9b2227293d201d77c7de435faf1d36ffdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 11 Nov 2024 22:36:22 -0300 Subject: [PATCH 1/3] Add MultiplayerCamera node Add a new camera that inherits from Camera2D. It can frame the player characters by positioning and zooming accordingly. It adds a margin of 128 px (one tile size) to the player positions. Add a new node for this camera to the main scene. It is disabled by default. So by enabling this one and disabling or removing the current camera for the character, this one takes precedence. The new multiplayer camera has the same limits and position smoothing that the current camera. This is based on the Godot recipe [1] but adapted to Godot 4 and to this project, with variable names improved. [1] https://kidscancode.org/godot_recipes/3.x/2d/multi_target_camera/ https://github.com/endlessm/moddable-platformer/issues/9 --- main.tscn | 11 ++++++++- scripts/multiplayer_camera.gd | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 scripts/multiplayer_camera.gd diff --git a/main.tscn b/main.tscn index c09889f..e9d3ed6 100644 --- a/main.tscn +++ b/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=13 format=3 uid="uid://dhcpt1kt8cs0g"] +[gd_scene load_steps=14 format=3 uid="uid://dhcpt1kt8cs0g"] [ext_resource type="PackedScene" uid="uid://8st4scqt06l8" path="res://components/player/player.tscn" id="2_7yl00"] [ext_resource type="PackedScene" uid="uid://jnrusvm3gric" path="res://spaces/background.tscn" id="2_tb5a2"] @@ -12,6 +12,7 @@ [ext_resource type="PackedScene" uid="uid://dk0xon0k7ga23" path="res://components/enemy/enemy.tscn" id="9_l6smt"] [ext_resource type="SpriteFrames" uid="uid://bo581k1esb50n" path="res://components/player/spriteframes-red.tres" id="9_qmofe"] [ext_resource type="PackedScene" uid="uid://beuisy5yrw0bq" path="res://components/flag/flag.tscn" id="12_dkbog"] +[ext_resource type="Script" path="res://scripts/multiplayer_camera.gd" id="13_0d2mj"] [node name="Main" type="Node2D"] @@ -221,3 +222,11 @@ position = Vector2(4096, 960) [node name="Flag" parent="." instance=ExtResource("12_dkbog")] position = Vector2(4192, 320) + +[node name="MultiplayerCamera" type="Camera2D" parent="."] +position = Vector2(0, 15) +enabled = false +limit_left = 0 +limit_bottom = 1080 +position_smoothing_enabled = true +script = ExtResource("13_0d2mj") diff --git a/scripts/multiplayer_camera.gd b/scripts/multiplayer_camera.gd new file mode 100644 index 0000000..872fd1e --- /dev/null +++ b/scripts/multiplayer_camera.gd @@ -0,0 +1,45 @@ +class_name MultiplayerCamera +extends Camera2D + +const FRAME_MARGIN: int = 128 +const MIN_ZOOM: float = 1.0 +const MAX_ZOOM: float = 0.4 + +var player_characters: Array[Player] + +@onready var viewport_size: Vector2 = get_viewport_rect().size + + +func _ready(): + if not enabled or not is_current(): + set_process(false) + return + + for pc in get_tree().get_nodes_in_group("players"): + player_characters.append(pc as Player) + + +func _physics_process(delta: float): + if not player_characters: + return + + var new_position: Vector2 = Vector2.ZERO + for pc: Player in player_characters: + new_position += pc.position + new_position /= player_characters.size() + if position_smoothing_enabled: + position = lerp(position, new_position, position_smoothing_speed * delta) + else: + position = new_position + + var frame = Rect2(position, Vector2.ONE) + for pc: Player in player_characters: + frame = frame.expand(pc.position) + frame = frame.grow_individual(FRAME_MARGIN, FRAME_MARGIN, FRAME_MARGIN, FRAME_MARGIN) + + var new_zoom: float + if frame.size.x > frame.size.y * viewport_size.aspect(): + new_zoom = clamp(viewport_size.x / frame.size.x, MAX_ZOOM, MIN_ZOOM) + else: + new_zoom = clamp(viewport_size.y / frame.size.y, MAX_ZOOM, MIN_ZOOM) + zoom = lerp(zoom, Vector2.ONE * new_zoom, 0.5) From 615e399c776556a5797aecfec33915e9bda7bbbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Mon, 11 Nov 2024 23:39:45 -0300 Subject: [PATCH 2/3] Background: Adapt to zoom out The background didn't work when zooming out either the existing camera or the new multiplayer camera because it doesn't repeat vertically. Adapt it to work: - Enlarge the farther layer using a ColorRect so it can cover the screen vertically at 0.4 zoom (the whole default level). - Also set the background to not follow the camera zoom. https://github.com/endlessm/moddable-platformer/issues/9 --- spaces/background.tscn | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/spaces/background.tscn b/spaces/background.tscn index 233ec83..bcfed84 100644 --- a/spaces/background.tscn +++ b/spaces/background.tscn @@ -16,11 +16,24 @@ fill_to = Vector2(0, 1) [node name="Background" type="ParallaxBackground"] follow_viewport_enabled = true +scroll_ignore_camera_zoom = true script = ExtResource("1_1jh5j") [node name="ParallaxLayer" type="ParallaxLayer" parent="."] unique_name_in_owner = true -motion_scale = Vector2(-1, -1) +motion_scale = Vector2(0, 0) +motion_mirroring = Vector2(1600, 0) + +[node name="ColorRect" type="ColorRect" parent="ParallaxLayer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -2352.0 +offset_right = 5129.0 +offset_bottom = 98.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.980392, 0.980392, 0.980392, 1) [node name="Sprite2D" type="Sprite2D" parent="ParallaxLayer"] texture = SubResource("GradientTexture2D_ljotv") From 5c7a056574742965bf1ff1acd2e3b71029c9e27e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= Date: Tue, 12 Nov 2024 00:10:32 -0300 Subject: [PATCH 3/3] Add multiplayer camera to MODS documentation https://github.com/endlessm/moddable-platformer/issues/9 --- doc/MODS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/MODS.md b/doc/MODS.md index 2230695..f55bc5d 100644 --- a/doc/MODS.md +++ b/doc/MODS.md @@ -144,6 +144,10 @@ Duplicate the `Player` node. Move it next to the existing player. Then change the Player to "Two" in the duplicated one. Now the game is multiplayer. +You will notice that the camera is following one of the player characters. So +try disabling the `Camera2D` node that's a child of the `Player` node. And then +enable the `MultiplayerCamera` node that's at the bottom of the Scene Dock. + ### Player and flag appearance Click on the `Player` node. In the inspector, observe where it says `Sprite