UNPKG

rpg-dialogue-js

Version:

A simple roleplay game dialogue engine and editor.

87 lines (77 loc) 3.18 kB
/** * @author Ikaros Kappler * @date 2019-02-03 * @modified 2021-03-01 Added `wrapMax` function. * @version 1.1.0 **/ import { Line } from "./Line"; import { Triangle } from "./Triangle"; import { Vertex } from "./Vertex"; /** * A collection of usefull geometry utilities. * * @global **/ export const geomutils = { /** * Compute the n-section of the angle – described as a triangle (A,B,C) – in point A. * * @param {Vertex} pA - The first triangle point. * @param {Vertex} pB - The second triangle point. * @param {Vertex} pC - The third triangle point. * @param {number} n - The number of desired angle sections (example: 2 means the angle will be divided into two sections, * means an returned array with length 1, the middle line). * * @return {Line[]} An array of n-1 lines secting the given angle in point A into n equal sized angle sections. The lines' first vertex is A. */ nsectAngle( pA:Vertex, pB:Vertex, pC:Vertex, n:number ) : Array<Line> { const triangle : Triangle = new Triangle( pA, pB, pC ); const lineAB : Line = new Line( pA, pB ); const lineAC : Line = new Line( pA, pC ); // Compute the difference; this is the angle between AB and AC var insideAngle : number = lineAB.angle( lineAC ); // We want the inner angles of the triangle, not the outer angle; // which one is which depends on the triangle 'direction' const clockwise : boolean = triangle.determinant() > 0; // For convenience convert the angle [-PI,PI] to [0,2*PI] if( insideAngle < 0 ) insideAngle = 2*Math.PI + insideAngle; if( !clockwise ) insideAngle = (2*Math.PI - insideAngle) * (-1); // Scale the rotated lines to the max leg length (looks better) const lineLength : number = Math.max( lineAB.length(), lineAC.length() ); const scaleFactor : number = lineLength/lineAB.length(); var result : Array<Line> = []; for( var i = 1; i < n; i++ ) { // Compute the i-th inner sector line result.push( new Line( pA, pB.clone().rotate((-i*(insideAngle/n)), pA) ).scale(scaleFactor) as Line ); } return result; }, /** * Wrap the value (e.g. an angle) into the given range of [0,max). * * @name wrapMax * @param {number} x - The value to wrap. * @param {number} max - The max bound to use for the range. * @return {number} The wrapped value inside the range [0,max). */ wrapMax( x:number, max:number ) : number { // Found at // https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi return (max + (x%max)) % max; }, /** * Wrap the value (e.g. an angle) into the given range of [min,max). * * @name wrapMinMax * @param {number} x - The value to wrap. * @param {number} min - The min bound to use for the range. * @param {number} max - The max bound to use for the range. * @return {number} The wrapped value inside the range [min,max). */ // Currently un-used wrapMinMax( x:number, min:number, max:number ) : number { return min + geomutils.wrapMax( x - min, max - min ); } };