fantasy-console/builtins.ts
2023-05-10 20:36:18 -07:00

195 lines
4.4 KiB
TypeScript

import {
setPixelsInRect,
clearScreen,
fillRect,
cameraPos,
fillCircle,
outlineCircle,
fillEllipse,
outlineEllipse,
setPixelColor,
} from "./window.ts";
import { CHAR, Font, font } from "./font.ts";
import { K, keyDown, keyPressed, keyReleased } from "./keyboard.ts";
import { addToContext, runCode } from "./runcode.ts";
import { resetRepl } from "./repl.ts";
import { COLOR } from "./colors.ts";
import { getSheet, getCodeSheet, getMapSheet } from "./sheet.ts";
import { saveCart, loadCart } from "./cart.ts";
import { outlineRect } from "./util.ts";
let spritesheet: number | null = null;
export const getSpritesheet = () => {
return spritesheet;
}
export const useSpritesheet = (sheet: number) => {
spritesheet = sheet;
}
export const drawSprite = (x: number, y: number, spr: number) => {
if (!spritesheet) {
return;
}
const {sheet_type, value: sprites} = getSheet(spritesheet);
if (sheet_type !== "spritesheet") {
throw "Trying to run a non-code sheet as code."
}
setPixelsInRect(x, y, 8, sprites[spr]);
}
export const drawIcon = (x: number, y: number, icon: Array<number>, color: number) => {
setPixelsInRect(x, y, 8, icon.map(n => n*color));
}
export const measureCharFont = (char: string, fnt: Font) => {
return (fnt.chars[char]?.length ?? 0)/fnt.height;
}
export const drawCharFont = (x: number, y: number, char: string, fnt: Font, color: number) => {
const w = measureCharFont(char, fnt);
if (!fnt.chars[char]) {
return 0;
}
setPixelsInRect(x, y, w, fnt.chars[char].map(n => n*color));
return w;
}
export const drawTextFont = (x: number, y: number, text: string, fnt: Font, color?: number) => {
let dx = 0;
[...text].forEach((char) => {
dx += 1+drawCharFont(x+dx, y, char, fnt, color ?? COLOR.WHITE);
});
return dx-1;
}
export const measureTextFont = (text: string, fnt: Font) => {
let w = 0;
[...text].forEach((char) => {
w += measureCharFont(char, fnt)+1;
});
return Math.max(0, w-1);
}
export const drawText = (x: number, y: number, text: string, color?: number) => {
return drawTextFont(x, y, text, font, color);
}
export const measureText = (text: string) => {
return measureTextFont(text, font);
}
export const camera = (x: number, y: number) => {
cameraPos.x = x;
cameraPos.y = y;
};
const faux = {
// Graphics
cls: () => {
resetRepl();
clearScreen();
},
camera,
sprsht: useSpritesheet,
spr: drawSprite,
txt: drawText,
rectfill: fillRect,
rect: outlineRect,
circfill: fillCircle,
circ: outlineCircle,
ovalfill: fillEllipse,
oval: outlineEllipse,
pset: setPixelColor,
map: (mapSheet: number, tileX: number, tileY: number, screenX: number, screenY: number, tileW: number, tileH: number) => {
const originalSpritesheet = getSpritesheet() ?? 0;
getMapSheet(mapSheet).values.forEach(([sprSheet, spr], i) => {
const x = i%64;
const y = Math.floor(i/64);
if (x >= tileX && y >= tileY && x < tileX + tileW && y < tileY + tileH) {
useSpritesheet(sprSheet);
drawSprite(screenX + (x-tileX)*8, screenY + (y-tileY)*8, spr);
}
});
useSpritesheet(originalSpritesheet);
},
// Map
mgetsht: (mapSheet: number, x: number, y: number) => {
if (x < 0 || x >= 64 || y < 0 || y >= 64) {
return undefined;
}
return getMapSheet(mapSheet).get(x, y)[0];
},
mgetspr: (mapSheet: number, x: number, y: number) => {
if (x < 0 || x >= 64 || y < 0 || y >= 64) {
return undefined;
}
return getMapSheet(mapSheet).get(x, y)[1];
},
mset: (mapSheet: number, x: number, y: number, sprSheet: number, spr: number) => {
if (x < 0 || x >= 64 || y < 0 || y >= 64) {
return;
}
getMapSheet(mapSheet).set(x, y, [sprSheet, spr]);
},
// Input
[CHAR.UP]: K.ARROW_UP,
[CHAR.DOWN]: K.ARROW_DOWN,
[CHAR.LEFT]: K.ARROW_LEFT,
[CHAR.RIGHT]: K.ARROW_RIGHT,
btn: keyDown,
btnp: keyPressed,
btnr: keyReleased,
// Cart
save: saveCart,
load: loadCart,
// JS
Array,
BigInt: BigInt,
Boolean,
Date,
Error,
Function,
Infinity: Infinity,
JSON: JSON,
Map,
NaN: NaN,
Number,
Object,
Promise,
Proxy,
Reflect: Reflect,
RegExp,
Set,
String,
Symbol: Symbol,
WeakMap,
WeakRef,
WeakSet,
isFinite,
isNaN,
// Math
max: Math.max,
min: Math.min,
floor: Math.floor,
ceil: Math.ceil,
sin: Math.sin,
cos: Math.cos,
atan2: Math.atan2,
sqrt: Math.sqrt,
abs: Math.abs,
rand: Math.random,
[CHAR.PI]: Math.PI,
// Other
code: (n: number) => {
return runCode(getCodeSheet(n));
},
log: console.log,
};
for (const key in faux) {
addToContext(key, faux[key as keyof typeof faux]);
}
export default faux;