samengine 1.6.5 → 1.7.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.
@@ -1 +1 @@
1
- export { version } from "./version.js";
1
+ export declare function version(): string;
@@ -1,2 +1,4 @@
1
- // Export the Version
2
- export { version } from "./version.js";
1
+ // Function to get the Version
2
+ export function version() {
3
+ return "1.7.0";
4
+ }
package/dist/index.d.ts CHANGED
@@ -3,7 +3,8 @@ export { renderText, renderBitmapText, drawRect, drawRectOutline, drawCircle, dr
3
3
  export type { Mouse } from "./input.js";
4
4
  export { setupInput, isKeyJustPressed, resetInput, getMouse } from "./input.js";
5
5
  export { dlog } from "./logger.js";
6
- export { saveGame, loadGame, clearSave } from "./save.js";
6
+ export type { SaveData } from "./save.js";
7
+ export { SAVE_KEY, saveGame, loadGame, clearSave, exportSave } from "./save.js";
7
8
  export type { Texture, DrawOptions, TextureAtlas, Animation, } from "./texture.js";
8
9
  export { loadTextureAsync, getTexture, drawTexture, loadAtlas, drawAtlasFrame, AnimationPlayer, drawAnimation, getFlipFromDirection, } from "./texture.js";
9
10
  export { createCanvas, enableFullscreen, setupFullscreenButton } from "./html.js";
package/dist/index.js CHANGED
@@ -5,8 +5,7 @@ export { renderText, renderBitmapText, drawRect, drawRectOutline, drawCircle, dr
5
5
  export { setupInput, isKeyJustPressed, resetInput, getMouse } from "./input.js";
6
6
  // Logging
7
7
  export { dlog } from "./logger.js";
8
- // Save System
9
- export { saveGame, loadGame, clearSave } from "./save.js";
8
+ export { SAVE_KEY, saveGame, loadGame, clearSave, exportSave } from "./save.js";
10
9
  export { loadTextureAsync, getTexture, drawTexture, loadAtlas, drawAtlasFrame, AnimationPlayer, drawAnimation, getFlipFromDirection, } from "./texture.js";
11
10
  // HTML Generation
12
11
  export { createCanvas, enableFullscreen, setupFullscreenButton } from "./html.js";
@@ -0,0 +1,24 @@
1
+ import { Vector2d } from "../types/vector2d.js";
2
+ import { PhysicsObject } from "./physicsObject.js";
3
+ export type Collider = {
4
+ type: "circle";
5
+ radius: number;
6
+ } | {
7
+ type: "box";
8
+ width: number;
9
+ height: number;
10
+ };
11
+ export declare function aabbCollision(a: PhysicsObject, b: PhysicsObject): {
12
+ normal: Vector2d;
13
+ penetration: number;
14
+ } | null;
15
+ export declare function circleCollision(a: PhysicsObject, b: PhysicsObject): {
16
+ normal: Vector2d;
17
+ penetration: number;
18
+ } | null;
19
+ export declare function circleBoxCollision(circleObj: PhysicsObject, boxObj: PhysicsObject): {
20
+ normal: Vector2d;
21
+ penetration: number;
22
+ } | null;
23
+ export declare function resolveCollision(a: PhysicsObject, b: PhysicsObject, normal: Vector2d): void;
24
+ export declare function positionalCorrection(a: PhysicsObject, b: PhysicsObject, normal: Vector2d, penetration: number): void;
@@ -0,0 +1,94 @@
1
+ import { add2d, dot2d, length2d, makeVector2d, normalize2d, scale2d, subtract2d } from "../types/vector2d.js";
2
+ import { clamp } from "../utils/math.js";
3
+ export function aabbCollision(a, b) {
4
+ const posA = a.body.position;
5
+ const posB = b.body.position;
6
+ const boxA = a.collider;
7
+ const boxB = b.collider;
8
+ const halfA = makeVector2d(boxA.width / 2, boxA.height / 2);
9
+ const halfB = makeVector2d(boxB.width / 2, boxB.height / 2);
10
+ const diff = subtract2d(posB, posA);
11
+ const overlapX = halfA.x + halfB.x - Math.abs(diff.x);
12
+ const overlapY = halfA.y + halfB.y - Math.abs(diff.y);
13
+ if (overlapX > 0 && overlapY > 0) {
14
+ // kleinste Achse bestimmen
15
+ if (overlapX < overlapY) {
16
+ return {
17
+ normal: makeVector2d(Math.sign(diff.x), 0),
18
+ penetration: overlapX,
19
+ };
20
+ }
21
+ else {
22
+ return {
23
+ normal: makeVector2d(0, Math.sign(diff.y)),
24
+ penetration: overlapY,
25
+ };
26
+ }
27
+ }
28
+ return null;
29
+ }
30
+ export function circleCollision(a, b) {
31
+ const posA = a.body.position;
32
+ const posB = b.body.position;
33
+ const diff = subtract2d(posB, posA);
34
+ const dist = length2d(diff);
35
+ const rA = a.collider.radius;
36
+ const rB = b.collider.radius;
37
+ if (dist < rA + rB) {
38
+ return {
39
+ normal: normalize2d(diff),
40
+ penetration: rA + rB - dist,
41
+ };
42
+ }
43
+ return null;
44
+ }
45
+ export function circleBoxCollision(circleObj, boxObj) {
46
+ const circle = circleObj.collider;
47
+ const box = boxObj.collider;
48
+ const circlePos = circleObj.body.position;
49
+ const boxPos = boxObj.body.position;
50
+ const half = makeVector2d(box.width / 2, box.height / 2);
51
+ // nächster Punkt auf Box
52
+ const closestX = clamp(circlePos.x, boxPos.x - half.x, boxPos.x + half.x);
53
+ const closestY = clamp(circlePos.y, boxPos.y - half.y, boxPos.y + half.y);
54
+ const closest = makeVector2d(closestX, closestY);
55
+ const diff = subtract2d(circlePos, closest);
56
+ const dist = length2d(diff);
57
+ if (dist < circle.radius) {
58
+ const normal = dist === 0
59
+ ? makeVector2d(0, -1) // fallback
60
+ : normalize2d(diff);
61
+ return {
62
+ normal,
63
+ penetration: circle.radius - dist,
64
+ };
65
+ }
66
+ return null;
67
+ }
68
+ export function resolveCollision(a, b, normal) {
69
+ const rv = subtract2d(b.body.velocity, a.body.velocity);
70
+ const velAlongNormal = dot2d(rv, normal);
71
+ if (velAlongNormal > 0)
72
+ return;
73
+ const restitution = Math.min(a.body.restitution, b.body.restitution);
74
+ const invMassA = a.body.isStatic ? 0 : 1 / a.body.mass;
75
+ const invMassB = b.body.isStatic ? 0 : 1 / b.body.mass;
76
+ const j = -(1 + restitution) * velAlongNormal /
77
+ (invMassA + invMassB);
78
+ const impulse = scale2d(normal, j);
79
+ if (!a.body.isStatic)
80
+ a.body.velocity = subtract2d(a.body.velocity, scale2d(impulse, invMassA));
81
+ if (!b.body.isStatic)
82
+ b.body.velocity = subtract2d(b.body.velocity, scale2d(impulse, invMassB));
83
+ }
84
+ export function positionalCorrection(a, b, normal, penetration) {
85
+ const percent = 0.8; // Stärke
86
+ const slop = 0.01;
87
+ const invMassA = a.body.isStatic ? 0 : 1 / a.body.mass;
88
+ const invMassB = b.body.isStatic ? 0 : 1 / b.body.mass;
89
+ const correction = scale2d(scale2d(normal, Math.max(penetration - slop, 0) / (invMassA + invMassB)), percent);
90
+ if (!a.body.isStatic)
91
+ a.body.position = subtract2d(a.body.position, scale2d(correction, invMassA));
92
+ if (!b.body.isStatic)
93
+ b.body.position = add2d(b.body.position, scale2d(correction, invMassB));
94
+ }
@@ -0,0 +1,7 @@
1
+ import { Vector2d } from "../types/vector2d.js";
2
+ import { PhysicsObject } from "./physicsObject.js";
3
+ export declare class PhysicsWorld {
4
+ objects: PhysicsObject[];
5
+ gravity: Vector2d;
6
+ step(dt: number): void;
7
+ }
@@ -0,0 +1,63 @@
1
+ import { makeVector2d, scale2d, add2d } from "../types/vector2d.js";
2
+ import { aabbCollision, circleBoxCollision, circleCollision, positionalCorrection, resolveCollision } from "./collision.js";
3
+ // Exapmle for a Use Case
4
+ // const world = new PhysicsWorld();
5
+ // const ball1 = new PhysicsObject(
6
+ // new RigidBody(new Vec2(100, 100), 1, 0.9),
7
+ // { type: "circle", radius: 20 }
8
+ // );
9
+ // const ball2 = new PhysicsObject(
10
+ // new RigidBody(new Vec2(200, 100), 1, 0.9),
11
+ // { type: "circle", radius: 20 }
12
+ // );
13
+ // world.objects.push(ball1, ball2);
14
+ // // Game Loop
15
+ // function update(dt: number) {
16
+ // world.step(dt);
17
+ // }
18
+ export class PhysicsWorld {
19
+ constructor() {
20
+ this.objects = [];
21
+ this.gravity = makeVector2d(0, 500); // px/s²
22
+ }
23
+ step(dt) {
24
+ // Bewegung
25
+ for (const obj of this.objects) {
26
+ if (obj.body.isStatic)
27
+ continue;
28
+ obj.body.velocity = add2d(obj.body.velocity, scale2d(this.gravity, dt));
29
+ obj.body.position = add2d(obj.body.position, scale2d(obj.body.velocity, dt));
30
+ }
31
+ // Kollisionen
32
+ for (let i = 0; i < this.objects.length; i++) {
33
+ for (let j = i + 1; j < this.objects.length; j++) {
34
+ const a = this.objects[i];
35
+ const b = this.objects[j];
36
+ let collision = null;
37
+ // Circle vs Circle
38
+ if (a.collider.type === "circle" && b.collider.type === "circle") {
39
+ collision = circleCollision(a, b);
40
+ }
41
+ // Box vs Box
42
+ else if (a.collider.type === "box" && b.collider.type === "box") {
43
+ collision = aabbCollision(a, b);
44
+ }
45
+ // Circle vs Box
46
+ else if (a.collider.type === "circle" && b.collider.type === "box") {
47
+ collision = circleBoxCollision(a, b);
48
+ }
49
+ // Box vs Circle (umdrehen!)
50
+ else if (a.collider.type === "box" && b.collider.type === "circle") {
51
+ collision = circleBoxCollision(b, a);
52
+ if (collision) {
53
+ collision.normal = scale2d(collision.normal, -1);
54
+ }
55
+ }
56
+ if (collision) {
57
+ resolveCollision(a, b, collision.normal);
58
+ positionalCorrection(a, b, collision.normal, collision.penetration);
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,15 @@
1
+ import { Vector2d } from "../types/vector2d.js";
2
+ import { Collider } from "./collision.js";
3
+ export declare class RigidBody {
4
+ position: Vector2d;
5
+ velocity: Vector2d;
6
+ mass: number;
7
+ restitution: number;
8
+ isStatic: boolean;
9
+ constructor(pos: Vector2d, mass?: number, restitution?: number, isStatic?: boolean);
10
+ }
11
+ export declare class PhysicsObject {
12
+ body: RigidBody;
13
+ collider: Collider;
14
+ constructor(body: RigidBody, collider: Collider);
15
+ }
@@ -0,0 +1,16 @@
1
+ import { makeVector2d } from "../types/vector2d.js";
2
+ export class RigidBody {
3
+ constructor(pos, mass = 1, restitution = 0.8, isStatic = false) {
4
+ this.position = pos;
5
+ this.velocity = makeVector2d(0, 0);
6
+ this.mass = isStatic ? Infinity : mass;
7
+ this.restitution = restitution;
8
+ this.isStatic = isStatic;
9
+ }
10
+ }
11
+ export class PhysicsObject {
12
+ constructor(body, collider) {
13
+ this.body = body;
14
+ this.collider = collider;
15
+ }
16
+ }
package/dist/save.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- type SaveData = Record<string, any>;
1
+ export type SaveData = Record<string, any>;
2
+ export declare let SAVE_KEY: string;
2
3
  export declare function saveGame(data: SaveData): void;
3
4
  export declare function loadGame(): SaveData | null;
4
5
  export declare function clearSave(): void;
5
- export {};
6
+ export declare function exportSave(): void;
package/dist/save.js CHANGED
@@ -1,4 +1,5 @@
1
- const SAVE_KEY = "my_game_save";
1
+ // Please rename the SaveKey
2
+ export let SAVE_KEY = "my_game_save";
2
3
  export function saveGame(data) {
3
4
  try {
4
5
  const json = JSON.stringify(data);
@@ -25,3 +26,23 @@ export function clearSave() {
25
26
  localStorage.removeItem(SAVE_KEY);
26
27
  console.log("Save cleared!");
27
28
  }
29
+ export function exportSave() {
30
+ try {
31
+ const json = localStorage.getItem(SAVE_KEY);
32
+ if (!json) {
33
+ console.warn("No save data found.");
34
+ return;
35
+ }
36
+ const blob = new Blob([json], { type: "application/json" });
37
+ const url = URL.createObjectURL(blob);
38
+ const a = document.createElement("a");
39
+ a.href = url;
40
+ a.download = "savegame.json";
41
+ a.click();
42
+ URL.revokeObjectURL(url);
43
+ console.log("Save exported!");
44
+ }
45
+ catch (err) {
46
+ console.error("Export failed:", err);
47
+ }
48
+ }
@@ -1,4 +1,4 @@
1
- export { type Vector2d, makeVector2d, add2d, subtract2d, length2d, normalize2d, dot2d, distance2d, clamp2d, lerp2d, map2d } from "./vector2d.js";
1
+ export { type Vector2d, makeVector2d, add2d, subtract2d, length2d, normalize2d, dot2d, distance2d, clamp2d, lerp2d, map2d, scale2d } from "./vector2d.js";
2
2
  export { type Vector3d, makeVector3d, add3d, subtract3d, length3d, normalize3d, dot3d, crossprodukt3d, distance3d, clamp3d, lerp3d, map3d } from "./vector3d.js";
3
3
  export { type Color, makeColor, invertcolor, invertHexColor } from "./color.js";
4
4
  export { type Rect, makeRect, centerRectX, centerRectY, centerRect, isPointInRect, isMouseInRect, isRectClicked } from "./rectangle.js";
@@ -1,6 +1,6 @@
1
1
  // Types Export
2
2
  // Vector 2D
3
- export { makeVector2d, add2d, subtract2d, length2d, normalize2d, dot2d, distance2d, clamp2d, lerp2d, map2d } from "./vector2d.js";
3
+ export { makeVector2d, add2d, subtract2d, length2d, normalize2d, dot2d, distance2d, clamp2d, lerp2d, map2d, scale2d } from "./vector2d.js";
4
4
  // Vector 3D
5
5
  export { makeVector3d, add3d, subtract3d, length3d, normalize3d, dot3d, crossprodukt3d, distance3d, clamp3d, lerp3d, map3d } from "./vector3d.js";
6
6
  // Color Type
@@ -12,3 +12,4 @@ export declare function distance2d(v1: Vector2d, v2: Vector2d): number;
12
12
  export declare function clamp2d(vector: Vector2d, min: Vector2d, max: Vector2d): Vector2d;
13
13
  export declare function lerp2d(start: Vector2d, end: Vector2d, t: Vector2d): Vector2d;
14
14
  export declare function map2d(value: Vector2d, inMin: Vector2d, inMax: Vector2d, outMin: Vector2d, outMax: Vector2d): Vector2d;
15
+ export declare function scale2d(value: Vector2d, vscale: number): Vector2d;
@@ -1,5 +1,5 @@
1
1
  // 2 Dimensional Vector Type
2
- import { clamp, lerp, map } from "../utils/math.js";
2
+ import { clamp, lerp, map, scale } from "../utils/math.js";
3
3
  // Function to create an Object of Type Vector2D
4
4
  export function makeVector2d(x, y) {
5
5
  return {
@@ -70,3 +70,10 @@ export function map2d(value, inMin, inMax, outMin, outMax) {
70
70
  y: map(value.y, inMin.y, inMax.y, outMin.y, outMax.y),
71
71
  };
72
72
  }
73
+ // Function to scale a Vector
74
+ export function scale2d(value, vscale) {
75
+ return {
76
+ x: scale(value.x, vscale),
77
+ y: scale(value.y, vscale),
78
+ };
79
+ }
@@ -1,4 +1,4 @@
1
- export { clamp, lerp, map } from "./math.js";
1
+ export { clamp, lerp, map, scale } from "./math.js";
2
2
  export { parse as parseMarkdown, parseToDocument as parseMarkdownToDocument, exportcss as exportMarkdownCSS } from "./markdown.js";
3
3
  export type { JSONValue } from "./jsonc-parser.js";
4
4
  export { parseJSONC } from "./jsonc-parser.js";
@@ -1,6 +1,6 @@
1
1
  // Utils Package
2
2
  // Math Utilities
3
- export { clamp, lerp, map } from "./math.js";
3
+ export { clamp, lerp, map, scale } from "./math.js";
4
4
  // Markdown Parser
5
5
  export { parse as parseMarkdown, parseToDocument as parseMarkdownToDocument, exportcss as exportMarkdownCSS } from "./markdown.js";
6
6
  export { parseJSONC } from "./jsonc-parser.js";
@@ -1,3 +1,4 @@
1
1
  export declare function clamp(input: number, min: number, max: number): number;
2
2
  export declare function lerp(start: number, end: number, t: number): number;
3
3
  export declare function map(value: number, inMin: number, inMax: number, outMin: number, outMax: number): number;
4
+ export declare function scale(n1: number, n2: number): number;
@@ -10,3 +10,7 @@ export function lerp(start, end, t) {
10
10
  export function map(value, inMin, inMax, outMin, outMax) {
11
11
  return (outMax - outMin) * ((value - inMin) / (inMax - inMin)) + outMin;
12
12
  }
13
+ // Scale
14
+ export function scale(n1, n2) {
15
+ return n1 * n2;
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samengine",
3
- "version": "1.6.5",
3
+ "version": "1.7.0",
4
4
  "description": "A TypeScript game library to make HTML Games",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -29,7 +29,6 @@
29
29
  "@types/node": "^25.5.2",
30
30
  "typescript": "^6.0.2"
31
31
  },
32
- "dependencies": {},
33
32
  "repository": {
34
33
  "type": "git",
35
34
  "url": "https://github.com/shadowdara/samengine"
@@ -1 +0,0 @@
1
- export declare function version(): string;
@@ -1,4 +0,0 @@
1
- // Function to get the Version
2
- export function version() {
3
- return "1.6.5";
4
- }