|Inertial camera panning and pinch-to-zoom!|
(on a mobile phone)
tl;dr: Last week I implemented traditional swipe-based level-camera controls in Godot. This includes drag-to-pan, multi-touch pinch-to-zoom, inertial panning, swipe gesture-smoothing, and automatic camera limits based on the level-boundaries.
I'll cover my touch-control implementation in more detail in a separate post!
What happened last week?
- Updated my camera-controller system to support swapping the active pan-and-zoom-controller.
- Created a traditional mobile touch-based pan-and-zoom camera controller.
- This includes a lot of cool features:
- The basics.
- Multi-touch pinch-to-zoom.
- Tracking multiple touches is a lot more complicated than just tracking one!
- Zoom to target position.
- This is important, because zooming without changing the pan offset position would probably cause the position you're trying to zoom into to exit the screen.
- Inertial panning.
- This lets the camera coast to a stop after you're done dragging, which makes it feel much smoother and more natural.
- Swipe gesture-smoothing.
- This fixes gesture-velocity values, because gesture positions can be very noisy and imprecise.
- Automatic camera limits based on the viewable region.
- This calculates the boundary of the level, and forces the camera to not go too far outside of it.
- How my swipe inertia works:
- Completely disabled when a touch is present.
- In LevelPointerListener, track the (app-physics) time and distance between the latest touch position and a touch position of at most x events ago.
- Will need to use a more recent x, if there are not at least x events in the current gesture.
- Use this time and distance diff to calculate a current gesture velocity.
- When the gesture is released, start applying physics to the camera position.
- Start refactoring my camera-pan/zoom-control system to support configuration as a traditional mobile touch-based controller.
- Add support for configuring the default camera-pan-controller.
- Add support for swapping the current camera-pan-controller based on bot selection.
- When a bot is selected, use my old navigation preselection camera controller.
- When a bot isn't selected, use the new more-traditional pan-and-zoom controller.
- Move the camera-pan-controller system into Scaffolder.
- Add better support for configuring the camera-pan-controller system.
- Add support for syncing old pan state when swapping the active camera-pan-controller.
- Add support for clearing navigation-pre-selection state when swapping camera-pan-controllers.
- Split-apart camera zoom and offset components for manual contributions, pan-controller contributions, camera-swap contributions, and misc contributions.
- This allows me to update camera offset/zoom simultaneously from multiple systems, without having them break each other.
- Move pointer-event tracking out of players and into levels.
- Add multi-touch support to LevelPointerListener.
- Update NavigationPreselectionDragPanController to rely on LevelpointerListener for touch updates.
- Move camera_controller to camera manifest class.
- Rename zoom_multiplier to zoom.
- Update LevelPointerListener to track level-space positions separately from screen-space positions.
- Move some NavigationPreselectionDragPanController-specific logic out of CameraPanController.
- Implement SwipePanController.
- Create a new level_manifest dictionary in ScaffolderSchema.
- Move the level-session reference into level-config.
- Add support for configuring default level-boundary margins for camera and character boundaries.
- Add support for limiting the boundary of the camera-pan-controller.
- Fix logic for clamping camera-pan-controller zoom and pan to the level's camera-bounds.
- Move scroll-to-zoom functionality out of camera-controller (as a manual override) and into camera-pan-controller (as a standard, limited control).
- Refactor scroll-to-zoom functionality to zoom into the cursor position rather than the current camera center position.
- Adjust max-zoom limit.
- Add support for tracking the center of a pinch.
- Update pinch-to-zoom to also focus the zoom around the pinch position.
- Add support for swipe inertia to my camera-pan-and-zoom system.
- Add support for tracking gesture velocity, and for smoothing this velocity by tracking touch events over a given time window.
- Fix a bug from checking a touch-registration before the touch was registered.
- Move CameraPanController to Scaffolder, and re-arrange camera-related files.
- Move camera parameters into CameraManifest and ScaffolderSchema.
- Add support for configuring whether the camera max-zoom limit should be defined by the level bounds or by a manifest constant.
- Fix a bug where the pan would still occur when the zoom is clipped to the min or max, while trying to zoom around a specific target position.
- Add support for omitting the Sc.logger.print argument or for passing in non-String values.
- Create a utility function for clamping a vector's length.
- Update CircularBuffer:
- Add size(), empty(), and peek() methods.
- Add support for configuring whether it should automatically free items that are overwritten.
- Continue creating a more-polished version of Meteor Power (my game-jam game) for release as a polished mobile app.
- The camera refactor was definitely the most complicated task on my list for this.
- So I should cover a lot more ground next week!