diff --git a/CHANGELOG.md b/CHANGELOG.md index 48f8b1980..163a06514 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Added `ex.lerpAngle(startAngleRadians: number, endAngleRadians: number, rotationType: RotationType, time: number): number` in order to lerp angles between each other - Added `pointerenter` and `pointerleave` events to `ex.TileMap` tiles! - Added `pointerenter` and `pointerleave` events to `ex.IsometricMap` tiles! - Added new `ex.BezierCurve` type for drawing cubic bezier curves diff --git a/src/engine/Math/lerp.ts b/src/engine/Math/lerp.ts index 7fc6cffdf..78b3e9e9c 100644 --- a/src/engine/Math/lerp.ts +++ b/src/engine/Math/lerp.ts @@ -1,3 +1,5 @@ +import { RotationType } from '../Actions/RotationType'; +import { TwoPI } from './util'; import { Vector } from './vector'; /** @@ -10,6 +12,51 @@ export function lerp(a: number, b: number, time: number): number { return (1 - time) * a + b * time; } +/** + * Linear interpolation between angles in radians + * @param startAngleRadians + * @param endAngleRadians + * @param rotationType + * @param time + */ +export function lerpAngle(startAngleRadians: number, endAngleRadians: number, rotationType: RotationType, time: number): number { + const shortestPathIsPositive = (startAngleRadians - endAngleRadians + TwoPI) % TwoPI >= Math.PI; + const distance1 = Math.abs(endAngleRadians - startAngleRadians); + const distance2 = TwoPI - distance1; + let shortDistance = 0; + let longDistance = 0; + if (distance1 > distance2) { + shortDistance = distance2; + longDistance = distance1; + } else { + shortDistance = distance1; + longDistance = distance2; + } + let distance = 0; + let direction = 1; + + switch (rotationType) { + case RotationType.ShortestPath: + distance = shortDistance; + direction = shortestPathIsPositive ? 1 : -1; + break; + case RotationType.LongestPath: + distance = longDistance; + direction = shortestPathIsPositive ? -1 : 1; + break; + case RotationType.Clockwise: + direction = 1; + distance = shortestPathIsPositive ? shortDistance : longDistance; + break; + case RotationType.CounterClockwise: + direction = -1; + distance = shortestPathIsPositive ? longDistance : shortDistance; + break; + } + + return startAngleRadians + direction * (distance * time); +} + /** * Linear interpolation between `a` and `b`, at `time = 0` the value will be `a` at `time = 1` the value will be `b` * @param a