samengine 1.6.4
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/README.md +145 -0
- package/dist/build/index.d.ts +1 -0
- package/dist/build/index.js +2 -0
- package/dist/build/version.d.ts +1 -0
- package/dist/build/version.js +4 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +13 -0
- package/dist/html.d.ts +18 -0
- package/dist/html.js +66 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +14 -0
- package/dist/input.d.ts +17 -0
- package/dist/input.js +111 -0
- package/dist/keys.d.ts +52 -0
- package/dist/keys.js +55 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +16 -0
- package/dist/renderer.d.ts +13 -0
- package/dist/renderer.js +81 -0
- package/dist/save.d.ts +5 -0
- package/dist/save.js +27 -0
- package/dist/sound/audioplayer.d.ts +17 -0
- package/dist/sound/audioplayer.js +84 -0
- package/dist/sound/index.d.ts +1 -0
- package/dist/sound/index.js +2 -0
- package/dist/texture.d.ts +37 -0
- package/dist/texture.js +171 -0
- package/dist/types/circle.d.ts +14 -0
- package/dist/types/circle.js +38 -0
- package/dist/types/color.d.ts +9 -0
- package/dist/types/color.js +27 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +13 -0
- package/dist/types/rectangle.d.ts +16 -0
- package/dist/types/rectangle.js +41 -0
- package/dist/types/triangle.d.ts +16 -0
- package/dist/types/triangle.js +49 -0
- package/dist/types/vector2d.d.ts +14 -0
- package/dist/types/vector2d.js +72 -0
- package/dist/types/vector3d.d.ts +16 -0
- package/dist/types/vector3d.js +86 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/jsonc-parser.d.ts +4 -0
- package/dist/utils/jsonc-parser.js +166 -0
- package/dist/utils/markdown.d.ts +41 -0
- package/dist/utils/markdown.js +657 -0
- package/dist/utils/math.d.ts +3 -0
- package/dist/utils/math.js +12 -0
- package/package.json +41 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class SoundSystem {
|
|
2
|
+
private ctx;
|
|
3
|
+
private bufferCache;
|
|
4
|
+
private activeSources;
|
|
5
|
+
private masterGain;
|
|
6
|
+
constructor();
|
|
7
|
+
load(url: string): Promise<AudioBuffer>;
|
|
8
|
+
play(url: string, options?: {
|
|
9
|
+
volume?: number;
|
|
10
|
+
loop?: boolean;
|
|
11
|
+
playbackRate?: number;
|
|
12
|
+
}): Promise<AudioBufferSourceNode>;
|
|
13
|
+
stopAll(): void;
|
|
14
|
+
setVolume(v: number): void;
|
|
15
|
+
resume(): Promise<void>;
|
|
16
|
+
pause(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export class SoundSystem {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.bufferCache = new Map();
|
|
4
|
+
this.activeSources = new Set();
|
|
5
|
+
// 👉 zuerst globalen nehmen, sonst neuen erstellen
|
|
6
|
+
this.ctx = window.__audioCtx ?? new AudioContext();
|
|
7
|
+
this.masterGain = this.ctx.createGain();
|
|
8
|
+
this.masterGain.gain.value = 1;
|
|
9
|
+
this.masterGain.connect(this.ctx.destination);
|
|
10
|
+
}
|
|
11
|
+
// ================= LOAD =================
|
|
12
|
+
async load(url) {
|
|
13
|
+
if (this.bufferCache.has(url)) {
|
|
14
|
+
return this.bufferCache.get(url);
|
|
15
|
+
}
|
|
16
|
+
let arrayBuffer;
|
|
17
|
+
// Check if resource is embedded in single-file export
|
|
18
|
+
const loadResource = window.__loadResource;
|
|
19
|
+
if (loadResource) {
|
|
20
|
+
const dataUri = loadResource(url);
|
|
21
|
+
if (dataUri) {
|
|
22
|
+
// Convert data URI to ArrayBuffer
|
|
23
|
+
const response = await fetch(dataUri);
|
|
24
|
+
arrayBuffer = await response.arrayBuffer();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Fallback to fetch if resource not found
|
|
28
|
+
const res = await fetch(url);
|
|
29
|
+
arrayBuffer = await res.arrayBuffer();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// Normal fetch for multi-file export
|
|
34
|
+
const res = await fetch(url);
|
|
35
|
+
arrayBuffer = await res.arrayBuffer();
|
|
36
|
+
}
|
|
37
|
+
const buffer = await this.ctx.decodeAudioData(arrayBuffer);
|
|
38
|
+
this.bufferCache.set(url, buffer);
|
|
39
|
+
return buffer;
|
|
40
|
+
}
|
|
41
|
+
// ================= PLAY =================
|
|
42
|
+
async play(url, options = {}) {
|
|
43
|
+
const buffer = await this.load(url);
|
|
44
|
+
const source = this.ctx.createBufferSource();
|
|
45
|
+
source.buffer = buffer;
|
|
46
|
+
source.loop = options.loop ?? false;
|
|
47
|
+
source.playbackRate.value = options.playbackRate ?? 1;
|
|
48
|
+
const gain = this.ctx.createGain();
|
|
49
|
+
gain.gain.value = options.volume ?? 1;
|
|
50
|
+
source.connect(gain);
|
|
51
|
+
gain.connect(this.masterGain);
|
|
52
|
+
source.start(0);
|
|
53
|
+
this.activeSources.add(source);
|
|
54
|
+
source.onended = () => {
|
|
55
|
+
this.activeSources.delete(source);
|
|
56
|
+
};
|
|
57
|
+
return source;
|
|
58
|
+
}
|
|
59
|
+
// ================= STOP =================
|
|
60
|
+
stopAll() {
|
|
61
|
+
for (const s of this.activeSources) {
|
|
62
|
+
try {
|
|
63
|
+
s.stop();
|
|
64
|
+
}
|
|
65
|
+
catch { }
|
|
66
|
+
}
|
|
67
|
+
this.activeSources.clear();
|
|
68
|
+
}
|
|
69
|
+
// ================= GLOBAL VOLUME =================
|
|
70
|
+
setVolume(v) {
|
|
71
|
+
this.masterGain.gain.value = v;
|
|
72
|
+
}
|
|
73
|
+
// ================= CONTEXT CONTROL =================
|
|
74
|
+
async resume() {
|
|
75
|
+
if (this.ctx.state === "suspended") {
|
|
76
|
+
await this.ctx.resume();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async pause() {
|
|
80
|
+
if (this.ctx.state === "running") {
|
|
81
|
+
await this.ctx.suspend();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SoundSystem } from "./audioplayer.js";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Rect } from "./types/rectangle.js";
|
|
2
|
+
export type Texture = HTMLImageElement | undefined;
|
|
3
|
+
export type DrawOptions = {
|
|
4
|
+
width?: number;
|
|
5
|
+
height?: number;
|
|
6
|
+
rotation?: number;
|
|
7
|
+
flipX?: boolean;
|
|
8
|
+
flipY?: boolean;
|
|
9
|
+
scale?: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function loadTextureAsync(src: string): Promise<HTMLImageElement>;
|
|
12
|
+
export declare function getTexture(src: string): Texture;
|
|
13
|
+
export declare function drawTexture(ctx: CanvasRenderingContext2D, texture: Texture, x: number, y: number, options?: DrawOptions): void;
|
|
14
|
+
export type TextureAtlas = {
|
|
15
|
+
image: HTMLImageElement;
|
|
16
|
+
frames: Record<string, Rect>;
|
|
17
|
+
};
|
|
18
|
+
export declare function loadAtlas(imageSrc: string, dataSrc: string): Promise<TextureAtlas>;
|
|
19
|
+
export declare function drawAtlasFrame(ctx: CanvasRenderingContext2D, atlas: TextureAtlas, frameName: string, x: number, y: number, options?: DrawOptions): void;
|
|
20
|
+
export declare class AnimationPlayer {
|
|
21
|
+
animation: Animation;
|
|
22
|
+
private time;
|
|
23
|
+
private currentFrameIndex;
|
|
24
|
+
private finished;
|
|
25
|
+
constructor(animation: Animation);
|
|
26
|
+
update(deltaTime: number): void;
|
|
27
|
+
getCurrentFrame(): string;
|
|
28
|
+
reset(): void;
|
|
29
|
+
isFinished(): boolean;
|
|
30
|
+
}
|
|
31
|
+
export type Animation = {
|
|
32
|
+
frames: string[];
|
|
33
|
+
fps: number;
|
|
34
|
+
loop?: boolean;
|
|
35
|
+
};
|
|
36
|
+
export declare function drawAnimation(ctx: CanvasRenderingContext2D, atlas: TextureAtlas, player: AnimationPlayer, x: number, y: number, options?: DrawOptions): void;
|
|
37
|
+
export declare function getFlipFromDirection(dir: number): boolean;
|
package/dist/texture.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { dlog } from "./logger.js";
|
|
2
|
+
const textures = {};
|
|
3
|
+
function getresourcepath(path) {
|
|
4
|
+
return "resources/" + path;
|
|
5
|
+
}
|
|
6
|
+
// Function to load a Texture Async
|
|
7
|
+
export function loadTextureAsync(src) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
// Wenn schon geladen
|
|
10
|
+
const existing = getTexture(src);
|
|
11
|
+
if (existing)
|
|
12
|
+
return resolve(existing);
|
|
13
|
+
const img = new Image();
|
|
14
|
+
// 🔹 Hier Pfad modifizieren, z.B. Prefix hinzufügen
|
|
15
|
+
let finalSrc = getresourcepath(src);
|
|
16
|
+
const cacheKey = finalSrc;
|
|
17
|
+
// Check if resources are embedded (single file build)
|
|
18
|
+
const embeddedResources = window.__resources;
|
|
19
|
+
if (embeddedResources && embeddedResources[src]) {
|
|
20
|
+
// Use embedded resource (data URI)
|
|
21
|
+
finalSrc = embeddedResources[src];
|
|
22
|
+
}
|
|
23
|
+
img.onload = () => {
|
|
24
|
+
// Cache speichern - always use the same cache key for consistency
|
|
25
|
+
textures[cacheKey] = img;
|
|
26
|
+
resolve(img);
|
|
27
|
+
};
|
|
28
|
+
img.onerror = () => {
|
|
29
|
+
const msg = `❌ Failed to load texture: ${finalSrc}`;
|
|
30
|
+
console.error(msg);
|
|
31
|
+
reject(new Error(msg));
|
|
32
|
+
};
|
|
33
|
+
// 🔹 Bild laden mit finalem Pfad
|
|
34
|
+
img.src = finalSrc;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
// Function to get the Texture
|
|
38
|
+
export function getTexture(src) {
|
|
39
|
+
return textures[getresourcepath(src)];
|
|
40
|
+
}
|
|
41
|
+
// Function to draw a texture to the Screen
|
|
42
|
+
export function drawTexture(ctx, texture, x, y, options = {}) {
|
|
43
|
+
const { width, height, rotation = 0, flipX = false, flipY = false, scale = 1 } = options;
|
|
44
|
+
if (!texture) {
|
|
45
|
+
dlog("Texture not found");
|
|
46
|
+
ctx.fillStyle = "magenta";
|
|
47
|
+
ctx.fillRect(x, y, (width ?? 32) * scale, (height ?? 32) * scale);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const w = (width ?? texture.width) * scale; // 🔹 scale anwenden
|
|
51
|
+
const h = (height ?? texture.height) * scale; // 🔹 scale anwenden
|
|
52
|
+
ctx.save();
|
|
53
|
+
const cx = x + w / 2;
|
|
54
|
+
const cy = y + h / 2;
|
|
55
|
+
ctx.translate(cx, cy);
|
|
56
|
+
ctx.rotate(rotation);
|
|
57
|
+
ctx.scale(flipX ? -1 : 1, flipY ? -1 : 1);
|
|
58
|
+
ctx.drawImage(texture, -w / 2, -h / 2, w, h);
|
|
59
|
+
ctx.restore();
|
|
60
|
+
}
|
|
61
|
+
// Funtion to load an Atlas
|
|
62
|
+
//
|
|
63
|
+
// JSON Format for the LoadAtlas Function
|
|
64
|
+
//
|
|
65
|
+
// {
|
|
66
|
+
// "frames": {
|
|
67
|
+
// "player_idle_0": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
68
|
+
// "player_idle_1": { "x": 32, "y": 0, "w": 32, "h": 32 }
|
|
69
|
+
// }
|
|
70
|
+
// }
|
|
71
|
+
//
|
|
72
|
+
export async function loadAtlas(imageSrc, dataSrc) {
|
|
73
|
+
const [image, data] = await Promise.all([
|
|
74
|
+
loadTextureAsync(imageSrc),
|
|
75
|
+
fetch(getresourcepath(dataSrc)).then(r => r.json())
|
|
76
|
+
]);
|
|
77
|
+
return {
|
|
78
|
+
image,
|
|
79
|
+
frames: data.frames
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function drawAtlasFrame(ctx, atlas, frameName, x, y, options = {}) {
|
|
83
|
+
const { width, height, rotation = 0, flipX = false, flipY = false, scale = 1 } = options;
|
|
84
|
+
const frame = atlas.frames[frameName];
|
|
85
|
+
if (!frame) {
|
|
86
|
+
dlog(`Frame not found: ${frameName}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const w = (width ?? frame.width) * scale;
|
|
90
|
+
const h = (height ?? frame.height) * scale;
|
|
91
|
+
ctx.save();
|
|
92
|
+
const cx = x + w / 2;
|
|
93
|
+
const cy = y + h / 2;
|
|
94
|
+
ctx.translate(cx, cy);
|
|
95
|
+
ctx.rotate(rotation);
|
|
96
|
+
ctx.scale(flipX ? -1 : 1, flipY ? -1 : 1);
|
|
97
|
+
ctx.drawImage(atlas.image, frame.x, frame.y, frame.width, frame.height, -w / 2, -h / 2, w, h);
|
|
98
|
+
ctx.restore();
|
|
99
|
+
}
|
|
100
|
+
//
|
|
101
|
+
//
|
|
102
|
+
// Animation Player
|
|
103
|
+
//
|
|
104
|
+
//
|
|
105
|
+
//
|
|
106
|
+
// // Define Animation
|
|
107
|
+
// const walkAnimation: Animation = {
|
|
108
|
+
// frames: ["walk_0", "walk_1", "walk_2", "walk_3"],
|
|
109
|
+
// fps: 8,
|
|
110
|
+
// loop: true
|
|
111
|
+
// };
|
|
112
|
+
//
|
|
113
|
+
// const player = new AnimationPlayer(walkAnimation);
|
|
114
|
+
//
|
|
115
|
+
// // Game Loop
|
|
116
|
+
// function update(dt: number) {
|
|
117
|
+
// player.update(dt);
|
|
118
|
+
// }
|
|
119
|
+
//
|
|
120
|
+
// function render(ctx: CanvasRenderingContext2D) {
|
|
121
|
+
// drawAnimation(ctx, atlas, player, 100, 100, 64, 64);
|
|
122
|
+
// }
|
|
123
|
+
//
|
|
124
|
+
//
|
|
125
|
+
// Animation Player Class
|
|
126
|
+
export class AnimationPlayer {
|
|
127
|
+
// Konstruktor Function
|
|
128
|
+
constructor(animation) {
|
|
129
|
+
this.animation = animation;
|
|
130
|
+
this.time = 0;
|
|
131
|
+
this.currentFrameIndex = 0;
|
|
132
|
+
this.finished = false;
|
|
133
|
+
}
|
|
134
|
+
update(deltaTime) {
|
|
135
|
+
if (this.finished)
|
|
136
|
+
return;
|
|
137
|
+
this.time += deltaTime;
|
|
138
|
+
const frameDuration = 1 / this.animation.fps;
|
|
139
|
+
while (this.time >= frameDuration) {
|
|
140
|
+
this.time -= frameDuration;
|
|
141
|
+
this.currentFrameIndex++;
|
|
142
|
+
if (this.currentFrameIndex >= this.animation.frames.length) {
|
|
143
|
+
if (this.animation.loop) {
|
|
144
|
+
this.currentFrameIndex = 0;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.currentFrameIndex = this.animation.frames.length - 1;
|
|
148
|
+
this.finished = true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
getCurrentFrame() {
|
|
154
|
+
return this.animation.frames[this.currentFrameIndex];
|
|
155
|
+
}
|
|
156
|
+
reset() {
|
|
157
|
+
this.time = 0;
|
|
158
|
+
this.currentFrameIndex = 0;
|
|
159
|
+
this.finished = false;
|
|
160
|
+
}
|
|
161
|
+
isFinished() {
|
|
162
|
+
return this.finished;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
export function drawAnimation(ctx, atlas, player, x, y, options = {}) {
|
|
166
|
+
const frame = player.getCurrentFrame();
|
|
167
|
+
drawAtlasFrame(ctx, atlas, frame, x, y, options);
|
|
168
|
+
}
|
|
169
|
+
export function getFlipFromDirection(dir) {
|
|
170
|
+
return dir < 0; // links = true
|
|
171
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Mouse } from "../input.js";
|
|
2
|
+
import { type Vector2d } from "./vector2d.js";
|
|
3
|
+
export type Circle = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
radius: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function makeCircle(x: number, y: number, radius: number): Circle;
|
|
9
|
+
export declare function centerCircle(circle: Circle): Vector2d;
|
|
10
|
+
export declare function isPointInCircle(x: number, y: number, circle: Circle): boolean;
|
|
11
|
+
export declare function isMouseInCircle(mouse: Mouse, circle: Circle): boolean;
|
|
12
|
+
export declare function isCircleClicked(mouse: Mouse, circle: Circle): boolean;
|
|
13
|
+
export declare function isCircleColliding(circle1: Circle, circle2: Circle): boolean;
|
|
14
|
+
export declare function getCircleDistance(circle1: Circle, circle2: Circle): number;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Circle Type for Hitboxes
|
|
2
|
+
// Function to create an Object of Type Circle
|
|
3
|
+
export function makeCircle(x, y, radius) {
|
|
4
|
+
return {
|
|
5
|
+
x: x,
|
|
6
|
+
y: y,
|
|
7
|
+
radius: radius,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
// Function to get the Center of the Circle as Vector2d
|
|
11
|
+
export function centerCircle(circle) {
|
|
12
|
+
return { x: circle.x, y: circle.y };
|
|
13
|
+
}
|
|
14
|
+
// Check if a Point is in the Circle
|
|
15
|
+
export function isPointInCircle(x, y, circle) {
|
|
16
|
+
const distance = Math.sqrt((x - circle.x) * (x - circle.x) +
|
|
17
|
+
(y - circle.y) * (y - circle.y));
|
|
18
|
+
return distance <= circle.radius;
|
|
19
|
+
}
|
|
20
|
+
// Check if Mouse is in the Circle
|
|
21
|
+
export function isMouseInCircle(mouse, circle) {
|
|
22
|
+
return isPointInCircle(mouse.x, mouse.y, circle);
|
|
23
|
+
}
|
|
24
|
+
// Function to check if a Circle is clicked
|
|
25
|
+
export function isCircleClicked(mouse, circle) {
|
|
26
|
+
return isMouseInCircle(mouse, circle) && mouse.justPressed;
|
|
27
|
+
}
|
|
28
|
+
// Check if two Circles collide
|
|
29
|
+
export function isCircleColliding(circle1, circle2) {
|
|
30
|
+
const distance = Math.sqrt((circle1.x - circle2.x) * (circle1.x - circle2.x) +
|
|
31
|
+
(circle1.y - circle2.y) * (circle1.y - circle2.y));
|
|
32
|
+
return distance <= (circle1.radius + circle2.radius);
|
|
33
|
+
}
|
|
34
|
+
// Check if Circle collides with Rectangle (imported from rectangle.ts would cause circular dependency)
|
|
35
|
+
export function getCircleDistance(circle1, circle2) {
|
|
36
|
+
return Math.sqrt((circle1.x - circle2.x) * (circle1.x - circle2.x) +
|
|
37
|
+
(circle1.y - circle2.y) * (circle1.y - circle2.y));
|
|
38
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type Color = {
|
|
2
|
+
r: number;
|
|
3
|
+
g: number;
|
|
4
|
+
b: number;
|
|
5
|
+
a?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function makeColor(r: number, g: number, b: number, a?: number): Color;
|
|
8
|
+
export declare function invertcolor(color: Color): Color;
|
|
9
|
+
export declare function invertHexColor(hex: string): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Function to create an Object of Type Color
|
|
2
|
+
export function makeColor(r, g, b, a) {
|
|
3
|
+
return {
|
|
4
|
+
r: r,
|
|
5
|
+
g: g,
|
|
6
|
+
b: b,
|
|
7
|
+
a: a
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function invertcolor(color) {
|
|
11
|
+
return {
|
|
12
|
+
r: 255 - color.r,
|
|
13
|
+
g: 255 - color.g,
|
|
14
|
+
b: 255 - color.b,
|
|
15
|
+
...(color.a !== undefined ? { a: color.a } : {}) // optional alpha behalten
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function invertHexColor(hex) {
|
|
19
|
+
// Entferne das führende #
|
|
20
|
+
const cleanHex = hex.replace('#', '');
|
|
21
|
+
// Wandeln in R, G, B
|
|
22
|
+
const r = 255 - parseInt(cleanHex.slice(0, 2), 16);
|
|
23
|
+
const g = 255 - parseInt(cleanHex.slice(2, 4), 16);
|
|
24
|
+
const b = 255 - parseInt(cleanHex.slice(4, 6), 16);
|
|
25
|
+
// Zurück in Hex-String
|
|
26
|
+
return '#' + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
|
|
27
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { type Vector2d, makeVector2d, add2d, subtract2d, length2d, normalize2d, dot2d, distance2d, clamp2d, lerp2d, map2d } from "./vector2d.js";
|
|
2
|
+
export { type Vector3d, makeVector3d, add3d, subtract3d, length3d, normalize3d, dot3d, crossprodukt3d, distance3d, clamp3d, lerp3d, map3d } from "./vector3d.js";
|
|
3
|
+
export { type Color, makeColor, invertcolor, invertHexColor } from "./color.js";
|
|
4
|
+
export { type Rect, makeRect, centerRectX, centerRectY, centerRect, isPointInRect, isMouseInRect, isRectClicked } from "./rectangle.js";
|
|
5
|
+
export { type Circle, makeCircle, centerCircle, isPointInCircle, isMouseInCircle, isCircleClicked, isCircleColliding, getCircleDistance } from "./circle.js";
|
|
6
|
+
export { type Triangle, makeTriangle, centerTriangle, isPointInTriangle, isMouseInTriangle, isTriangleClicked, getTrianglePerimeter, } from "./triangle.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Types Export
|
|
2
|
+
// Vector 2D
|
|
3
|
+
export { makeVector2d, add2d, subtract2d, length2d, normalize2d, dot2d, distance2d, clamp2d, lerp2d, map2d } from "./vector2d.js";
|
|
4
|
+
// Vector 3D
|
|
5
|
+
export { makeVector3d, add3d, subtract3d, length3d, normalize3d, dot3d, crossprodukt3d, distance3d, clamp3d, lerp3d, map3d } from "./vector3d.js";
|
|
6
|
+
// Color Type
|
|
7
|
+
export { makeColor, invertcolor, invertHexColor } from "./color.js";
|
|
8
|
+
// Retangle Type
|
|
9
|
+
export { makeRect, centerRectX, centerRectY, centerRect, isPointInRect, isMouseInRect, isRectClicked } from "./rectangle.js";
|
|
10
|
+
// Circle Type
|
|
11
|
+
export { makeCircle, centerCircle, isPointInCircle, isMouseInCircle, isCircleClicked, isCircleColliding, getCircleDistance } from "./circle.js";
|
|
12
|
+
// Triangle Type
|
|
13
|
+
export { makeTriangle, centerTriangle, isPointInTriangle, isMouseInTriangle, isTriangleClicked, getTrianglePerimeter, } from "./triangle.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Mouse } from "../input.js";
|
|
2
|
+
import { type Vector2d } from "./vector2d.js";
|
|
3
|
+
export type Rect = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
borderRadius?: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function makeRect(x: number, y: number, width: number, height: number, borderRadius?: number): Rect;
|
|
11
|
+
export declare function centerRectX(rect: Rect): number;
|
|
12
|
+
export declare function centerRectY(rect: Rect): number;
|
|
13
|
+
export declare function centerRect(rect: Rect): Vector2d;
|
|
14
|
+
export declare function isPointInRect(x: number, y: number, rect: Rect): boolean;
|
|
15
|
+
export declare function isMouseInRect(mouse: Mouse, rect: Rect): boolean;
|
|
16
|
+
export declare function isRectClicked(mouse: Mouse, rect: Rect): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Rectangle Type for Hitboxes
|
|
2
|
+
// Function to create an Object of Type rect
|
|
3
|
+
export function makeRect(x, y, width, height, borderRadius = 0) {
|
|
4
|
+
return {
|
|
5
|
+
x: x,
|
|
6
|
+
y: y,
|
|
7
|
+
height: height,
|
|
8
|
+
width: width,
|
|
9
|
+
borderRadius: borderRadius
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
// Function to get the Center of the Width of the Object
|
|
13
|
+
export function centerRectX(rect) {
|
|
14
|
+
return (rect.x + (rect.width / 2));
|
|
15
|
+
}
|
|
16
|
+
// Function to get the Center of the Height of the Object
|
|
17
|
+
export function centerRectY(rect) {
|
|
18
|
+
return (rect.y + (rect.height / 2));
|
|
19
|
+
}
|
|
20
|
+
// Get the Center of a Rectangle
|
|
21
|
+
export function centerRect(rect) {
|
|
22
|
+
let vector = { x: centerRectX(rect), y: centerRectY(rect) };
|
|
23
|
+
return vector;
|
|
24
|
+
}
|
|
25
|
+
// Check if a Point in the Rectangle
|
|
26
|
+
export function isPointInRect(x, y, rect) {
|
|
27
|
+
return (x >= rect.x &&
|
|
28
|
+
x <= rect.x + rect.width &&
|
|
29
|
+
y >= rect.y &&
|
|
30
|
+
y <= rect.y + rect.height);
|
|
31
|
+
}
|
|
32
|
+
export function isMouseInRect(mouse, rect) {
|
|
33
|
+
return (mouse.x >= rect.x &&
|
|
34
|
+
mouse.x <= rect.x + rect.width &&
|
|
35
|
+
mouse.y >= rect.y &&
|
|
36
|
+
mouse.y <= rect.y + rect.height);
|
|
37
|
+
}
|
|
38
|
+
// Function to check if a Rectangle is clicked
|
|
39
|
+
export function isRectClicked(mouse, rect) {
|
|
40
|
+
return isMouseInRect(mouse, rect) && mouse.justPressed;
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Mouse } from "../input.js";
|
|
2
|
+
import { type Vector2d } from "./vector2d.js";
|
|
3
|
+
export type Triangle = {
|
|
4
|
+
x1: number;
|
|
5
|
+
y1: number;
|
|
6
|
+
x2: number;
|
|
7
|
+
y2: number;
|
|
8
|
+
x3: number;
|
|
9
|
+
y3: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function makeTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): Triangle;
|
|
12
|
+
export declare function centerTriangle(triangle: Triangle): Vector2d;
|
|
13
|
+
export declare function isPointInTriangle(x: number, y: number, triangle: Triangle): boolean;
|
|
14
|
+
export declare function isMouseInTriangle(mouse: Mouse, triangle: Triangle): boolean;
|
|
15
|
+
export declare function isTriangleClicked(mouse: Mouse, triangle: Triangle): boolean;
|
|
16
|
+
export declare function getTrianglePerimeter(triangle: Triangle): number;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Triangle Type for Hitboxes
|
|
2
|
+
// Function to create an Object of Type triangle
|
|
3
|
+
export function makeTriangle(x1, y1, x2, y2, x3, y3) {
|
|
4
|
+
return {
|
|
5
|
+
x1: x1,
|
|
6
|
+
x2: x2,
|
|
7
|
+
x3: x3,
|
|
8
|
+
y1: y1,
|
|
9
|
+
y2: y2,
|
|
10
|
+
y3: y3,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// Helper function to calculate the area of a triangle (used for point-in-triangle)
|
|
14
|
+
function getTriangleArea(x1, y1, x2, y2, x3, y3) {
|
|
15
|
+
return Math.abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0);
|
|
16
|
+
}
|
|
17
|
+
// Function to get the Center of the Triangle
|
|
18
|
+
export function centerTriangle(triangle) {
|
|
19
|
+
return {
|
|
20
|
+
x: (triangle.x1 + triangle.x2 + triangle.x3) / 3,
|
|
21
|
+
y: (triangle.y1 + triangle.y2 + triangle.y3) / 3
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// Check if a Point is in the Triangle using barycentric coordinates
|
|
25
|
+
export function isPointInTriangle(x, y, triangle) {
|
|
26
|
+
const areaTriangle = getTriangleArea(triangle.x1, triangle.y1, triangle.x2, triangle.y2, triangle.x3, triangle.y3);
|
|
27
|
+
const area1 = getTriangleArea(x, y, triangle.x2, triangle.y2, triangle.x3, triangle.y3);
|
|
28
|
+
const area2 = getTriangleArea(triangle.x1, triangle.y1, x, y, triangle.x3, triangle.y3);
|
|
29
|
+
const area3 = getTriangleArea(triangle.x1, triangle.y1, triangle.x2, triangle.y2, x, y);
|
|
30
|
+
return Math.abs(areaTriangle - (area1 + area2 + area3)) < 0.01;
|
|
31
|
+
}
|
|
32
|
+
// Check if Mouse is in the Triangle
|
|
33
|
+
export function isMouseInTriangle(mouse, triangle) {
|
|
34
|
+
return isPointInTriangle(mouse.x, mouse.y, triangle);
|
|
35
|
+
}
|
|
36
|
+
// Function to check if a Triangle is clicked
|
|
37
|
+
export function isTriangleClicked(mouse, triangle) {
|
|
38
|
+
return isMouseInTriangle(mouse, triangle) && mouse.justPressed;
|
|
39
|
+
}
|
|
40
|
+
// Get the Perimeter of the Triangle
|
|
41
|
+
export function getTrianglePerimeter(triangle) {
|
|
42
|
+
const side1 = Math.sqrt((triangle.x2 - triangle.x1) * (triangle.x2 - triangle.x1) +
|
|
43
|
+
(triangle.y2 - triangle.y1) * (triangle.y2 - triangle.y1));
|
|
44
|
+
const side2 = Math.sqrt((triangle.x3 - triangle.x2) * (triangle.x3 - triangle.x2) +
|
|
45
|
+
(triangle.y3 - triangle.y2) * (triangle.y3 - triangle.y2));
|
|
46
|
+
const side3 = Math.sqrt((triangle.x1 - triangle.x3) * (triangle.x1 - triangle.x3) +
|
|
47
|
+
(triangle.y1 - triangle.y3) * (triangle.y1 - triangle.y3));
|
|
48
|
+
return side1 + side2 + side3;
|
|
49
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type Vector2d = {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
};
|
|
5
|
+
export declare function makeVector2d(x: number, y: number): Vector2d;
|
|
6
|
+
export declare function add2d(vector1: Vector2d, vector2: Vector2d): Vector2d;
|
|
7
|
+
export declare function subtract2d(vector1: Vector2d, vector2: Vector2d): Vector2d;
|
|
8
|
+
export declare function length2d(vector: Vector2d): number;
|
|
9
|
+
export declare function normalize2d(vector: Vector2d): Vector2d;
|
|
10
|
+
export declare function dot2d(v1: Vector2d, v2: Vector2d): number;
|
|
11
|
+
export declare function distance2d(v1: Vector2d, v2: Vector2d): number;
|
|
12
|
+
export declare function clamp2d(vector: Vector2d, min: Vector2d, max: Vector2d): Vector2d;
|
|
13
|
+
export declare function lerp2d(start: Vector2d, end: Vector2d, t: Vector2d): Vector2d;
|
|
14
|
+
export declare function map2d(value: Vector2d, inMin: Vector2d, inMax: Vector2d, outMin: Vector2d, outMax: Vector2d): Vector2d;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// 2 Dimensional Vector Type
|
|
2
|
+
import { clamp, lerp, map } from "../utils/math.js";
|
|
3
|
+
// Function to create an Object of Type Vector2D
|
|
4
|
+
export function makeVector2d(x, y) {
|
|
5
|
+
return {
|
|
6
|
+
x: x,
|
|
7
|
+
y: y
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
// Function to add 2 Vectors together
|
|
11
|
+
export function add2d(vector1, vector2) {
|
|
12
|
+
return {
|
|
13
|
+
x: vector1.x + vector2.x,
|
|
14
|
+
y: vector1.y + vector2.y,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Function to subtract 2 Vectors from each other
|
|
18
|
+
export function subtract2d(vector1, vector2) {
|
|
19
|
+
return {
|
|
20
|
+
x: vector1.x - vector2.x,
|
|
21
|
+
y: vector1.y - vector2.y,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// Function to get the length from an Vector
|
|
25
|
+
export function length2d(vector) {
|
|
26
|
+
let produkt = vector.x * vector.x + vector.y * vector.y;
|
|
27
|
+
let root = Math.sqrt(produkt);
|
|
28
|
+
return root;
|
|
29
|
+
}
|
|
30
|
+
// Function to normalize a Vector 2d
|
|
31
|
+
export function normalize2d(vector) {
|
|
32
|
+
// Check if the Vector is zero because then you dont need to
|
|
33
|
+
// calculate sth
|
|
34
|
+
if (vector.x == 0 && vector.y == 0) {
|
|
35
|
+
return vector;
|
|
36
|
+
}
|
|
37
|
+
let root = length2d(vector);
|
|
38
|
+
vector.x = vector.x / root;
|
|
39
|
+
vector.y = vector.y / root;
|
|
40
|
+
return vector;
|
|
41
|
+
}
|
|
42
|
+
// Function to make scalar produkt from an Vector
|
|
43
|
+
export function dot2d(v1, v2) {
|
|
44
|
+
return (v1.x * v2.x + v1.y * v2.y);
|
|
45
|
+
}
|
|
46
|
+
// crossprodukt (only for 3 Dimensinal Vectors)
|
|
47
|
+
// Calculate the Distance between 2 Vectors
|
|
48
|
+
export function distance2d(v1, v2) {
|
|
49
|
+
let tmp = subtract2d(v1, v2);
|
|
50
|
+
return length2d(tmp);
|
|
51
|
+
}
|
|
52
|
+
// Function to clamp a Vector 2d
|
|
53
|
+
export function clamp2d(vector, min, max) {
|
|
54
|
+
return {
|
|
55
|
+
x: clamp(vector.x, min.x, max.x),
|
|
56
|
+
y: clamp(vector.y, min.y, max.y),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Lerp for a 2d Vector
|
|
60
|
+
export function lerp2d(start, end, t) {
|
|
61
|
+
return {
|
|
62
|
+
x: lerp(start.x, end.x, t.x),
|
|
63
|
+
y: lerp(start.y, end.y, t.y),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Map Function for a 2d Vector
|
|
67
|
+
export function map2d(value, inMin, inMax, outMin, outMax) {
|
|
68
|
+
return {
|
|
69
|
+
x: map(value.x, inMin.x, inMax.x, outMin.x, outMax.x),
|
|
70
|
+
y: map(value.y, inMin.y, inMax.y, outMin.y, outMax.y),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type Vector3d = {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
z: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function makeVector3d(x: number, y: number, z: number): Vector3d;
|
|
7
|
+
export declare function add3d(vector1: Vector3d, vector2: Vector3d): Vector3d;
|
|
8
|
+
export declare function subtract3d(vector1: Vector3d, vector2: Vector3d): Vector3d;
|
|
9
|
+
export declare function length3d(vector: Vector3d): number;
|
|
10
|
+
export declare function normalize3d(vector: Vector3d): Vector3d;
|
|
11
|
+
export declare function dot3d(v1: Vector3d, v2: Vector3d): number;
|
|
12
|
+
export declare function crossprodukt3d(v1: Vector3d, v2: Vector3d): Vector3d;
|
|
13
|
+
export declare function distance3d(v1: Vector3d, v2: Vector3d): number;
|
|
14
|
+
export declare function clamp3d(vector: Vector3d, min: Vector3d, max: Vector3d): Vector3d;
|
|
15
|
+
export declare function lerp3d(start: Vector3d, end: Vector3d, t: Vector3d): Vector3d;
|
|
16
|
+
export declare function map3d(value: Vector3d, inMin: Vector3d, inMax: Vector3d, outMin: Vector3d, outMax: Vector3d): Vector3d;
|