samengine 1.9.1 → 1.10.0
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 +20 -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 +262 -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/internal/projcreator/downloadZip.d.ts +4 -0
- package/dist/nonbrowser/internal/projcreator/downloadZip.js +83 -0
- package/dist/nonbrowser/internal/projcreator/main.d.ts +1 -0
- package/dist/nonbrowser/internal/projcreator/main.js +81 -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 +36 -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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import { downloadAndExtract, flattenGitHubZip } from "./downloadZip.js";
|
|
5
|
+
const USERNAME = "Shadowdara";
|
|
6
|
+
const REPO = "samengine-project-templates";
|
|
7
|
+
export async function run() {
|
|
8
|
+
const answers = await inquirer.prompt([
|
|
9
|
+
{
|
|
10
|
+
name: "projectName",
|
|
11
|
+
message: "Project name?",
|
|
12
|
+
default: "my-game"
|
|
13
|
+
}
|
|
14
|
+
]);
|
|
15
|
+
const targetDir = path.join(process.cwd(), answers.projectName);
|
|
16
|
+
console.log("📦 Downloading template repo...");
|
|
17
|
+
await downloadAndExtract(`https://codeload.github.com/${USERNAME}/${REPO}/zip/refs/heads/main`, targetDir);
|
|
18
|
+
await flattenGitHubZip(targetDir);
|
|
19
|
+
// -------------------------
|
|
20
|
+
// 1. VERSIONEN LADEN
|
|
21
|
+
// -------------------------
|
|
22
|
+
const versions = (await fs.readdir(targetDir))
|
|
23
|
+
.filter(v => fs.statSync(path.join(targetDir, v)).isDirectory());
|
|
24
|
+
const { version } = await inquirer.prompt([
|
|
25
|
+
{
|
|
26
|
+
name: "version",
|
|
27
|
+
message: "Choose version",
|
|
28
|
+
type: "select",
|
|
29
|
+
choices: versions
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
const versionPath = path.join(targetDir, version);
|
|
33
|
+
// -------------------------
|
|
34
|
+
// 2. STARTER LADEN
|
|
35
|
+
// -------------------------
|
|
36
|
+
const starters = (await fs.readdir(versionPath))
|
|
37
|
+
.filter(s => fs.statSync(path.join(versionPath, s)).isDirectory());
|
|
38
|
+
const { starter } = await inquirer.prompt([
|
|
39
|
+
{
|
|
40
|
+
name: "starter",
|
|
41
|
+
message: "Choose starter",
|
|
42
|
+
type: "select",
|
|
43
|
+
choices: starters
|
|
44
|
+
}
|
|
45
|
+
]);
|
|
46
|
+
// -------------------------
|
|
47
|
+
// 3. CLEANUP (KEEP ONLY SELECTED)
|
|
48
|
+
// -------------------------
|
|
49
|
+
for (const v of await fs.readdir(targetDir)) {
|
|
50
|
+
const vPath = path.join(targetDir, v);
|
|
51
|
+
if (!(await fs.stat(vPath)).isDirectory())
|
|
52
|
+
continue;
|
|
53
|
+
if (v !== version) {
|
|
54
|
+
await fs.remove(vPath);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// remove other starters inside selected version
|
|
58
|
+
for (const s of await fs.readdir(vPath)) {
|
|
59
|
+
const sPath = path.join(vPath, s);
|
|
60
|
+
if (!(await fs.stat(sPath)).isDirectory())
|
|
61
|
+
continue;
|
|
62
|
+
if (s !== starter) {
|
|
63
|
+
await fs.remove(sPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// -------------------------
|
|
68
|
+
// 4. MOVE STARTER TO ROOT
|
|
69
|
+
// -------------------------
|
|
70
|
+
const starterPath = path.join(targetDir, version, starter);
|
|
71
|
+
const files = await fs.readdir(starterPath);
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
await fs.move(path.join(starterPath, file), path.join(targetDir, file), { overwrite: true });
|
|
74
|
+
}
|
|
75
|
+
// -------------------------
|
|
76
|
+
// 5. FINAL CLEANUP
|
|
77
|
+
// -------------------------
|
|
78
|
+
await fs.remove(path.join(targetDir, version));
|
|
79
|
+
console.log("✅ Done!");
|
|
80
|
+
console.log(`👉 cd ${answers.projectName} && npm install`);
|
|
81
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minifies generated HTML for release builds.
|
|
3
|
+
*
|
|
4
|
+
* The minifier also processes inline CSS and JavaScript, which matters for
|
|
5
|
+
* single-file builds because they can place the whole game shell into one
|
|
6
|
+
* `index.html`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function compressHTML(html: string): Promise<string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { minify } from "html-minifier-terser";
|
|
2
|
+
/**
|
|
3
|
+
* Minifies generated HTML for release builds.
|
|
4
|
+
*
|
|
5
|
+
* The minifier also processes inline CSS and JavaScript, which matters for
|
|
6
|
+
* single-file builds because they can place the whole game shell into one
|
|
7
|
+
* `index.html`.
|
|
8
|
+
*/
|
|
9
|
+
export async function compressHTML(html) {
|
|
10
|
+
return await minify(html, {
|
|
11
|
+
collapseWhitespace: true,
|
|
12
|
+
removeComments: true,
|
|
13
|
+
removeRedundantAttributes: true,
|
|
14
|
+
removeEmptyAttributes: true,
|
|
15
|
+
minifyCSS: true,
|
|
16
|
+
minifyJS: true,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Vector2d } from "../types/vector2d.js";
|
|
2
2
|
import { PhysicsObject } from "./physicsObject.js";
|
|
3
|
+
/**
|
|
4
|
+
* Collision shape used by `PhysicsObject`.
|
|
5
|
+
*
|
|
6
|
+
* Circle and box colliders are centered on `body.position`. Box width and height
|
|
7
|
+
* are full extents, not half extents.
|
|
8
|
+
*/
|
|
3
9
|
export type Collider = {
|
|
4
10
|
type: "circle";
|
|
5
11
|
radius: number;
|
|
@@ -8,17 +14,44 @@ export type Collider = {
|
|
|
8
14
|
width: number;
|
|
9
15
|
height: number;
|
|
10
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Tests two axis-aligned box colliders for overlap.
|
|
19
|
+
*
|
|
20
|
+
* @returns Collision normal and penetration depth, or `null` when separated.
|
|
21
|
+
*/
|
|
11
22
|
export declare function aabbCollision(a: PhysicsObject, b: PhysicsObject): {
|
|
12
23
|
normal: Vector2d;
|
|
13
24
|
penetration: number;
|
|
14
25
|
} | null;
|
|
26
|
+
/**
|
|
27
|
+
* Tests two circle colliders for overlap.
|
|
28
|
+
*
|
|
29
|
+
* @returns Collision normal from `a` to `b` and penetration depth, or `null`.
|
|
30
|
+
*/
|
|
15
31
|
export declare function circleCollision(a: PhysicsObject, b: PhysicsObject): {
|
|
16
32
|
normal: Vector2d;
|
|
17
33
|
penetration: number;
|
|
18
34
|
} | null;
|
|
35
|
+
/**
|
|
36
|
+
* Tests a circle collider against a box collider.
|
|
37
|
+
*
|
|
38
|
+
* The returned normal points from the closest box point toward the circle.
|
|
39
|
+
*/
|
|
19
40
|
export declare function circleBoxCollision(circleObj: PhysicsObject, boxObj: PhysicsObject): {
|
|
20
41
|
normal: Vector2d;
|
|
21
42
|
penetration: number;
|
|
22
43
|
} | null;
|
|
44
|
+
/**
|
|
45
|
+
* Applies an impulse to two bodies so their velocities respond to a collision.
|
|
46
|
+
*
|
|
47
|
+
* Static bodies are treated as having inverse mass `0`, so only dynamic bodies
|
|
48
|
+
* receive velocity changes.
|
|
49
|
+
*/
|
|
23
50
|
export declare function resolveCollision(a: PhysicsObject, b: PhysicsObject, normal: Vector2d): void;
|
|
51
|
+
/**
|
|
52
|
+
* Moves overlapping bodies apart to remove visible penetration.
|
|
53
|
+
*
|
|
54
|
+
* The correction is distributed by inverse mass, so lighter dynamic bodies move
|
|
55
|
+
* more than heavier ones and static bodies do not move.
|
|
56
|
+
*/
|
|
24
57
|
export declare function positionalCorrection(a: PhysicsObject, b: PhysicsObject, normal: Vector2d, penetration: number): void;
|
|
@@ -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
|
}
|