@makefully/platypus 4.1.5 → 4.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +3 -3
- package/lib/platypus.js +1 -1
- package/package.json +7 -6
- package/src/AABB.js +685 -0
- package/src/ActionState.js +121 -0
- package/src/AssetManager.js +206 -0
- package/src/CollisionData.js +96 -0
- package/src/CollisionDataContainer.js +127 -0
- package/src/CollisionShape.js +315 -0
- package/src/Component.js +231 -0
- package/src/Data.js +64 -0
- package/src/DataMap.js +204 -0
- package/src/Entity.js +404 -0
- package/src/EntityLinker.js +113 -0
- package/src/EventHandler.js +115 -0
- package/src/EventHandlerList.js +251 -0
- package/src/Game.js +840 -0
- package/src/Gamepad.js +175 -0
- package/src/ID3CaptionPlayer.js +61 -0
- package/src/Messenger.js +365 -0
- package/src/PIXIAnimation.js +622 -0
- package/src/RandomSet.js +140 -0
- package/src/SFXPlayer.js +120 -0
- package/src/StateMap.js +252 -0
- package/src/Storage.js +152 -0
- package/src/TickerClient.js +48 -0
- package/src/TickerServer.js +23 -0
- package/src/TimeEvent.js +50 -0
- package/src/TimeEventList.js +100 -0
- package/src/VOPlayer.js +684 -0
- package/src/Vector.js +702 -0
- package/src/components/AIChaser.js +161 -0
- package/src/components/AIPacer.js +107 -0
- package/src/components/AudioMusic.js +151 -0
- package/src/components/AudioSFX.js +673 -0
- package/src/components/AudioVO.js +301 -0
- package/src/components/CollisionBasic.js +826 -0
- package/src/components/CollisionFilter.js +74 -0
- package/src/components/CollisionGroup.js +448 -0
- package/src/components/CollisionTiles.js +608 -0
- package/src/components/ComponentSwitcher.js +173 -0
- package/src/components/ControllerInput.js +65 -0
- package/src/components/Counter.js +165 -0
- package/src/components/EntityCamera.js +215 -0
- package/src/components/EntityContainer.js +549 -0
- package/src/components/EntityController.js +541 -0
- package/src/components/HandlerCamera.js +1052 -0
- package/src/components/HandlerCollision.js +1318 -0
- package/src/components/HandlerController.js +291 -0
- package/src/components/HandlerLogic.js +394 -0
- package/src/components/HandlerRender.js +217 -0
- package/src/components/Interactive.js +502 -0
- package/src/components/LevelBuilder.js +524 -0
- package/src/components/LogicAngularMovement.js +154 -0
- package/src/components/LogicAttachment.js +265 -0
- package/src/components/LogicButton.js +466 -0
- package/src/components/LogicCarrier.js +39 -0
- package/src/components/LogicDestroyMe.js +58 -0
- package/src/components/LogicDirectionalMovement.js +325 -0
- package/src/components/LogicDragDrop.js +371 -0
- package/src/components/LogicImpactLaunch.js +144 -0
- package/src/components/LogicPacingPlatform.js +64 -0
- package/src/components/LogicPortable.js +112 -0
- package/src/components/LogicPortal.js +115 -0
- package/src/components/LogicPushable.js +98 -0
- package/src/components/LogicRebounder.js +136 -0
- package/src/components/LogicRegionSpawner.js +139 -0
- package/src/components/LogicRotationalMovement.js +205 -0
- package/src/components/LogicSpawner.js +159 -0
- package/src/components/LogicStateMachine.js +382 -0
- package/src/components/LogicSwitch.js +77 -0
- package/src/components/LogicTeleportee.js +68 -0
- package/src/components/LogicTeleporter.js +93 -0
- package/src/components/LogicTimer.js +178 -0
- package/src/components/LogicWindUpRacer.js +179 -0
- package/src/components/Motion.js +371 -0
- package/src/components/Mover.js +566 -0
- package/src/components/Node.js +289 -0
- package/src/components/NodeMap.js +295 -0
- package/src/components/NodeResident.js +636 -0
- package/src/components/Orientation.js +697 -0
- package/src/components/RandomEvents.js +73 -0
- package/src/components/RelativePosition.js +204 -0
- package/src/components/RelayFamily.js +106 -0
- package/src/components/RelayGame.js +53 -0
- package/src/components/RelayLinker.js +94 -0
- package/src/components/RelayParent.js +57 -0
- package/src/components/RelaySelf.js +55 -0
- package/src/components/Render.js +178 -0
- package/src/components/RenderAnimator.js +275 -0
- package/src/components/RenderContainer.js +646 -0
- package/src/components/RenderDebug.js +319 -0
- package/src/components/RenderDestroyMe.js +59 -0
- package/src/components/RenderLottie.js +149 -0
- package/src/components/RenderProgress.js +120 -0
- package/src/components/RenderSpine.js +840 -0
- package/src/components/RenderSprite.js +527 -0
- package/src/components/RenderText.js +147 -0
- package/src/components/RenderTiles.js +1440 -0
- package/src/components/SceneChanger.js +128 -0
- package/src/components/TiledLoader.js +1459 -0
- package/src/components/Timeline.js +314 -0
- package/src/components/Tutorial.js +267 -0
- package/src/components/Tween.js +296 -0
- package/src/components/VoiceOver.js +373 -0
- package/src/components/XHR.js +129 -0
- package/src/components/index.js +79 -0
- package/src/factory.js +305 -0
- package/src/index.js +159 -0
- package/src/mixins/PIXI.Graphics.js +41 -0
- package/src/platypus.css +68 -0
- package/src/sayHello.js +50 -0
- package/src/shapes/Capsule.js +74 -0
- package/src/shapes/Circle.js +43 -0
- package/src/shapes/Ellipse.js +117 -0
- package/src/shapes/Point.js +191 -0
- package/src/shapes/Polygon.js +112 -0
- package/src/shapes/Polyline.js +97 -0
- package/src/shapes/Rectangle.js +78 -0
- package/src/shapes/RoundedRectangle.js +33 -0
- package/src/shapes/Segment.js +346 -0
- package/src/shapes/adjustedXY.js +19 -0
- package/src/shapes/castFromBox2D.js +92 -0
- package/src/shapes/castFromObject.js +53 -0
- package/src/shapes/castFromPixiGraphics.js +6 -0
- package/src/shapes/castFromPixiShape.js +89 -0
- package/src/shapes/castToBox2D.js +190 -0
- package/src/shapes/castToPixiGraphics.js +100 -0
- package/src/shapes/castToPixiShape.js +61 -0
- package/src/shapes/checkPointsMap.js +313 -0
- package/src/shapes/index.js +35 -0
- package/src/utils/array.js +73 -0
- package/src/utils/string.js +39 -0
- package/lib/243.platypus.mjs +0 -1
- package/lib/platypus.mjs +0 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This adds support for a tiny API to PIXI.Graphics similar to the CreateJS Graphics API. This is used for backwards support for RenderSprite masks.
|
|
3
|
+
*/
|
|
4
|
+
import {Graphics} from 'pixi.js';
|
|
5
|
+
|
|
6
|
+
export default (function () {
|
|
7
|
+
const gfx = Graphics.prototype;
|
|
8
|
+
|
|
9
|
+
gfx.a = gfx.a || gfx.arc;
|
|
10
|
+
gfx.at = gfx.at || gfx.arcTo;
|
|
11
|
+
gfx.bt = gfx.bt || gfx.bezierCurveTo;
|
|
12
|
+
gfx.c = gfx.c || gfx.clear;
|
|
13
|
+
gfx.dc = gfx.dc || gfx.circle;
|
|
14
|
+
gfx.de = gfx.de || gfx.ellipse;
|
|
15
|
+
gfx.dr = gfx.dr || gfx.rect;
|
|
16
|
+
gfx.ef = gfx.ef || gfx.endFill;
|
|
17
|
+
gfx.f = gfx.f || gfx.beginFill;
|
|
18
|
+
gfx.lt = gfx.lt || gfx.lineTo;
|
|
19
|
+
gfx.mt = gfx.mt || gfx.moveTo;
|
|
20
|
+
gfx.qt = gfx.qt || gfx.quadraticCurveTo;
|
|
21
|
+
gfx.r = gfx.r || gfx.rect;
|
|
22
|
+
gfx.rr = gfx.rr || gfx.roundRect;
|
|
23
|
+
|
|
24
|
+
/* Other CreateJS shortcuts that are unsupported by PIXI
|
|
25
|
+
gfx.cp
|
|
26
|
+
gfx.lf
|
|
27
|
+
gfx.rf
|
|
28
|
+
gfx.bf
|
|
29
|
+
gfx.ss
|
|
30
|
+
gfx.sd
|
|
31
|
+
gfx.s
|
|
32
|
+
gfx.ls
|
|
33
|
+
gfx.rs
|
|
34
|
+
gfx.bs
|
|
35
|
+
gfx.es
|
|
36
|
+
gfx.rc
|
|
37
|
+
gfx.dp
|
|
38
|
+
gfx.p
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
} ());
|
package/src/platypus.css
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
div#captions {
|
|
2
|
+
user-select: none;
|
|
3
|
+
-moz-user-select: none;
|
|
4
|
+
-webkit-user-select: none;
|
|
5
|
+
-ms-user-select: none;
|
|
6
|
+
-webkit-touch-callout: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
canvas.platypus-canvas {
|
|
10
|
+
height: 100%;
|
|
11
|
+
position: relative;
|
|
12
|
+
width: 100%;
|
|
13
|
+
|
|
14
|
+
user-select: none;
|
|
15
|
+
-moz-user-select: none;
|
|
16
|
+
-webkit-user-select: none;
|
|
17
|
+
-ms-user-select: none;
|
|
18
|
+
-webkit-touch-callout: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.platypus-debugging {
|
|
22
|
+
position: fixed;
|
|
23
|
+
pointer-events: none;
|
|
24
|
+
color: #fff;
|
|
25
|
+
font-size: 12px;
|
|
26
|
+
padding: 5px;
|
|
27
|
+
background: rgba(0, 0, 0, 0.4);
|
|
28
|
+
z-index: 2;
|
|
29
|
+
font-family: "Lucida Console", Monaco, monospace;
|
|
30
|
+
-webkit-touch-callout: none;
|
|
31
|
+
user-select: none;
|
|
32
|
+
cursor: default;
|
|
33
|
+
margin: 0;
|
|
34
|
+
line-height: 1.5em;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#framerate {
|
|
38
|
+
top: 0;
|
|
39
|
+
left: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#platypus-logging {
|
|
43
|
+
top: 0;
|
|
44
|
+
right: 0;
|
|
45
|
+
max-width: 40%;
|
|
46
|
+
max-height: 40%;
|
|
47
|
+
overflow-x: auto;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#platypus-logging .general {color: lightgreen;}
|
|
51
|
+
#platypus-logging .log {color: white;}
|
|
52
|
+
#platypus-logging .warn {color: yellow;}
|
|
53
|
+
#platypus-logging .debug {color: lightblue;}
|
|
54
|
+
#platypus-logging .error {color: lightcoral;}
|
|
55
|
+
#platypus-logging span {padding-right: 1.5em;}
|
|
56
|
+
|
|
57
|
+
#toggle-platypus-debugging {
|
|
58
|
+
position: fixed;
|
|
59
|
+
top: 0;
|
|
60
|
+
right: 0;
|
|
61
|
+
font-size: 12px;
|
|
62
|
+
padding: 5px;
|
|
63
|
+
background: rgba(0, 0, 0, 0.4);
|
|
64
|
+
font-family: "Lucida Console", Monaco, monospace;
|
|
65
|
+
border: none;
|
|
66
|
+
color: white;
|
|
67
|
+
z-index: 3;
|
|
68
|
+
}
|
package/src/sayHello.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* global console, document, platypus */
|
|
2
|
+
import {VERSION as pixiVersion} from 'pixi.js';
|
|
3
|
+
import {arrayCache} from './utils/array.js';
|
|
4
|
+
|
|
5
|
+
const
|
|
6
|
+
getPortion = (num, min, max) => Math.floor(num * min / max),
|
|
7
|
+
getStyle = (title, version) => {
|
|
8
|
+
const
|
|
9
|
+
min = 204,
|
|
10
|
+
A = 65,
|
|
11
|
+
v = version?.split?.('.'),
|
|
12
|
+
useVersion = v?.length >= 3,
|
|
13
|
+
r = useVersion ? parseInt(v[0], 10) : (title.charCodeAt(0) || A) - A,
|
|
14
|
+
g = useVersion ? parseInt(v[1], 10) : (title.charCodeAt(1) || A) - A,
|
|
15
|
+
b = useVersion ? parseInt(v[2], 10) : (title.charCodeAt(2) || A) - A,
|
|
16
|
+
max = Math.max(r, g, b, 1);
|
|
17
|
+
|
|
18
|
+
return `color: #ffffff; line-height: 1.5em; border-radius: 6px; background-color: rgb(${getPortion(r, min, max)},${getPortion(g, min, max)},${getPortion(b, min, max)});`;
|
|
19
|
+
},
|
|
20
|
+
getVersions = (arr) => arr.reduce((arr, str) => {
|
|
21
|
+
arr.push(getStyle(str, str.substr(str.lastIndexOf(' ') - str.length + 1)), 'line-height: 1.5em;');
|
|
22
|
+
return arr;
|
|
23
|
+
}, []);
|
|
24
|
+
|
|
25
|
+
export default function (app) {
|
|
26
|
+
const
|
|
27
|
+
{options = {}} = app,
|
|
28
|
+
{version = '(?)'} = options,
|
|
29
|
+
docAuth = document.getElementsByName('author')?.[0]?.getAttribute('content') ?? '',
|
|
30
|
+
author = docAuth ? `by ${docAuth}` : '',
|
|
31
|
+
title = `${options.name ?? app.name ?? document.title ?? ''}${version ? ` ${version}` : ''}`,
|
|
32
|
+
using = arrayCache.setUp(),
|
|
33
|
+
{springroll, supports} = platypus;
|
|
34
|
+
|
|
35
|
+
if (springroll) {
|
|
36
|
+
using.push('SpringRoll ' + springroll.version);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
using.push('Pixi.js ' + pixiVersion);
|
|
40
|
+
|
|
41
|
+
if (supports.firefox || supports.chrome) {
|
|
42
|
+
console.log(`%c ${title} %c ${author}`, getStyle(title, title.substr(title.lastIndexOf(' ') - title.length + 1)), 'line-height: 1.5em;');
|
|
43
|
+
using.push(`Platypus ${platypus.version}`);
|
|
44
|
+
console.log(`Using %c ${using.join(' %c %c ')} %c `, ...getVersions(using));
|
|
45
|
+
} else {
|
|
46
|
+
console.log(`--- "${title}" ${author} - Using ${using.join(', ')}, and Platypus ${platypus.version} ---`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
arrayCache.recycle(using);
|
|
50
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import adjustedXY from "./adjustedXY";
|
|
2
|
+
import Circle from "./Circle";
|
|
3
|
+
import Rectangle from "./Rectangle";
|
|
4
|
+
import Segment from "./Segment";
|
|
5
|
+
|
|
6
|
+
const
|
|
7
|
+
axisInfo = {
|
|
8
|
+
x: {
|
|
9
|
+
axis: 'x',
|
|
10
|
+
alt: 'y',
|
|
11
|
+
length: 'width',
|
|
12
|
+
breadth: 'height'
|
|
13
|
+
},
|
|
14
|
+
y: {
|
|
15
|
+
axis: 'y',
|
|
16
|
+
alt: 'x',
|
|
17
|
+
length: 'height',
|
|
18
|
+
breadth: 'width'
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default class Capsule extends Segment {
|
|
23
|
+
constructor (...args) {
|
|
24
|
+
super(...args);
|
|
25
|
+
this.type = 'capsule';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
initialize (options) {
|
|
29
|
+
if (!options.points && (!options.a || !options.b) && options.width && options.height) {
|
|
30
|
+
const
|
|
31
|
+
{alt, axis, breadth, length} = axisInfo[options.width > options.height ? 'x' : 'y'],
|
|
32
|
+
radius = options[breadth] / 2,
|
|
33
|
+
len = options[length] - 2 * radius,
|
|
34
|
+
hl = len / 2;
|
|
35
|
+
|
|
36
|
+
super.initialize({
|
|
37
|
+
...options,
|
|
38
|
+
a: {
|
|
39
|
+
[axis]: -hl,
|
|
40
|
+
[alt]: 0
|
|
41
|
+
},
|
|
42
|
+
b: {
|
|
43
|
+
[axis]: hl,
|
|
44
|
+
[alt]: 0
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
this.radius = radius;
|
|
48
|
+
} else {
|
|
49
|
+
super.initialize(options);
|
|
50
|
+
this.radius = options.radius ?? 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
duplicate () {
|
|
55
|
+
return new Capsule(this);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
toObject (options) {
|
|
59
|
+
const
|
|
60
|
+
{a, b, radius, type} = this,
|
|
61
|
+
{scale = 1} = options;
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
a: adjustedXY(a, options),
|
|
65
|
+
b: adjustedXY(b, options),
|
|
66
|
+
radius: radius * scale,
|
|
67
|
+
type
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static validateDefinition (definition) {
|
|
72
|
+
return Rectangle.validateDefinition(definition) || (Circle.validateDefinition(definition) && Segment.validateDefinition(definition));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import adjustedXY from "./adjustedXY";
|
|
2
|
+
import Point from "./Point";
|
|
3
|
+
|
|
4
|
+
export default class Circle extends Point {
|
|
5
|
+
constructor (...args) {
|
|
6
|
+
super(...args);
|
|
7
|
+
this.type = 'circle';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
initialize (options) {
|
|
11
|
+
super.initialize(options);
|
|
12
|
+
this.radius = options.radius ?? 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
duplicate () {
|
|
16
|
+
return new Circle(this);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
isPointInside ({x, y}, epsilon = 1e-6) {
|
|
20
|
+
const
|
|
21
|
+
{registration} = this,
|
|
22
|
+
dx = x - registration.x,
|
|
23
|
+
dy = y - registration.y;
|
|
24
|
+
|
|
25
|
+
return (dx * dx + dy * dy) <= (this.radius + epsilon) ** 2;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
toObject (options) {
|
|
29
|
+
const
|
|
30
|
+
{radius, type} = this,
|
|
31
|
+
{scale = 1} = options;
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
radius: radius * scale,
|
|
35
|
+
type,
|
|
36
|
+
...adjustedXY(this, options)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static validateDefinition ({radius} = {}) {
|
|
41
|
+
return typeof radius === 'number' && radius > 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import adjustedXY from "./adjustedXY";
|
|
2
|
+
import Capsule from "./Capsule";
|
|
3
|
+
import Rectangle from "./Rectangle";
|
|
4
|
+
import Segment from "./Segment";
|
|
5
|
+
|
|
6
|
+
export default class Ellipse extends Segment {
|
|
7
|
+
constructor (...args) {
|
|
8
|
+
super(...args);
|
|
9
|
+
this.type = 'ellipse';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get halfHeight () {
|
|
13
|
+
return this.height / 2;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
set halfHeight (hh) {
|
|
17
|
+
this.height = hh * 2;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get halfWidth () {
|
|
21
|
+
return this.width / 2;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set halfWidth (hw) {
|
|
25
|
+
this.width = hw * 2;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
initialize (options) {
|
|
29
|
+
const
|
|
30
|
+
{a, b, height, points, width} = options;
|
|
31
|
+
|
|
32
|
+
if (!points && !(a && b)) {
|
|
33
|
+
const
|
|
34
|
+
hw = width / 2,
|
|
35
|
+
hh = height / 2;
|
|
36
|
+
|
|
37
|
+
if (width > height) {
|
|
38
|
+
const
|
|
39
|
+
c = Math.sqrt(hw * hw - hh * hh);
|
|
40
|
+
|
|
41
|
+
super.initialize({
|
|
42
|
+
...options,
|
|
43
|
+
a: {x: -c, y: 0},
|
|
44
|
+
b: {x: c, y: 0}
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
const
|
|
48
|
+
c = Math.sqrt(hh * hh - hw * hw);
|
|
49
|
+
|
|
50
|
+
super.initialize({
|
|
51
|
+
...options,
|
|
52
|
+
a: {x: 0, y: -c},
|
|
53
|
+
b: {x: 0, y: c}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
super.initialize(options);
|
|
58
|
+
}
|
|
59
|
+
this.height = height;
|
|
60
|
+
this.width = width;
|
|
61
|
+
Object.defineProperties(this, {
|
|
62
|
+
constantSumOfDistances: {
|
|
63
|
+
get () {
|
|
64
|
+
return Math.max(this.width, this.height);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
//TODO: accept rotation
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
toCapsule () {
|
|
73
|
+
const
|
|
74
|
+
{a, b, constantSumOfDistances, width, height} = this,
|
|
75
|
+
hw = width / 2,
|
|
76
|
+
hh = height / 2,
|
|
77
|
+
radius = (width > height) ? hh : hw,
|
|
78
|
+
eOffset = this.getLength(),
|
|
79
|
+
cOffset = constantSumOfDistances - radius - radius,
|
|
80
|
+
ratio = cOffset / eOffset;
|
|
81
|
+
|
|
82
|
+
return new Capsule({
|
|
83
|
+
a: {
|
|
84
|
+
x: a.x * ratio,
|
|
85
|
+
y: a.y * ratio
|
|
86
|
+
},
|
|
87
|
+
b: {
|
|
88
|
+
x: b.x * ratio,
|
|
89
|
+
y: b.y * ratio
|
|
90
|
+
},
|
|
91
|
+
radius
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
duplicate () {
|
|
96
|
+
return new Ellipse(this);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
toObject (options) {
|
|
100
|
+
const
|
|
101
|
+
{a, b, height, radius, type, width} = this,
|
|
102
|
+
{scale = 1} = options;
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
a: adjustedXY(a, options),
|
|
106
|
+
b: adjustedXY(b, options),
|
|
107
|
+
height: height * scale,
|
|
108
|
+
radius: radius * scale,
|
|
109
|
+
type,
|
|
110
|
+
width: width * scale
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static validateDefinition (definition) {
|
|
115
|
+
return Rectangle.validateDefinition(definition);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/* global platypus */
|
|
2
|
+
import Vector from '../Vector';
|
|
3
|
+
import checkPointsMap from './checkPointsMap';
|
|
4
|
+
import adjustedXY from './adjustedXY';
|
|
5
|
+
import castToPixiShape from './castToPixiShape';
|
|
6
|
+
import castToPixiGraphics from './castToPixiGraphics';
|
|
7
|
+
import castToBox2D from './castToBox2D';
|
|
8
|
+
|
|
9
|
+
const
|
|
10
|
+
PI2 = Math.PI * 2;
|
|
11
|
+
|
|
12
|
+
export default class Point {
|
|
13
|
+
constructor (options) {
|
|
14
|
+
this.type = 'point';
|
|
15
|
+
this.registration = new Vector();
|
|
16
|
+
this.initialize(options);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get rotation () {
|
|
20
|
+
return (this.revolutions * PI2) % PI2;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
set rotation (rotation) {
|
|
24
|
+
this.revolutions = rotation / PI2;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get x () {
|
|
28
|
+
return this.registration.x;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
set x (x) {
|
|
32
|
+
this.moveX(x);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get y () {
|
|
36
|
+
return this.registration.y;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
set y (y) {
|
|
40
|
+
this.moveY(y);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
initialize ({revolutions, rotation = 0, x = 0, y = 0}) {
|
|
44
|
+
this.moveX(x);
|
|
45
|
+
this.moveY(y);
|
|
46
|
+
this.revolutions = revolutions ?? (rotation / PI2);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// "to" castings (toObject must be defined by inheriting classes)
|
|
50
|
+
|
|
51
|
+
toBox2D (...args) {
|
|
52
|
+
return castToBox2D(this, ...args);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
toJSON (options, ...args) {
|
|
56
|
+
return JSON.stringify(this.toObject(options), ...args);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
toObject (options) {
|
|
60
|
+
const
|
|
61
|
+
{type} = this;
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
type,
|
|
65
|
+
...adjustedXY(this, options)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
toPixiShape (...args) {
|
|
70
|
+
return castToPixiShape(this, ...args);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
toPixiGraphics (...args) {
|
|
74
|
+
return castToPixiGraphics(this, ...args);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
move ({x, y}) {
|
|
78
|
+
this.moveX(x);
|
|
79
|
+
this.moveY(y);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
moveX (x) {
|
|
83
|
+
this.registration.x = x;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
moveY (y) {
|
|
87
|
+
this.registration.y = y;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
shift ({x, y}) {
|
|
91
|
+
this.shiftX(x);
|
|
92
|
+
this.shiftY(y);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
shiftX (x) {
|
|
96
|
+
this.moveX(this.x + x);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
shiftY (y) {
|
|
100
|
+
this.moveY(this.y + y);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
checkVisibility (shapes) {
|
|
104
|
+
const
|
|
105
|
+
segments = shapes.reduce((list, shape) => {
|
|
106
|
+
const
|
|
107
|
+
{segments} = shape;
|
|
108
|
+
|
|
109
|
+
if (segments) {
|
|
110
|
+
list.push(...segments);
|
|
111
|
+
} else {
|
|
112
|
+
list.push(shape)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return list;
|
|
116
|
+
}, []);
|
|
117
|
+
|
|
118
|
+
return segments.filter((seg) => {
|
|
119
|
+
// Midpoint of segment
|
|
120
|
+
const
|
|
121
|
+
mid = seg.a && seg.b ? {
|
|
122
|
+
x: (seg.a.x + seg.b.x) / 2,
|
|
123
|
+
y: (seg.a.y + seg.b.y) / 2
|
|
124
|
+
} : seg;
|
|
125
|
+
|
|
126
|
+
return !segments.some((blocker) => (seg !== blocker) && blocker.intersects?.({a: this, b: mid}));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getClosestPoints (shape, offset) {
|
|
131
|
+
let
|
|
132
|
+
closestPoints = null;
|
|
133
|
+
|
|
134
|
+
if (offset?.x ?? offset?.y) {
|
|
135
|
+
const
|
|
136
|
+
offsetShape = shape.duplicate();
|
|
137
|
+
|
|
138
|
+
offsetShape.shift(offset);
|
|
139
|
+
closestPoints = checkPointsMap[offsetShape.type]?.[this.type]?.(offsetShape, this) ?? null;
|
|
140
|
+
//TODO: discard/recycle shape
|
|
141
|
+
} else {
|
|
142
|
+
closestPoints = checkPointsMap[shape.type]?.[this.type]?.(shape, this) ?? null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!closestPoints) {
|
|
146
|
+
platypus.debug.warn(`No closest point support for "${checkPointsMap[shape.type] ? this.type : shape.type}" shapes.`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return closestPoints;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
duplicate () {
|
|
153
|
+
return new Point(this);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getRadians () {
|
|
157
|
+
return this.revolutions * PI2;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
getDegrees () {
|
|
161
|
+
return this.revolutions * 360;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getSinCos () {
|
|
165
|
+
const
|
|
166
|
+
{rotation} = this;
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
sin: Math.sin(rotation),
|
|
170
|
+
cos: Math.cos(rotation)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
toArray (local = false) {
|
|
175
|
+
if (local) {
|
|
176
|
+
const
|
|
177
|
+
{registration: {x, y}} = this;
|
|
178
|
+
|
|
179
|
+
return [x, y];
|
|
180
|
+
} else {
|
|
181
|
+
const
|
|
182
|
+
{x, y} = this;
|
|
183
|
+
|
|
184
|
+
return [x, y];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
static validateDefinition ({x, y} = {}) {
|
|
189
|
+
return typeof x === 'number' && typeof y === 'number' && !isNaN(x) && !isNaN(y);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/* global platypus */
|
|
2
|
+
import Polyline from "./Polyline";
|
|
3
|
+
|
|
4
|
+
const
|
|
5
|
+
MIN_VERTICES = 3,
|
|
6
|
+
MAX_VERTICES = 8,
|
|
7
|
+
SHARED_VERTICES = 2;
|
|
8
|
+
|
|
9
|
+
export default class Polygon extends Polyline {
|
|
10
|
+
constructor (...args) {
|
|
11
|
+
super(...args);
|
|
12
|
+
this.type = 'polygon';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get loop () {
|
|
16
|
+
return true; // Unlike Polyline, this can never not be a loop.
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
set loop (value) {
|
|
20
|
+
if (!value) {
|
|
21
|
+
throw new Error('Polygon shapes are comprised of a loop of segments.');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
initialize (options) {
|
|
26
|
+
super.initialize(options);
|
|
27
|
+
this._loop = true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
isPointInside ({x, y}) {
|
|
31
|
+
const
|
|
32
|
+
{points} = this;
|
|
33
|
+
let inside = false;
|
|
34
|
+
|
|
35
|
+
for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
|
|
36
|
+
const
|
|
37
|
+
a = points[i],
|
|
38
|
+
b = points[j];
|
|
39
|
+
|
|
40
|
+
if ((a.y > y) !== (b.y > y) && x < (b.x - a.x) * (y - a.y) / (b.y - a.y) + a.x) {
|
|
41
|
+
inside = !inside;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return inside;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
duplicate () {
|
|
48
|
+
return new Polygon(this);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
decompose () {
|
|
52
|
+
const
|
|
53
|
+
decomp = platypus.game.options.modules?.['poly-decomp'],
|
|
54
|
+
polygon = this.toArray2D(true);
|
|
55
|
+
|
|
56
|
+
if (decomp?.isSimple(polygon)) {
|
|
57
|
+
return decomp.quickDecomp(polygon).map((points) => new Polygon({
|
|
58
|
+
points
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
split (min = MIN_VERTICES, max = MAX_VERTICES) {
|
|
66
|
+
const
|
|
67
|
+
breakAtMaxSize = min + max - SHARED_VERTICES,
|
|
68
|
+
arr = [],
|
|
69
|
+
convexPolygons = this.decompose() ?? [this]; // break into convex polygons if not already, since splitting a concave polygon could create polygon comprised of non-matching shapes.
|
|
70
|
+
let altSide = 0;
|
|
71
|
+
|
|
72
|
+
convexPolygons.forEach((polygon) => {
|
|
73
|
+
const
|
|
74
|
+
points = [...polygon.points];
|
|
75
|
+
let {length} = points;
|
|
76
|
+
|
|
77
|
+
while (length > max) {
|
|
78
|
+
const
|
|
79
|
+
count = (length >= breakAtMaxSize) ? max : Math.ceil(length / 2),
|
|
80
|
+
deleteCount = count - SHARED_VERTICES,
|
|
81
|
+
breakOff = points.splice((altSide - 1) * deleteCount, altSide ? deleteCount : Infinity);
|
|
82
|
+
|
|
83
|
+
breakOff.push(points[points.length - 1], points[0]);
|
|
84
|
+
|
|
85
|
+
arr.push(new Polygon({
|
|
86
|
+
points: breakOff
|
|
87
|
+
}));
|
|
88
|
+
|
|
89
|
+
altSide = 1 - altSide;
|
|
90
|
+
length = points.length;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
arr.push(new Polygon({
|
|
94
|
+
points
|
|
95
|
+
}));
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return arr;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static validateDefinition (definition = {}) {
|
|
102
|
+
const
|
|
103
|
+
{points} = definition,
|
|
104
|
+
{length = 0} = points ?? [];
|
|
105
|
+
|
|
106
|
+
if (length < 3) {
|
|
107
|
+
return false;
|
|
108
|
+
} else {
|
|
109
|
+
return Polyline.validateDefinition(definition);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|