From b0baf3228a2b6ebbee0f3cfabc34485b895fe92a Mon Sep 17 00:00:00 2001 From: Jochum van der Ploeg Date: Sat, 14 Dec 2024 13:16:40 +0100 Subject: [PATCH 1/3] feat: refactor the `CameraComponent3D` --- packages/flame_3d/lib/camera.dart | 2 + .../lib/src/camera/camera_component_3d.dart | 166 ++++-------------- .../lib/src/camera/first_person_camera.dart | 37 ++++ .../lib/src/camera/third_person_camera.dart | 52 ++++++ .../flame_3d/lib/src/game/flame_game_3d.dart | 9 +- 5 files changed, 133 insertions(+), 133 deletions(-) create mode 100644 packages/flame_3d/lib/src/camera/first_person_camera.dart create mode 100644 packages/flame_3d/lib/src/camera/third_person_camera.dart diff --git a/packages/flame_3d/lib/camera.dart b/packages/flame_3d/lib/camera.dart index cf4e46ba3ba..78d020f6928 100644 --- a/packages/flame_3d/lib/camera.dart +++ b/packages/flame_3d/lib/camera.dart @@ -3,4 +3,6 @@ export 'package:flame/camera.dart'; export 'package:vector_math/vector_math.dart' show Frustum; export 'src/camera/camera_component_3d.dart'; +export 'src/camera/first_person_camera.dart'; +export 'src/camera/third_person_camera.dart'; export 'src/camera/world_3d.dart'; diff --git a/packages/flame_3d/lib/src/camera/camera_component_3d.dart b/packages/flame_3d/lib/src/camera/camera_component_3d.dart index 0d849f66501..1f96ac8cf55 100644 --- a/packages/flame_3d/lib/src/camera/camera_component_3d.dart +++ b/packages/flame_3d/lib/src/camera/camera_component_3d.dart @@ -3,8 +3,6 @@ import 'package:flame_3d/game.dart'; enum CameraProjection { perspective, orthographic } -enum CameraMode { custom, free, orbital, firstPerson, thirdPerson } - /// {@template camera_component_3d} /// [CameraComponent3D] is a component through which a [World3D] is observed. /// {@endtemplate} @@ -13,16 +11,17 @@ class CameraComponent3D extends CameraComponent { CameraComponent3D({ this.fovY = 60, Vector3? position, + Quaternion? rotation, Vector3? target, Vector3? up, this.projection = CameraProjection.perspective, - this.mode = CameraMode.free, World3D? super.world, super.viewport, super.viewfinder, super.backdrop, super.hudComponents, }) : position = position?.clone() ?? Vector3.zero(), + rotation = rotation ?? Quaternion.identity(), target = target?.clone() ?? Vector3(0, 0, -1), _up = up?.clone() ?? Vector3(0, 1, 0); @@ -56,152 +55,61 @@ class CameraComponent3D extends CameraComponent { set up(Vector3 up) => _up.setFrom(up); final Vector3 _up; + /// The rotation of the camera. + Quaternion rotation; + /// The current camera projection. CameraProjection projection; - /// The current camera mode. - CameraMode mode; - /// The view matrix of the camera, this is without any projection applied on /// it. Matrix4 get viewMatrix => _viewMatrix..setAsViewMatrix(position, target, up); final Matrix4 _viewMatrix = Matrix4.zero(); /// The projection matrix of the camera. - Matrix4 get projectionMatrix { - final aspectRatio = viewport.virtualSize.x / viewport.virtualSize.y; - return switch (projection) { - CameraProjection.perspective => _projectionMatrix - ..setAsPerspective(fovY, aspectRatio, distanceNear, distanceFar), - CameraProjection.orthographic => _projectionMatrix - ..setAsOrthographic(fovY, aspectRatio, distanceNear, distanceFar) - }; - } - + Matrix4 get projectionMatrix => switch (projection) { + CameraProjection.perspective => _projectionMatrix + ..setAsPerspective( + fovY, + viewport.virtualSize.x / viewport.virtualSize.y, + distanceNear, + distanceFar, + ), + CameraProjection.orthographic => _projectionMatrix + ..setAsOrthographic( + fovY, + viewport.virtualSize.x / viewport.virtualSize.y, + distanceNear, + distanceFar, + ) + }; final Matrix4 _projectionMatrix = Matrix4.zero(); + /// The view projection matrix used for rendering. Matrix4 get viewProjectionMatrix => _viewProjectionMatrix ..setFrom(projectionMatrix) ..multiply(viewMatrix); final Matrix4 _viewProjectionMatrix = Matrix4.zero(); - final Frustum _frustum = Frustum(); - + /// The frustum of the [viewProjectionMatrix]. Frustum get frustum => _frustum..setFromMatrix(viewProjectionMatrix); + final Frustum _frustum = Frustum(); - void moveForward(double distance, {bool moveInWorldPlane = false}) { - final forward = this.forward..scale(distance); - - if (moveInWorldPlane) { - forward.y = 0; - forward.normalize(); - } - - position.add(forward); - target.add(forward); - } - - void moveUp(double distance) { - final up = this.up..scale(distance); - position.add(up); - target.add(up); - } - - void moveRight(double distance, {bool moveInWorldPlane = false}) { - final right = this.right..scale(distance); - - if (moveInWorldPlane) { - right.y = 0; - right.normalize(); - } - - position.add(right); - target.add(right); - } - - void moveToTarget(double delta) { - var distance = position.distanceTo(target); - distance += delta; - - if (distance <= 0) { - distance = 0.001; - } - - final forward = this.forward; - position.setValues( - target.x + (forward.x * -distance), - target.y + (forward.y * -distance), - target.z + (forward.z * -distance), - ); - } - - void yaw(double angle, {bool rotateAroundTarget = false}) { - final targetPosition = (target - position)..applyAxisAngle(up, angle); - - if (rotateAroundTarget) { - position.setValues( - target.x - targetPosition.x, - target.y - targetPosition.y, - target.z - targetPosition.z, - ); - } else { - target.setValues( - position.x + targetPosition.x, - position.y + targetPosition.y, - position.z + targetPosition.z, - ); - } - } - - void pitch( - double angle, { - bool lockView = false, - bool rotateAroundTarget = false, - bool rotateUp = false, - }) { - var localAngle = angle; - final up = this.up; - final targetPosition = target - position; - - if (lockView) { - final maxAngleUp = up.angleTo(targetPosition); - if (localAngle > maxAngleUp) { - localAngle = maxAngleUp; - } - - var maxAngleDown = (-up).angleTo(targetPosition); - maxAngleDown *= -1.0; - - if (localAngle < maxAngleDown) { - localAngle = maxAngleDown; - } - } - - final right = this.right; - targetPosition.applyAxisAngle(right, localAngle); - - if (rotateAroundTarget) { - position.setValues( - target.x - targetPosition.x, - target.y - targetPosition.y, - target.z - targetPosition.z, - ); - } else { - target.setValues( - position.x + targetPosition.x, - position.y + targetPosition.y, - position.z + targetPosition.z, - ); - } - - if (rotateUp) { - _up.applyAxisAngle(right, angle); - } + /// Rotates the camera's yaw and pitch. + /// + /// Both [yawDelta] and [pitchDelta] are in radians. + void rotate(double yawDelta, double pitchDelta) { + // Create quaternions for both yaw and pitch rotations. + final yawRotation = Quaternion.axisAngle(Vector3(0, 1, 0), yawDelta); + final pitchRotation = Quaternion.axisAngle(Vector3(1, 0, 0), pitchDelta); + + // Multiply the yaw with the current and pitch rotation to get the new + // camera rotation. + rotation = (yawRotation * rotation * pitchRotation)..normalize(); } - void roll(double angle) { - _up.applyAxisAngle(forward, angle); - } + /// Resets the camera's rotation to its default state, making it look forward. + void resetRotation() => rotation = Quaternion.identity(); static CameraComponent3D? get currentCamera => CameraComponent.currentCamera as CameraComponent3D?; diff --git a/packages/flame_3d/lib/src/camera/first_person_camera.dart b/packages/flame_3d/lib/src/camera/first_person_camera.dart new file mode 100644 index 00000000000..34aa06552aa --- /dev/null +++ b/packages/flame_3d/lib/src/camera/first_person_camera.dart @@ -0,0 +1,37 @@ +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/core.dart'; +import 'package:meta/meta.dart'; + +class FirstPersonCamera extends CameraComponent3D { + FirstPersonCamera({ + required this.following, + super.fovY, + super.position, + super.rotation, + super.up, + super.projection, + super.world, + super.viewport, + super.viewfinder, + super.backdrop, + super.hudComponents, + }); + + /// The point the camera should follow. + Vector3 following; + + @override + @mustCallSuper + void update(double dt) { + // Always set the camera's position to the following point. + position.setFrom(following); + + // Compute the desired target to look at. + target.setFrom(position + _getForwardDirection()); + } + + Vector3 _getForwardDirection() { + final forward = Vector3(0, 0, -1)..applyQuaternion(rotation); + return forward.normalized(); + } +} diff --git a/packages/flame_3d/lib/src/camera/third_person_camera.dart b/packages/flame_3d/lib/src/camera/third_person_camera.dart new file mode 100644 index 00000000000..493c1e50310 --- /dev/null +++ b/packages/flame_3d/lib/src/camera/third_person_camera.dart @@ -0,0 +1,52 @@ +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/core.dart'; +import 'package:meta/meta.dart'; + +class ThirdPersonCamera extends CameraComponent3D { + ThirdPersonCamera({ + required this.following, + double distance = 5.0, + this.followDamping = 1.0, + super.fovY, + super.position, + super.rotation, + super.up, + super.projection, + super.world, + super.viewport, + super.viewfinder, + super.backdrop, + super.hudComponents, + }) : _distance = distance; + + /// The point the camera should follow. + Vector3 following; + + /// The distance the camera should maintain from the `following` point. + double get distance => _distance; + set distance(double value) => _distance = value.clamp(0.1, double.infinity); + double _distance; + + /// Damping factor for smoothing out rotation and position changes. + /// + /// If the value is `1`, no damping is applied. + double followDamping; + + @override + @mustCallSuper + void update(double dt) { + // Compute the desired position based on the rotation and distance. + final desiredPosition = following + _getRotatedOffset(); + + // Smoothly interpolate the camera's position toward the desired position. + position = position + (desiredPosition - position) * (followDamping * dt); + + // Always look at the following point. + target.setFrom(following); + } + + Vector3 _getRotatedOffset() { + final forward = Vector3(0, 0, -1)..applyQuaternion(rotation); + return forward.normalized() * -distance; + } +} diff --git a/packages/flame_3d/lib/src/game/flame_game_3d.dart b/packages/flame_3d/lib/src/game/flame_game_3d.dart index ec3fa7d8ec9..1ec37a35ecf 100644 --- a/packages/flame_3d/lib/src/game/flame_game_3d.dart +++ b/packages/flame_3d/lib/src/game/flame_game_3d.dart @@ -3,16 +3,17 @@ import 'dart:ui'; import 'package:flame/game.dart'; import 'package:flame_3d/camera.dart'; -class FlameGame3D extends FlameGame { +class FlameGame3D + extends FlameGame { FlameGame3D({ super.children, W? world, - CameraComponent3D? camera, + C? camera, }) : super( world: world ?? World3D(clearColor: const Color(0xFFFFFFFF)) as W, - camera: camera ?? CameraComponent3D(), + camera: camera ?? CameraComponent3D() as C, ); @override - CameraComponent3D get camera => super.camera as CameraComponent3D; + C get camera => super.camera as C; } From f0a4b3a0c2a4c47fb271e1c01e3144c8ab3eb667 Mon Sep 17 00:00:00 2001 From: Jochum van der Ploeg Date: Sat, 14 Dec 2024 13:30:18 +0100 Subject: [PATCH 2/3] feat: refactor the `CameraComponent3D` --- .../lib/keyboard_controlled_camera.dart | 196 ------------------ packages/flame_3d/example/lib/main.dart | 70 +++---- packages/flame_3d/example/lib/player_box.dart | 7 +- packages/flame_3d/example/lib/simple_hud.dart | 1 - .../example/lib/touch_controlled_camera.dart | 27 +++ 5 files changed, 61 insertions(+), 240 deletions(-) delete mode 100644 packages/flame_3d/example/lib/keyboard_controlled_camera.dart create mode 100644 packages/flame_3d/example/lib/touch_controlled_camera.dart diff --git a/packages/flame_3d/example/lib/keyboard_controlled_camera.dart b/packages/flame_3d/example/lib/keyboard_controlled_camera.dart deleted file mode 100644 index 936e8685631..00000000000 --- a/packages/flame_3d/example/lib/keyboard_controlled_camera.dart +++ /dev/null @@ -1,196 +0,0 @@ -import 'package:flame/components.dart' show KeyboardHandler; -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flutter/gestures.dart' show kMiddleMouseButton; -import 'package:flutter/services.dart' - show KeyEvent, KeyRepeatEvent, LogicalKeyboardKey, PointerEvent; - -class KeyboardControlledCamera extends CameraComponent3D with KeyboardHandler { - KeyboardControlledCamera({ - super.world, - super.viewport, - super.viewfinder, - super.backdrop, - super.hudComponents, - }) : super( - projection: CameraProjection.perspective, - mode: CameraMode.firstPerson, - position: Vector3(0, 2, 4), - target: Vector3(0, 2, 0), - up: Vector3(0, 1, 0), - fovY: 60, - ); - - final double moveSpeed = 0.9; - final double rotationSpeed = 0.3; - final double panSpeed = 2; - final double orbitalSpeed = 0.5; - - Set _keysDown = {}; - PointerEvent? pointerEvent; - double scrollMove = 0; - - final Matrix4 _orbitalMatrix = Matrix4.identity(); - - @override - bool onKeyEvent(KeyEvent event, Set keysPressed) { - _keysDown = keysPressed; - - // Switch camera mode - if (isKeyDown(Key.digit1)) { - mode = CameraMode.free; - up = Vector3(0, 1, 0); // Reset roll - } else if (isKeyDown(Key.digit2)) { - mode = CameraMode.firstPerson; - up = Vector3(0, 1, 0); // Reset roll - } else if (isKeyDown(Key.digit3)) { - mode = CameraMode.thirdPerson; - up = Vector3(0, 1, 0); // Reset roll - } else if (isKeyDown(Key.digit4)) { - mode = CameraMode.orbital; - up = Vector3(0, 1, 0); // Reset roll - } - - if (isKeyDown(Key.keyP) && event is! KeyRepeatEvent) { - if (projection == CameraProjection.perspective) { - // Create an isometric view. - mode = CameraMode.thirdPerson; - projection = CameraProjection.orthographic; - - position = Vector3(0, 2, -100); - target = Vector3(0, 2, 0); - up = Vector3(0, 1, 0); - fovY = 20; - - yaw(-135 * degrees2Radians, rotateAroundTarget: true); - pitch(-45 * degrees2Radians, lockView: true, rotateAroundTarget: true); - } else if (projection == CameraProjection.orthographic) { - // Reset to default view. - mode = CameraMode.thirdPerson; - projection = CameraProjection.perspective; - - position = Vector3(0, 2, 10); - target = Vector3(0, 2, 0); - up = Vector3(0, 1, 0); - fovY = 60; - } - } - - return false; - } - - @override - void update(double dt) { - final moveInWorldPlane = switch (mode) { - CameraMode.firstPerson || CameraMode.thirdPerson => true, - _ => false, - }; - final rotateAroundTarget = switch (mode) { - CameraMode.thirdPerson || CameraMode.orbital => true, - _ => false, - }; - final lockView = switch (mode) { - CameraMode.free || CameraMode.firstPerson || CameraMode.orbital => true, - _ => false, - }; - - if (mode == CameraMode.orbital) { - final rotation = _orbitalMatrix - ..setIdentity() - ..rotate(up, orbitalSpeed * dt); - final view = rotation.transform3(position - target); - position = target + view; - } else { - // Camera rotation - if (isKeyDown(Key.arrowDown)) { - pitch( - -rotationSpeed * dt, - lockView: lockView, - rotateAroundTarget: rotateAroundTarget, - ); - } else if (isKeyDown(Key.arrowUp)) { - pitch( - rotationSpeed * dt, - lockView: lockView, - rotateAroundTarget: rotateAroundTarget, - ); - } - if (isKeyDown(Key.arrowRight)) { - yaw(-rotationSpeed * dt, rotateAroundTarget: rotateAroundTarget); - } else if (isKeyDown(Key.arrowLeft)) { - yaw(rotationSpeed * dt, rotateAroundTarget: rotateAroundTarget); - } - if (isKeyDown(Key.keyQ)) { - roll(-rotationSpeed * dt); - } else if (isKeyDown(Key.keyE)) { - roll(rotationSpeed * dt); - } - - // Camera movement, if mode is free and mouse button is down we pan the - // camera. - if (pointerEvent != null) { - if (mode == CameraMode.free && - pointerEvent?.buttons == kMiddleMouseButton) { - final mouseDelta = pointerEvent!.delta; - if (mouseDelta.dx > 0) { - moveRight(panSpeed * dt, moveInWorldPlane: moveInWorldPlane); - } else if (mouseDelta.dx < 0) { - moveRight(-panSpeed * dt, moveInWorldPlane: moveInWorldPlane); - } - if (mouseDelta.dy > 0) { - moveUp(-panSpeed * dt); - } else if (mouseDelta.dy < 0) { - moveUp(panSpeed * dt); - } - } else { - const mouseMoveSensitivity = 0.003; - yaw( - (pointerEvent?.delta.dx ?? 0) * mouseMoveSensitivity, - rotateAroundTarget: rotateAroundTarget, - ); - pitch( - (pointerEvent?.delta.dy ?? 0) * mouseMoveSensitivity, - lockView: lockView, - rotateAroundTarget: rotateAroundTarget, - ); - } - pointerEvent = null; - } - - // Keyboard movement - if (isKeyDown(Key.keyW)) { - moveForward(moveSpeed * dt); - } else if (isKeyDown(Key.keyS)) { - moveForward(-moveSpeed * dt); - } - if (isKeyDown(Key.keyA)) { - moveRight(-moveSpeed * dt); - } else if (isKeyDown(Key.keyD)) { - moveRight(moveSpeed * dt); - } - - if (mode == CameraMode.free) { - if (isKeyDown(Key.space)) { - moveUp(moveSpeed * dt); - } else if (isKeyDown(Key.controlLeft)) { - moveUp(-moveSpeed * dt); - } - } - } - - // if (mode == CameraMode.thirdPerson || - // mode == CameraMode.orbital || - // mode == CameraMode.free) { - // moveToTarget(-scrollMove); - // if (isKeyDown(Key.numpadSubtract)) { - // moveToTarget(2 * dt); - // } else if (isKeyDown(Key.numpadAdd)) { - // moveToTarget(-2 * dt); - // } - // } - } - - bool isKeyDown(Key key) => _keysDown.contains(key); -} - -typedef Key = LogicalKeyboardKey; diff --git a/packages/flame_3d/example/lib/main.dart b/packages/flame_3d/example/lib/main.dart index d58aea29c58..18c0d8dcec5 100644 --- a/packages/flame_3d/example/lib/main.dart +++ b/packages/flame_3d/example/lib/main.dart @@ -2,37 +2,25 @@ import 'dart:async'; import 'dart:math'; import 'package:example/crate.dart'; -import 'package:example/keyboard_controlled_camera.dart'; import 'package:example/player_box.dart'; import 'package:example/rotating_light.dart'; -import 'package:example/simple_hud.dart'; +import 'package:example/touch_controlled_camera.dart'; import 'package:flame/events.dart'; -import 'package:flame/extensions.dart' as v64 show Vector2; -import 'package:flame/game.dart' show FlameGame, GameWidget; +import 'package:flame/game.dart' show GameWidget; import 'package:flame_3d/camera.dart'; import 'package:flame_3d/components.dart'; import 'package:flame_3d/game.dart'; import 'package:flame_3d/resources.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart' show runApp, Color, Colors, Listener; +import 'package:flutter/material.dart' show runApp, Color, Colors; -class ExampleGame3D extends FlameGame - with HasKeyboardHandlerComponents { +class ExampleGame3D extends FlameGame3D + with DragCallbacks, ScrollDetector { ExampleGame3D() : super( world: World3D(clearColor: const Color(0xFFFFFFFF)), - camera: KeyboardControlledCamera( - viewport: FixedResolutionViewport( - resolution: v64.Vector2(800, 600), - ), - hudComponents: [SimpleHud()], - ), + camera: TouchControlledCamera(), ); - @override - KeyboardControlledCamera get camera => - super.camera as KeyboardControlledCamera; - @override FutureOr onLoad() async { world.addAll([ @@ -146,30 +134,38 @@ class ExampleGame3D extends FlameGame ); } } + + @override + void onScroll(PointerScrollInfo info) { + const scrollSensitivity = 0.01; + final delta = info.scrollDelta.global.y.clamp(-10, 10) * scrollSensitivity; + + camera.distance += delta; + } + + @override + void onDragUpdate(DragUpdateEvent event) { + camera.delta.setValues(event.deviceDelta.x, event.deviceDelta.y); + super.onDragUpdate(event); + } + + @override + void onDragEnd(DragEndEvent event) { + camera.delta.setZero(); + super.onDragEnd(event); + } + + @override + void onDragCancel(DragCancelEvent event) { + camera.delta.setZero(); + super.onDragCancel(event); + } } void main() { final example = ExampleGame3D(); - runApp( - Listener( - onPointerMove: (event) { - if (!event.down) { - return; - } - example.camera.pointerEvent = event; - }, - onPointerSignal: (event) { - if (event is! PointerScrollEvent || !event.down) { - return; - } - example.camera.scrollMove = event.delta.dy / 3000; - }, - onPointerUp: (event) => example.camera.pointerEvent = null, - onPointerCancel: (event) => example.camera.pointerEvent = null, - child: GameWidget(game: example), - ), - ); + runApp(GameWidget(game: example)); } extension on Random { diff --git a/packages/flame_3d/example/lib/player_box.dart b/packages/flame_3d/example/lib/player_box.dart index 39bc0c34e70..e15444b965b 100644 --- a/packages/flame_3d/example/lib/player_box.dart +++ b/packages/flame_3d/example/lib/player_box.dart @@ -2,7 +2,6 @@ import 'dart:ui'; import 'package:example/main.dart'; import 'package:flame/components.dart' show HasGameReference; -import 'package:flame_3d/camera.dart'; import 'package:flame_3d/components.dart'; import 'package:flame_3d/game.dart'; import 'package:flame_3d/resources.dart'; @@ -20,10 +19,6 @@ class PlayerBox extends MeshComponent with HasGameReference { @override void renderTree(Canvas canvas) { - // Only show the box if we are in third person mode. - if (game.camera.mode == CameraMode.thirdPerson) { - position.setFrom(game.camera.target); - super.renderTree(canvas); - } + game.camera.target = position + Vector3(0, 2, 0); } } diff --git a/packages/flame_3d/example/lib/simple_hud.dart b/packages/flame_3d/example/lib/simple_hud.dart index 757a70a34a1..3cc3d69c9a2 100644 --- a/packages/flame_3d/example/lib/simple_hud.dart +++ b/packages/flame_3d/example/lib/simple_hud.dart @@ -61,7 +61,6 @@ Camera controls: canvas, ''' FPS: $fps -Mode: ${game.camera.mode.name} Projection: ${game.camera.projection.name} Culled: ${game.world.culled} diff --git a/packages/flame_3d/example/lib/touch_controlled_camera.dart b/packages/flame_3d/example/lib/touch_controlled_camera.dart new file mode 100644 index 00000000000..cfb96364201 --- /dev/null +++ b/packages/flame_3d/example/lib/touch_controlled_camera.dart @@ -0,0 +1,27 @@ +import 'package:example/simple_hud.dart'; +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/core.dart'; +import 'package:flame/extensions.dart' as v64 show Vector2; + +class TouchControlledCamera extends ThirdPersonCamera { + TouchControlledCamera() + : super( + following: Vector3(0, 2, 0), + followDamping: 1, + position: Vector3(0, 2, 4), + projection: CameraProjection.perspective, + distance: 3, + viewport: FixedResolutionViewport( + resolution: v64.Vector2(800, 600), + ), + hudComponents: [SimpleHud()], + ); + + Vector2 delta = Vector2.zero(); + + @override + void update(double dt) { + super.update(dt); + rotate(delta.x * dt, delta.y * dt); + } +} From c86420a5b84ca5991fe7b3e766cbb8201a94954e Mon Sep 17 00:00:00 2001 From: Jochum van der Ploeg Date: Sat, 14 Dec 2024 13:33:32 +0100 Subject: [PATCH 3/3] feat: refactor the `CameraComponent3D` --- packages/flame_3d/example/lib/touch_controlled_camera.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flame_3d/example/lib/touch_controlled_camera.dart b/packages/flame_3d/example/lib/touch_controlled_camera.dart index cfb96364201..eb9e76e18ee 100644 --- a/packages/flame_3d/example/lib/touch_controlled_camera.dart +++ b/packages/flame_3d/example/lib/touch_controlled_camera.dart @@ -1,7 +1,7 @@ import 'package:example/simple_hud.dart'; +import 'package:flame/extensions.dart' as v64 show Vector2; import 'package:flame_3d/camera.dart'; import 'package:flame_3d/core.dart'; -import 'package:flame/extensions.dart' as v64 show Vector2; class TouchControlledCamera extends ThirdPersonCamera { TouchControlledCamera()