Skip to content

Replace custom camera behavior with Phantom Camera for hooking#2227

Open
manuq wants to merge 7 commits into
mainfrom
camera-when-hooking
Open

Replace custom camera behavior with Phantom Camera for hooking#2227
manuq wants to merge 7 commits into
mainfrom
camera-when-hooking

Conversation

@manuq
Copy link
Copy Markdown
Collaborator

@manuq manuq commented May 19, 2026

Grappling hook scenes: use Phantom Camera

In scenes:

  • tutorial_grappling.tscn
  • grappling_hook_needles.tscn
  • grappling_hook_powerup.tscn
  • void_grappling.tscn
  • void_grappling_round_2.tscn

Add the PhantomCameraHost node to the Camera2D in order to control it.

Add a PhantomCamera2D node to the scene as well. Set priority to 10, so it will be active when the one at the tip
of the string isn't. Set follow target to the Player node. Also enable follow
damping which is similar to the previous position smoothing of Camera2D.

Use the Void TileMapLayer in each scene (except one) as the limit target of the
PhantomCamera2D node. Paint the tilemap to match the existing limit. In the
cases in which the void tiles were used to block the player going out of the
camera/world bounderies, use water instead.

Zoom out each PhantomCamera2D when grabbing the longer thread powerup.

PlayerHook: Add PhantomCamera2D at the tip of the string

Set follow mode to Framed and set dead zone to 0.5 width and height. Also enable
follow dumping. Otherwise the transitions between cameras is smooth, but the
transition when the tip of the string changes to another needle or other
hookable object isn't.

And change its priority to:

  • Zero when the camera is not supposed to follow the tip
  • 20 when the camera should follow the tip

Add a function to use the same limit target for the camera that's at
the tip of the string.

Remove FrameCameraBehavior node

Most scenes that had the grappling hook ability active, had this node as child
of the camera for controlling it. With the target set to the HookEnding marker
of PlayerHook in player.

This will be in favour of using Phanton Camera in next commit.

@github-actions
Copy link
Copy Markdown

Play this branch at https://play.threadbare.game/branches/endlessm/camera-when-hooking/.

(This launches the game from the start, not directly at the change(s) in this pull request.)

@manuq manuq changed the title Camera when hooking Replace custom camera behavior with Phantom Camera for hooking May 20, 2026
@manuq manuq force-pushed the camera-when-hooking branch from eee6c59 to f651688 Compare May 20, 2026 00:56
@manuq
Copy link
Copy Markdown
Collaborator Author

manuq commented May 20, 2026

The main issue I'm finding is:

I added a PhantomCamera2D to each scene for following the player, instead of one to the player scene, because of the camera limits. But when switching to the PhantomCamera2D at the tip of the string (in PlayerHook), it doesn't have those limits so the undecorated world appears. This is noticeable, for example, in the tutorial grapping:

Grabacion.de.pantalla.desde.2026-05-19.22-15-40.mp4

Also, something I need to fix: when grabbing the longer thread we tween the camera zoom to zoom out, and that has to be done with Phantom Camera now.

@wjt
Copy link
Copy Markdown
Member

wjt commented May 20, 2026

We could simply declare that the level designer needs to dress enough of the level around each hook point :)

manuq added 5 commits May 20, 2026 14:02
Most scenes that had the grappling hook ability active, had this node as child
of the camera for controlling it. With the target set to the HookEnding marker
of PlayerHook in player.

This will be in favour of using Phanton Camera in next commit.
Set follow mode to Framed and set dead zone to 0.5 width and height. Also enable
follow dumping. Otherwise the transitions between cameras is smooth, but the
transition when the tip of the string changes to another needle or other
hookable object isn't.

And change its priority to:
- Zero when the camera is not supposed to follow the tip
- 20 when the camera should follow the tip
In scenes:
- tutorial_grappling.tscn
- grappling_hook_needles.tscn
- grappling_hook_powerup.tscn
- void_grappling.tscn
- void_grappling_round_2.tscn

Add the PhantomCameraHost node to the Camera2D in order to control it.

Add a PhantomCamera2D node to the scene as well, copying the same limits from
the Camera2D. Set priority to 10, so it will be active when the one at the tip
of the string isn't. Set follow target to the Player node. Also enable follow
damping which is similar to the previous position smoothing of Camera2D.
Use the Void TileMapLayer in each scene as the limit target of the
PhantomCamera2D node. Paint the tilemap to match the existing limit. In the
cases in which the void tiles were used to block the player going out of the
camera/world bounderies, use water instead.

PlayerHook: Add a function to use the same limit target for the camera that's at
the tip of the string.
@manuq manuq force-pushed the camera-when-hooking branch from aa03657 to 84a710d Compare May 20, 2026 18:00
@manuq
Copy link
Copy Markdown
Collaborator Author

manuq commented May 20, 2026

We could simply declare that the level designer needs to dress enough of the level around each hook point :)

I made it work by using a tilemap layer as the limit target. I think I like that the world bounderies is now done by painting tiles rather than by numbers (which I always tried to make them match multiplying by 64 in the input field).

Then in the player hook script, I added this method that is called before the camera at the tip of the string is activated (by changing its priority). To assign the limit target to this other camera:

## Return the absolute path to the limit target of the current active camera, if it has one.
func _get_phantom_camera_limit_target() -> NodePath:
	var phantom_camera_hosts := PhantomCameraManager.phantom_camera_hosts
	if not phantom_camera_hosts:
		return ""
	var active_pcam := phantom_camera_hosts[0].get_active_pcam() as PhantomCamera2D
	if not active_pcam:
		return ""
	if not active_pcam.limit_target:
		return ""
	if active_pcam.limit_target.is_absolute():
		return active_pcam.limit_target
	var absolute_target_path := NodePath(
		String(active_pcam.get_path()) + "/" + String(active_pcam.limit_target)
	)
	return absolute_target_path

I repainted the Void tilemap to be the bounderies. Then I realized that in some scenes, the void tilemap was also used to limit the player to go back (by painting it outside boundaries). So I used water instead. Check the vertical water line at the west side:

Captura desde 2026-05-20 14-54-19

But! Now I realize that the enemies are painting void tiles, so they are enlarging the boundaries. Ouch. So I'm redoing this, by using the water tilemap as the limit target.

@manuq manuq marked this pull request as ready for review May 20, 2026 21:43
@manuq manuq requested a review from a team as a code owner May 20, 2026 21:43
@manuq
Copy link
Copy Markdown
Collaborator Author

manuq commented May 20, 2026

I fixed the above. I also fixed the zoom out when grabbing the longer thread in the 2 scenes that have it. I did it by zooming out each PhantomCamera2D. This goes a bit against what's indended in the addon, which I guess will have a second already zoomed-out PhantomCamera2D, and alternate between them by priority. But in that case we'll need 2 zoomed out versions, one for the camera following the player and one for the one at the end of the tip. So I'm not sure... should I do that instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants