minimojs 1.0.0-alpha.15 → 1.0.0-alpha.16
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/dist/internal/PhysicsSystem.js +12 -12
- package/dist/internal/RenderSystem.js +54 -0
- package/dist/minimo.d.ts +60 -0
- package/dist/minimo.js +86 -0
- package/package.json +1 -1
|
@@ -37,12 +37,12 @@ export class PhysicsSystem {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
overlap(a, b) {
|
|
40
|
-
const halfWidthA = a.
|
|
41
|
-
const halfHeightA = a.
|
|
42
|
-
const halfWidthB = b.
|
|
43
|
-
const halfHeightB = b.
|
|
44
|
-
return (Math.abs(a.
|
|
45
|
-
Math.abs(a.
|
|
40
|
+
const halfWidthA = a.bodyDisplayWidth / 2;
|
|
41
|
+
const halfHeightA = a.bodyDisplayHeight / 2;
|
|
42
|
+
const halfWidthB = b.bodyDisplayWidth / 2;
|
|
43
|
+
const halfHeightB = b.bodyDisplayHeight / 2;
|
|
44
|
+
return (Math.abs(a.bodyCenterX - b.bodyCenterX) < halfWidthA + halfWidthB &&
|
|
45
|
+
Math.abs(a.bodyCenterY - b.bodyCenterY) < halfHeightA + halfHeightB);
|
|
46
46
|
}
|
|
47
47
|
overlapAny(listA, listB) {
|
|
48
48
|
for (const a of listA) {
|
|
@@ -100,12 +100,12 @@ export class PhysicsSystem {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
getCollisionResolution(a, b) {
|
|
103
|
-
const halfWidthA = a.
|
|
104
|
-
const halfHeightA = a.
|
|
105
|
-
const halfWidthB = b.
|
|
106
|
-
const halfHeightB = b.
|
|
107
|
-
const dx = b.
|
|
108
|
-
const dy = b.
|
|
103
|
+
const halfWidthA = a.bodyDisplayWidth / 2;
|
|
104
|
+
const halfHeightA = a.bodyDisplayHeight / 2;
|
|
105
|
+
const halfWidthB = b.bodyDisplayWidth / 2;
|
|
106
|
+
const halfHeightB = b.bodyDisplayHeight / 2;
|
|
107
|
+
const dx = b.bodyCenterX - a.bodyCenterX;
|
|
108
|
+
const dy = b.bodyCenterY - a.bodyCenterY;
|
|
109
109
|
const overlapX = halfWidthA + halfWidthB - Math.abs(dx);
|
|
110
110
|
const overlapY = halfHeightA + halfHeightB - Math.abs(dy);
|
|
111
111
|
if (overlapX <= 0 || overlapY <= 0) {
|
|
@@ -196,6 +196,60 @@ export class RenderSystem {
|
|
|
196
196
|
ctx.fillText(entry.text, entry.x, entry.y);
|
|
197
197
|
ctx.restore();
|
|
198
198
|
}
|
|
199
|
+
if (options.debugBodies) {
|
|
200
|
+
this.drawBodyDebugOverlay(ctx, sorted, options.scrollX, options.scrollY);
|
|
201
|
+
}
|
|
202
|
+
if (options.debugInputAreas) {
|
|
203
|
+
this.drawInputDebugOverlay(ctx, sorted, options.scrollX, options.scrollY);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
drawBodyDebugOverlay(ctx, sprites, scrollX, scrollY) {
|
|
207
|
+
ctx.save();
|
|
208
|
+
ctx.setLineDash([6, 4]);
|
|
209
|
+
ctx.lineWidth = 2;
|
|
210
|
+
for (const sprite of sprites) {
|
|
211
|
+
const halfWidth = sprite.bodyDisplayWidth / 2;
|
|
212
|
+
const halfHeight = sprite.bodyDisplayHeight / 2;
|
|
213
|
+
const centerX = sprite.ignoreScroll ? sprite.bodyCenterX : sprite.bodyCenterX - scrollX;
|
|
214
|
+
const centerY = sprite.ignoreScroll ? sprite.bodyCenterY : sprite.bodyCenterY - scrollY;
|
|
215
|
+
const left = Math.round(centerX - halfWidth) + 0.5;
|
|
216
|
+
const top = Math.round(centerY - halfHeight) + 0.5;
|
|
217
|
+
const width = Math.max(1, Math.round(sprite.bodyDisplayWidth) - 1);
|
|
218
|
+
const height = Math.max(1, Math.round(sprite.bodyDisplayHeight) - 1);
|
|
219
|
+
const stroke = sprite.isStatic
|
|
220
|
+
? 'rgba(0, 217, 255, 0.95)'
|
|
221
|
+
: 'rgba(255, 77, 109, 0.95)';
|
|
222
|
+
const fill = sprite.isStatic
|
|
223
|
+
? 'rgba(0, 217, 255, 0.12)'
|
|
224
|
+
: 'rgba(255, 77, 109, 0.12)';
|
|
225
|
+
ctx.strokeStyle = stroke;
|
|
226
|
+
ctx.fillStyle = fill;
|
|
227
|
+
ctx.fillRect(left, top, width, height);
|
|
228
|
+
ctx.strokeRect(left, top, width, height);
|
|
229
|
+
}
|
|
230
|
+
ctx.restore();
|
|
231
|
+
}
|
|
232
|
+
drawInputDebugOverlay(ctx, sprites, scrollX, scrollY) {
|
|
233
|
+
ctx.save();
|
|
234
|
+
ctx.setLineDash([3, 5]);
|
|
235
|
+
ctx.lineWidth = 2;
|
|
236
|
+
for (const sprite of sprites) {
|
|
237
|
+
const halfWidth = sprite.displayWidth / 2;
|
|
238
|
+
const halfHeight = sprite.displayHeight / 2;
|
|
239
|
+
const centerX = sprite.ignoreScroll ? sprite.renderX : sprite.renderX - scrollX;
|
|
240
|
+
const centerY = sprite.ignoreScroll ? sprite.renderY : sprite.renderY - scrollY;
|
|
241
|
+
const left = Math.round(centerX - halfWidth) + 0.5;
|
|
242
|
+
const top = Math.round(centerY - halfHeight) + 0.5;
|
|
243
|
+
const width = Math.max(1, Math.round(sprite.displayWidth) - 1);
|
|
244
|
+
const height = Math.max(1, Math.round(sprite.displayHeight) - 1);
|
|
245
|
+
const stroke = "rgba(255, 196, 0, 0.98)";
|
|
246
|
+
const fill = "rgba(255, 196, 0, 0.10)";
|
|
247
|
+
ctx.strokeStyle = stroke;
|
|
248
|
+
ctx.fillStyle = fill;
|
|
249
|
+
ctx.fillRect(left, top, width, height);
|
|
250
|
+
ctx.strokeRect(left, top, width, height);
|
|
251
|
+
}
|
|
252
|
+
ctx.restore();
|
|
199
253
|
}
|
|
200
254
|
renderLoadingScreen(options) {
|
|
201
255
|
const ctx = options.context;
|
package/dist/minimo.d.ts
CHANGED
|
@@ -252,6 +252,52 @@ export declare abstract class BaseSprite {
|
|
|
252
252
|
* Effective rendered/collision height in pixels.
|
|
253
253
|
*/
|
|
254
254
|
get displayHeight(): number;
|
|
255
|
+
/**
|
|
256
|
+
* Optional logical body width used by physics helpers and collision checks.
|
|
257
|
+
*
|
|
258
|
+
* When `null` (default), MinimoJS uses the sprite's visual {@link BaseSprite.width}.
|
|
259
|
+
* When set, this value is scaled by {@link BaseSprite.scale} the same way as the
|
|
260
|
+
* visual sprite size.
|
|
261
|
+
*/
|
|
262
|
+
bodyWidth: number | null;
|
|
263
|
+
/**
|
|
264
|
+
* Optional logical body height used by physics helpers and collision checks.
|
|
265
|
+
*
|
|
266
|
+
* When `null` (default), MinimoJS uses the sprite's visual {@link BaseSprite.height}.
|
|
267
|
+
* When set, this value is scaled by {@link BaseSprite.scale} the same way as the
|
|
268
|
+
* visual sprite size.
|
|
269
|
+
*/
|
|
270
|
+
bodyHeight: number | null;
|
|
271
|
+
/**
|
|
272
|
+
* Horizontal body offset, in local sprite pixels before scale is applied.
|
|
273
|
+
*
|
|
274
|
+
* Positive values move the collision body to the right of the sprite's rendered center.
|
|
275
|
+
* Negative values move it to the left.
|
|
276
|
+
*/
|
|
277
|
+
bodyOffsetX: number;
|
|
278
|
+
/**
|
|
279
|
+
* Vertical body offset, in local sprite pixels before scale is applied.
|
|
280
|
+
*
|
|
281
|
+
* Positive values move the collision body downward relative to the sprite's
|
|
282
|
+
* rendered center. Negative values move it upward.
|
|
283
|
+
*/
|
|
284
|
+
bodyOffsetY: number;
|
|
285
|
+
/**
|
|
286
|
+
* Effective collision-body width in pixels after applying {@link BaseSprite.scale}.
|
|
287
|
+
*/
|
|
288
|
+
get bodyDisplayWidth(): number;
|
|
289
|
+
/**
|
|
290
|
+
* Effective collision-body height in pixels after applying {@link BaseSprite.scale}.
|
|
291
|
+
*/
|
|
292
|
+
get bodyDisplayHeight(): number;
|
|
293
|
+
/**
|
|
294
|
+
* Resolved body center X used internally by physics helpers and collision checks.
|
|
295
|
+
*/
|
|
296
|
+
get bodyCenterX(): number;
|
|
297
|
+
/**
|
|
298
|
+
* Resolved body center Y used internally by physics helpers and collision checks.
|
|
299
|
+
*/
|
|
300
|
+
get bodyCenterY(): number;
|
|
255
301
|
/**
|
|
256
302
|
* CSS text color used when rendering this sprite.
|
|
257
303
|
*
|
|
@@ -982,6 +1028,20 @@ export declare class Game {
|
|
|
982
1028
|
from: string;
|
|
983
1029
|
to: string;
|
|
984
1030
|
} | null;
|
|
1031
|
+
/**
|
|
1032
|
+
* When `true`, MinimoJS draws every sprite's collision body as an overlay.
|
|
1033
|
+
*
|
|
1034
|
+
* This is a runtime debugging aid only. It does not change collisions,
|
|
1035
|
+
* input, rendering order, or physics behavior.
|
|
1036
|
+
*/
|
|
1037
|
+
debugBodies: boolean;
|
|
1038
|
+
/**
|
|
1039
|
+
* When `true`, MinimoJS draws every sprite's input area as an overlay.
|
|
1040
|
+
*
|
|
1041
|
+
* This is a runtime debugging aid only. It does not change input behavior,
|
|
1042
|
+
* physics, or rendering.
|
|
1043
|
+
*/
|
|
1044
|
+
debugInputAreas: boolean;
|
|
985
1045
|
/**
|
|
986
1046
|
* Background color for the full web page (`document.body`).
|
|
987
1047
|
* Set to any valid CSS color string. Default: `null` (engine leaves page background unchanged).
|
package/dist/minimo.js
CHANGED
|
@@ -53,6 +53,36 @@ export class BaseSprite {
|
|
|
53
53
|
this.scale = 1;
|
|
54
54
|
/** @internal */
|
|
55
55
|
this._renderData = null;
|
|
56
|
+
/**
|
|
57
|
+
* Optional logical body width used by physics helpers and collision checks.
|
|
58
|
+
*
|
|
59
|
+
* When `null` (default), MinimoJS uses the sprite's visual {@link BaseSprite.width}.
|
|
60
|
+
* When set, this value is scaled by {@link BaseSprite.scale} the same way as the
|
|
61
|
+
* visual sprite size.
|
|
62
|
+
*/
|
|
63
|
+
this.bodyWidth = null;
|
|
64
|
+
/**
|
|
65
|
+
* Optional logical body height used by physics helpers and collision checks.
|
|
66
|
+
*
|
|
67
|
+
* When `null` (default), MinimoJS uses the sprite's visual {@link BaseSprite.height}.
|
|
68
|
+
* When set, this value is scaled by {@link BaseSprite.scale} the same way as the
|
|
69
|
+
* visual sprite size.
|
|
70
|
+
*/
|
|
71
|
+
this.bodyHeight = null;
|
|
72
|
+
/**
|
|
73
|
+
* Horizontal body offset, in local sprite pixels before scale is applied.
|
|
74
|
+
*
|
|
75
|
+
* Positive values move the collision body to the right of the sprite's rendered center.
|
|
76
|
+
* Negative values move it to the left.
|
|
77
|
+
*/
|
|
78
|
+
this.bodyOffsetX = 0;
|
|
79
|
+
/**
|
|
80
|
+
* Vertical body offset, in local sprite pixels before scale is applied.
|
|
81
|
+
*
|
|
82
|
+
* Positive values move the collision body downward relative to the sprite's
|
|
83
|
+
* rendered center. Negative values move it upward.
|
|
84
|
+
*/
|
|
85
|
+
this.bodyOffsetY = 0;
|
|
56
86
|
/**
|
|
57
87
|
* CSS text color used when rendering this sprite.
|
|
58
88
|
*
|
|
@@ -179,6 +209,44 @@ export class BaseSprite {
|
|
|
179
209
|
const safeScale = Number.isFinite(this.scale) ? this.scale : 1;
|
|
180
210
|
return this.height * Math.max(0, safeScale);
|
|
181
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Effective collision-body width in pixels after applying {@link BaseSprite.scale}.
|
|
214
|
+
*/
|
|
215
|
+
get bodyDisplayWidth() {
|
|
216
|
+
const safeScale = Number.isFinite(this.scale) ? this.scale : 1;
|
|
217
|
+
const baseWidth = typeof this.bodyWidth === "number" &&
|
|
218
|
+
Number.isFinite(this.bodyWidth) &&
|
|
219
|
+
this.bodyWidth > 0
|
|
220
|
+
? this.bodyWidth
|
|
221
|
+
: this.width;
|
|
222
|
+
return baseWidth * Math.max(0, safeScale);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Effective collision-body height in pixels after applying {@link BaseSprite.scale}.
|
|
226
|
+
*/
|
|
227
|
+
get bodyDisplayHeight() {
|
|
228
|
+
const safeScale = Number.isFinite(this.scale) ? this.scale : 1;
|
|
229
|
+
const baseHeight = typeof this.bodyHeight === "number" &&
|
|
230
|
+
Number.isFinite(this.bodyHeight) &&
|
|
231
|
+
this.bodyHeight > 0
|
|
232
|
+
? this.bodyHeight
|
|
233
|
+
: this.height;
|
|
234
|
+
return baseHeight * Math.max(0, safeScale);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Resolved body center X used internally by physics helpers and collision checks.
|
|
238
|
+
*/
|
|
239
|
+
get bodyCenterX() {
|
|
240
|
+
const safeScale = Number.isFinite(this.scale) ? this.scale : 1;
|
|
241
|
+
return this.renderX + this.bodyOffsetX * Math.max(0, safeScale);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Resolved body center Y used internally by physics helpers and collision checks.
|
|
245
|
+
*/
|
|
246
|
+
get bodyCenterY() {
|
|
247
|
+
const safeScale = Number.isFinite(this.scale) ? this.scale : 1;
|
|
248
|
+
return this.renderY + this.bodyOffsetY * Math.max(0, safeScale);
|
|
249
|
+
}
|
|
182
250
|
getAnchorOffsetX() {
|
|
183
251
|
return 0;
|
|
184
252
|
}
|
|
@@ -1053,6 +1121,20 @@ export class Game {
|
|
|
1053
1121
|
* ```
|
|
1054
1122
|
*/
|
|
1055
1123
|
this.backgroundGradient = null;
|
|
1124
|
+
/**
|
|
1125
|
+
* When `true`, MinimoJS draws every sprite's collision body as an overlay.
|
|
1126
|
+
*
|
|
1127
|
+
* This is a runtime debugging aid only. It does not change collisions,
|
|
1128
|
+
* input, rendering order, or physics behavior.
|
|
1129
|
+
*/
|
|
1130
|
+
this.debugBodies = false;
|
|
1131
|
+
/**
|
|
1132
|
+
* When `true`, MinimoJS draws every sprite's input area as an overlay.
|
|
1133
|
+
*
|
|
1134
|
+
* This is a runtime debugging aid only. It does not change input behavior,
|
|
1135
|
+
* physics, or rendering.
|
|
1136
|
+
*/
|
|
1137
|
+
this.debugInputAreas = false;
|
|
1056
1138
|
/**
|
|
1057
1139
|
* Background color for the full web page (`document.body`).
|
|
1058
1140
|
* Set to any valid CSS color string. Default: `null` (engine leaves page background unchanged).
|
|
@@ -2584,6 +2666,8 @@ export class Game {
|
|
|
2584
2666
|
background: this.background,
|
|
2585
2667
|
backgroundGradient: this.backgroundGradient,
|
|
2586
2668
|
pageBackground: this.pageBackground,
|
|
2669
|
+
debugBodies: this.debugBodies,
|
|
2670
|
+
debugInputAreas: this.debugInputAreas,
|
|
2587
2671
|
});
|
|
2588
2672
|
}
|
|
2589
2673
|
/** @internal */ _renderTransition() {
|
|
@@ -2615,6 +2699,8 @@ export class Game {
|
|
|
2615
2699
|
background: this.background,
|
|
2616
2700
|
backgroundGradient: this.backgroundGradient,
|
|
2617
2701
|
pageBackground: this.pageBackground,
|
|
2702
|
+
debugBodies: this.debugBodies,
|
|
2703
|
+
debugInputAreas: this.debugInputAreas,
|
|
2618
2704
|
});
|
|
2619
2705
|
}
|
|
2620
2706
|
/** @internal */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minimojs",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.16",
|
|
4
4
|
"description": "MinimoJS v1 — ultra-minimal, flat, deterministic 2D web game engine. Emoji-only sprites, rAF loop, TypeScript-first, LLM-friendly.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/minimo.js",
|