core2d 2.10.2

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/src/Sprite.mjs ADDED
@@ -0,0 +1,368 @@
1
+ "use strict";
2
+
3
+ import { Animation } from "./Animation.mjs";
4
+ import { Direction } from "./Direction.mjs";
5
+ import { Frame } from "./Frame.mjs";
6
+ import { Rect } from "./Rect.mjs";
7
+ import { Static } from "./Static.mjs";
8
+
9
+ export class Sprite extends Rect {
10
+ constructor() {
11
+ super();
12
+ this.accelerationX = 0;
13
+ this.accelerationY = 0;
14
+ this.alpha = 1;
15
+ this.boundary = null;
16
+ this.color = null;
17
+ this.essential = false;
18
+ this.expiration = 0;
19
+ this.expired = false;
20
+ this.layerIndex = 0;
21
+ this.maxSpeedX = 0;
22
+ this.maxSpeedY = 0;
23
+ this.solid = false;
24
+ this.speedX = 0;
25
+ this.speedY = 0;
26
+ this.visible = true;
27
+ this._animation = null;
28
+ this._lastSpeedX = 0;
29
+ this._lastSpeedY = 0;
30
+ this._lastX = this.x;
31
+ this._lastY = this.y;
32
+ this._tags = {};
33
+ this._tick = 0;
34
+ }
35
+
36
+ get angle() {
37
+ return Static.toDegrees(Math.atan2(this.speedY, this.speedX));
38
+ }
39
+
40
+ get direction() {
41
+ const DIRECTION = new Direction();
42
+
43
+ if (this.x < this._lastX) {
44
+ DIRECTION.setLeft();
45
+ } else if (this.x > this._lastX) {
46
+ DIRECTION.setRight();
47
+ }
48
+
49
+ if (this.y < this._lastY) {
50
+ DIRECTION.setTop();
51
+ } else if (this.y > this._lastY) {
52
+ DIRECTION.setBottom();
53
+ }
54
+
55
+ return DIRECTION;
56
+ }
57
+
58
+ get image() {
59
+ return this._animation && this._animation.image;
60
+ }
61
+
62
+ get tick() {
63
+ return this._tick;
64
+ }
65
+
66
+ setAccelerationX(accelerationX = 0) {
67
+ this.accelerationX = accelerationX;
68
+ return this;
69
+ }
70
+
71
+ setAccelerationY(accelerationY = 0) {
72
+ this.accelerationY = accelerationY;
73
+ return this;
74
+ }
75
+
76
+ setAlpha(alpha = 1) {
77
+ this.alpha = alpha;
78
+ return this;
79
+ }
80
+
81
+ setBoundary(rect = null) {
82
+ this.boundary = rect || this.scene;
83
+ return this;
84
+ }
85
+
86
+ setColor(color) {
87
+ this.color = color;
88
+ return this;
89
+ }
90
+
91
+ setEssential(isEssential = true) {
92
+ this.essential = isEssential;
93
+ return this;
94
+ }
95
+
96
+ setExpiration(expiration = 0) {
97
+ this.expiration = expiration;
98
+ return this;
99
+ }
100
+
101
+ setExpired(isExpired = true) {
102
+ this.expired = isExpired;
103
+ return this;
104
+ }
105
+
106
+ setLayerIndex(layerIndex = 0) {
107
+ this.layerIndex = layerIndex;
108
+ return this;
109
+ }
110
+
111
+ setMaxSpeedX(maxSpeedX = 0) {
112
+ this.maxSpeedX = maxSpeedX;
113
+ return this;
114
+ }
115
+
116
+ setMaxSpeedY(maxSpeedY = 0) {
117
+ this.maxSpeedY = maxSpeedY;
118
+ return this;
119
+ }
120
+
121
+ setSolid(isSolid = true) {
122
+ this.solid = isSolid;
123
+ return this;
124
+ }
125
+
126
+ setSpeedX(speedX = 0) {
127
+ this.speedX = speedX;
128
+ return this;
129
+ }
130
+
131
+ setSpeedY(speedY = 0) {
132
+ this.speedY = speedY;
133
+ return this;
134
+ }
135
+
136
+ setVisible(isVisible = true) {
137
+ this.visible = isVisible;
138
+ return this;
139
+ }
140
+
141
+ setAnimation(animation) {
142
+ if (animation == this._animation) {
143
+ return this;
144
+ }
145
+
146
+ this._animation = animation;
147
+ this._animation.setFrameIndex(0);
148
+ this.height = this._animation.height;
149
+ this.width = this._animation.width;
150
+ return this;
151
+ }
152
+
153
+ setImage(image) {
154
+ this.setAnimation(new Animation([new Frame(image)]));
155
+ return this;
156
+ }
157
+
158
+ set image(image) {
159
+ this.setImage(image);
160
+ }
161
+
162
+ setSpeedToAngle(speed, degrees) {
163
+ const RADIANS = Static.toRadians(degrees);
164
+ this.setSpeedX(speed * Math.cos(RADIANS));
165
+ this.setSpeedY(speed * Math.sin(RADIANS));
166
+ return this;
167
+ }
168
+
169
+ setSpeedToPoint(speed, point) {
170
+ const SQUARE_DISTANCE = Math.abs(this.centerX - point.x) + Math.abs(this.centerY - point.y);
171
+ this.setSpeedX((point.x - this.centerX) * speed / SQUARE_DISTANCE);
172
+ this.setSpeedY((point.y - this.centerY) * speed / SQUARE_DISTANCE);
173
+ return this;
174
+ }
175
+
176
+ addTag(tag) {
177
+ this._tags[tag] = true;
178
+ return this;
179
+ }
180
+
181
+ bounceFrom(direction) {
182
+ if ((this.speedX < 0 && direction.left) || (this.speedX > 0 && direction.right)) {
183
+ this.bounceX();
184
+ }
185
+
186
+ if ((this.speedY < 0 && direction.top) || (this.speedY > 0 && direction.bottom)) {
187
+ this.bounceY();
188
+ }
189
+
190
+ return this;
191
+ }
192
+
193
+ bounceX() {
194
+ this.setSpeedX(this.speedX * -1);
195
+ this.x += this.speedX;
196
+ return this;
197
+ }
198
+
199
+ bounceY() {
200
+ this.setSpeedY(this.speedY * -1);
201
+ this.y += this.speedY;
202
+ return this;
203
+ }
204
+
205
+ expire() {
206
+ this.expired = true;
207
+ }
208
+
209
+ getCollision(sprite) {
210
+ const DIRECTION = new Direction();
211
+ const TA = this.top;
212
+ const RA = this.right;
213
+ const BA = this.bottom;
214
+ const LA = this.left;
215
+ const XA = this.centerX;
216
+ const YA = this.centerY;
217
+ const TB = sprite.top;
218
+ const RB = sprite.right;
219
+ const BB = sprite.bottom;
220
+ const LB = sprite.left;
221
+
222
+ if (XA <= LB && RA < RB) {
223
+ DIRECTION.setRight();
224
+ } else if (XA >= RB && LA > LB) {
225
+ DIRECTION.setLeft();
226
+ }
227
+
228
+ if (YA <= TB && BA < BB) {
229
+ DIRECTION.setBottom();
230
+ } else if (YA >= BB && TA > TB) {
231
+ DIRECTION.setTop();
232
+ }
233
+
234
+ return DIRECTION;
235
+ }
236
+
237
+ hasCollision(rect) {
238
+ return !(
239
+ this.left > rect.right ||
240
+ this.right < rect.left ||
241
+ this.top > rect.bottom ||
242
+ this.bottom < rect.top
243
+ );
244
+ }
245
+
246
+ hasTag(tag) {
247
+ return this._tags[tag];
248
+ }
249
+
250
+ init() {
251
+ // no default behavior
252
+ }
253
+
254
+ offBoundary() {
255
+ this.setExpired();
256
+ }
257
+
258
+ onAnimationLoop() {
259
+ // no default behavior
260
+ }
261
+
262
+ onCollision(sprite) {
263
+ // no default behavior
264
+ return sprite;
265
+ }
266
+
267
+ pause() {
268
+ this._lastSpeedX = this.speedX;
269
+ this._lastSpeedY = this.speedY;
270
+ this.speedX = 0;
271
+ this.speedY = 0;
272
+ return this;
273
+ }
274
+
275
+ render(context) {
276
+ if (!this.visible) {
277
+ return false;
278
+ }
279
+
280
+ const X = Math.floor(this.x + this.scene.x);
281
+ const Y = Math.floor(this.y + this.scene.y);
282
+
283
+ if (this.alpha < 1) {
284
+ context.globalAlpha = this.alpha;
285
+ }
286
+
287
+ if (this.color) {
288
+ context.fillStyle = this.color;
289
+ context.fillRect(X, Y, this.width, this.height);
290
+ }
291
+
292
+ if (this._animation) {
293
+ context.drawImage(this._animation.image, X, Y, this.width, this.height);
294
+ }
295
+
296
+ if (this.alpha < 1) {
297
+ context.globalAlpha = 1;
298
+ }
299
+
300
+ return true;
301
+ }
302
+
303
+ resume() {
304
+ this.speedX = this._lastSpeedX;
305
+ this.speedY = this._lastSpeedY;
306
+ return this;
307
+ }
308
+
309
+ stop() {
310
+ this._lastSpeedX = 0;
311
+ this._lastSpeedY = 0;
312
+ this.speedX = 0;
313
+ this.speedY = 0;
314
+ }
315
+
316
+ sync() {
317
+ this._lastX = this.x;
318
+ this._lastY = this.y;
319
+ this.update();
320
+
321
+ if (++this._tick == this.expiration) {
322
+ this.setExpired();
323
+ }
324
+
325
+ if (this.expired) {
326
+ return true;
327
+ }
328
+
329
+ if (this._animation && this._animation.sync()) {
330
+ this.onAnimationLoop();
331
+ }
332
+
333
+ this.x += this.speedX;
334
+ this.y += this.speedY;
335
+ this.speedX += this.accelerationX;
336
+ this.speedY += this.accelerationY;
337
+
338
+ if (this.maxSpeedX && Math.abs(this.speedX) > this.maxSpeedX) {
339
+ const SIGNAL = this.speedX / Math.abs(this.speedX);
340
+ this.speedX = this.maxSpeedX * SIGNAL;
341
+ }
342
+
343
+ if (this.maxSpeedY && Math.abs(this.speedY) > this.maxSpeedY) {
344
+ const SIGNAL = this.speedY / Math.abs(this.speedY);
345
+ this.speedY = this.maxSpeedY * SIGNAL;
346
+ }
347
+
348
+ if (this.boundary && !this.hasCollision(this.boundary)) {
349
+ this.offBoundary();
350
+ }
351
+
352
+ return false;
353
+ }
354
+
355
+ update() {
356
+ // no default behavior
357
+ }
358
+
359
+ zoom(ratio) {
360
+ const widthChange = this.width * ratio;
361
+ this.width += widthChange;
362
+ this.x -= widthChange / 2;
363
+ const heightChange = this.height * ratio;
364
+ this.height += heightChange;
365
+ this.y -= heightChange / 2;
366
+ return this;
367
+ }
368
+ }
package/src/Static.mjs ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ import { ACL } from "./ACL.mjs";
4
+
5
+ export class Static {
6
+ static checkCollisions(sprites) {
7
+ const LENGTH = sprites.length;
8
+
9
+ for (let i = 0; i < LENGTH - 1; ++i) {
10
+ const LEFT_SPRITE = sprites[i];
11
+
12
+ for (let j = i + 1; j < LENGTH; ++j) {
13
+ const RIGHT_SPRITE = sprites[j];
14
+
15
+ if (LEFT_SPRITE.hasCollision(RIGHT_SPRITE)) {
16
+ LEFT_SPRITE.collided = true;
17
+ LEFT_SPRITE.onCollision(RIGHT_SPRITE);
18
+ RIGHT_SPRITE.collided = true;
19
+ RIGHT_SPRITE.onCollision(LEFT_SPRITE);
20
+ }
21
+ }
22
+ }
23
+ }
24
+
25
+ static getElement(id) {
26
+ const element = ACL.document.getElementById(id);
27
+
28
+ if (!element) {
29
+ console.warn(`Could not find element with id: ${id}`);
30
+ }
31
+
32
+ return element;
33
+ }
34
+
35
+ static getElements(name) {
36
+ return Array.from(ACL.document.getElementsByTagName(name));
37
+ }
38
+
39
+ static getGamepads() {
40
+ if (!navigator.getGamepads) {
41
+ return [];
42
+ }
43
+
44
+ return navigator.getGamepads();
45
+ }
46
+
47
+ static getImage(image) {
48
+ if ("string" == typeof(image)) {
49
+ return this.getElement(image);
50
+ }
51
+
52
+ return image;
53
+ }
54
+
55
+ static makeEnum(array) {
56
+ return this.makeHash(array, true);
57
+ }
58
+
59
+ static makeHash(array, indexed) {
60
+ const RESULT = {};
61
+
62
+ for (let i = 0; i < array.length; ++i) {
63
+ const VALUE = array[i];
64
+ RESULT[VALUE] = indexed ? i : VALUE;
65
+ }
66
+
67
+ return RESULT;
68
+ }
69
+
70
+ static toDegrees(radians) {
71
+ return radians * 180 / Math.PI;
72
+ }
73
+
74
+ static toRadians(degrees) {
75
+ return degrees * Math.PI / 180;
76
+ }
77
+ }
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+
3
+ import { ACL } from "./ACL.mjs";
4
+ import { Color } from "./Color.mjs";
5
+ import { FontFamily } from "./FontFamily.mjs";
6
+ import { Sprite } from "./Sprite.mjs";
7
+
8
+ const hiddenCanvas = ACL.document.createElement("canvas");
9
+ const hiddenContext = hiddenCanvas.getContext("2d");
10
+
11
+ export class TextSprite extends Sprite {
12
+ constructor(text = "") {
13
+ super();
14
+ this._text = text;
15
+ this._fontFamily = FontFamily.Monospace;
16
+ this._fontSize = 16;
17
+ this.fontColor = Color.White;
18
+ this.lineWidth = 0;
19
+ this.shadowBlur = 0;
20
+ this.shadowColor = null;
21
+ this.shadowOffsetX = 0;
22
+ this.shadowOffsetY = 0;
23
+ this.strokeStyle = null;
24
+ this._updateFont();
25
+ }
26
+
27
+ render(context) {
28
+ if (Sprite.prototype.render.call(this, context)) {
29
+ context.fillStyle = this.fontColor;
30
+ context.font = this._font;
31
+ context.textBaseline = "top";
32
+
33
+ if (this.shadowColor) {
34
+ context.shadowColor = this.shadowColor;
35
+ context.shadowOffsetX = this.shadowOffsetX;
36
+ context.shadowOffsetY = this.shadowOffsetY;
37
+ context.shadowBlur = this.shadowBlur;
38
+ }
39
+
40
+ context.fillText(this._text, this.left + this.scene.x, this.bottom + this.scene.y, this.width);
41
+
42
+ if (this.shadowColor) {
43
+ context.shadowColor = null;
44
+ context.shadowOffsetX = 0;
45
+ context.shadowOffsetY = 0;
46
+ context.shadowBlur = 0;
47
+ }
48
+
49
+ if (this.strokeStyle) {
50
+ context.lineWidth = this.lineWidth;
51
+ context.strokeStyle = this.strokeStyle;
52
+ context.strokeText(this._text, this.left + this.scene.x, this.bottom + this.scene.y, this.width);
53
+ context.lineWidth = 0;
54
+ context.strokeStyle = null;
55
+ }
56
+ }
57
+ }
58
+
59
+ setFontColor(fontColor) {
60
+ this.fontColor = fontColor;
61
+ return this;
62
+ }
63
+
64
+ setFontFamily(fontFamily) {
65
+ this._fontFamily = fontFamily;
66
+ this._updateFont();
67
+ return this;
68
+ }
69
+
70
+ setFontSize(fontSize) {
71
+ this._fontSize = fontSize;
72
+ this.height = fontSize;
73
+ this._updateFont();
74
+ return this;
75
+ }
76
+
77
+ setLineWidth(lineWidth) {
78
+ this.lineWidth = lineWidth;
79
+ return this;
80
+ }
81
+
82
+ setShadowBlur(shadowBlur) {
83
+ this.shadowBlur = shadowBlur;
84
+ return this;
85
+ }
86
+
87
+ setShadowColor(shadowColor) {
88
+ this.shadowColor = shadowColor;
89
+ return this;
90
+ }
91
+
92
+ setShadowOffsetX(shadowOffsetX) {
93
+ this.shadowOffsetX = shadowOffsetX;
94
+ return this;
95
+ }
96
+
97
+ setShadowOffsetY(shadowOffsetY) {
98
+ this.shadowOffsetY = shadowOffsetY;
99
+ return this;
100
+ }
101
+
102
+ setStrokeStyle(strokeStyle) {
103
+ this.strokeStyle = strokeStyle;
104
+ return this;
105
+ }
106
+
107
+ setText(text) {
108
+ this._text = text;
109
+ this._updateFont();
110
+ return this;
111
+ }
112
+
113
+ get fontFamily() {
114
+ return this._fontFamily;
115
+ }
116
+
117
+ get fontSize() {
118
+ return this._fontSize;
119
+ }
120
+
121
+ get text() {
122
+ return this._text;
123
+ }
124
+
125
+ set fontFamily(fontFamily) {
126
+ this.setFontFamily(fontFamily);
127
+ }
128
+
129
+ set fontSize(fontSize) {
130
+ this.setFontSize(fontSize);
131
+ }
132
+
133
+ set text(text) {
134
+ this.setText(text);
135
+ }
136
+
137
+ _updateFont() {
138
+ this._font = `${this._fontSize}px ${this._fontFamily}`;
139
+ hiddenContext.textBaseline = "top";
140
+ hiddenContext.font = this._font;
141
+ const measurement = hiddenContext.measureText(this._text);
142
+ this.width = measurement.width;
143
+ }
144
+ }
package/src/Touch.mjs ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ import { Point } from "./Point.mjs";
4
+
5
+ export class Touch extends Point {
6
+ constructor(event) {
7
+ super();
8
+ event.preventDefault();
9
+ this._isDown = true;
10
+ this.updateCoordinates(event);
11
+
12
+ addEventListener("touchend", (event) => {
13
+ event.preventDefault();
14
+ this._isDown = false;
15
+ this.updateCoordinates(event);
16
+ }, false);
17
+
18
+ addEventListener("touchmove", (event) => {
19
+ event.preventDefault();
20
+ this.updateCoordinates(event);
21
+ }, false);
22
+
23
+ addEventListener("touchstart", () => {
24
+ event.preventDefault();
25
+ this._isDown = true;
26
+ this.updateCoordinates(event);
27
+ }, false);
28
+ }
29
+
30
+ get command() {
31
+ return this._isDown;
32
+ }
33
+
34
+ updateCoordinates(event) {
35
+ const TOUCHES = event.changedTouches;
36
+ const TOUCH = TOUCHES[0];
37
+ this.x = TOUCH.pageX;
38
+ this.y = TOUCH.pageY;
39
+ }
40
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ import { Color } from "./Color.mjs";
4
+ import { Sprite } from "./Sprite.mjs";
5
+
6
+ export class Transition extends Sprite {
7
+ init() {
8
+ this.setColor(Color.Black);
9
+ this.setHeight(this.scene.height);
10
+ this._increase = this.scene.width / 32;
11
+ }
12
+
13
+ sync() {
14
+ if (this.width > this.scene.width) {
15
+ return true;
16
+ }
17
+
18
+ this.width += this._increase;
19
+ return Sprite.prototype.sync.call(this);
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ import { Sprite } from "../Sprite.mjs";
4
+
5
+ export class BaseTile extends Sprite {
6
+ constructor(id) {
7
+ super();
8
+ this.setImage(id);
9
+ }
10
+ }
@@ -0,0 +1,24 @@
1
+ "use static";
2
+
3
+ import { Sprite } from "../Sprite.mjs";
4
+
5
+ export class ClickableSprite extends Sprite {
6
+ constructor() {
7
+ super();
8
+ this.addTag("clickable");
9
+ this.setSolid();
10
+ }
11
+
12
+ onClick() {
13
+ // no default behavior
14
+ }
15
+
16
+ onHoverIn() {
17
+ // no default behavior
18
+ }
19
+
20
+ onHoverOut() {
21
+ // no default behavior
22
+ }
23
+ }
24
+
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ import { Command } from "../Command.mjs";
4
+ import { Core2D } from "../Core2D.mjs";
5
+ import { Sprite } from "../Sprite.mjs";
6
+
7
+ export class ControllableSprite extends Sprite {
8
+ constructor() {
9
+ super();
10
+ this.controller = Core2D.getController();
11
+ this.step = 2;
12
+ }
13
+
14
+ setStep(step) {
15
+ this.step = step;
16
+ return this;
17
+ }
18
+
19
+ sync() {
20
+ if (this.controller.keyDown(Command.LEFT) && this.left > 0) {
21
+ this.x -= this.step;
22
+ }
23
+
24
+ if (this.controller.keyDown(Command.RIGHT) && this.right < this.scene.width) {
25
+ this.x += this.step;
26
+ }
27
+
28
+ if (this.controller.keyDown(Command.UP) && this.top > 0) {
29
+ this.y -= this.step;
30
+ }
31
+
32
+ if (this.controller.keyDown(Command.DOWN) && this.bottom < this.scene.height) {
33
+ this.y += this.step;
34
+ }
35
+
36
+ return Sprite.prototype.sync.call(this);
37
+ }
38
+ }