flake update, fixed camera delta issues

This commit is contained in:
Rakarake 2025-10-31 18:43:50 +01:00
parent f80686405c
commit 9a8ab09f6b
7 changed files with 106 additions and 342 deletions

6
flake.lock generated
View file

@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1758277210,
"narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=",
"lastModified": 1761672384,
"narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8eaee110344796db060382e15d3af0a9fc396e0e",
"rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c",
"type": "github"
},
"original": {

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=331 format=3 uid="uid://dlyt5o2dona1a"]
[gd_scene load_steps=329 format=3 uid="uid://dlyt5o2dona1a"]
[ext_resource type="Script" uid="uid://d1de5fg4m1l34" path="res://characters/player/Player.gd" id="1_l3wc5"]
[ext_resource type="Script" uid="uid://bgvnlvv0wk71g" path="res://global/state_machine/StateMachine.gd" id="2_ae3rk"]
@ -27,7 +27,6 @@
[ext_resource type="Texture2D" uid="uid://cwettaht5gv6p" path="res://characters/player/assets/dash/dash l.png" id="16_jkw2e"]
[ext_resource type="Texture2D" uid="uid://dg8hlsbjnkyk8" path="res://characters/player/assets/dash/dash r.png" id="17_sr6c1"]
[ext_resource type="Texture2D" uid="uid://bg13lokmcibls" path="res://characters/player/assets/jump_air_start/jump_air_start_l.png" id="18_jhsvs"]
[ext_resource type="Script" uid="uid://cx3oein6oqpdq" path="res://global/camera/ExtendedCamera.gd" id="18_kiohe"]
[ext_resource type="Texture2D" uid="uid://ranfgcgolsx7" path="res://characters/player/assets/fall/fall l.png" id="18_ud0bh"]
[ext_resource type="Texture2D" uid="uid://dwbooseeuk2vd" path="res://characters/player/assets/fall/fall r.png" id="19_kjtfw"]
[ext_resource type="Texture2D" uid="uid://di4gxt84ty5xu" path="res://characters/player/assets/jump_air_start/jump_air_start_r.png" id="19_xc04u"]
@ -77,7 +76,7 @@
[ext_resource type="Resource" uid="uid://d1k41a2na47bn" path="res://characters/player/ground_run_stats.tres" id="56_1scf8"]
[ext_resource type="Texture2D" uid="uid://dnixehn6vw3cj" path="res://characters/player/assets/wavedash/wavedash_L.png" id="56_ebbxk"]
[ext_resource type="Texture2D" uid="uid://c30q7ol4u8mef" path="res://characters/player/assets/wavedash/wavedash_R.png" id="57_7cktu"]
[ext_resource type="Script" uid="uid://60wby2r3n4tx" path="res://global/camera/PlayerCamera2.gd" id="63_wa5ni"]
[ext_resource type="Script" uid="uid://60wby2r3n4tx" path="res://global/camera/PlayerCamera.gd" id="63_wa5ni"]
[ext_resource type="Script" uid="uid://ddhsdf13or1da" path="res://global/state_machine/misc/JumpStats.gd" id="64_5bsmn"]
[ext_resource type="Script" uid="uid://dbhp6ek2kwibq" path="res://global/camera/Limits.gd" id="65_8qlk8"]
[ext_resource type="PackedScene" uid="uid://d0wkusth6nbhh" path="res://global/camera/CameraProperties.tscn" id="66_8qlk8"]
@ -3122,11 +3121,6 @@ graph_offset = Vector2(-558.423, -222.60501)
script = ExtResource("65_8qlk8")
metadata/_custom_type_script = "uid://dbhp6ek2kwibq"
[sub_resource type="Curve" id="Curve_w1mwi"]
_limits = [0.0, 300.0, 0.0, 1.0]
_data = [Vector2(0.474308, 247.826), 0.0, 0.0, 0, 0]
point_count = 1
[sub_resource type="Curve" id="Curve_fgnmx"]
_limits = [0.0, 2000.0, 0.0, 500.0]
_data = [Vector2(0, 899.383), 0.0, -0.438914, 0, 0, Vector2(329.256, 0), -7.08199, 0.0, 0, 0]
@ -3256,7 +3250,6 @@ fallback_properties = NodePath("../CameraProperties")
[node name="CameraProperties" parent="." instance=ExtResource("66_8qlk8")]
inherit_transform = true
limits = SubResource("Resource_55jfm")
friction = 23.474
[node name="UI" type="CanvasLayer" parent="."]
layer = 3
@ -3286,19 +3279,6 @@ offset_right = 527.0
offset_bottom = 134.0
text = "another nord W"
[node name="FollowCamera" type="Camera2D" parent="."]
editor_description = "The camera with the player's default attributes"
scale = Vector2(4.20469, 2.8766)
enabled = false
script = ExtResource("18_kiohe")
inherit_position = true
inherit_limit = true
look_aside_enabled = true
look_aside = 34.0
look_aside_speed_curve = SubResource("Curve_w1mwi")
y_camera_pan_enabled = true
y_camera_pan_amount = 400.0
[node name="StateMachine" type="Node2D" parent="."]
script = ExtResource("2_ae3rk")
initial_state = NodePath("Run")

View file

@ -1,31 +1,19 @@
extends Node2D
@export var original_properties: NodePath
## If enabled, takes control of viewport transform.
@export var enabled := false
## The default camera properties.
@export var fallback_properties: NodePath
## The x distance which the camera looks away from the player in the direction
## the player is facing.
@export
var look_aside := 0.0
## This curve determines the speed of the camera when looking in the opposite direction.
## X: 0-1 the current percentage of distance the camera needs to pan, y: the
## velocity of the camera.
@export
var look_aside_speed_curve: Curve
## Wether camera pan up/down is enabled.
@export
var y_camera_pan_enabled := false
var x_pan := 0.0
## How much does the camera pan up/down.
@export
var y_camera_pan_amount := 0.0
var y_pan_amount := 0.0
## Set by owner, expected to be -1.0 to 1.0
var y_pan := 0.0
## Enables outputting debug info for this camera. Shows center of camera gizmo if gizmos are turned on.
## Outputs properties to debug screen.
@ -33,46 +21,62 @@ var y_camera_pan_amount := 0.0
## Set by owner.
var looking_right := true
## Set by owner, expected to be -1.0 to 1.0
var y_camera_pan := 0.0
var properties := ["transform", "smoothing", "limits"]
## Used as dummy values
var example_properties := {
"transform": Transform2D.IDENTITY,
"smoothing": 1.0,
"limits": {"left": -10000000, "right": 10000000, "top": -10000000, "bottom": 10000000},
}
## The default camera properties.
@export var fallback_properties: NodePath
## Stack of references to CamerProperties
@onready var camera_stack : Array[CameraProperties] = [ get_node(fallback_properties) ]
## Schema: { <property_name>: <property_progress> (seconds) }
var property_progress := {}
## Used for smoothing
## Schema: { <property_name>: <reference to node> }
var current_properties := {}
@onready var _camera_stack : Array[CameraProperties] = [ get_node(fallback_properties) ]
var _transition_progress := 1.0
var _current_transform: Transform2D = Transform2D.IDENTITY
var _velocity := Vector2.ZERO
func _ready():
# Start at 100% the first camera
for p in properties:
property_progress[p] = 1.0
#original_properties[p] = example_properties[p].duplicate()
#current_properties[p] = example_properties[p].duplicate()
reset_smoothing()
func reset_smoothing():
_velocity = Vector2.ZERO
_transition_progress = 500.0
_current_transform = _get_target_transform()
func remove_camera(c):
# if on top of stack, transition
if _camera_stack[-1] == c:
_camera_stack.erase(c)
_transition_progress = 0.0
# remove duplicates
while _camera_stack.has(c):
_camera_stack.erase(c)
func apply_camera(c):
# if already on top don't transition
if !_camera_stack[-1] == c:
# remove duplcates
while _camera_stack.has(c):
_camera_stack.erase(c)
_camera_stack.push_back(c)
_transition_progress = 0.0
## Finds the active CameraProperties for a given property.
## depth can be specified to get the camera of second/third/... priority.
func _get_camera(property: String, depth: int = 0):
var current_depth := depth
for i in camera_stack.size():
var index = camera_stack.size() -1 -i
var c = camera_stack[index]
for i in _camera_stack.size():
var index = _camera_stack.size() -1 -i
var c = _camera_stack[index]
# Clean up destroyed cameras
if c == null:
camera_stack.remove_at(index)
_camera_stack.remove_at(index)
else:
if c[property + "_curve"] != null:
if property == "transform" && c.inherit_transform:
if current_depth <= 0:
return c
else:
current_depth -= 1
elif property == "limits" && c.limits != null:
if current_depth <= 0:
return c
else:
@ -80,131 +84,70 @@ func _get_camera(property: String, depth: int = 0):
# there wasn't a camera with this depth? try getting one with higher priority
return _get_camera(property, depth - 1)
## Set timers and original properties on properites that changed after operation "op".
func _reset(op):
var p_to_c := {}
# get list of destination cameras for every property
for p in properties:
p_to_c[p] = _get_camera(p)
# remove/add camera
op.call()
# get list of destination cameras for every property
var new_p_to_c := {}
for p in properties:
new_p_to_c[p] = _get_camera(p)
# reset timers for the properties that changed
for key in p_to_c:
if p_to_c[key] != new_p_to_c[key]:
# reset timer
property_progress[key] = 0.0
get_node(original_properties)[key] = p_to_c[key]
func remove_camera(c):
var op = func(): camera_stack.erase(c)
_reset(op)
func _clamp_with_limits(value: Vector2, limits: Limits, middle_offset: Vector2) -> Vector2:
return Vector2(
clampf(value.x, limits.left + middle_offset.x, limits.right - middle_offset.x),
clampf(value.y, limits.top + middle_offset.y, limits.bottom - middle_offset.y)
)
func apply_camera(c):
var op = func(): camera_stack.push_back(c)
_reset(op)
# Takes the currently focused node and applies limits
func _get_target_transform() -> Transform2D:
var middle_offset = _get_middle_offset()
var target_node = _get_camera("transform")
var target_node_transform_without_position = target_node.transform
target_node_transform_without_position.origin = Vector2.ZERO
# apply limits
var target_pos = _clamp_with_limits(target_node.global_position, _get_camera("limits").limits, middle_offset)
var target_transform = target_node_transform_without_position.translated(target_pos)
return target_transform
func _update_timers(delta: float):
for p in properties:
property_progress[p] += delta
func _property_step(property: String, op):
var n = _get_camera(property)
var curve = n[property + "_curve"]
var time = property_progress[property]
var old = get_node(original_properties)[property]
var fraction = curve.sample(time)
op.call(fraction, old, n)
## Also sets up current_properties
func reset_smoothing():
current_properties["smoothing"] = _get_camera("smoothing").smoothing
current_properties["transform"] = _get_camera("transform").global_transform
if !current_properties.has("limits"):
current_properties["limits"] = {}
current_properties["limits"]["left"] = _get_camera("limits").limit_left
current_properties["limits"]["right"] = _get_camera("limits").limit_right
current_properties["limits"]["top"] = _get_camera("limits").limit_top
current_properties["limits"]["bottom"] = _get_camera("limits").limit_bottom
for p in properties:
get_node(original_properties)[p] = _get_camera(p)
func _get_middle_offset() -> Vector2:
return get_viewport().content_scale_size / 2
func _process(delta: float):
# Lookaside (x-pan)
var target_pos = look_aside if looking_right else - look_aside
var curve_x = 1 - (abs(target_pos - position.x) / (look_aside * 2))
position.x += sign(target_pos) * look_aside_speed_curve.sample(
curve_x) * delta
position.x = clamp(position.x, -look_aside, look_aside)
# y-pan
position.y = y_camera_pan_amount * y_camera_pan
# update viewport
if enabled:
_update_timers(delta)
# y pan clamp
get_node(fallback_properties).position.y = y_pan_amount * y_pan
# x pan (look aside)
get_node(fallback_properties).position.x = x_pan if looking_right else - x_pan
_property_step("smoothing", func(_fraction, _old, target_node):
# property smoothing is not smoothed
current_properties["smoothing"] = target_node.smoothing
)
var smoothing = current_properties["smoothing"]
_property_step("limits", func(fraction, old, target_node):
current_properties["limits"]["left"] = target_node.limit_left
current_properties["limits"]["right"] = target_node.limit_right
current_properties["limits"]["top"] = target_node.limit_top
current_properties["limits"]["bottom"] = target_node.limit_bottom
)
_property_step("transform", func(fraction, old, target_node):
# We are not interested in inherited transform properties except for position
var end_target_pos = target_node.transform.global_transform
var end_target = target_node.transform.translated(end_target_pos)
# progress transition
_transition_progress += delta
var old_target = old.transform.translated(old.global_transform.origin)
var intermediate_target: Transform2D = old_target.interpolate_with(end_target, fraction)
# the offset of the viewport to account for the screen size
var middle_offset: Vector2 = get_viewport().content_scale_size / 2
# bind intermediate_target by limits
intermediate_target.origin.x = clampf(intermediate_target.origin.x,
current_properties["limits"]["left"] + middle_offset.x,
current_properties["limits"]["right"] - middle_offset.x,
)
intermediate_target.origin.y = clampf(intermediate_target.origin.y,
current_properties["limits"]["top"] + middle_offset.y,
current_properties["limits"]["bottom"] - middle_offset.y,
)
#intermediate_target.origin = intermediate_target.origin.clamp(
# Vector2(current_properties["limits"]["left"],
# current_properties["limits"]["top"]
# ),
# Vector2(current_properties["limits"]["right"],
# current_properties["limits"]["bottom"]
# )
#)
current_properties["transform"] = current_properties["transform"]\
.interpolate_with(intermediate_target, smoothing * delta)
var middle_offset: Vector2 = _get_middle_offset()
# update position
var target_transform: Transform2D = _get_target_transform()
var smoothing = _camera_stack[-1].smoothing_curve.sample(_transition_progress)
var friction = _camera_stack[-1].friction
var accel = (target_transform.origin - _current_transform.origin) * smoothing
_velocity += accel + (-_velocity) * friction
_current_transform = _current_transform.translated(_velocity * delta)
# TODO add interpolation of scaling, skewing and rotation individually,
# could do it by building one matrix
# apply accel to velocity
# interpolate between _current_transform and intermediate_transform
#_current_transform = _current_transform.interpolate_with(target_transform, smoothing * delta)
# apply to viewport
get_viewport().canvas_transform = current_properties["transform"].inverse().translated(middle_offset)
)
get_viewport().canvas_transform = _current_transform.inverse().translated(middle_offset)
#var n = _get_camera("transform")
#var curve = n.transform_curve
#var time = property_progress["transform"]
#var old: Transform2D = original_properties["transform"]
#var end_target: Transform2D = n.global_transform
#var fraction = curve.sample(time)
#var intermediate_target = old.interpolate_with(end_target, fraction)
#current_properties["transform"] = current_properties["transform"]\
# .iterpolate_with(intermediate_target, smoothing * delta)
# debug
Debug.stat_set({ "key": "player camera transform", "value": str(_current_transform) })
Debug.stat_set({ "key": "player camera stack", "value": str(_camera_stack) })
Debug.stat_set({ "key": "player camera transition progress", "value": str(_transition_progress) })
#var follow_node: Node2D = get_node(player)
#var middle_offset = get_viewport().content_scale_size / 2
#_current_transform = _current_transform.interpolate_with(Transform2D(0.0, follow_node.global_position), smoothing * delta)
#get_viewport().canvas_transform = _current_transform.inverse().translated(middle_offset)
# for debugging
queue_redraw()
#get_viewport().canvas_transform = follow_node.global_transform.inverse().translated(middle_offset)
func _draw():
if debug_show && Debug.show_gizmos:
draw_circle(_get_target_transform().origin - global_position, 10.0, Color.YELLOW)

View file

@ -1 +1 @@
uid://cwul8pyopo3co
uid://60wby2r3n4tx

View file

@ -1,149 +0,0 @@
extends Node2D
## If enabled, takes control of viewport transform.
@export var enabled := false
## The x distance which the camera looks away from the player in the direction
## the player is facing.
@export
var x_pan := 0.0
## How much does the camera pan up/down.
@export
var y_pan_amount := 0.0
## Set by owner, expected to be -1.0 to 1.0
var y_pan := 0.0
## Enables outputting debug info for this camera. Shows center of camera gizmo if gizmos are turned on.
## Outputs properties to debug screen.
@export var debug_show := false
## Set by owner.
var looking_right := true
## The default camera properties.
@export var fallback_properties: NodePath
## Stack of references to CamerProperties
@onready var _camera_stack : Array[CameraProperties] = [ get_node(fallback_properties) ]
var _transition_progress := 1.0
var _current_transform: Transform2D = Transform2D.IDENTITY
var _velocity := Vector2.ZERO
func _ready():
reset_smoothing()
func reset_smoothing():
_velocity = Vector2.ZERO
_transition_progress = 500.0
_current_transform = _get_target_transform()
func remove_camera(c):
# if on top of stack, transition
if _camera_stack[-1] == c:
_camera_stack.erase(c)
_transition_progress = 0.0
# remove duplicates
while _camera_stack.has(c):
_camera_stack.erase(c)
func apply_camera(c):
# if already on top don't transition
if !_camera_stack[-1] == c:
# remove duplcates
while _camera_stack.has(c):
_camera_stack.erase(c)
_camera_stack.push_back(c)
_transition_progress = 0.0
## Finds the active CameraProperties for a given property.
## depth can be specified to get the camera of second/third/... priority.
func _get_camera(property: String, depth: int = 0):
var current_depth := depth
for i in _camera_stack.size():
var index = _camera_stack.size() -1 -i
var c = _camera_stack[index]
# Clean up destroyed cameras
if c == null:
_camera_stack.remove_at(index)
else:
if property == "transform" && c.inherit_transform:
if current_depth <= 0:
return c
else:
current_depth -= 1
elif property == "limits" && c.limits != null:
if current_depth <= 0:
return c
else:
current_depth -= 1
# there wasn't a camera with this depth? try getting one with higher priority
return _get_camera(property, depth - 1)
func _clamp_with_limits(value: Vector2, limits: Limits, middle_offset: Vector2) -> Vector2:
return Vector2(
clampf(value.x, limits.left + middle_offset.x, limits.right - middle_offset.x),
clampf(value.y, limits.top + middle_offset.y, limits.bottom - middle_offset.y)
)
func _get_target_transform() -> Transform2D:
var middle_offset = _get_middle_offset()
var target_node = _get_camera("transform")
var target_node_transform_without_position = target_node.transform
target_node_transform_without_position.origin = Vector2.ZERO
# apply limits
var target_pos = _clamp_with_limits(target_node.global_position, _get_camera("limits").limits, middle_offset)
var target_transform = target_node_transform_without_position.translated(target_pos)
return target_transform
func _get_middle_offset() -> Vector2:
return get_viewport().content_scale_size / 2
func _process(delta: float):
if enabled:
# y pan clamp
get_node(fallback_properties).position.y = y_pan_amount * y_pan
# x pan (look aside)
get_node(fallback_properties).position.x = x_pan if looking_right else - x_pan
# progress transition
_transition_progress += delta
# the offset of the viewport to account for the screen size
var middle_offset: Vector2 = _get_middle_offset()
# update position
var target_transform: Transform2D = _get_target_transform()
var smoothing = _camera_stack[-1].smoothing_curve.sample(_transition_progress)
var friction = _camera_stack[-1].friction * delta
var accel = (target_transform.origin - _current_transform.origin) * smoothing * delta
_velocity += accel + (-_velocity) * friction
_current_transform = _current_transform.translated(_velocity)
# apply accel to velocity
# interpolate between _current_transform and intermediate_transform
#_current_transform = _current_transform.interpolate_with(target_transform, smoothing * delta)
# apply to viewport
get_viewport().canvas_transform = _current_transform.inverse().translated(middle_offset)
# debug
Debug.stat_set({ "key": "player camera transform", "value": str(_current_transform) })
Debug.stat_set({ "key": "player camera stack", "value": str(_camera_stack) })
Debug.stat_set({ "key": "player camera transition progress", "value": str(_transition_progress) })
# for debugging
queue_redraw()
func _draw():
if debug_show && Debug.show_gizmos:
draw_circle(_get_target_transform().origin - global_position, 10.0, Color.YELLOW)

View file

@ -1 +0,0 @@
uid://60wby2r3n4tx

View file

@ -22,17 +22,12 @@ size = Vector2(121.5, 876.5)
[sub_resource type="Resource" id="Resource_y1jh6"]
script = ExtResource("2_tdtq1")
left = 0.0
right = 1e+07
top = -1e+07
bottom = 1000.0
metadata/_custom_type_script = "uid://dbhp6ek2kwibq"
[sub_resource type="Resource" id="Resource_ytue1"]
script = ExtResource("2_tdtq1")
left = -1e+07
right = 2000.0
top = -1e+07
bottom = 1e+07
metadata/_custom_type_script = "uid://dbhp6ek2kwibq"
[sub_resource type="RectangleShape2D" id="RectangleShape2D_xx7wp"]
@ -46,10 +41,6 @@ size = Vector2(630, 754.5)
[sub_resource type="Resource" id="Resource_gawt8"]
script = ExtResource("2_tdtq1")
left = -1e+07
right = 1e+07
top = -1e+07
bottom = 1e+07
metadata/_custom_type_script = "uid://dbhp6ek2kwibq"
[sub_resource type="RectangleShape2D" id="RectangleShape2D_6n8gr"]