FIXME
This commit is contained in:
@@ -5,15 +5,15 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "nage",
|
"name": "nage",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.3.14",
|
"@biomejs/biome": "latest",
|
||||||
"@types/bun": "1.3.8",
|
"@types/bun": "latest",
|
||||||
"lz-string": "1.5.0",
|
"lz-string": "latest",
|
||||||
"solid-js": "1.9.11",
|
"solid-js": "latest",
|
||||||
"vite": "7.3.1",
|
"vite": "latest",
|
||||||
"vite-plugin-solid": "2.11.10",
|
"vite-plugin-solid": "latest",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "5.9.3",
|
"typescript": "latest",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -54,23 +54,23 @@
|
|||||||
|
|
||||||
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
||||||
|
|
||||||
"@biomejs/biome": ["@biomejs/biome@2.3.14", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.14", "@biomejs/cli-darwin-x64": "2.3.14", "@biomejs/cli-linux-arm64": "2.3.14", "@biomejs/cli-linux-arm64-musl": "2.3.14", "@biomejs/cli-linux-x64": "2.3.14", "@biomejs/cli-linux-x64-musl": "2.3.14", "@biomejs/cli-win32-arm64": "2.3.14", "@biomejs/cli-win32-x64": "2.3.14" }, "bin": { "biome": "bin/biome" } }, "sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA=="],
|
"@biomejs/biome": ["@biomejs/biome@2.4.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.4", "@biomejs/cli-darwin-x64": "2.4.4", "@biomejs/cli-linux-arm64": "2.4.4", "@biomejs/cli-linux-arm64-musl": "2.4.4", "@biomejs/cli-linux-x64": "2.4.4", "@biomejs/cli-linux-x64-musl": "2.4.4", "@biomejs/cli-win32-arm64": "2.4.4", "@biomejs/cli-win32-x64": "2.4.4" }, "bin": { "biome": "bin/biome" } }, "sha512-tigwWS5KfJf0cABVd52NVaXyAVv4qpUXOWJ1rxFL8xF1RVoeS2q/LK+FHgYoKMclJCuRoCWAPy1IXaN9/mS61Q=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A=="],
|
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jZ+Xc6qvD6tTH5jM6eKX44dcbyNqJHssfl2nnwT6vma6B1sj7ZLTGIk6N5QwVBs5xGN52r3trk5fgd3sQ9We9A=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA=="],
|
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-Dh1a/+W+SUCXhEdL7TiX3ArPTFCQKJTI1mGncZNWfO+6suk+gYA4lNyJcBB+pwvF49uw0pEbUS49BgYOY4hzUg=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ=="],
|
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-V/NFfbWhsUU6w+m5WYbBenlEAz8eYnSqRMDMAW3K+3v0tYVkNyZn8VU0XPxk/lOqNXLSCCrV7FmV/u3SjCBShg=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg=="],
|
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+sPAXq3bxmFwhVFJnSwkSF5Rw2ZAJMH3MF6C9IveAEOdSpgajPhoQhbbAK12SehN9j2QrHpk4J/cHsa/HqWaYQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.14", "", { "os": "linux", "cpu": "x64" }, "sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA=="],
|
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.4", "", { "os": "linux", "cpu": "x64" }, "sha512-R4+ZCDtG9kHArasyBO+UBD6jr/FcFCTH8QkNTOCu0pRJzCWyWC4EtZa2AmUZB5h3e0jD7bRV2KvrENcf8rndBg=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.14", "", { "os": "linux", "cpu": "x64" }, "sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ=="],
|
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gGvFTGpOIQDb5CQ2VC0n9Z2UEqlP46c4aNgHmAMytYieTGEcfqhfCFnhs6xjt0S3igE6q5GLuIXtdQt3Izok+g=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A=="],
|
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-trzCqM7x+Gn832zZHgr28JoYagQNX4CZkUZhMUac2YxvvyDRLJDrb5m9IA7CaZLlX6lTQmADVfLEKP1et1Ma4Q=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ=="],
|
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.4", "", { "os": "win32", "cpu": "x64" }, "sha512-gnOHKVPFAAPrpoPt2t+Q6FZ7RPry/FDV3GcpU53P3PtLNnQjBmKyN2Vh/JtqXet+H4pme8CC76rScwdjDcT1/A=="],
|
||||||
|
|
||||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
|
|
||||||
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
|
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
|
"@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
|
|
||||||
"browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
|
"browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
|
"bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001763", "", {}, "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001763", "", {}, "sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ=="],
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { drawSprite, type Sprite, spriteSheetMap } from "#/engine/Sprite.ts";
|
||||||
|
import type { Vector } from "#/engine/Vector.ts";
|
||||||
|
|
||||||
|
export type Drawable = {
|
||||||
|
position: Vector;
|
||||||
|
sprite: Sprite;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function isDrawable<T>(
|
||||||
|
entity: {
|
||||||
|
position?: Vector;
|
||||||
|
sprite?: Sprite;
|
||||||
|
} & T,
|
||||||
|
): entity is Drawable & T {
|
||||||
|
return (
|
||||||
|
typeof entity.position === "object" && typeof entity.sprite === "object"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function draw(ctx: CanvasRenderingContext2D, drawable: Drawable): void {
|
||||||
|
drawSprite(
|
||||||
|
ctx,
|
||||||
|
spriteSheetMap.get(drawable.sprite.src)!,
|
||||||
|
drawable.sprite.xStart,
|
||||||
|
drawable.sprite.yStart,
|
||||||
|
drawable.position.x,
|
||||||
|
drawable.position.y,
|
||||||
|
);
|
||||||
|
}
|
||||||
+42
-26
@@ -1,3 +1,4 @@
|
|||||||
|
import { type Drawable, draw, isDrawable } from "#/engine/Drawable.ts";
|
||||||
import {
|
import {
|
||||||
entityMap,
|
entityMap,
|
||||||
entityProcessMap,
|
entityProcessMap,
|
||||||
@@ -5,7 +6,7 @@ import {
|
|||||||
} from "#/engine/Entity.ts";
|
} from "#/engine/Entity.ts";
|
||||||
import { type Graph, getNeighbours } from "#/engine/Graph.ts";
|
import { type Graph, getNeighbours } from "#/engine/Graph.ts";
|
||||||
import { useWithAsyncCache } from "#/engine/lib/cache.ts";
|
import { useWithAsyncCache } from "#/engine/lib/cache.ts";
|
||||||
import { playAnimation } from "./Sprite";
|
import { animateSprite, type SpriteAnimation } from "#/engine/Sprite.ts";
|
||||||
|
|
||||||
export type EntityData = {
|
export type EntityData = {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -22,11 +23,13 @@ export type SceneData = {
|
|||||||
export type EntityMap = Map<
|
export type EntityMap = Map<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
process: ProcessEntity<object>;
|
process: ProcessEntity<{ id: number }>;
|
||||||
instances: Array<object>;
|
instances: Array<{ id: number }>;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type AnimationMap = Map<number, SpriteAnimation>;
|
||||||
|
|
||||||
export type Scene = {
|
export type Scene = {
|
||||||
data: SceneData;
|
data: SceneData;
|
||||||
entityMap: EntityMap;
|
entityMap: EntityMap;
|
||||||
@@ -49,7 +52,11 @@ export const sceneDataMap = new Map<string, SceneData>();
|
|||||||
export const sceneEntiyMap = new Map<string, EntityMap>();
|
export const sceneEntiyMap = new Map<string, EntityMap>();
|
||||||
export const sceneGraph: Graph<string> = new Map();
|
export const sceneGraph: Graph<string> = new Map();
|
||||||
|
|
||||||
const sceneInstancesDrawMap = new Map<string, Array<object>>();
|
const sceneInstancesDrawMap = new Map<
|
||||||
|
string,
|
||||||
|
Array<Drawable & { id: number }>
|
||||||
|
>();
|
||||||
|
const sceneInstancesAnimationMap = new Map<string, AnimationMap>();
|
||||||
|
|
||||||
export const [loadScene, sceneCache] = useWithAsyncCache(
|
export const [loadScene, sceneCache] = useWithAsyncCache(
|
||||||
async (name: string) => {
|
async (name: string) => {
|
||||||
@@ -60,7 +67,7 @@ export const [loadScene, sceneCache] = useWithAsyncCache(
|
|||||||
entityInstanceMap.clear();
|
entityInstanceMap.clear();
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
data.entities.map(async (entityData: EntityData) => {
|
data.entities.map(async (entityData: EntityData, index: number) => {
|
||||||
await import(`#/game/entities/${entityData.name}/entity.ts`);
|
await import(`#/game/entities/${entityData.name}/entity.ts`);
|
||||||
|
|
||||||
if (!entityInstanceMap.has(entityData.name)) {
|
if (!entityInstanceMap.has(entityData.name)) {
|
||||||
@@ -75,6 +82,7 @@ export const [loadScene, sceneCache] = useWithAsyncCache(
|
|||||||
structuredClone({
|
structuredClone({
|
||||||
...entityMap.get(entityData.name)!,
|
...entityMap.get(entityData.name)!,
|
||||||
...entityData,
|
...entityData,
|
||||||
|
id: index,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -104,19 +112,17 @@ function processEntities(delta: number): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: type stuff and fixme WIP
|
|
||||||
function processSystems(ctx: CanvasRenderingContext2D, delta: number): void {
|
function processSystems(ctx: CanvasRenderingContext2D, delta: number): void {
|
||||||
const drawables = sceneInstancesDrawMap.get(currentScene.data.name)!;
|
const drawables = sceneInstancesDrawMap.get(currentScene.data.name)!;
|
||||||
|
const animationsMap = sceneInstancesAnimationMap.get(currentScene.data.name)!;
|
||||||
|
|
||||||
for (const drawable of drawables.sort(
|
for (const drawable of drawables.sort(
|
||||||
(a, b) => a.position.y - b.position.y,
|
(a, b) => a.position.y - b.position.y,
|
||||||
)) {
|
)) {
|
||||||
playAnimation(
|
if (animationsMap.has(drawable.id)) {
|
||||||
ctx,
|
animateSprite(animationsMap.get(drawable.id)!, delta);
|
||||||
drawable.animation,
|
}
|
||||||
drawable.position.x,
|
draw(ctx, drawable);
|
||||||
drawable.position.y,
|
|
||||||
delta,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,19 +182,29 @@ export async function setScene(name: string): Promise<void> {
|
|||||||
const data = sceneDataMap.get(name)!;
|
const data = sceneDataMap.get(name)!;
|
||||||
const process = sceneProcessMap.get(name)!;
|
const process = sceneProcessMap.get(name)!;
|
||||||
const entityInstanceMap = sceneEntiyMap.get(name)!;
|
const entityInstanceMap = sceneEntiyMap.get(name)!;
|
||||||
// TODO: test for drawable first
|
|
||||||
sceneInstancesDrawMap.set(
|
const drawableInstances: Array<Drawable & { id: number }> = [];
|
||||||
data.name,
|
sceneInstancesDrawMap.set(data.name, drawableInstances);
|
||||||
entityInstanceMap.values().reduce(
|
|
||||||
(acc, cur) => {
|
const animateInstances: AnimationMap = new Map();
|
||||||
for (const instance of cur.instances) {
|
sceneInstancesAnimationMap.set(data.name, animateInstances);
|
||||||
acc.push(instance);
|
|
||||||
}
|
for (const entity of entityInstanceMap.values()) {
|
||||||
return acc;
|
for (const instance of entity.instances) {
|
||||||
},
|
if (isDrawable(instance)) {
|
||||||
[] as Array<object>,
|
drawableInstances.push(instance);
|
||||||
),
|
}
|
||||||
);
|
if (
|
||||||
|
(instance as { id: number; animation: SpriteAnimation }).animation !==
|
||||||
|
undefined
|
||||||
|
) {
|
||||||
|
animateInstances.set(
|
||||||
|
instance.id,
|
||||||
|
(instance as { id: number; animation: SpriteAnimation }).animation, // FIXME
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const preProcess = scenePreProcessMap.get(name);
|
const preProcess = scenePreProcessMap.get(name);
|
||||||
if (preProcess) {
|
if (preProcess) {
|
||||||
|
|||||||
+21
-18
@@ -1,4 +1,12 @@
|
|||||||
import { loadImage } from "./lib/loadImage";
|
import { loadImage } from "#/engine/lib/loadImage.ts";
|
||||||
|
|
||||||
|
export type Sprite = {
|
||||||
|
src: string;
|
||||||
|
xStart: number;
|
||||||
|
yStart: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type SpriteSheet = {
|
export type SpriteSheet = {
|
||||||
image: HTMLImageElement;
|
image: HTMLImageElement;
|
||||||
@@ -9,7 +17,7 @@ export type SpriteSheet = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type SpriteAnimation = {
|
export type SpriteAnimation = {
|
||||||
src: string;
|
sprite: Sprite;
|
||||||
xIndex: number;
|
xIndex: number;
|
||||||
yIndex: number;
|
yIndex: number;
|
||||||
frameTime: number;
|
frameTime: number;
|
||||||
@@ -49,12 +57,14 @@ export async function useSpriteSheetSrc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createSpriteAnimation(
|
export function createSpriteAnimation(
|
||||||
src: string,
|
sprite: Sprite,
|
||||||
frameTime: number,
|
frameTime: number,
|
||||||
yIndex: number,
|
yIndex: number,
|
||||||
): SpriteAnimation {
|
): SpriteAnimation {
|
||||||
|
sprite.yStart = yIndex * spriteSheetMap.get(sprite.src)!.frameHeight;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
src,
|
sprite,
|
||||||
xIndex: 0,
|
xIndex: 0,
|
||||||
yIndex,
|
yIndex,
|
||||||
frameTime,
|
frameTime,
|
||||||
@@ -65,8 +75,8 @@ export function createSpriteAnimation(
|
|||||||
export function drawSprite(
|
export function drawSprite(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
sheet: SpriteSheet,
|
sheet: SpriteSheet,
|
||||||
xIndex: number,
|
xStart: number,
|
||||||
yIndex: number,
|
yStart: number,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
width?: number,
|
width?: number,
|
||||||
@@ -74,8 +84,8 @@ export function drawSprite(
|
|||||||
): void {
|
): void {
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
sheet.image,
|
sheet.image,
|
||||||
xIndex * sheet.frameWidth,
|
xStart,
|
||||||
yIndex * sheet.frameHeight,
|
yStart,
|
||||||
sheet.frameWidth,
|
sheet.frameWidth,
|
||||||
sheet.frameHeight,
|
sheet.frameHeight,
|
||||||
x,
|
x,
|
||||||
@@ -85,15 +95,8 @@ export function drawSprite(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function playAnimation(
|
export function animateSprite(animation: SpriteAnimation, delta: number): void {
|
||||||
ctx: CanvasRenderingContext2D,
|
const sheet = spriteSheetMap.get(animation.sprite.src)!;
|
||||||
animation: SpriteAnimation,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
delta: number,
|
|
||||||
): void {
|
|
||||||
const sheet = spriteSheetMap.get(animation.src)!;
|
|
||||||
|
|
||||||
if ((animation.frameDelta += delta) > animation.frameTime) {
|
if ((animation.frameDelta += delta) > animation.frameTime) {
|
||||||
animation.frameDelta = 0;
|
animation.frameDelta = 0;
|
||||||
if ((animation.xIndex += 1) >= sheet.xFrames) {
|
if ((animation.xIndex += 1) >= sheet.xFrames) {
|
||||||
@@ -101,5 +104,5 @@ export function playAnimation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawSprite(ctx, sheet, animation.xIndex, animation.yIndex, x, y);
|
animation.sprite.xStart = animation.xIndex * sheet.frameWidth;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { keyboardInput } from "#/engine/Keyboard.ts";
|
|||||||
import { pointer } from "#/engine/Pointer.ts";
|
import { pointer } from "#/engine/Pointer.ts";
|
||||||
import {
|
import {
|
||||||
createSpriteAnimation,
|
createSpriteAnimation,
|
||||||
|
type Sprite,
|
||||||
type SpriteAnimation,
|
type SpriteAnimation,
|
||||||
useSpriteSheetSrc,
|
useSpriteSheetSrc,
|
||||||
} from "#/engine/Sprite.ts";
|
} from "#/engine/Sprite.ts";
|
||||||
@@ -15,17 +16,26 @@ export type Hero = {
|
|||||||
position: Vector;
|
position: Vector;
|
||||||
velocity: Vector;
|
velocity: Vector;
|
||||||
body: Circle;
|
body: Circle;
|
||||||
|
sprite: Sprite;
|
||||||
animation: SpriteAnimation;
|
animation: SpriteAnimation;
|
||||||
};
|
};
|
||||||
|
|
||||||
const speed = 0.05;
|
const speed = 0.05;
|
||||||
const idleSheet = await useSpriteSheetSrc(charIdle, 2, 4);
|
const idleSheet = await useSpriteSheetSrc(charIdle, 2, 4);
|
||||||
|
const sprite = {
|
||||||
|
src: idleSheet,
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
};
|
||||||
|
|
||||||
const state: Hero = {
|
const state: Hero = {
|
||||||
position: createVector(),
|
position: createVector(),
|
||||||
velocity: createVector(),
|
velocity: createVector(),
|
||||||
body: createCircle(createVector(), 4),
|
body: createCircle(createVector(), 4),
|
||||||
animation: createSpriteAnimation(idleSheet, 500, 2),
|
sprite,
|
||||||
|
animation: createSpriteAnimation(sprite, 500, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
const process = defineEntity("hero", state);
|
const process = defineEntity("hero", state);
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
import { defineEntity } from "#/engine/Entity.ts";
|
import { defineEntity } from "#/engine/Entity.ts";
|
||||||
import { createSpriteAnimation, useSpriteSheetSrc } from "#/engine/Sprite.ts";
|
import { createSpriteAnimation, useSpriteSheetSrc } from "#/engine/Sprite.ts";
|
||||||
import { createVector } from "#/engine/Vector";
|
import { createVector } from "#/engine/Vector.ts";
|
||||||
import portal from "#/game/assets/portal.png";
|
import portal from "#/game/assets/portal.png";
|
||||||
|
|
||||||
const portalSheet = await useSpriteSheetSrc(portal, 3, 1);
|
const portalSheet = await useSpriteSheetSrc(portal, 3, 1);
|
||||||
|
const sprite = {
|
||||||
|
src: portalSheet,
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
};
|
||||||
|
|
||||||
defineEntity("portal", {
|
defineEntity("portal", {
|
||||||
position: createVector(64, 64),
|
position: createVector(64, 64),
|
||||||
animation: createSpriteAnimation(portalSheet, 400, 0),
|
sprite,
|
||||||
|
animation: createSpriteAnimation(sprite, 400, 0),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { defineEntity } from "#/engine/Entity.ts";
|
import { defineEntity } from "#/engine/Entity.ts";
|
||||||
import {
|
import {
|
||||||
createSpriteAnimation,
|
createSpriteAnimation,
|
||||||
|
type Sprite,
|
||||||
type SpriteAnimation,
|
type SpriteAnimation,
|
||||||
useSpriteSheetSrc,
|
useSpriteSheetSrc,
|
||||||
} from "#/engine/Sprite.ts";
|
} from "#/engine/Sprite.ts";
|
||||||
@@ -9,11 +10,28 @@ import { viewport } from "#/engine/Viewport.ts";
|
|||||||
import charIdle from "#/game/assets/char-idle.png";
|
import charIdle from "#/game/assets/char-idle.png";
|
||||||
import charWalk from "#/game/assets/char-walk.png";
|
import charWalk from "#/game/assets/char-walk.png";
|
||||||
|
|
||||||
const sprites = {
|
const sheets = {
|
||||||
idle: await useSpriteSheetSrc(charIdle, 2, 4),
|
idle: await useSpriteSheetSrc(charIdle, 2, 4),
|
||||||
walk: await useSpriteSheetSrc(charWalk, 4, 4),
|
walk: await useSpriteSheetSrc(charWalk, 4, 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sprites = {
|
||||||
|
idle: {
|
||||||
|
src: sheets.idle,
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
},
|
||||||
|
walk: {
|
||||||
|
src: sheets.walk,
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const animations = {
|
const animations = {
|
||||||
idle: createSpriteAnimation(sprites.idle, 500, 2),
|
idle: createSpriteAnimation(sprites.idle, 500, 2),
|
||||||
walk: createSpriteAnimation(sprites.walk, 250, 2),
|
walk: createSpriteAnimation(sprites.walk, 250, 2),
|
||||||
@@ -26,11 +44,18 @@ const process = defineEntity<{
|
|||||||
idle: SpriteAnimation;
|
idle: SpriteAnimation;
|
||||||
walk: SpriteAnimation;
|
walk: SpriteAnimation;
|
||||||
};
|
};
|
||||||
|
sprite: Sprite;
|
||||||
|
sprites: {
|
||||||
|
idle: Sprite;
|
||||||
|
walk: Sprite;
|
||||||
|
};
|
||||||
stuff: number;
|
stuff: number;
|
||||||
}>("testEntity", {
|
}>("testEntity", {
|
||||||
position: createVector(),
|
position: createVector(),
|
||||||
animations,
|
|
||||||
animation: animations.idle,
|
animation: animations.idle,
|
||||||
|
animations,
|
||||||
|
sprite: sprites.idle,
|
||||||
|
sprites,
|
||||||
stuff: 1,
|
stuff: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,8 +64,10 @@ process((entity, _delta) => {
|
|||||||
if (entity.position.x > viewport.canvas.width - 16) {
|
if (entity.position.x > viewport.canvas.width - 16) {
|
||||||
entity.stuff = -1;
|
entity.stuff = -1;
|
||||||
entity.animation = entity.animations.walk;
|
entity.animation = entity.animations.walk;
|
||||||
|
entity.sprite = entity.sprites.walk;
|
||||||
} else if (entity.position.x < 0) {
|
} else if (entity.position.x < 0) {
|
||||||
entity.stuff = 1;
|
entity.stuff = 1;
|
||||||
entity.animation = entity.animations.idle;
|
entity.animation = entity.animations.idle;
|
||||||
|
entity.sprite = entity.sprites.idle;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { pointer } from "#/engine/Pointer.ts";
|
|||||||
import { defineScene } from "#/engine/Scene.ts";
|
import { defineScene } from "#/engine/Scene.ts";
|
||||||
import { spriteSheetMap } from "#/engine/Sprite.ts";
|
import { spriteSheetMap } from "#/engine/Sprite.ts";
|
||||||
import { createVector } from "#/engine/Vector";
|
import { createVector } from "#/engine/Vector";
|
||||||
import type { Hero } from "#/game/entities/hero/entity.ts";
|
|
||||||
import data from "./data.json";
|
import data from "./data.json";
|
||||||
|
|
||||||
const { process, preProcess, linkScenes } = defineScene(data);
|
const { process, preProcess, linkScenes } = defineScene(data);
|
||||||
@@ -12,11 +11,11 @@ linkScenes(["fooScene"] as const);
|
|||||||
|
|
||||||
preProcess((entityInstanceMap) => {
|
preProcess((entityInstanceMap) => {
|
||||||
const entry = entityInstanceMap.get("hero")!;
|
const entry = entityInstanceMap.get("hero")!;
|
||||||
const instance = entry.instances[0] as Hero;
|
const instance = entry.instances[0];
|
||||||
const sheet = spriteSheetMap.get(instance.animation.src)!;
|
// const sheet = spriteSheetMap.get(instance.animation.src)!;
|
||||||
|
|
||||||
instance.position.x = data.width - sheet.frameHeight;
|
instance.position.x = data.width - 16;
|
||||||
instance.position.y = data.height - sheet.frameWidth;
|
instance.position.y = data.height - 16;
|
||||||
});
|
});
|
||||||
|
|
||||||
const cirle = createCircle(createVector(), 4);
|
const cirle = createCircle(createVector(), 4);
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@
|
|||||||
"check": "biome check --write"
|
"check": "biome check --write"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.3.14",
|
"@biomejs/biome": "2.4.4",
|
||||||
"@types/bun": "1.3.8",
|
"@types/bun": "1.3.9",
|
||||||
"lz-string": "1.5.0",
|
"lz-string": "1.5.0",
|
||||||
"solid-js": "1.9.11",
|
"solid-js": "1.9.11",
|
||||||
"vite": "7.3.1",
|
"vite": "7.3.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user