Add basic controls
This commit is contained in:
+2
-3
@@ -21,14 +21,13 @@ export const entityMap = new Map<string, Entity<unknown>>();
|
||||
export const entityAnimateMap = new Map<string, Animate<Indirect>>();
|
||||
export const entityProcessMap = new Map<string, Process<Indirect>>();
|
||||
|
||||
export function useEntity<T extends { animation: Animation }>(
|
||||
meta: { url: string },
|
||||
export function defineEntity<T extends { animation: Animation }>(
|
||||
name: string,
|
||||
state: T,
|
||||
): {
|
||||
animate: (fn: Animate<T>) => void;
|
||||
process: (fn: Process<T>) => void;
|
||||
} {
|
||||
const name = meta.url.match(/entities\/(.+)\/entity\.ts$/)![1];
|
||||
entityMap.set(name, {
|
||||
name,
|
||||
position: createVector(),
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
export type KeyboardInput = {
|
||||
arrowUp: boolean;
|
||||
arrowDown: boolean;
|
||||
arrowLeft: boolean;
|
||||
arrowRight: boolean;
|
||||
enter: boolean;
|
||||
escape: boolean;
|
||||
};
|
||||
|
||||
export const keyboardInput: KeyboardInput = {
|
||||
arrowUp: false,
|
||||
arrowDown: false,
|
||||
arrowLeft: false,
|
||||
arrowRight: false,
|
||||
enter: false,
|
||||
escape: false,
|
||||
};
|
||||
|
||||
function onKeyDown(event: KeyboardEvent) {
|
||||
switch (event.key) {
|
||||
case "ArrowUp":
|
||||
keyboardInput.arrowUp = true;
|
||||
break;
|
||||
case "ArrowDown":
|
||||
keyboardInput.arrowDown = true;
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
keyboardInput.arrowLeft = true;
|
||||
break;
|
||||
case "ArrowRight":
|
||||
keyboardInput.arrowRight = true;
|
||||
break;
|
||||
case "Enter":
|
||||
keyboardInput.enter = true;
|
||||
break;
|
||||
case "Escape":
|
||||
keyboardInput.escape = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onKeyUp(event: KeyboardEvent) {
|
||||
switch (event.key) {
|
||||
case "ArrowUp":
|
||||
keyboardInput.arrowUp = false;
|
||||
break;
|
||||
case "ArrowDown":
|
||||
keyboardInput.arrowDown = false;
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
keyboardInput.arrowLeft = false;
|
||||
break;
|
||||
case "ArrowRight":
|
||||
keyboardInput.arrowRight = false;
|
||||
break;
|
||||
case "Enter":
|
||||
keyboardInput.enter = false;
|
||||
break;
|
||||
case "Escape":
|
||||
keyboardInput.escape = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function listenKeyboard(): () => void {
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
document.addEventListener("keyup", onKeyUp);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
document.removeEventListener("keyup", onKeyUp);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { Vector } from "#/lib/Vector.ts";
|
||||
import { viewport } from "./Viewport.ts";
|
||||
|
||||
export type Pointer = {
|
||||
isDown: boolean;
|
||||
position: Vector;
|
||||
};
|
||||
|
||||
export const pointer: Pointer = {
|
||||
isDown: false,
|
||||
position: { x: 0, y: 0 },
|
||||
};
|
||||
|
||||
function onMouseDown(event: MouseEvent): void {
|
||||
adjustPointerPosition(pointer, event.clientX, event.clientY);
|
||||
pointer.isDown = event.button === 0 ? true : pointer.isDown;
|
||||
}
|
||||
|
||||
function onTouchStart(event: TouchEvent): void {
|
||||
adjustPointerPosition(
|
||||
pointer,
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY,
|
||||
);
|
||||
pointer.isDown = true;
|
||||
}
|
||||
|
||||
function onMouseMove(event: MouseEvent): void {
|
||||
adjustPointerPosition(pointer, event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
function onTouchMove(event: TouchEvent): void {
|
||||
adjustPointerPosition(
|
||||
pointer,
|
||||
event.touches[0].clientX,
|
||||
event.touches[0].clientY,
|
||||
);
|
||||
}
|
||||
|
||||
function onMouseUp(event: MouseEvent): void {
|
||||
pointer.isDown = event.button === 0 ? false : pointer.isDown;
|
||||
}
|
||||
|
||||
function onTouchEnd(event: TouchEvent): void {
|
||||
pointer.isDown = event.touches.length === 0 ? false : pointer.isDown;
|
||||
}
|
||||
|
||||
function onContextMenu(event: MouseEvent): void {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function adjustPointerPosition(
|
||||
pointer: Pointer,
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
): void {
|
||||
const { ctx, translation: position, initialScale } = viewport;
|
||||
const clientRect = ctx.canvas.getBoundingClientRect();
|
||||
|
||||
pointer.position.x = (clientX - clientRect.x + position.x) / initialScale;
|
||||
pointer.position.y = (clientY - clientRect.y + position.y) / initialScale;
|
||||
}
|
||||
|
||||
export function listenPointer(): () => void {
|
||||
const canvas = viewport.ctx.canvas;
|
||||
|
||||
canvas.addEventListener("mousedown", onMouseDown);
|
||||
canvas.addEventListener("touchstart", onTouchStart);
|
||||
canvas.addEventListener("mousemove", onMouseMove);
|
||||
canvas.addEventListener("touchmove", onTouchMove);
|
||||
canvas.addEventListener("mouseup", onMouseUp);
|
||||
canvas.addEventListener("touchend", onTouchEnd);
|
||||
canvas.addEventListener("contextmenu", onContextMenu);
|
||||
|
||||
return () => {
|
||||
canvas.removeEventListener("mousedown", onMouseDown);
|
||||
canvas.removeEventListener("touchstart", onTouchStart);
|
||||
canvas.removeEventListener("mousemove", onMouseMove);
|
||||
canvas.removeEventListener("touchmove", onTouchMove);
|
||||
canvas.removeEventListener("mouseup", onMouseUp);
|
||||
canvas.removeEventListener("touchend", onTouchEnd);
|
||||
canvas.removeEventListener("contextmenu", onContextMenu);
|
||||
};
|
||||
}
|
||||
+4
-4
@@ -1,5 +1,3 @@
|
||||
import { useWithAsyncCache } from "#/lib/cache.ts";
|
||||
import { type Graph, getNeighbours } from "#/lib/Graph.ts";
|
||||
import {
|
||||
type Animate as AnimateEntity,
|
||||
type Entity,
|
||||
@@ -8,7 +6,9 @@ import {
|
||||
entityProcessMap,
|
||||
type Indirect,
|
||||
type Process as ProcessEntity,
|
||||
} from "./Entity.ts";
|
||||
} from "#/engine/Entity.ts";
|
||||
import { useWithAsyncCache } from "#/lib/cache.ts";
|
||||
import { type Graph, getNeighbours } from "#/lib/Graph.ts";
|
||||
|
||||
export type SceneData = {
|
||||
name: string;
|
||||
@@ -121,7 +121,7 @@ function linkScenes(a: string, b: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function useScene(data: SceneData): {
|
||||
export function defineScene(data: SceneData): {
|
||||
linkScenes: <T extends readonly string[]>(
|
||||
names: T,
|
||||
) => (name: T[number]) => Promise<void>;
|
||||
|
||||
Reference in New Issue
Block a user