Reorganize
This commit is contained in:
28
io/cart.ts
Normal file
28
io/cart.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { path } from "../deps.ts";
|
||||
import initialCart from "../data/initialCart.json" assert { type: "json" };
|
||||
import { Sheet } from "./sheet.ts";
|
||||
|
||||
const extension = ".faux";
|
||||
|
||||
let staticCart = initialCart as Array<Sheet>;
|
||||
let cart: Array<Sheet> = JSON.parse(JSON.stringify(staticCart));
|
||||
|
||||
const virtualPathToRealPath = (virtualFname: string) => {
|
||||
const vfname = virtualFname + extension;
|
||||
const realPath = path.join(".", "carts", ...vfname.split("/"));
|
||||
return realPath;
|
||||
}
|
||||
|
||||
export const saveCart = async (fname: string) => {
|
||||
await Deno.writeTextFile(virtualPathToRealPath(fname), JSON.stringify(getCart()));
|
||||
}
|
||||
|
||||
export const loadCart = async (fname: string) => {
|
||||
const json = await Deno.readTextFile(virtualPathToRealPath(fname));
|
||||
staticCart = JSON.parse(json);
|
||||
cart = JSON.parse(json);
|
||||
}
|
||||
|
||||
export const getCart = () => {
|
||||
return cart;
|
||||
}
|
174
io/keyboard.ts
Normal file
174
io/keyboard.ts
Normal file
@ -0,0 +1,174 @@
|
||||
import { font, CHAR } from "../data/font.ts";
|
||||
|
||||
const keyboard = new Map<number, {first: boolean, repeat: boolean, held: boolean}>();
|
||||
|
||||
export const K = {
|
||||
ESCAPE: 256,
|
||||
ENTER: 257,
|
||||
TAB: 258,
|
||||
BACKSPACE: 259,
|
||||
INSERT: 260,
|
||||
DELETE: 261,
|
||||
ARROW_RIGHT: 262,
|
||||
ARROW_LEFT: 263,
|
||||
ARROW_DOWN: 264,
|
||||
ARROW_UP: 265,
|
||||
PAGE_UP: 266,
|
||||
PAGE_DOWN: 267,
|
||||
HOME: 268,
|
||||
END: 269,
|
||||
CAPS_LOCK: 280,
|
||||
F1: 290,
|
||||
F2: 291,
|
||||
F3: 292,
|
||||
F4: 293,
|
||||
F5: 294,
|
||||
F6: 295,
|
||||
F7: 296,
|
||||
F8: 297,
|
||||
F9: 298,
|
||||
F10: 299,
|
||||
F11: 300,
|
||||
F12: 301,
|
||||
SHIFT_LEFT: 340,
|
||||
CTRL_LEFT: 341,
|
||||
ALT_LEFT: 342,
|
||||
SHIFT_RIGHT: 344,
|
||||
CTRL_RIGHT: 345,
|
||||
ALT_RIGHT: 346,
|
||||
}
|
||||
|
||||
export const shiftMap = {
|
||||
"1": "!",
|
||||
"2": "@",
|
||||
"3": "#",
|
||||
"4": "$",
|
||||
"5": "%",
|
||||
"6": "^",
|
||||
"7": "&",
|
||||
"8": "*",
|
||||
"9": "(",
|
||||
"0": ")",
|
||||
"`": "~",
|
||||
"-": "_",
|
||||
"=": "+",
|
||||
"[": "{",
|
||||
"]": "}",
|
||||
"\\": "|",
|
||||
";": ":",
|
||||
"'": '"',
|
||||
",": "<",
|
||||
".": ">",
|
||||
"/": "?",
|
||||
}
|
||||
|
||||
export const altMap = {
|
||||
"w": CHAR.UP,
|
||||
"a": CHAR.LEFT,
|
||||
"s": CHAR.DOWN,
|
||||
"d": CHAR.RIGHT,
|
||||
"p": CHAR.PI,
|
||||
}
|
||||
|
||||
addEventListener("keydown", (evt) => {
|
||||
// console.log("keydown", evt.key, evt.key.charCodeAt(0));
|
||||
const key = evt.key.charCodeAt(0);
|
||||
const isRepeat = keyboard.has(key) && keyboard.get(key)?.held!;
|
||||
keyboard.set(key, {
|
||||
first: !isRepeat,
|
||||
repeat: isRepeat,
|
||||
held: true,
|
||||
});
|
||||
});
|
||||
|
||||
addEventListener("keyup", (evt) => {
|
||||
// console.log("keyup", evt.key, evt.key.charCodeAt(0));
|
||||
const key = evt.key.charCodeAt(0);
|
||||
keyboard.set(key, {
|
||||
first: false,
|
||||
repeat: false,
|
||||
held: false,
|
||||
});
|
||||
});
|
||||
|
||||
export const refreshKeyboard = () => {
|
||||
keyboard.forEach(({held}, key) => {
|
||||
if (!held) {
|
||||
keyboard.delete(key);
|
||||
} else {
|
||||
keyboard.set(key, {
|
||||
first: false,
|
||||
repeat: false,
|
||||
held: true,
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const keyPressed = (key: string | number) => {
|
||||
if (typeof key === "string") {
|
||||
key = key.toUpperCase().charCodeAt(0);
|
||||
}
|
||||
return keyboard.has(key) && (keyboard.get(key)?.first! || keyboard.get(key)?.repeat!);
|
||||
}
|
||||
|
||||
export const keyDown = (key: string | number) => {
|
||||
if (typeof key === "string") {
|
||||
key = key.toUpperCase().charCodeAt(0);
|
||||
}
|
||||
return keyboard.has(key) && keyboard.get(key)?.held!;
|
||||
}
|
||||
|
||||
export const shiftKeyDown = () => {
|
||||
return keyDown(K.SHIFT_LEFT) || keyDown(K.SHIFT_RIGHT);
|
||||
}
|
||||
|
||||
export const ctrlKeyDown = () => {
|
||||
return keyDown(K.CTRL_LEFT) || keyDown(K.CTRL_RIGHT);
|
||||
}
|
||||
|
||||
export const altKeyDown = () => {
|
||||
return keyDown(K.ALT_LEFT) || keyDown(K.ALT_RIGHT);
|
||||
}
|
||||
|
||||
export const keyReleased = (key: string | number) => {
|
||||
if (typeof key === "string") {
|
||||
key = key.toUpperCase().charCodeAt(0);
|
||||
}
|
||||
return keyboard.has(key) && !keyboard.get(key)?.held!;
|
||||
}
|
||||
|
||||
export const getKeysPressed = () => {
|
||||
const result = [...keyboard.entries()].filter(([_key, value]) => {
|
||||
return value.first || value.repeat;
|
||||
}).map(([key]) => key);
|
||||
return result;
|
||||
}
|
||||
|
||||
export const getKeyboardString = () => {
|
||||
let str = "";
|
||||
if (ctrlKeyDown()) {
|
||||
return str;
|
||||
}
|
||||
for (const key of getKeysPressed()) {
|
||||
let char = String.fromCharCode(key).toLowerCase();
|
||||
if (shiftKeyDown()) {
|
||||
if (char in shiftMap) {
|
||||
char = shiftMap[char as keyof typeof shiftMap];
|
||||
} else {
|
||||
char = char.toUpperCase();
|
||||
}
|
||||
}
|
||||
if (altKeyDown()) {
|
||||
if (char in altMap) {
|
||||
char = altMap[char as keyof typeof altMap];
|
||||
} else {
|
||||
char = char.toUpperCase();
|
||||
}
|
||||
}
|
||||
if (char in font.chars) {
|
||||
str += char;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
121
io/mouse.ts
Normal file
121
io/mouse.ts
Normal file
@ -0,0 +1,121 @@
|
||||
import { WindowMouseEvent } from "https://deno.land/x/dwm@0.3.3/mod.ts";
|
||||
import { gameWindow } from "./window.ts";
|
||||
|
||||
export const M = {
|
||||
NONE: -1,
|
||||
LEFT: 0,
|
||||
RIGHT: 1,
|
||||
MIDDLE: 2,
|
||||
}
|
||||
|
||||
const mouseButtonsDown = {
|
||||
[M.LEFT]: false,
|
||||
[M.RIGHT]: false,
|
||||
[M.MIDDLE]: false,
|
||||
};
|
||||
|
||||
type MouseEventType = "click" | "down" | "up" | "move" | "dblclick";
|
||||
|
||||
const mouseEvents: Array<{
|
||||
type: MouseEventType,
|
||||
button: typeof M[keyof typeof M],
|
||||
x: number,
|
||||
y: number,
|
||||
prevX?: number,
|
||||
prevY?: number
|
||||
}> = [];
|
||||
|
||||
let mouseX = 0;
|
||||
let mouseY = 0;
|
||||
|
||||
const eventPixelCoords = (evt: WindowMouseEvent) => {
|
||||
const {width, height} = gameWindow.size;
|
||||
const min = Math.min(width, height);
|
||||
const pixX = Math.floor(128*(evt.clientX-(width-min)/2)/min);
|
||||
const pixY = Math.floor(128*(evt.clientY-(height-min)/2)/min);
|
||||
if (pixX < 0 || pixX > 128 || pixY < 0 || pixY > 128) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
x: pixX,
|
||||
y: pixY,
|
||||
}
|
||||
}
|
||||
|
||||
const pushEvent = (type: MouseEventType, evt: WindowMouseEvent, extra?: Partial<typeof mouseEvents[0]>) => {
|
||||
const coords = eventPixelCoords(evt);
|
||||
if (!coords) {
|
||||
return
|
||||
}
|
||||
mouseEvents.push({type, button: evt.button, ...coords, ...(extra ?? {})});
|
||||
}
|
||||
|
||||
const evtInBounds = (evt: WindowMouseEvent) => {
|
||||
return !!eventPixelCoords(evt);
|
||||
}
|
||||
|
||||
addEventListener("dblclick", (evt) => {
|
||||
pushEvent("dblclick", evt);
|
||||
});
|
||||
|
||||
addEventListener("click", (evt) => {
|
||||
pushEvent("click", evt);
|
||||
});
|
||||
|
||||
addEventListener("mousedown", (evt) => {
|
||||
if (evtInBounds(evt)) {
|
||||
mouseButtonsDown[evt.button] = true;
|
||||
}
|
||||
pushEvent("down", evt);
|
||||
});
|
||||
|
||||
addEventListener("mouseup", (evt) => {
|
||||
if (evtInBounds(evt)) {
|
||||
mouseButtonsDown[evt.button] = false;
|
||||
}
|
||||
pushEvent("up", evt);
|
||||
});
|
||||
|
||||
addEventListener("mousemove", (evt) => {
|
||||
const coords = eventPixelCoords(evt);
|
||||
pushEvent("up", evt, {prevX: mouseX, prevY: mouseY});
|
||||
if (coords) {
|
||||
mouseX = coords.x;
|
||||
mouseY = coords.y;
|
||||
}
|
||||
});
|
||||
|
||||
export const mousePos = () => {
|
||||
return {
|
||||
x: mouseX,
|
||||
y: mouseY,
|
||||
}
|
||||
}
|
||||
|
||||
export const getMouseX = () => {
|
||||
return mouseX;
|
||||
}
|
||||
|
||||
export const getMouseY = () => {
|
||||
return mouseY;
|
||||
}
|
||||
|
||||
export const refreshMouse = () => {
|
||||
mouseEvents.length = 0;
|
||||
}
|
||||
|
||||
export const mouseDown = (button: number = M.LEFT) => {
|
||||
return mouseEvents.some(ev => ev.button === button && ev.type === "down");
|
||||
}
|
||||
|
||||
export const mouseClick = (button: number = M.LEFT) => {
|
||||
return mouseEvents.some(ev => ev.button === button && ev.type === "click");
|
||||
}
|
||||
|
||||
export const mouseDoubleClick = (button: number = M.LEFT) => {
|
||||
return mouseEvents.some(ev => ev.button === button && ev.type === "dblclick");
|
||||
}
|
||||
|
||||
export const mouseHeld = (button: number = M.LEFT) => {
|
||||
return mouseButtonsDown[button];
|
||||
}
|
56
io/sheet.ts
Normal file
56
io/sheet.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { getCart } from "./cart.ts";
|
||||
import { LinearGrid } from "../util/util.ts";
|
||||
// import { runCode, addToContext } from "./runcode.ts";
|
||||
|
||||
// "code" | "spritesheet" | "map" | "sfx" | "patterns" | "fonts"
|
||||
export type Sheet = {
|
||||
sheet_type: "code",
|
||||
value: string,
|
||||
} | {
|
||||
sheet_type: "spritesheet",
|
||||
value: Array<Array<number>>,
|
||||
} | {
|
||||
sheet_type: "map",
|
||||
value: Array<[number, number]>,
|
||||
} | {
|
||||
sheet_type: "none",
|
||||
value: null,
|
||||
}
|
||||
export type SheetType = Sheet["sheet_type"];
|
||||
|
||||
export const getSheet = (n: number): Sheet => {
|
||||
return getCart()[n];
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
export const setSheet = (n: number, type: SheetType, value: any) => {
|
||||
return getCart()[n] = {sheet_type: type, value};
|
||||
}
|
||||
|
||||
export const getCodeSheet = (sheet: number) => {
|
||||
const {sheet_type, value} = getSheet(sheet);
|
||||
if (sheet_type !== "code") {
|
||||
throw "Trying to use a non-code sheet as code."
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const getSpriteSheet = (sheet: number) => {
|
||||
const {sheet_type, value} = getSheet(sheet);
|
||||
if (sheet_type !== "spritesheet") {
|
||||
throw Error("Trying to use a non-sprite sheet as a spritesheet.");
|
||||
}
|
||||
while (value.length < 128) {
|
||||
value.push(Array(64).fill(0));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const getMapSheet = (sheet: number) => {
|
||||
const {sheet_type, value} = getSheet(sheet);
|
||||
if (sheet_type !== "map") {
|
||||
throw "Trying to use a non-map sheet as a map."
|
||||
}
|
||||
sheet_type
|
||||
return LinearGrid(value, 64);
|
||||
}
|
256
io/window.ts
Normal file
256
io/window.ts
Normal file
@ -0,0 +1,256 @@
|
||||
import {
|
||||
createWindow,
|
||||
getProcAddress,
|
||||
gl,
|
||||
} from "../deps.ts";
|
||||
export {mainloop} from "../deps.ts";
|
||||
import { COLOR, palette } from "../data/colors.ts";
|
||||
|
||||
export const gameWindow = createWindow({
|
||||
title: "Faux",
|
||||
width: 512,
|
||||
height: 512,
|
||||
resizable: true,
|
||||
glVersion: [3, 2],
|
||||
gles: true,
|
||||
});
|
||||
|
||||
gl.load(getProcAddress);
|
||||
|
||||
function loadShader(type: number, src: string) {
|
||||
const shader = gl.CreateShader(type);
|
||||
gl.ShaderSource(
|
||||
shader,
|
||||
1,
|
||||
new Uint8Array(
|
||||
new BigUint64Array([
|
||||
BigInt(
|
||||
Deno.UnsafePointer.value(
|
||||
Deno.UnsafePointer.of(new TextEncoder().encode(src)),
|
||||
),
|
||||
),
|
||||
]).buffer,
|
||||
),
|
||||
new Int32Array([src.length]),
|
||||
);
|
||||
gl.CompileShader(shader);
|
||||
const status = new Int32Array(1);
|
||||
gl.GetShaderiv(shader, gl.COMPILE_STATUS, status);
|
||||
if (status[0] === gl.FALSE) {
|
||||
const logLength = new Int32Array(1);
|
||||
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, logLength);
|
||||
const log = new Uint8Array(logLength[0]);
|
||||
gl.GetShaderInfoLog(shader, logLength[0], logLength, log);
|
||||
console.log(new TextDecoder().decode(log));
|
||||
gl.DeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
const vShaderSrc = `
|
||||
attribute vec4 vPosition;
|
||||
attribute vec4 vCol;
|
||||
varying vec4 color;
|
||||
void main() {
|
||||
gl_Position = vPosition;
|
||||
color = vCol;
|
||||
}
|
||||
`;
|
||||
|
||||
const fShaderSrc = `
|
||||
precision mediump float;
|
||||
varying vec4 color;
|
||||
void main() {
|
||||
gl_FragColor = color;
|
||||
}
|
||||
`;
|
||||
|
||||
const vShader = loadShader(gl.VERTEX_SHADER, vShaderSrc);
|
||||
const fShader = loadShader(gl.FRAGMENT_SHADER, fShaderSrc);
|
||||
|
||||
const program = gl.CreateProgram();
|
||||
gl.AttachShader(program, vShader);
|
||||
gl.AttachShader(program, fShader);
|
||||
|
||||
gl.BindAttribLocation(program, 0, new TextEncoder().encode("vPosition\0"));
|
||||
gl.BindAttribLocation(program, 1, new TextEncoder().encode("vCol\0"));
|
||||
|
||||
gl.LinkProgram(program);
|
||||
|
||||
const status = new Int32Array(1);
|
||||
gl.GetProgramiv(program, gl.LINK_STATUS, status);
|
||||
if (status[0] === gl.FALSE) {
|
||||
const logLength = new Int32Array(1);
|
||||
gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, logLength);
|
||||
const log = new Uint8Array(logLength[0]);
|
||||
gl.GetProgramInfoLog(program, logLength[0], logLength, log);
|
||||
console.log(new TextDecoder().decode(log));
|
||||
gl.DeleteProgram(program);
|
||||
Deno.exit(1);
|
||||
}
|
||||
|
||||
gl.ClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
const pixelsPerRow = 128;
|
||||
|
||||
const top = 1;
|
||||
const left = -1;
|
||||
const cell = 2/pixelsPerRow;
|
||||
|
||||
const getHalfAsInt = (n: number) => Number(parseInt(Math.floor(n/2).toString()));
|
||||
|
||||
addEventListener("resize", (event) => {
|
||||
const {width, height} = event;
|
||||
const min = Math.min(width, height);
|
||||
gl.Viewport(getHalfAsInt(width-min), getHalfAsInt(height-min), min, min);
|
||||
});
|
||||
|
||||
const px = (x: number, y: number) => {
|
||||
// deno-fmt-ignore
|
||||
return [
|
||||
left + x*cell, top - y*cell, 0,
|
||||
left + (x+1)*cell, top - y*cell, 0,
|
||||
left + x*cell, top - (y+1)*cell, 0,
|
||||
left + (x+1)*cell, top - y*cell, 0,
|
||||
left + x*cell, top - (y+1)*cell, 0,
|
||||
left + (x+1)*cell, top - (y+1)*cell, 0,
|
||||
];
|
||||
}
|
||||
|
||||
const paletteX6 = palette.map(rgba => [...rgba, ...rgba, ...rgba, ...rgba, ...rgba, ...rgba]);
|
||||
|
||||
const c = (n: number) => {
|
||||
return paletteX6[n];
|
||||
}
|
||||
|
||||
const allPixelTriangles = new Float32Array(
|
||||
Array(pixelsPerRow*pixelsPerRow).fill(null).flatMap((_, i) => px(i%pixelsPerRow,Math.floor(i/pixelsPerRow)))
|
||||
)
|
||||
|
||||
const allPixelColors = new Float32Array(
|
||||
Array(pixelsPerRow*pixelsPerRow).fill(null).flatMap(() => c(1))
|
||||
)
|
||||
|
||||
export const cameraPos = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
}
|
||||
|
||||
export const setPixelColorRaw = (x: number, y: number, color: number) => {
|
||||
if (x < 0 || y < 0 || x > 127 || y > 127) {
|
||||
return;
|
||||
}
|
||||
if (color !== 0) {
|
||||
const col = c(color);
|
||||
allPixelColors.set(col, 4*6*(128*y+x));
|
||||
}
|
||||
}
|
||||
|
||||
export const setPixelColor = (x: number, y: number, color: number) => {
|
||||
return setPixelColorRaw(Math.floor(x - cameraPos.x), Math.floor(y - cameraPos.y), color);
|
||||
}
|
||||
|
||||
export const setPixelsInRect = (x: number, y: number, w: number, pixels: Array<number>) => {
|
||||
for (let i = 0; i < pixels.length; i++) {
|
||||
setPixelColor(x+i%w, y+Math.floor(i/w), pixels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
export const setPixelsInRectRaw = (x: number, y: number, w: number, pixels: Array<number>) => {
|
||||
for (let i = 0; i < pixels.length; i++) {
|
||||
setPixelColorRaw(x+i%w, y+Math.floor(i/w), pixels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
export const fillRect = (x: number, y: number, w: number, h: number, color: number) => {
|
||||
setPixelsInRect(x, y, w, Array(w*h).fill(color));
|
||||
}
|
||||
|
||||
export const fillCircle = (x: number, y: number, r: number, color: number) => {
|
||||
const left = Math.floor(x-r-1);
|
||||
const top = Math.floor(y-r-1);
|
||||
for (let i = left; i <= Math.ceil(x+r+1); i ++) {
|
||||
for (let j = top; j <= Math.ceil(y+r+1); j ++) {
|
||||
if (Math.sqrt((x-i)**2 + (y-j)**2) <= r+0.5) {
|
||||
setPixelColor(i, j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const outlineCircle = (x: number, y: number, r: number, color: number) => {
|
||||
const left = Math.floor(x-r-1);
|
||||
const top = Math.floor(y-r-1);
|
||||
const inR = (d: number) => d <= r+0.5 && d > r-0.5;
|
||||
for (let i = left; i <= Math.ceil(x+r+1); i ++) {
|
||||
for (let j = top; j <= Math.ceil(y+r+1); j ++) {
|
||||
const d = Math.sqrt((x-i)**2 + (y-j)**2);
|
||||
if (inR(d)) {
|
||||
const dh = Math.sqrt((x-(i+Math.sign(i-x)))**2 + (y-j)**2);
|
||||
const dv = Math.sqrt((x-i)**2 + (y-(j+Math.sign(j-y)))**2);
|
||||
const h = Math.abs(x-i) > Math.abs(y-j);
|
||||
if (!inR(h ? dh : dv)) {
|
||||
setPixelColor(i, j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const fillEllipse = (x0: number, y0: number, x1: number, y1: number, color: number) => {
|
||||
const x = 0.5*(x0 + x1);
|
||||
const y = 0.5*(y0 + y1);
|
||||
const rx = Math.abs(x0-x1)/2;
|
||||
const ry = Math.abs(y0-y1)/2;
|
||||
const left = Math.floor(x-rx-1);
|
||||
const top = Math.floor(y-ry-1);
|
||||
for (let i = left; i <= Math.ceil(x+rx+1); i ++) {
|
||||
for (let j = top; j <= Math.ceil(y+ry+1); j ++) {
|
||||
if (Math.sqrt(((x-i)/rx)**2 + ((y-j)/ry)**2) <= 1+(1/(rx+ry))) {
|
||||
setPixelColor(i, j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const outlineEllipse = (x0: number, y0: number, x1: number, y1: number, color: number) => {
|
||||
const x = 0.5*(x0 + x1);
|
||||
const y = 0.5*(y0 + y1);
|
||||
const rx = Math.abs(x0-x1)/2;
|
||||
const ry = Math.abs(y0-y1)/2;
|
||||
const left = Math.floor(x-rx-1);
|
||||
const top = Math.floor(y-ry-1);
|
||||
const inR = (d: number) => d <= 1+1/(rx+ry);
|
||||
for (let i = left; i <= Math.ceil(x+rx+1); i ++) {
|
||||
for (let j = top; j <= Math.ceil(y+ry+1); j ++) {
|
||||
const d = Math.sqrt(((x-i)/rx)**2 + ((y-j)/ry)**2);
|
||||
if (inR(d)) {
|
||||
const dh = Math.sqrt(((x-(i+Math.sign(i-x)))/rx)**2 + ((y-j)/ry)**2);
|
||||
const dv = Math.sqrt(((x-i)/rx)**2 + ((y-(j+Math.sign(j-y)))/ry)**2);
|
||||
if (!inR(dh) || !inR(dv)) {
|
||||
setPixelColor(i, j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const fillRectRaw = (x: number, y: number, w: number, h: number, color: number) => {
|
||||
setPixelsInRectRaw(x, y, w, Array(w*h).fill(color));
|
||||
}
|
||||
|
||||
export const clearScreen = (color?: number) => {
|
||||
fillRectRaw(0, 0, 128, 128, color ?? COLOR.BLACK);
|
||||
}
|
||||
|
||||
export const frame = () => {
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.UseProgram(program);
|
||||
gl.VertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, allPixelTriangles);
|
||||
gl.VertexAttribPointer(1, 4, gl.FLOAT, gl.FALSE, 0, allPixelColors);
|
||||
gl.EnableVertexAttribArray(0);
|
||||
gl.EnableVertexAttribArray(1);
|
||||
gl.DrawArrays(gl.TRIANGLES, 0, 6*pixelsPerRow*pixelsPerRow);
|
||||
gameWindow.swapBuffers();
|
||||
}
|
Reference in New Issue
Block a user