diff --git a/README.md b/README.md index 27b99c9..e4c8269 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,11 @@ GameState.get_effective_multiplier(generator_id, kind) -> float { "save_format_version": 5, "currencies": { - "": { - "current": {"m": float, "e": int}, - "total": {"m": float, "e": int}, - "all_time": {"m": float, "e": int} - } + "": { + "current": {"m": float, "e": int}, + "total": {"m": float, "e": int}, + "all_time": {"m": float, "e": int} + } }, "generator_states": { ... }, "buff_levels": { "farm_flux": 5 }, diff --git a/core/edge_scroll_camera.gd b/core/edge_scroll_camera.gd new file mode 100644 index 0000000..aab10f0 --- /dev/null +++ b/core/edge_scroll_camera.gd @@ -0,0 +1,69 @@ +## Scrolls the camera when the mouse cursor reaches the screen edge. +## Attach to a Camera2D node. Requires an OrthographicCamera2D or ViewportContainer +## to determine screen bounds at runtime. +extends Camera2D + +## Speed at which the camera scrolls (pixels per second). +@export var scroll_speed: float = 400.0 + +## Distance from the edge (in pixels) that triggers scrolling. +@export var edge_margin: float = 40.0 + +## Whether to clamp the camera position to a specific region. +@export var clamp_enabled: bool = false + +## Minimum bounds when clamping (in world space). +@export var clamp_min: Vector2 = Vector2.ZERO + +## Maximum bounds when clamping (in world space). +@export var clamp_max: Vector2 = Vector2.ZERO + +var _screen_rect: Rect2 + + +func _ready() -> void: + _update_screen_rect() + var viewport: Viewport = get_viewport() + if viewport != null: + viewport.size_changed.connect(_update_screen_rect) + + +func _process(delta: float) -> void: + if is_zero_approx(scroll_speed): + return + + var mouse_pos: Vector2 = get_viewport().get_mouse_position() + var scroll_dir: Vector2 = _get_scroll_direction(mouse_pos) + + if scroll_dir != Vector2.ZERO: + position += scroll_dir * scroll_speed * delta + + if clamp_enabled: + _clamp_position() + + +func _get_scroll_direction(mouse_pos: Vector2) -> Vector2: + var direction: Vector2 = Vector2.ZERO + + if mouse_pos.x < _screen_rect.position.x + edge_margin: + direction.x -= 1.0 + elif mouse_pos.x > _screen_rect.position.x + _screen_rect.size.x - edge_margin: + direction.x += 1.0 + + if mouse_pos.y < _screen_rect.position.y + edge_margin: + direction.y -= 1.0 + elif mouse_pos.y > _screen_rect.position.y + _screen_rect.size.y - edge_margin: + direction.y += 1.0 + + return direction.normalized() + + +func _clamp_position() -> void: + position.x = clampf(position.x, clamp_min.x, clamp_max.x) + position.y = clampf(position.y, clamp_min.y, clamp_max.y) + + +func _update_screen_rect() -> void: + var viewport: Viewport = get_viewport() + if viewport != null: + _screen_rect = viewport.get_visible_rect() diff --git a/core/edge_scroll_camera.gd.uid b/core/edge_scroll_camera.gd.uid new file mode 100644 index 0000000..08087d9 --- /dev/null +++ b/core/edge_scroll_camera.gd.uid @@ -0,0 +1 @@ +uid://b6systw05frh0 diff --git a/docs/gyms/tiny_sword/tiny_sword.tscn b/docs/gyms/tiny_sword/tiny_sword.tscn index c1bc9fb..e4dbdff 100644 --- a/docs/gyms/tiny_sword/tiny_sword.tscn +++ b/docs/gyms/tiny_sword/tiny_sword.tscn @@ -16,6 +16,7 @@ [ext_resource type="PackedScene" uid="uid://bf8lqbexvnx6e" path="res://docs/gyms/tiny_sword/buildings/monastery/monastery.tscn" id="13_no27p"] [ext_resource type="PackedScene" uid="uid://rejxvjwybkll" path="res://sandbox/tiny_swords/Terrain/Resources/Wood/Trees/tree_1.tscn" id="14_0cs5o"] [ext_resource type="PackedScene" uid="uid://bp5ng4vu4ot4a" path="res://docs/gyms/tiny_sword/buildings/alchemy_tower/alchemy_tower.tscn" id="14_hum8s"] +[ext_resource type="Script" uid="uid://b6systw05frh0" path="res://core/edge_scroll_camera.gd" id="17_x77df"] [node name="TinySwords" type="Node" unique_id=498237642] @@ -32,6 +33,22 @@ script = ExtResource("5_x77df") config = ExtResource("6_xnhlc") game_state = NodePath("..") +[node name="CanvasLayer" type="CanvasLayer" parent="LevelGameState" unique_id=993804078] + +[node name="UI" type="Control" parent="LevelGameState/CanvasLayer" unique_id=1299828389] +layout_mode = 3 +anchors_preset = 0 + +[node name="CurrencyPanel" parent="LevelGameState/CanvasLayer/UI" unique_id=2000000001 instance=ExtResource("9_cpnl")] +layout_mode = 1 + +[node name="GoalsDebugUI" parent="LevelGameState/CanvasLayer/UI" unique_id=1494700185 instance=ExtResource("10_qifrv")] +layout_mode = 1 +offset_left = 1433.0 +offset_top = 5.0 +offset_right = 1913.0 +offset_bottom = 263.0 + [node name="World" type="Node2D" parent="LevelGameState" unique_id=2118297724] [node name="ForestProps" type="Node2D" parent="LevelGameState/World" unique_id=649424542] @@ -72,18 +89,6 @@ position = Vector2(105, 920) [node name="AlchemyTower" parent="LevelGameState/World" unique_id=51852160 instance=ExtResource("14_hum8s")] position = Vector2(1239, 775) -[node name="UI" type="Control" parent="LevelGameState" unique_id=1299828389] -layout_mode = 3 -anchors_preset = 0 -offset_right = 40.0 -offset_bottom = 40.0 - -[node name="CurrencyPanel" parent="LevelGameState/UI" unique_id=2000000001 instance=ExtResource("9_cpnl")] -layout_mode = 1 - -[node name="GoalsDebugUI" parent="LevelGameState/UI" unique_id=1494700185 instance=ExtResource("10_qifrv")] -layout_mode = 1 -offset_left = 1433.0 -offset_top = 5.0 -offset_right = 1913.0 -offset_bottom = 263.0 +[node name="Camera2D" type="Camera2D" parent="." unique_id=1494908331] +offset = Vector2(960, 540) +script = ExtResource("17_x77df") diff --git a/docs/museums/edge_scroll_camera.tscn b/docs/museums/edge_scroll_camera.tscn new file mode 100644 index 0000000..0ba817b --- /dev/null +++ b/docs/museums/edge_scroll_camera.tscn @@ -0,0 +1,13 @@ +[gd_scene format=3 uid="uid://5vli1vqiqdrl"] + +[ext_resource type="Script" uid="uid://b6systw05frh0" path="res://core/edge_scroll_camera.gd" id="1_08uhj"] +[ext_resource type="Texture2D" uid="uid://bgtt3wu43tajh" path="res://icon.svg" id="2_c5cli"] + +[node name="EdgeScrollCamera" type="Node2D" unique_id=1977543223] + +[node name="Camera2D" type="Camera2D" parent="." unique_id=455629291] +script = ExtResource("1_08uhj") + +[node name="Icon" type="Sprite2D" parent="." unique_id=629901180] +position = Vector2(469, 252) +texture = ExtResource("2_c5cli")