14 private Func<Vector2>? _followPixel;
15 private Vector2 _followOffsetPx;
16 private bool _followHard;
17 private float _followSpeedPxPerSec;
18 private float _followSnapPx;
21 private IMovableOnSceneLayer? _followGridTarget;
22 private Vector2 _followGridOffset;
23 private float _followSpeedTilesPerSec;
24 private float _followSnapTiles;
27 private Func<float, float>? _followEasing;
28 private float _followDurationSec;
48 Vector2 offsetPx =
default)
51 throw new ArgumentOutOfRangeException(nameof(speed));
53 _followPixel = getPixelPos ??
throw new ArgumentNullException(nameof(getPixelPos));
54 _followGridTarget =
null;
59 _followOffsetPx = offsetPx;
60 _followSpeedPxPerSec = speed;
61 _followSnapPx = MathF.Max(0f, snap);
62 _followSpeedTilesPerSec = 0f;
63 _followSnapTiles = 0f;
68 _followOffsetPx = Vector2.Zero;
69 _followSpeedTilesPerSec = speed;
70 _followSnapTiles = MathF.Max(0f, snap);
71 _followSpeedPxPerSec = 0f;
77 _followDurationSec = 0f;
98 Func<float, float>? easing =
null,
100 Vector2 offsetPx =
default)
102 if (durationSec <= 0f)
103 throw new ArgumentOutOfRangeException(nameof(durationSec));
105 _followPixel = getPixelPos ??
throw new ArgumentNullException(nameof(getPixelPos));
106 _followGridTarget =
null;
109 _followOffsetPx = offsetPx;
110 _followEasing = easing ?? EasingFunctions.Linear;
111 _followDurationSec = durationSec;
116 _followSnapPx = MathF.Max(0f, snap);
117 _followSnapTiles = 0f;
121 _followSnapTiles = MathF.Max(0f, snap);
126 _followSpeedPxPerSec = 0f;
127 _followSpeedTilesPerSec = 0f;
150 Vector2 offsetPx =
default)
152 var easing = EasingFunctions.From(easingKind);
165 _followPixel = getPixelPos ??
throw new ArgumentNullException(nameof(getPixelPos));
166 _followGridTarget =
null;
169 _followOffsetPx = (_mover.PositionSpace ==
MovementSpace.Pixel) ? offsetPx : Vector2.Zero;
172 _followSpeedPxPerSec = 0f;
174 _followSpeedTilesPerSec = 0f;
175 _followSnapTiles = 0f;
176 _followEasing =
null;
177 _followDurationSec = 0f;
192 float speedTilesPerSec,
193 float snapTiles = 0.25f,
194 Vector2 gridOffset =
default,
195 Vector2 pixelOffset =
default)
197 if (speedTilesPerSec <= 0)
198 throw new ArgumentOutOfRangeException(nameof(speedTilesPerSec));
200 _followGridTarget = tileTarget ??
throw new ArgumentNullException(nameof(tileTarget));
201 _followGridOffset = gridOffset;
205 _followSpeedTilesPerSec = speedTilesPerSec;
206 _followSnapTiles = MathF.Max(0f, snapTiles);
207 _followSpeedPxPerSec = 0f;
210 _followOffsetPx = (_mover.PositionSpace ==
MovementSpace.Pixel) ? pixelOffset : Vector2.Zero;
213 _followEasing =
null;
214 _followDurationSec = 0f;
232 Func<float, float>? easing =
null,
234 Vector2 gridOffset =
default,
235 Vector2 pixelOffset =
default)
237 if (durationSec <= 0f)
238 throw new ArgumentOutOfRangeException(nameof(durationSec));
240 _followGridTarget = tileTarget ??
throw new ArgumentNullException(nameof(tileTarget));
241 _followGridOffset = gridOffset;
245 _followOffsetPx = (_mover.PositionSpace ==
MovementSpace.Pixel) ? pixelOffset : Vector2.Zero;
247 _followEasing = easing ?? EasingFunctions.Linear;
248 _followDurationSec = durationSec;
254 _followSnapPx = MathF.Max(0f, snap);
255 _followSnapTiles = MathF.Max(0f, snap);
258 _followSpeedPxPerSec = 0f;
259 _followSpeedTilesPerSec = 0f;
278 Vector2 gridOffset =
default,
279 Vector2 pixelOffset =
default)
281 var easing = EasingFunctions.From(easingKind);
282 FollowTileSoft(tileTarget, durationSec, easing, snap, gridOffset, pixelOffset);
295 Vector2 gridOffset =
default,
296 Vector2 pixelOffset =
default)
298 _followGridTarget = tileTarget ??
throw new ArgumentNullException(nameof(tileTarget));
299 _followGridOffset = gridOffset;
303 _followOffsetPx = (_mover.PositionSpace ==
MovementSpace.Pixel) ? pixelOffset : Vector2.Zero;
306 _followSpeedTilesPerSec = 0f;
307 _followSnapTiles = 0f;
308 _followSpeedPxPerSec = 0f;
310 _followEasing =
null;
311 _followDurationSec = 0f;
321 _followGridTarget =
null;
322 _followEasing =
null;
323 _followDurationSec = 0f;
326 _followSpeedPxPerSec = 0f;
328 _followSpeedTilesPerSec = 0f;
329 _followSnapTiles = 0f;
330 _followOffsetPx = Vector2.Zero;
331 _followGridOffset = Vector2.Zero;
336 private bool AdvanceFollow()
339 if (_followPixel is not
null)
341 var goalPx = _followPixel() + _followOffsetPx;
346 return Advance_TargetPixel_MoverGrid(goalPx);
351 return Advance_TargetPixel_MoverPixel(goalPx);
356 if (_followGridTarget is not
null)
358 var layer = _followGridTarget.SceneLayer;
361 var goalCoordinates = _followGridTarget.GetPosition() + _followGridOffset;
366 return Advance_TargetGrid_MoverGrid(goalCoordinates);
371 return Advance_TargetGrid_MoverPixel(goalCoordinates, layer);
378 private bool Advance_TargetPixel_MoverGrid(Vector2 goalPx)
381 if (_sceneLayer is
null || _coords is
null)
382 throw new InvalidOperationException(
"Pixel->Grid follow requires scene layer/coords.");
384 var gridPt = _coords.GetSceneLayerCoordinatesAtPixel(_sceneLayer,
new PointF(goalPx.X, goalPx.Y));
385 var goalGrid =
new Vector2(gridPt.X, gridPt.Y);
389 _mover.SetPosition(goalGrid);
393 if (_followEasing is not
null && _followDurationSec > 0f)
395 MoveTo(goalGrid, _followDurationSec, _followEasing, _followSnapTiles);
399 MoveToward(goalGrid, _followSpeedTilesPerSec, _followSnapTiles);
403 private bool Advance_TargetPixel_MoverPixel(Vector2 goalPx)
407 _mover.SetPosition(goalPx);
412 if (_followEasing is not
null && _followDurationSec > 0f)
414 MoveTo(goalPx, _followDurationSec, _followEasing, _followSnapPx);
419 MoveToward(goalPx, _followSpeedPxPerSec, _followSnapPx);
425 private bool Advance_TargetGrid_MoverGrid(Vector2 goalCoordinates)
429 _mover.SetPosition(goalCoordinates);
433 if (_followEasing is not
null && _followDurationSec > 0f)
435 MoveTo(goalCoordinates, _followDurationSec, _followEasing, _followSnapTiles);
440 MoveToward(goalCoordinates, _followSpeedTilesPerSec, _followSnapTiles);
444 private bool Advance_TargetGrid_MoverPixel(Vector2 goalCoordinates, SceneLayer sceneLayer)
446 var targetPx = sceneLayer.CoordinateSystem.GetAnchorPixelAtSceneLayerCoordinates(sceneLayer,
new PointF(goalCoordinates.X, goalCoordinates.Y));
447 var goalPx =
new Vector2(targetPx.X, targetPx.Y) + _followOffsetPx;
451 _mover.SetPosition(goalPx);
455 if (_followEasing is not
null && _followDurationSec > 0f)
457 MoveTo(goalPx, _followDurationSec, _followEasing, _followSnapPx);
462 var pxRight = sceneLayer.CoordinateSystem.GetAnchorPixelAtSceneLayerCoordinates(sceneLayer,
new PointF(goalCoordinates.X + 1f, goalCoordinates.Y));
463 float pxPerTile = MathF.Max(1f,
new Vector2(pxRight.X - targetPx.X, pxRight.Y - targetPx.Y).Length());
464 float speedPxPerSec = _followSpeedTilesPerSec * pxPerTile;
465 float snap = _followSnapTiles * pxPerTile;
Central controller responsible for managing all movement modes for a single IMovable object....
void FollowTileSoft(IMovableOnSceneLayer tileTarget, float durationSec, Func< float, float >? easing=null, float snap=0.5f, Vector2 gridOffset=default, Vector2 pixelOffset=default)
Start following a grid (tile) target using a duration-based tween (easing). When easing is active,...
void FollowPixelSoft(Func< Vector2 > getPixelPos, float speed, float snap=0.5f, Vector2 offsetPx=default)
Start following a pixel-space target at a constant speed. The speed and snap units are interpreted ...
MovementController MoveToward(Vector2 target, float speedPerSec, float snapEpsilon=0.5f)
Begins scripted motion toward the specified target position at a constant speed.
void FollowTileSoft(IMovableOnSceneLayer tileTarget, float durationSec, EasingKind easingKind, float snap=0.5f, Vector2 gridOffset=default, Vector2 pixelOffset=default)
Convenience overload of FollowTileSoft(IMovableOnSceneLayer, float, Func<float, float>?...
void FollowPixelSoft(Func< Vector2 > getPixelPos, float durationSec, EasingKind easingKind, float snap=0.5f, Vector2 offsetPx=default)
Start following a pixel-space target using a duration-based tween (easing). When easing is active,...
void CancelScript()
Cancels any active scripted movement and clears the current script state. Raises ScriptedMovementStop...
void FollowPixelHard(Func< Vector2 > getPixelPos, Vector2 offsetPx=default)
Hard-follow a pixel-space target. The follower snaps directly to the target every update (no tweening...
void FollowPixelSoft(Func< Vector2 > getPixelPos, float durationSec, Func< float, float >? easing=null, float snap=0.5f, Vector2 offsetPx=default)
Start following a pixel-space target using a duration-based tween (easing). When easing is active,...
void FollowTileSoft(IMovableOnSceneLayer tileTarget, float speedTilesPerSec, float snapTiles=0.25f, Vector2 gridOffset=default, Vector2 pixelOffset=default)
Start following a grid (tile) target at a constant speed (tiles/sec). If the follower is pixel-space,...
MovementController MoveTo(Vector2 target, float durationSec, Func< float, float >? easing=null, float snapEpsilon=0.5f)
Begins a scripted tween toward the specified target position over a fixed duration....
void FollowTileHard(IMovableOnSceneLayer tileTarget, Vector2 gridOffset=default, Vector2 pixelOffset=default)
Hard-follow a grid (tile) target. The follower snaps directly to the target grid coordinate each upda...
void Unfollow()
Stop following any target and clear all follow/tween state (targets, speeds, offsets,...
Implemented by grid-space IMovable objects that belong to a specific Scenes.SceneLayer.
MovementSpace PositionSpace
Which unit system this mover uses for its position.
EasingKind
Enumeration of all supported easing functions for animation and movement interpolation....
MovementSpace
Specifies the coordinate system used for movement calculations and updates.