samengine 1.9.1 → 1.10.1
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/LICENSE +201 -0
- package/README.md +168 -0
- package/dist/config/buildconfig.d.ts +146 -0
- package/dist/config/buildconfig.js +115 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.js +1 -0
- package/dist/core.d.ts +17 -0
- package/dist/core.js +24 -0
- package/dist/html.d.ts +29 -0
- package/dist/html.js +20 -0
- package/dist/input.d.ts +51 -0
- package/dist/input.js +44 -3
- package/dist/keys.d.ts +6 -0
- package/dist/keys.js +6 -2
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +8 -1
- package/dist/nonbrowser/getversion.d.ts +13 -0
- package/dist/nonbrowser/getversion.js +35 -0
- package/dist/nonbrowser/ghresolver.d.ts +1 -0
- package/dist/nonbrowser/ghresolver.js +7 -0
- package/dist/nonbrowser/index.d.ts +9 -0
- package/dist/nonbrowser/index.js +9 -0
- package/dist/nonbrowser/internal/buildhelper.d.ts +42 -0
- package/dist/nonbrowser/internal/buildhelper.js +144 -0
- package/dist/nonbrowser/internal/cli/argparser.d.ts +18 -0
- package/dist/nonbrowser/internal/cli/argparser.js +36 -0
- package/dist/nonbrowser/internal/cli/main.d.ts +13 -0
- package/dist/nonbrowser/internal/cli/main.js +265 -0
- package/dist/nonbrowser/internal/config.d.ts +9 -0
- package/dist/nonbrowser/internal/config.js +40 -0
- package/dist/nonbrowser/internal/exporthtml.d.ts +37 -0
- package/dist/nonbrowser/internal/exporthtml.js +622 -0
- package/dist/nonbrowser/utils.d.ts +8 -0
- package/dist/nonbrowser/utils.js +18 -0
- package/dist/physics/collision.d.ts +33 -0
- package/dist/physics/collision.js +27 -0
- package/dist/physics/physicsEngine.d.ts +18 -0
- package/dist/physics/physicsEngine.js +18 -0
- package/dist/physics/physicsObject.d.ts +20 -0
- package/dist/physics/physicsObject.js +20 -0
- package/dist/renderer.d.ts +78 -0
- package/dist/renderer.js +72 -9
- package/dist/samegui/index.d.ts +29 -0
- package/dist/samegui/index.js +26 -0
- package/dist/save.d.ts +12 -0
- package/dist/save.js +10 -0
- package/dist/sound/audioplayer.d.ts +39 -0
- package/dist/sound/audioplayer.js +39 -5
- package/dist/storage/index.d.ts +40 -2
- package/dist/storage/index.js +34 -3
- package/dist/text/index.d.ts +14 -0
- package/dist/text/index.js +58 -0
- package/dist/texture.d.ts +100 -0
- package/dist/texture.js +75 -41
- package/dist/types/button.d.ts +25 -0
- package/dist/types/button.js +22 -0
- package/dist/types/circle.d.ts +26 -0
- package/dist/types/circle.js +21 -7
- package/dist/types/color.d.ts +17 -0
- package/dist/types/color.js +11 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/rectangle.d.ts +29 -0
- package/dist/types/rectangle.js +23 -7
- package/dist/types/triangle.d.ts +23 -0
- package/dist/types/triangle.js +20 -6
- package/dist/types/vector2d.d.ts +42 -0
- package/dist/types/vector2d.js +39 -11
- package/dist/types/vector3d.d.ts +38 -0
- package/dist/types/vector3d.js +35 -11
- package/dist/utils/index.d.ts +11 -4
- package/dist/utils/index.js +11 -4
- package/dist/utils/logger/index.d.ts +24 -0
- package/dist/utils/logger/index.js +44 -0
- package/dist/utils/math.d.ts +18 -0
- package/dist/utils/math.js +18 -4
- package/package.json +29 -11
- package/dist/utils/csv/index.d.ts +0 -3
- package/dist/utils/csv/index.js +0 -2
- package/dist/utils/csv/parser.d.ts +0 -25
- package/dist/utils/csv/parser.js +0 -212
- package/dist/utils/csv/stringifier.d.ts +0 -30
- package/dist/utils/csv/stringifier.js +0 -130
- package/dist/utils/csv/types.d.ts +0 -63
- package/dist/utils/csv/types.js +0 -1
- package/dist/utils/jsonc-parser.d.ts +0 -4
- package/dist/utils/jsonc-parser.js +0 -166
- package/dist/utils/markdown.d.ts +0 -41
- package/dist/utils/markdown.js +0 -699
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { add2d, dot2d, length2d, makeVector2d, normalize2d, scale2d, subtract2d } from "../types/vector2d.js";
|
|
2
2
|
import { clamp } from "../utils/math.js";
|
|
3
|
+
/**
|
|
4
|
+
* Tests two axis-aligned box colliders for overlap.
|
|
5
|
+
*
|
|
6
|
+
* @returns Collision normal and penetration depth, or `null` when separated.
|
|
7
|
+
*/
|
|
3
8
|
export function aabbCollision(a, b) {
|
|
4
9
|
const posA = a.body.position;
|
|
5
10
|
const posB = b.body.position;
|
|
@@ -27,6 +32,11 @@ export function aabbCollision(a, b) {
|
|
|
27
32
|
}
|
|
28
33
|
return null;
|
|
29
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Tests two circle colliders for overlap.
|
|
37
|
+
*
|
|
38
|
+
* @returns Collision normal from `a` to `b` and penetration depth, or `null`.
|
|
39
|
+
*/
|
|
30
40
|
export function circleCollision(a, b) {
|
|
31
41
|
const posA = a.body.position;
|
|
32
42
|
const posB = b.body.position;
|
|
@@ -42,6 +52,11 @@ export function circleCollision(a, b) {
|
|
|
42
52
|
}
|
|
43
53
|
return null;
|
|
44
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Tests a circle collider against a box collider.
|
|
57
|
+
*
|
|
58
|
+
* The returned normal points from the closest box point toward the circle.
|
|
59
|
+
*/
|
|
45
60
|
export function circleBoxCollision(circleObj, boxObj) {
|
|
46
61
|
const circle = circleObj.collider;
|
|
47
62
|
const box = boxObj.collider;
|
|
@@ -65,6 +80,12 @@ export function circleBoxCollision(circleObj, boxObj) {
|
|
|
65
80
|
}
|
|
66
81
|
return null;
|
|
67
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Applies an impulse to two bodies so their velocities respond to a collision.
|
|
85
|
+
*
|
|
86
|
+
* Static bodies are treated as having inverse mass `0`, so only dynamic bodies
|
|
87
|
+
* receive velocity changes.
|
|
88
|
+
*/
|
|
68
89
|
export function resolveCollision(a, b, normal) {
|
|
69
90
|
const rv = subtract2d(b.body.velocity, a.body.velocity);
|
|
70
91
|
let velAlongNormal = dot2d(rv, normal);
|
|
@@ -83,6 +104,12 @@ export function resolveCollision(a, b, normal) {
|
|
|
83
104
|
if (!b.body.isStatic)
|
|
84
105
|
b.body.velocity = add2d(b.body.velocity, scale2d(impulse, invMassB));
|
|
85
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Moves overlapping bodies apart to remove visible penetration.
|
|
109
|
+
*
|
|
110
|
+
* The correction is distributed by inverse mass, so lighter dynamic bodies move
|
|
111
|
+
* more than heavier ones and static bodies do not move.
|
|
112
|
+
*/
|
|
86
113
|
export function positionalCorrection(a, b, normal, penetration) {
|
|
87
114
|
const percent = 1.0; // vorher 0.8
|
|
88
115
|
const slop = 0.001; // vorher 0.01
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { Vector2d } from "../types/vector2d.js";
|
|
2
2
|
import { PhysicsObject } from "./physicsObject.js";
|
|
3
|
+
/**
|
|
4
|
+
* Simple 2D physics simulation.
|
|
5
|
+
*
|
|
6
|
+
* `step(dt)` applies gravity, integrates positions, checks all object pairs, and
|
|
7
|
+
* resolves circle/box collisions. The implementation is intentionally small and
|
|
8
|
+
* best suited for arcade-style games rather than physically exact simulation.
|
|
9
|
+
*/
|
|
3
10
|
export declare class PhysicsWorld {
|
|
4
11
|
objects: PhysicsObject[];
|
|
5
12
|
gravity: Vector2d;
|
|
13
|
+
/**
|
|
14
|
+
* Advances the simulation by `dt` seconds.
|
|
15
|
+
*
|
|
16
|
+
* Use the delta time from `startEngine` for frame-rate independent motion.
|
|
17
|
+
*/
|
|
6
18
|
step(dt: number): void;
|
|
7
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Sets gravity by direction and strength.
|
|
22
|
+
*
|
|
23
|
+
* `x` and `y` describe the direction vector and do not need to be normalized.
|
|
24
|
+
* `strength` becomes the final acceleration magnitude.
|
|
25
|
+
*/
|
|
8
26
|
export declare function setGravityDirection(world: PhysicsWorld, x: number, y: number, strength: number): void;
|
|
@@ -15,11 +15,23 @@ import { aabbCollision, circleBoxCollision, circleCollision, positionalCorrectio
|
|
|
15
15
|
// function update(dt: number) {
|
|
16
16
|
// world.step(dt);
|
|
17
17
|
// }
|
|
18
|
+
/**
|
|
19
|
+
* Simple 2D physics simulation.
|
|
20
|
+
*
|
|
21
|
+
* `step(dt)` applies gravity, integrates positions, checks all object pairs, and
|
|
22
|
+
* resolves circle/box collisions. The implementation is intentionally small and
|
|
23
|
+
* best suited for arcade-style games rather than physically exact simulation.
|
|
24
|
+
*/
|
|
18
25
|
export class PhysicsWorld {
|
|
19
26
|
constructor() {
|
|
20
27
|
this.objects = [];
|
|
21
28
|
this.gravity = makeVector2d(0, 500); // px/s²
|
|
22
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Advances the simulation by `dt` seconds.
|
|
32
|
+
*
|
|
33
|
+
* Use the delta time from `startEngine` for frame-rate independent motion.
|
|
34
|
+
*/
|
|
23
35
|
step(dt) {
|
|
24
36
|
// Bewegung
|
|
25
37
|
for (const obj of this.objects) {
|
|
@@ -74,6 +86,12 @@ export class PhysicsWorld {
|
|
|
74
86
|
}
|
|
75
87
|
}
|
|
76
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Sets gravity by direction and strength.
|
|
91
|
+
*
|
|
92
|
+
* `x` and `y` describe the direction vector and do not need to be normalized.
|
|
93
|
+
* `strength` becomes the final acceleration magnitude.
|
|
94
|
+
*/
|
|
77
95
|
export function setGravityDirection(world, x, y, strength) {
|
|
78
96
|
const len = Math.sqrt(x * x + y * y);
|
|
79
97
|
if (len === 0)
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
import { Vector2d } from "../types/vector2d.js";
|
|
2
2
|
import { Collider } from "./collision.js";
|
|
3
|
+
/**
|
|
4
|
+
* Physical body state used by the simple physics world.
|
|
5
|
+
*
|
|
6
|
+
* Positions and velocities use canvas-style 2D coordinates. Static bodies get
|
|
7
|
+
* infinite mass and are not moved by gravity or collision impulses.
|
|
8
|
+
*/
|
|
3
9
|
export declare class RigidBody {
|
|
4
10
|
position: Vector2d;
|
|
5
11
|
velocity: Vector2d;
|
|
6
12
|
mass: number;
|
|
7
13
|
restitution: number;
|
|
8
14
|
isStatic: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a rigid body.
|
|
17
|
+
*
|
|
18
|
+
* @param pos Initial center position.
|
|
19
|
+
* @param mass Body mass. Ignored for static bodies.
|
|
20
|
+
* @param restitution Bounciness factor used during collision resolution.
|
|
21
|
+
* @param isStatic Whether the body should behave like an immovable object.
|
|
22
|
+
*/
|
|
9
23
|
constructor(pos: Vector2d, mass?: number, restitution?: number, isStatic?: boolean);
|
|
10
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Combines physical state with a collision shape.
|
|
27
|
+
*/
|
|
11
28
|
export declare class PhysicsObject {
|
|
12
29
|
body: RigidBody;
|
|
13
30
|
collider: Collider;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a physics object from a body and collider.
|
|
33
|
+
*/
|
|
14
34
|
constructor(body: RigidBody, collider: Collider);
|
|
15
35
|
}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { makeVector2d } from "../types/vector2d.js";
|
|
2
|
+
/**
|
|
3
|
+
* Physical body state used by the simple physics world.
|
|
4
|
+
*
|
|
5
|
+
* Positions and velocities use canvas-style 2D coordinates. Static bodies get
|
|
6
|
+
* infinite mass and are not moved by gravity or collision impulses.
|
|
7
|
+
*/
|
|
2
8
|
export class RigidBody {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a rigid body.
|
|
11
|
+
*
|
|
12
|
+
* @param pos Initial center position.
|
|
13
|
+
* @param mass Body mass. Ignored for static bodies.
|
|
14
|
+
* @param restitution Bounciness factor used during collision resolution.
|
|
15
|
+
* @param isStatic Whether the body should behave like an immovable object.
|
|
16
|
+
*/
|
|
3
17
|
constructor(pos, mass = 1, restitution = 0.8, isStatic = false) {
|
|
4
18
|
this.position = pos;
|
|
5
19
|
this.velocity = makeVector2d(0, 0);
|
|
@@ -8,7 +22,13 @@ export class RigidBody {
|
|
|
8
22
|
this.isStatic = isStatic;
|
|
9
23
|
}
|
|
10
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Combines physical state with a collision shape.
|
|
27
|
+
*/
|
|
11
28
|
export class PhysicsObject {
|
|
29
|
+
/**
|
|
30
|
+
* Creates a physics object from a body and collider.
|
|
31
|
+
*/
|
|
12
32
|
constructor(body, collider) {
|
|
13
33
|
this.body = body;
|
|
14
34
|
this.collider = collider;
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,18 +1,96 @@
|
|
|
1
1
|
import { type Rect } from "./types/rectangle.js";
|
|
2
2
|
import { type Circle } from "./types/circle.js";
|
|
3
3
|
import { type Triangle } from "./types/triangle.js";
|
|
4
|
+
/**
|
|
5
|
+
* Draws normal browser/canvas text at the given position.
|
|
6
|
+
*
|
|
7
|
+
* The text baseline is set to `"top"`, so `x` and `y` describe the upper-left
|
|
8
|
+
* corner of the text area rather than the alphabetic baseline.
|
|
9
|
+
*
|
|
10
|
+
* @param ctx Canvas 2D rendering context to draw into.
|
|
11
|
+
* @param text Text that should be rendered.
|
|
12
|
+
* @param x Horizontal canvas coordinate.
|
|
13
|
+
* @param y Vertical canvas coordinate.
|
|
14
|
+
* @param color Fill color used for the text. Defaults to white.
|
|
15
|
+
* @param font Canvas font string, for example `"20px Arial"`.
|
|
16
|
+
* @deprecated Use samengine/text instead!
|
|
17
|
+
*/
|
|
4
18
|
export declare function renderText(ctx: CanvasRenderingContext2D, text: string, x: number, y: number, color?: string, font?: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Maps a character to the rectangle where that character is located inside a
|
|
21
|
+
* bitmap font spritesheet.
|
|
22
|
+
*/
|
|
5
23
|
export type CharMap = Record<string, Rect>;
|
|
24
|
+
/**
|
|
25
|
+
* Renders text from a bitmap font spritesheet.
|
|
26
|
+
*
|
|
27
|
+
* Every character in `text` is looked up in `charMap`. Characters that are not
|
|
28
|
+
* present in the map are skipped. Each source rectangle is drawn next to the
|
|
29
|
+
* previous one, so this is best suited for fixed-height bitmap fonts.
|
|
30
|
+
*
|
|
31
|
+
* @param ctx Canvas 2D rendering context to draw into.
|
|
32
|
+
* @param text Text to render.
|
|
33
|
+
* @param x Start x coordinate.
|
|
34
|
+
* @param y Start y coordinate.
|
|
35
|
+
* @param sprite Image containing all bitmap font glyphs.
|
|
36
|
+
* @param charMap Mapping from character to source rectangle in `sprite`.
|
|
37
|
+
* @param scale Size multiplier for rendered glyphs.
|
|
38
|
+
*/
|
|
6
39
|
export declare function renderBitmapText(ctx: CanvasRenderingContext2D, text: string, x: number, y: number, sprite: HTMLImageElement, charMap: CharMap, scale?: number): void;
|
|
40
|
+
/**
|
|
41
|
+
* Draws a filled rectangle.
|
|
42
|
+
*
|
|
43
|
+
* If `rect.borderRadius` is greater than `0` and the browser supports
|
|
44
|
+
* `CanvasRenderingContext2D.roundRect`, a rounded rectangle is drawn.
|
|
45
|
+
* Otherwise the function falls back to `fillRect`.
|
|
46
|
+
*/
|
|
7
47
|
export declare function drawRect(ctx: CanvasRenderingContext2D, rect: Rect, color?: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Draws the outline of a rectangle.
|
|
50
|
+
*
|
|
51
|
+
* Supports `rect.borderRadius` in the same way as `drawRect`.
|
|
52
|
+
*
|
|
53
|
+
* @param lineWidth Stroke width in canvas pixels.
|
|
54
|
+
*/
|
|
8
55
|
export declare function drawRectOutline(ctx: CanvasRenderingContext2D, rect: Rect, color?: string, lineWidth?: number): void;
|
|
56
|
+
/**
|
|
57
|
+
* Draws a filled circle using the circle center and radius.
|
|
58
|
+
*/
|
|
9
59
|
export declare function drawCircle(ctx: CanvasRenderingContext2D, circle: Circle, color?: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Draws the outline of a circle using the circle center and radius.
|
|
62
|
+
*
|
|
63
|
+
* @param lineWidth Stroke width in canvas pixels.
|
|
64
|
+
*/
|
|
10
65
|
export declare function drawCircleOutline(ctx: CanvasRenderingContext2D, circle: Circle, color?: string, lineWidth?: number): void;
|
|
66
|
+
/**
|
|
67
|
+
* Draws a filled triangle from three points.
|
|
68
|
+
*/
|
|
11
69
|
export declare function drawTriangle(ctx: CanvasRenderingContext2D, triangle: Triangle, color?: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Draws the outline of a triangle from three points.
|
|
72
|
+
*
|
|
73
|
+
* @param lineWidth Stroke width in canvas pixels.
|
|
74
|
+
*/
|
|
12
75
|
export declare function drawTriangleOutline(ctx: CanvasRenderingContext2D, triangle: Triangle, color?: string, lineWidth?: number): void;
|
|
76
|
+
/**
|
|
77
|
+
* Renders one horizontally repeating parallax background layer.
|
|
78
|
+
*
|
|
79
|
+
* `cameraX` is multiplied by `speed` to create the parallax offset. Lower speed
|
|
80
|
+
* values make the layer move more slowly and feel farther away. The image is
|
|
81
|
+
* repeated horizontally until the full canvas width is covered.
|
|
82
|
+
*/
|
|
13
83
|
export declare function renderParallaxBackground(ctx: CanvasRenderingContext2D, image: HTMLImageElement, cameraX: number, speed?: number, canvasWidth?: number, canvasHeight?: number): void;
|
|
14
84
|
export interface ParallaxLayer {
|
|
85
|
+
/** Image used for this layer. It must be loaded before it can be rendered. */
|
|
15
86
|
image: HTMLImageElement;
|
|
87
|
+
/** Movement multiplier relative to `cameraX`. */
|
|
16
88
|
speed: number;
|
|
17
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Renders multiple parallax layers in array order.
|
|
92
|
+
*
|
|
93
|
+
* Place distant background layers first and foreground layers later so they draw
|
|
94
|
+
* on top of earlier layers.
|
|
95
|
+
*/
|
|
18
96
|
export declare function renderParallaxLayers(ctx: CanvasRenderingContext2D, layers: ParallaxLayer[], cameraX: number): void;
|
package/dist/renderer.js
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Draws normal browser/canvas text at the given position.
|
|
3
|
+
*
|
|
4
|
+
* The text baseline is set to `"top"`, so `x` and `y` describe the upper-left
|
|
5
|
+
* corner of the text area rather than the alphabetic baseline.
|
|
6
|
+
*
|
|
7
|
+
* @param ctx Canvas 2D rendering context to draw into.
|
|
8
|
+
* @param text Text that should be rendered.
|
|
9
|
+
* @param x Horizontal canvas coordinate.
|
|
10
|
+
* @param y Vertical canvas coordinate.
|
|
11
|
+
* @param color Fill color used for the text. Defaults to white.
|
|
12
|
+
* @param font Canvas font string, for example `"20px Arial"`.
|
|
13
|
+
* @deprecated Use samengine/text instead!
|
|
14
|
+
*/
|
|
2
15
|
export function renderText(ctx, text, x, y, color = "white", font = "20px Arial") {
|
|
3
16
|
ctx.fillStyle = color;
|
|
4
17
|
ctx.font = font;
|
|
5
18
|
ctx.textBaseline = "top";
|
|
6
19
|
ctx.fillText(text, x, y);
|
|
7
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Renders text from a bitmap font spritesheet.
|
|
23
|
+
*
|
|
24
|
+
* Every character in `text` is looked up in `charMap`. Characters that are not
|
|
25
|
+
* present in the map are skipped. Each source rectangle is drawn next to the
|
|
26
|
+
* previous one, so this is best suited for fixed-height bitmap fonts.
|
|
27
|
+
*
|
|
28
|
+
* @param ctx Canvas 2D rendering context to draw into.
|
|
29
|
+
* @param text Text to render.
|
|
30
|
+
* @param x Start x coordinate.
|
|
31
|
+
* @param y Start y coordinate.
|
|
32
|
+
* @param sprite Image containing all bitmap font glyphs.
|
|
33
|
+
* @param charMap Mapping from character to source rectangle in `sprite`.
|
|
34
|
+
* @param scale Size multiplier for rendered glyphs.
|
|
35
|
+
*/
|
|
8
36
|
export function renderBitmapText(ctx, text, x, y, sprite, charMap, scale = 1) {
|
|
9
37
|
let offsetX = 0;
|
|
10
38
|
for (const c of text) {
|
|
@@ -16,7 +44,13 @@ export function renderBitmapText(ctx, text, x, y, sprite, charMap, scale = 1) {
|
|
|
16
44
|
}
|
|
17
45
|
}
|
|
18
46
|
// ===== SHAPE DRAWING =====
|
|
19
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Draws a filled rectangle.
|
|
49
|
+
*
|
|
50
|
+
* If `rect.borderRadius` is greater than `0` and the browser supports
|
|
51
|
+
* `CanvasRenderingContext2D.roundRect`, a rounded rectangle is drawn.
|
|
52
|
+
* Otherwise the function falls back to `fillRect`.
|
|
53
|
+
*/
|
|
20
54
|
export function drawRect(ctx, rect, color = "white") {
|
|
21
55
|
ctx.fillStyle = color;
|
|
22
56
|
const radius = rect.borderRadius ?? 0;
|
|
@@ -29,7 +63,13 @@ export function drawRect(ctx, rect, color = "white") {
|
|
|
29
63
|
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
|
|
30
64
|
}
|
|
31
65
|
}
|
|
32
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Draws the outline of a rectangle.
|
|
68
|
+
*
|
|
69
|
+
* Supports `rect.borderRadius` in the same way as `drawRect`.
|
|
70
|
+
*
|
|
71
|
+
* @param lineWidth Stroke width in canvas pixels.
|
|
72
|
+
*/
|
|
33
73
|
export function drawRectOutline(ctx, rect, color = "white", lineWidth = 1) {
|
|
34
74
|
ctx.strokeStyle = color;
|
|
35
75
|
ctx.lineWidth = lineWidth;
|
|
@@ -43,14 +83,20 @@ export function drawRectOutline(ctx, rect, color = "white", lineWidth = 1) {
|
|
|
43
83
|
ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
|
|
44
84
|
}
|
|
45
85
|
}
|
|
46
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Draws a filled circle using the circle center and radius.
|
|
88
|
+
*/
|
|
47
89
|
export function drawCircle(ctx, circle, color = "white") {
|
|
48
90
|
ctx.fillStyle = color;
|
|
49
91
|
ctx.beginPath();
|
|
50
92
|
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
|
|
51
93
|
ctx.fill();
|
|
52
94
|
}
|
|
53
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Draws the outline of a circle using the circle center and radius.
|
|
97
|
+
*
|
|
98
|
+
* @param lineWidth Stroke width in canvas pixels.
|
|
99
|
+
*/
|
|
54
100
|
export function drawCircleOutline(ctx, circle, color = "white", lineWidth = 1) {
|
|
55
101
|
ctx.strokeStyle = color;
|
|
56
102
|
ctx.lineWidth = lineWidth;
|
|
@@ -58,7 +104,9 @@ export function drawCircleOutline(ctx, circle, color = "white", lineWidth = 1) {
|
|
|
58
104
|
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
|
|
59
105
|
ctx.stroke();
|
|
60
106
|
}
|
|
61
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Draws a filled triangle from three points.
|
|
109
|
+
*/
|
|
62
110
|
export function drawTriangle(ctx, triangle, color = "white") {
|
|
63
111
|
ctx.fillStyle = color;
|
|
64
112
|
ctx.beginPath();
|
|
@@ -68,7 +116,11 @@ export function drawTriangle(ctx, triangle, color = "white") {
|
|
|
68
116
|
ctx.closePath();
|
|
69
117
|
ctx.fill();
|
|
70
118
|
}
|
|
71
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Draws the outline of a triangle from three points.
|
|
121
|
+
*
|
|
122
|
+
* @param lineWidth Stroke width in canvas pixels.
|
|
123
|
+
*/
|
|
72
124
|
export function drawTriangleOutline(ctx, triangle, color = "white", lineWidth = 1) {
|
|
73
125
|
ctx.strokeStyle = color;
|
|
74
126
|
ctx.lineWidth = lineWidth;
|
|
@@ -79,7 +131,13 @@ export function drawTriangleOutline(ctx, triangle, color = "white", lineWidth =
|
|
|
79
131
|
ctx.closePath();
|
|
80
132
|
ctx.stroke();
|
|
81
133
|
}
|
|
82
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Renders one horizontally repeating parallax background layer.
|
|
136
|
+
*
|
|
137
|
+
* `cameraX` is multiplied by `speed` to create the parallax offset. Lower speed
|
|
138
|
+
* values make the layer move more slowly and feel farther away. The image is
|
|
139
|
+
* repeated horizontally until the full canvas width is covered.
|
|
140
|
+
*/
|
|
83
141
|
export function renderParallaxBackground(ctx, image, cameraX, speed = 0.5, canvasWidth = ctx.canvas.width, canvasHeight = ctx.canvas.height) {
|
|
84
142
|
if (!image.complete)
|
|
85
143
|
return;
|
|
@@ -89,7 +147,12 @@ export function renderParallaxBackground(ctx, image, cameraX, speed = 0.5, canva
|
|
|
89
147
|
ctx.drawImage(image, x, 0, image.width, canvasHeight);
|
|
90
148
|
}
|
|
91
149
|
}
|
|
92
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Renders multiple parallax layers in array order.
|
|
152
|
+
*
|
|
153
|
+
* Place distant background layers first and foreground layers later so they draw
|
|
154
|
+
* on top of earlier layers.
|
|
155
|
+
*/
|
|
93
156
|
export function renderParallaxLayers(ctx, layers, cameraX) {
|
|
94
157
|
for (const layer of layers) {
|
|
95
158
|
renderParallaxBackground(ctx, layer.image, cameraX, layer.speed);
|
package/dist/samegui/index.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
export type UIElementType = "button" | "text" | "checkbox";
|
|
2
|
+
/**
|
|
3
|
+
* Stored DOM node for one immediate-mode UI element.
|
|
4
|
+
*/
|
|
2
5
|
export type UIElement = {
|
|
3
6
|
el: HTMLElement;
|
|
4
7
|
type: UIElementType;
|
|
5
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Tiny immediate-mode HTML overlay for debug tools and simple in-game menus.
|
|
11
|
+
*
|
|
12
|
+
* Call `begin()` before emitting UI for the frame, then call `button`, `text`,
|
|
13
|
+
* and `checkbox` in a stable order, and finally call `end()`. Elements are
|
|
14
|
+
* backed by real DOM nodes but identified by hashed labels or explicit ids.
|
|
15
|
+
*/
|
|
6
16
|
export declare class HtmlUI {
|
|
7
17
|
private root;
|
|
8
18
|
private panel;
|
|
@@ -11,10 +21,29 @@ export declare class HtmlUI {
|
|
|
11
21
|
private frameIds;
|
|
12
22
|
private valueMap;
|
|
13
23
|
constructor();
|
|
24
|
+
/**
|
|
25
|
+
* Starts a new UI frame and records which controls are used this frame.
|
|
26
|
+
*/
|
|
14
27
|
begin(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Ends the UI frame and clears one-frame button click states.
|
|
30
|
+
*/
|
|
15
31
|
end(): void;
|
|
16
32
|
private getButton;
|
|
33
|
+
/**
|
|
34
|
+
* Creates or updates a button.
|
|
35
|
+
*
|
|
36
|
+
* @returns `true` during the frame after the DOM button was clicked.
|
|
37
|
+
*/
|
|
17
38
|
button(label: string, idOverride?: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Creates or updates a text label in the overlay panel.
|
|
41
|
+
*/
|
|
18
42
|
text(label: string, idOverride?: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Creates or updates a checkbox and returns its current value.
|
|
45
|
+
*
|
|
46
|
+
* `defaultValue` is only used the first time the checkbox id appears.
|
|
47
|
+
*/
|
|
19
48
|
checkbox(label: string, defaultValue: boolean, idOverride?: string): boolean;
|
|
20
49
|
}
|
package/dist/samegui/index.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
// HTML Overlay
|
|
2
2
|
import { hash } from "../utils/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Tiny immediate-mode HTML overlay for debug tools and simple in-game menus.
|
|
5
|
+
*
|
|
6
|
+
* Call `begin()` before emitting UI for the frame, then call `button`, `text`,
|
|
7
|
+
* and `checkbox` in a stable order, and finally call `end()`. Elements are
|
|
8
|
+
* backed by real DOM nodes but identified by hashed labels or explicit ids.
|
|
9
|
+
*/
|
|
3
10
|
export class HtmlUI {
|
|
4
11
|
constructor() {
|
|
5
12
|
this.elements = new Map();
|
|
@@ -22,9 +29,15 @@ export class HtmlUI {
|
|
|
22
29
|
this.panel.style.borderRadius = "6px";
|
|
23
30
|
this.root.appendChild(this.panel);
|
|
24
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Starts a new UI frame and records which controls are used this frame.
|
|
34
|
+
*/
|
|
25
35
|
begin() {
|
|
26
36
|
this.frameIds = [];
|
|
27
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Ends the UI frame and clears one-frame button click states.
|
|
40
|
+
*/
|
|
28
41
|
end() {
|
|
29
42
|
// reset clicks AFTER frame
|
|
30
43
|
for (const id of this.frameIds) {
|
|
@@ -49,6 +62,11 @@ export class HtmlUI {
|
|
|
49
62
|
}
|
|
50
63
|
return e.el;
|
|
51
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Creates or updates a button.
|
|
67
|
+
*
|
|
68
|
+
* @returns `true` during the frame after the DOM button was clicked.
|
|
69
|
+
*/
|
|
52
70
|
button(label, idOverride) {
|
|
53
71
|
const id = hash(idOverride ?? label);
|
|
54
72
|
this.frameIds.push(id);
|
|
@@ -60,6 +78,9 @@ export class HtmlUI {
|
|
|
60
78
|
};
|
|
61
79
|
return this.clicked.get(id) === true;
|
|
62
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates or updates a text label in the overlay panel.
|
|
83
|
+
*/
|
|
63
84
|
text(label, idOverride) {
|
|
64
85
|
const id = hash(idOverride ?? label);
|
|
65
86
|
this.frameIds.push(id);
|
|
@@ -73,6 +94,11 @@ export class HtmlUI {
|
|
|
73
94
|
}
|
|
74
95
|
e.el.textContent = label;
|
|
75
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Creates or updates a checkbox and returns its current value.
|
|
99
|
+
*
|
|
100
|
+
* `defaultValue` is only used the first time the checkbox id appears.
|
|
101
|
+
*/
|
|
76
102
|
checkbox(label, defaultValue, idOverride) {
|
|
77
103
|
const id = hash(idOverride ?? label);
|
|
78
104
|
this.frameIds.push(id);
|
package/dist/save.d.ts
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Old save data shape used by the legacy save helpers.
|
|
3
|
+
*
|
|
2
4
|
* @deprecated Use samengine/storage instead
|
|
3
5
|
*/
|
|
4
6
|
export type SaveData = Record<string, any>;
|
|
5
7
|
/**
|
|
8
|
+
* localStorage key used by the legacy save helpers.
|
|
9
|
+
*
|
|
6
10
|
* @deprecated Use samengine/storage instead
|
|
7
11
|
*/
|
|
8
12
|
export declare let SAVE_KEY: string;
|
|
9
13
|
/**
|
|
14
|
+
* Stores save data as JSON under `SAVE_KEY`.
|
|
15
|
+
*
|
|
10
16
|
* @deprecated Use samengine/storage instead
|
|
11
17
|
*/
|
|
12
18
|
export declare function saveGame(data: SaveData): void;
|
|
13
19
|
/**
|
|
20
|
+
* Loads and parses JSON save data from `SAVE_KEY`.
|
|
21
|
+
*
|
|
14
22
|
* @deprecated Use samengine/storage instead
|
|
15
23
|
*/
|
|
16
24
|
export declare function loadGame(): SaveData | null;
|
|
17
25
|
/**
|
|
26
|
+
* Removes the current save entry from localStorage.
|
|
27
|
+
*
|
|
18
28
|
* @deprecated Use samengine/storage instead
|
|
19
29
|
*/
|
|
20
30
|
export declare function clearSave(): void;
|
|
21
31
|
/**
|
|
32
|
+
* Downloads the current save data as `savegame.json`.
|
|
33
|
+
*
|
|
22
34
|
* @deprecated Use samengine/storage instead
|
|
23
35
|
*/
|
|
24
36
|
export declare function exportSave(): void;
|
package/dist/save.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
// Please rename the SaveKey
|
|
2
2
|
/**
|
|
3
|
+
* localStorage key used by the legacy save helpers.
|
|
4
|
+
*
|
|
3
5
|
* @deprecated Use samengine/storage instead
|
|
4
6
|
*/
|
|
5
7
|
export let SAVE_KEY = "my_game_save";
|
|
6
8
|
/**
|
|
9
|
+
* Stores save data as JSON under `SAVE_KEY`.
|
|
10
|
+
*
|
|
7
11
|
* @deprecated Use samengine/storage instead
|
|
8
12
|
*/
|
|
9
13
|
export function saveGame(data) {
|
|
@@ -17,6 +21,8 @@ export function saveGame(data) {
|
|
|
17
21
|
}
|
|
18
22
|
}
|
|
19
23
|
/**
|
|
24
|
+
* Loads and parses JSON save data from `SAVE_KEY`.
|
|
25
|
+
*
|
|
20
26
|
* @deprecated Use samengine/storage instead
|
|
21
27
|
*/
|
|
22
28
|
export function loadGame() {
|
|
@@ -32,6 +38,8 @@ export function loadGame() {
|
|
|
32
38
|
}
|
|
33
39
|
}
|
|
34
40
|
/**
|
|
41
|
+
* Removes the current save entry from localStorage.
|
|
42
|
+
*
|
|
35
43
|
* @deprecated Use samengine/storage instead
|
|
36
44
|
*/
|
|
37
45
|
export function clearSave() {
|
|
@@ -39,6 +47,8 @@ export function clearSave() {
|
|
|
39
47
|
console.log("Save cleared!");
|
|
40
48
|
}
|
|
41
49
|
/**
|
|
50
|
+
* Downloads the current save data as `savegame.json`.
|
|
51
|
+
*
|
|
42
52
|
* @deprecated Use samengine/storage instead
|
|
43
53
|
*/
|
|
44
54
|
export function exportSave() {
|
|
@@ -1,17 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Audio based sound manager for short effects and looping music.
|
|
3
|
+
*
|
|
4
|
+
* Sounds are decoded once and cached by URL. In normal builds, audio files are
|
|
5
|
+
* loaded with `fetch(url)`. Single-file exports can provide `window.__loadResource`
|
|
6
|
+
* to resolve embedded resources before falling back to normal fetch.
|
|
7
|
+
*/
|
|
1
8
|
export declare class SoundSystem {
|
|
2
9
|
private ctx;
|
|
3
10
|
private bufferCache;
|
|
4
11
|
private activeSources;
|
|
5
12
|
private masterGain;
|
|
13
|
+
/**
|
|
14
|
+
* Creates or reuses an `AudioContext` and connects a master gain node.
|
|
15
|
+
*
|
|
16
|
+
* Browsers often require user interaction before audio can play. If playback
|
|
17
|
+
* is blocked or suspended, call `resume()` from a click/key handler.
|
|
18
|
+
*/
|
|
6
19
|
constructor();
|
|
20
|
+
/**
|
|
21
|
+
* Loads, decodes, and caches an audio file.
|
|
22
|
+
*
|
|
23
|
+
* @param url Audio URL or embedded resource key.
|
|
24
|
+
* @returns Decoded `AudioBuffer`.
|
|
25
|
+
*/
|
|
7
26
|
load(url: string): Promise<AudioBuffer>;
|
|
27
|
+
/**
|
|
28
|
+
* Plays an audio file and returns the active source node.
|
|
29
|
+
*
|
|
30
|
+
* @param url Audio URL or embedded resource key.
|
|
31
|
+
* @param options Per-playback settings such as volume, loop, and speed.
|
|
32
|
+
*/
|
|
8
33
|
play(url: string, options?: {
|
|
9
34
|
volume?: number;
|
|
10
35
|
loop?: boolean;
|
|
11
36
|
playbackRate?: number;
|
|
12
37
|
}): Promise<AudioBufferSourceNode>;
|
|
38
|
+
/**
|
|
39
|
+
* Stops every source started through this `SoundSystem`.
|
|
40
|
+
*/
|
|
13
41
|
stopAll(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Sets the master volume for all current and future sounds.
|
|
44
|
+
*
|
|
45
|
+
* `1` is full volume, `0` is silent. Values above `1` amplify.
|
|
46
|
+
*/
|
|
14
47
|
setVolume(v: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* Resumes the underlying `AudioContext` if the browser suspended it.
|
|
50
|
+
*/
|
|
15
51
|
resume(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Suspends the underlying `AudioContext` without clearing loaded buffers.
|
|
54
|
+
*/
|
|
16
55
|
pause(): Promise<void>;
|
|
17
56
|
}
|