Compare commits

...

21 Commits

Author SHA1 Message Date
Dylan Pizzo
86d605b130 Update the readme 2025-02-19 20:04:40 -08:00
dylan
f652e8d20f Reorganize 2023-05-18 19:45:49 -07:00
dylan
9b48560cce Allow top level await 2023-05-16 23:45:29 -07:00
dylan
9cb77c7d59 Update README again 2023-05-14 23:41:46 -07:00
dylan
a7efee86e5 Update README 2023-05-14 23:39:22 -07:00
dylan
a9f153e379 Automate more of build process 2023-05-14 23:20:36 -07:00
dylan
f416e7a427 Some logo ideas 2023-05-14 16:00:24 -07:00
dylan
c09c6c0a71 Change cart extension to .faux 2023-05-14 15:37:12 -07:00
dylan
267e49f532 Add build back to gitignore 2023-05-14 15:34:06 -07:00
dylan
792c282fdc Delete build artifacts 2023-05-14 15:33:47 -07:00
dylan
6d7d65dc67 Fix mouse events 2023-05-14 14:25:02 -07:00
dylan
31f77c22da Add parseFloat and parseInt 2023-05-14 14:09:20 -07:00
dylan
a6d093d728 Disable mset for now 2023-05-14 13:54:52 -07:00
dylan
7b04080e9e Update manual 2023-05-14 13:44:22 -07:00
dylan
69a954696a update manual 2023-05-13 18:19:16 -07:00
dylan
3bc7212d86 build 2023-05-13 18:17:34 -07:00
dylan
8303cef501 Link to js Math object 2023-05-13 17:25:22 -07:00
dylan
51f6856fba Add a user manual 2023-05-13 17:24:20 -07:00
dylan
2ec4243027 cleanup 2023-05-13 16:24:36 -07:00
dylan
d542b2a2bc Add window resizing 2023-05-13 16:24:14 -07:00
dylan
1aea0b1221 Putting temp release up 2023-05-13 15:41:06 -07:00
40 changed files with 344 additions and 169 deletions

View File

@ -1,13 +1,25 @@
# fantasy-console # Faux
To run, This is a custom fantasy-console (like Pico 8) written in Deno/Typescript.
Go to the [Releases](https://git.playbox.link/dylan/fantasy-console/releases) page to find downloadable executables.
NOTE: If you are running Faux on Linux, you will need to have `xsel` installed.
## Developing
Faux is written in [TypeScript](https://www.typescriptlang.org/) to be run or compiled by [Deno](https://deno.com/runtime).
If you want to build from source, you should have Deno installed, clone this repo, and then...
To run:
``` ```
deno task run deno task run
``` ```
To compile To compile:
``` ```
deno task build deno task build_all
``` ```
You may need to install `xsel` on Linux machines to use this. NOTE: Development is happening solely on Linux, so some build commands may fail if you are not on Linux or do not have some build dependencies installed.

22
cart.ts
View File

@ -1,22 +0,0 @@
import { path } from "./deps.ts";
import initialCart from "./initialCart.json" assert { type: "json" };
import { Sheet } from "./sheet.ts";
let cart = initialCart as Array<Sheet>;
const virtualPathToRealPath = (virtualFname: string) => {
const realPath = path.join(".", "carts", ...virtualFname.split("/"));
return realPath;
}
export const saveCart = async (fname: string) => {
await Deno.writeTextFile(virtualPathToRealPath(fname+".fx"), JSON.stringify(getCart()));
}
export const loadCart = async (fname: string) => {
cart = JSON.parse(await Deno.readTextFile(virtualPathToRealPath(fname+".fx")));
}
export const getCart = () => {
return cart;
}

1
carts/logo.faux Normal file

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
[{"sheet_type":"code","value":"// Sample\n\nlet r = 0;\nlet d = 1;\nreturn {\n\tinit() {},\n\tupdate() {\n\t\tif (r >= 20) {\n\t\t\td = -1;\n\t\t} else if (r < 0) {\n\t\t\td = 1;\n\t\t}\n\t\tr += d*0.1;\t\n\t},\n\tdraw() {\n\t\tcls();\n\t\tcirc(50, 50, 6, 17);\n\t\ttxt(10,10,\"Hello, World!\");\n\t}\n}"},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
[{"sheet_type":"code","value":"// Sample\n\nlet r = 0;\nlet d = 1;\nreturn {\n\tinit() {},\n\tupdate() {\n\t\tif (r >= 20) {\n\t\t\td = -1;\n\t\t} else if (r < 0) {\n\t\t\td = 1;\n\t\t}\n\t\tr += d*0.1;\t\n\t},\n\tdraw() {\n\t\tcls();\n\t\trectfill(50,50,46,21,6);\n\t\toval(50, 50, 95, 70, 17);\n\t\ttxt(10,10,\"Hello, World!\");\n\t}\n}"},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
[{"sheet_type":"code","value":"\nx = 0;\nbool = true;\nstring = \"hi\";\n\nreturn {\n\tinit() {\n\t\t// init\n\t},\n\tupdate() {\n\t\t// update\n\t},\n\tdraw() {\n\t\t// draw\n\t\tcls();\n\t\ttxt(20, 20, \"hello, world\");\n\t}\n}"},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null}]

View File

@ -1 +0,0 @@
[{"sheet_type":"code","value":"\nx = 0;\nbool = true;\nstring = \"hi\";\ntext = code(1);\n\nreturn {\n\tinit() {\n\t\t// init\n\t},\n\tupdate() {\n\t\t// update\n\t},\n\tdraw() {\n\t\t// draw\n\t\tcls();\n\t\ttxt(20, 20, text);\n\t}\n}"},{"sheet_type":"code","value":"return \"hi from sheet 01.\";"},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null},{"sheet_type":"none","value":null}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,8 @@
"tasks": { "tasks": {
"run": "deno run -A --unstable index.ts", "run": "deno run -A --unstable index.ts",
"build": "deno compile --output build/faux -A --unstable index.ts", "build": "deno compile --output build/faux -A --unstable index.ts",
"build_linux": "deno compile --output build/faux_linux --target x86_64-unknown-linux-gnu -A --unstable index.ts", "build_linux": "mkdir -p ./build/zips ; mkdir -p ./build/linux ; cp ./manual.md ./build/linux/README.md ; deno compile --output build/linux/faux --target x86_64-unknown-linux-gnu -A --unstable index.ts ; cd ./build/linux ; zip -r ../zips/faux_linux.zip . ; cd ../..",
"build_windows": "deno compile --output build/faux_windows --target x86_64-pc-windows-msvc -A --unstable index.ts" "build_windows": "mkdir -p ./build/zips ; mkdir -p ./build/windows ; cp ./manual.md ./build/windows/README.md ; deno compile --output build/windows/faux --target x86_64-pc-windows-msvc -A --unstable index.ts ; cd ./build/windows ; zip -r ../zips/faux_windows.zip . ; cd ../..",
"build_all": "deno task build_linux & deno task build_windows"
} }
} }

134
docs/manual.md Normal file
View File

@ -0,0 +1,134 @@
# Faux Manual
This document is up-to-date as of May 14, 2023.
Faux is a [fantasy console](https://en.wikipedia.org/wiki/Fantasy_video_game_console) heavily inspired by [PICO-8](https://www.lexaloffle.com/pico-8.php), but with several alternative design choices. It is probably nowhere near as resource efficient either.
This console being in its infancy, this document is literally the only documentation that exists. As such, anything not found in this documentation should be asked of the author, or assumed to be similar to PICO-8.
## What's different from PICO-8?
Glad you asked.
Probably the most important difference is that cartridges are written in JavaScript rather than Lua.
Another huge design difference is that rather than having a fixed amount of sprite/map/music data, a Faux cartridge is made up of up to 16 "sheets". Each sheet can store a certain amount of data in a specific format. Sheets can be used to hold sprite data, map data, code, and eventually music/sfx, fonts, and other types of data. The first sheet must always be a code sheet and must return an object with three properties: `init`, `update`, and `draw`, each of which should be a function.
## Code
The code used in faux cartridges is JavaScript, but without a lot of the language built-ins. Instead, faux provides it's own api to accomplish things like drawing sprites, etc.
In the code editor, a few special characters can be inserted by holding alt while pressing another key. Currently, the characters that can be added in this way are:
Symbols for arrows:
- `⬆️` (Alt+W)
- `⬅️` (Alt+A)
- `⬇️` (Alt+S)
- `➡️` (Alt+D)
And math symbols:
- `π` (Alt+P)
### Graphics
- `cls(color?: number)` clears the screen to the given color if provided, otherwise, black.
- `camera(x: number, y: number)` draws everything from here on with an offset of (-x, -y).
- `sprsht(sheet: number)` sets the current spritesheet used for drawing sprites with the `spr` function below.
- `spr(x: number, y: number, sprite: number)` draws the given sprite from the current spritesheet at (x,y).
- `txt(x: number, y: number, text: string, color?: number)` draws the given text at (x,y) in the provided color (or white if none provided).
- `rectfill(x: number, y: number, w: number, h: number, color: number)` fills a rectangle with the given color with a top-left corner at (x,y) and a width of w and a height of h.
- `rect(x: number, y: number, w: number, h: number, color: number)` outlines a rectangle with the given color with a top-left corner at (x,y) and a width of w and a height of h.
- `circfill(x: number, y: number, r: number, color: number)` fills a circle with the given color with a center at (x,y) and a radius of r.
- `circ(x: number, y: number, r: number, color: number)` outlines a circle with the given color with a center at (x,y) and a radius of r.
- `ovalfill(x0: number, y0: number, x1: number, y1: number, color: number)` fills an ellipse with the given color whose bounding box has a top-left corner at (x0,y0) and a bottom-right corner at (x1,y1).
- `oval(x0: number, y0: number, x1: number, y1: number, color: number)` outlines an ellipse with the given color whose bounding box has a top-left corner at (x0,y0) and a bottom-right corner at (x1,y1).
- `pset(x: number, y: number, color: number)` sets the color of the pixel at (x,y) to the given color.
- `map(mapSheet: number, tileX: number, tileY: number, screenX: number, screenY: number, tileW: number, tileH: number)` draws the map of the given sheet to the screen at (screenX,screenY) beginning from from the tile at (tileX,tileY) and drawing tileW many tiles across, and tileH many tiles down.
### Map
- `mgetsht(mapSheet: number, x: number, y: number)` returns the sheet number of the sprite at tile (x,y) in the given map
- `mgetspr(mapSheet: number, x: number, y: number)` returns the sprite number within it's sheet of the sprite at tile (x,y) in the given map
- `mset(mapSheet: number, x: number, y: number, sprSheet: number, spr: number)` sets the sprite at tile (x,y) in the given map to the given sprite of the given spritesheet. **(THIS FUNCTION IS TEMPORARILY UNAVAILABLE.)**
### Input
- `btn(key: string | number)` returns a boolean indicating whether the given key is currently held down.
- `btnp(key: string | number)` returns a boolean indicating whether the given key has just been pressed. Fires repeatedly after a time, as when typing.
- `btnr(key: string | number)` returns a boolean indicating whether the given key has just been released.
There are also values:
- `⬆️` a number that corresponds to the up arrow.
- `⬅️` a number that corresponds to the left arrow.
- `⬇️` a number that corresponds to the down arrow.
- `➡️` a number that corresponds to the right arrow.
### System
- `save(name: string)` saves the cartridge
- `load(name: string)` loads the cartridge
- `play()` plays the cartridge
### Misc.
- `code(sheet: number)` executes the code in the given sheet as a function and returns any return value.
- `log(...args: any)` logs the given args to the stdout of faux.
### REPL Only
- `print(val: any)` only really should be used in the repl.
- `printVal(val: any)` only really should be used in the repl.
### Math functions
These are all identical to what Javascript typically has under the [`Math`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) namespace:
- `max`
- `min`
- `floor`
- `ceil`
- `sin`
- `cos`
- `atan2`
- `sqrt`
- `abs`
- `rand`
Faux also provides:
- `π` which is just `Math.PI` in regular JS.
### JS Objects
The following JS objects/functions/value are exactly provided as is in a typical JS environment:
- [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
- [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
- [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
- [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
- [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
- [`Function`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function)
- [`Infinity`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity)
- [`JSON`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON)
- [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
- [`NaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN)
- [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
- [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
- [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
- [`Reflect`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)
- [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp)
- [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
- [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
- [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)
- [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)
- [`WeakRef`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef)
- [`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)
- [`isFinite`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
- [`isNaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN)
- [`eval`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)
- [`parseFloat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat)
- [`parseInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt)

View File

@ -1,7 +1,7 @@
- [x] load - [x] load
- [x] save - [x] save
- [ ] folder - [ ] folder
- [ ] ls - [ ] ls (cd?)
- [x] run - [x] run
- [ ] stop - [ ] stop
- [ ] resume - [ ] resume

View File

@ -1,13 +1,13 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { CHAR, font } from "./font.ts"; import { CHAR, font } from "../data/font.ts";
import { drawText, measureText } from "./builtins.ts"; import { drawText, measureText } from "../runtime/builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { getCodeSheet, setSheet } from "./sheet.ts"; import { getCodeSheet, setSheet } from "../io/sheet.ts";
import { K, ctrlKeyDown, getKeyboardString, keyPressed, shiftKeyDown } from "./keyboard.ts"; import { K, ctrlKeyDown, getKeyboardString, keyPressed, shiftKeyDown } from "../io/keyboard.ts";
import { clipboard, tokenize } from "./deps.ts"; import { clipboard, tokenize } from "../deps.ts";
import { getBuiltins } from "./runcode.ts"; import { getBuiltins } from "../runtime/runcode.ts";
import { page } from "./viewsheets.ts"; import { page } from "./viewsheets.ts";
import { mouseDown, mouseHeld, mousePos } from "./mouse.ts"; import { mouseDown, mouseHeld, mousePos } from "../io/mouse.ts";
const historyDebounceFrames = 20; const historyDebounceFrames = 20;

View File

@ -1,13 +1,13 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { codetab } from "./codetab.ts"; import { codetab } from "./codetab.ts";
import { spritetab } from "./spritetab.ts"; import { spritetab } from "./spritetab.ts";
import { viewsheets, page } from "./viewsheets.ts"; import { viewsheets, page } from "./viewsheets.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { mouseClick, mousePos } from "./mouse.ts"; import { mouseClick, mousePos } from "../io/mouse.ts";
import { drawIcon } from "./builtins.ts"; import { drawIcon } from "../runtime/builtins.ts";
import { inRect } from "./util.ts"; import { inRect } from "../util/util.ts";
import { sheetsIcon, trashIcon } from "./icons.ts"; import { sheetsIcon, trashIcon } from "../data/icons.ts";
import { SheetType, setSheet } from "./sheet.ts"; import { SheetType, setSheet } from "../io/sheet.ts";
import { nonetab } from "./nonetab.ts"; import { nonetab } from "./nonetab.ts";
import { maptab } from "./maptab.ts"; import { maptab } from "./maptab.ts";

View File

@ -1,13 +1,11 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { drawSprite, drawText } from "./builtins.ts"; import { drawSprite, drawText, useSpritesheet } from "../runtime/builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { getMapSheet, getSheet, setSheet } from "./sheet.ts"; import { getMapSheet, getSheet, setSheet } from "../io/sheet.ts";
import { M, mouseClick, mouseDown, mouseHeld, mousePos } from "./mouse.ts"; import { M, mouseClick, mouseDown, mouseHeld, mousePos } from "../io/mouse.ts";
import { drawTransparentRect, drawVoidRect, inRect, reGrid } from "./util.ts"; import { drawTransparentRect, drawVoidRect, inRect, reGrid } from "../util/util.ts";
import { page } from "./viewsheets.ts"; import { page } from "./viewsheets.ts";
import { useSpritesheet } from "./builtins.ts"; import { keyPressed, K } from "../io/keyboard.ts";
import { keyPressed } from "./keyboard.ts";
import { K } from "./keyboard.ts";
const state = { const state = {
selectedSpriteSheet: 0, selectedSpriteSheet: 0,

View File

@ -1,12 +1,11 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { drawIcon, drawText } from "./builtins.ts"; import { drawIcon, drawText, useSpritesheet } from "../runtime/builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { getSheet, setSheet } from "./sheet.ts"; import { getSheet, setSheet } from "../io/sheet.ts";
import { mouseClick, mousePos } from "./mouse.ts"; import { mouseClick, mousePos } from "../io/mouse.ts";
import { reGridWithGap } from "./util.ts"; import { reGridWithGap } from "../util/util.ts";
import { page } from "./viewsheets.ts"; import { page } from "./viewsheets.ts";
import { useSpritesheet } from "./builtins.ts"; import { codeIcon, mapIcon, spriteIcon } from "../data/icons.ts";
import { codeIcon, mapIcon, spriteIcon } from "./icons.ts";
const gridX = 8; const gridX = 8;
const gridY = 40; const gridY = 40;

View File

@ -1,11 +1,10 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { drawSprite, drawText } from "./builtins.ts"; import { drawSprite, drawText, useSpritesheet } from "../runtime/builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { getSpriteSheet, setSheet } from "./sheet.ts"; import { getSpriteSheet, setSheet } from "../io/sheet.ts";
import { mouseClick, mouseHeld, mousePos } from "./mouse.ts"; import { mouseClick, mouseHeld, mousePos } from "../io/mouse.ts";
import { drawTransparentRect, inRect, outlineRect, reGrid } from "./util.ts"; import { drawTransparentRect, inRect, outlineRect, reGrid } from "../util/util.ts";
import { page } from "./viewsheets.ts"; import { page } from "./viewsheets.ts";
import { useSpritesheet } from "./builtins.ts";
const state = { const state = {
selectedSprite: 0, selectedSprite: 0,

View File

@ -1,12 +1,12 @@
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { drawIcon, drawText } from "./builtins.ts"; import { drawIcon, drawText } from "../runtime/builtins.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { getSheet } from "./sheet.ts"; import { getSheet } from "../io/sheet.ts";
import { mouseClick, mousePos } from "./mouse.ts"; import { mouseClick, mousePos } from "../io/mouse.ts";
import { getCart } from "./cart.ts"; import { getCart } from "../io/cart.ts";
import { font } from "./font.ts"; import { font } from "../data/font.ts";
import { codeIcon, spriteIcon, mapIcon } from "./icons.ts"; import { codeIcon, spriteIcon, mapIcon } from "../data/icons.ts";
import { reGridWithGap } from "./util.ts"; import { reGridWithGap } from "../util/util.ts";
const fontHeight = font.height; const fontHeight = font.height;

View File

@ -2,24 +2,24 @@ import {
mainloop, mainloop,
frame, frame,
clearScreen, clearScreen,
} from "./window.ts"; } from "./io/window.ts";
import { runCode } from "./runcode.ts"; import { runCode } from "./runtime/runcode.ts";
import { getCodeSheet } from "./sheet.ts"; import { getCodeSheet } from "./io/sheet.ts";
import { refreshKeyboard, keyPressed, K } from "./keyboard.ts"; import { refreshKeyboard, keyPressed, K } from "./io/keyboard.ts";
import { repl, resetRepl } from "./repl.ts"; import { repl, resetRepl } from "./repl/repl.ts";
import { addToContext } from "./runcode.ts"; import { addToContext } from "./runtime/runcode.ts";
import { editmode } from "./editmode.ts"; import { editmode } from "./editor/editmode.ts";
import { refreshMouse } from "./mouse.ts"; import { refreshMouse } from "./io/mouse.ts";
import { camera } from "./builtins.ts"; import { camera } from "./runtime/builtins.ts";
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
let game: any = null; let game: any = null;
let mode: "play" | "edit" | "repl" = "repl"; let mode: "play" | "edit" | "repl" = "repl";
addToContext("play", () => { addToContext("play", async () => {
game = await runCode(getCodeSheet(0));
mode = "play"; mode = "play";
game = runCode(getCodeSheet(0));
game.init(); game.init();
}); });
@ -43,8 +43,8 @@ await mainloop(async (_t) => {
} else { } else {
if (mode === "play") { if (mode === "play") {
if (game) { if (game) {
game.update(); await game.update();
game.draw(); await game.draw();
} }
frame(); frame();
} else if (mode === "repl") { } else if (mode === "repl") {

28
io/cart.ts Normal file
View 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;
}

View File

@ -1,4 +1,4 @@
import { font, CHAR } from "./font.ts"; import { font, CHAR } from "../data/font.ts";
const keyboard = new Map<number, {first: boolean, repeat: boolean, held: boolean}>(); const keyboard = new Map<number, {first: boolean, repeat: boolean, held: boolean}>();

View File

@ -13,8 +13,11 @@ const mouseButtonsDown = {
[M.RIGHT]: false, [M.RIGHT]: false,
[M.MIDDLE]: false, [M.MIDDLE]: false,
}; };
type MouseEventType = "click" | "down" | "up" | "move" | "dblclick";
const mouseEvents: Array<{ const mouseEvents: Array<{
type: "click" | "down" | "up" | "move" | "dblclick", type: MouseEventType,
button: typeof M[keyof typeof M], button: typeof M[keyof typeof M],
x: number, x: number,
y: number, y: number,
@ -27,37 +30,59 @@ let mouseY = 0;
const eventPixelCoords = (evt: WindowMouseEvent) => { const eventPixelCoords = (evt: WindowMouseEvent) => {
const {width, height} = gameWindow.size; const {width, height} = gameWindow.size;
const pixX = Math.floor(128*evt.clientX/width); const min = Math.min(width, height);
const pixY = Math.floor(128*evt.clientY/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 { return {
x: pixX, x: pixX,
y: pixY, 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) => { addEventListener("dblclick", (evt) => {
mouseEvents.push({type: "dblclick", button: evt.button, ...eventPixelCoords(evt)}); pushEvent("dblclick", evt);
}); });
addEventListener("click", (evt) => { addEventListener("click", (evt) => {
mouseEvents.push({type: "click", button: evt.button, ...eventPixelCoords(evt)}); pushEvent("click", evt);
}); });
addEventListener("mousedown", (evt) => { addEventListener("mousedown", (evt) => {
mouseButtonsDown[evt.button] = true; if (evtInBounds(evt)) {
mouseEvents.push({type: "down", button: evt.button, ...eventPixelCoords(evt)}); mouseButtonsDown[evt.button] = true;
}
pushEvent("down", evt);
}); });
addEventListener("mouseup", (evt) => { addEventListener("mouseup", (evt) => {
mouseButtonsDown[evt.button] = false; if (evtInBounds(evt)) {
mouseEvents.push({type: "up", button: evt.button, ...eventPixelCoords(evt)}); mouseButtonsDown[evt.button] = false;
}
pushEvent("up", evt);
}); });
addEventListener("mousemove", (evt) => { addEventListener("mousemove", (evt) => {
const coords = eventPixelCoords(evt); const coords = eventPixelCoords(evt);
mouseEvents.push({type: "move", button: evt.button, ...eventPixelCoords(evt), prevX: mouseX, prevY: mouseY}); pushEvent("up", evt, {prevX: mouseX, prevY: mouseY});
mouseX = coords.x; if (coords) {
mouseY = coords.y; mouseX = coords.x;
mouseY = coords.y;
}
}); });
export const mousePos = () => { export const mousePos = () => {

View File

@ -1,5 +1,5 @@
import { getCart } from "./cart.ts"; import { getCart } from "./cart.ts";
import { LinearGrid } from "./util.ts"; import { LinearGrid } from "../util/util.ts";
// import { runCode, addToContext } from "./runcode.ts"; // import { runCode, addToContext } from "./runcode.ts";
// "code" | "spritesheet" | "map" | "sfx" | "patterns" | "fonts" // "code" | "spritesheet" | "map" | "sfx" | "patterns" | "fonts"
@ -18,7 +18,7 @@ export type Sheet = {
} }
export type SheetType = Sheet["sheet_type"]; export type SheetType = Sheet["sheet_type"];
export const getSheet = (n: number) => { export const getSheet = (n: number): Sheet => {
return getCart()[n]; return getCart()[n];
} }
@ -51,5 +51,6 @@ export const getMapSheet = (sheet: number) => {
if (sheet_type !== "map") { if (sheet_type !== "map") {
throw "Trying to use a non-map sheet as a map." throw "Trying to use a non-map sheet as a map."
} }
sheet_type
return LinearGrid(value, 64); return LinearGrid(value, 64);
} }

View File

@ -2,15 +2,15 @@ import {
createWindow, createWindow,
getProcAddress, getProcAddress,
gl, gl,
} from "./deps.ts"; } from "../deps.ts";
export {mainloop} from "./deps.ts"; export {mainloop} from "../deps.ts";
import { COLOR, palette } from "./colors.ts"; import { COLOR, palette } from "../data/colors.ts";
export const gameWindow = createWindow({ export const gameWindow = createWindow({
title: "Faux", title: "Faux",
width: 1024, width: 512,
height: 1024, height: 512,
resizable: false, resizable: true,
glVersion: [3, 2], glVersion: [3, 2],
gles: true, gles: true,
}); });
@ -92,16 +92,20 @@ if (status[0] === gl.FALSE) {
gl.ClearColor(0.0, 0.0, 0.0, 1.0); gl.ClearColor(0.0, 0.0, 0.0, 1.0);
addEventListener("resize", (event) => {
gl.Viewport(0, 0, event.width, event.height);
});
const pixelsPerRow = 128; const pixelsPerRow = 128;
const top = 1; const top = 1;
const left = -1; const left = -1;
const cell = 2/pixelsPerRow; 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) => { const px = (x: number, y: number) => {
// deno-fmt-ignore // deno-fmt-ignore
return [ return [
@ -238,7 +242,6 @@ export const fillRectRaw = (x: number, y: number, w: number, h: number, color: n
export const clearScreen = (color?: number) => { export const clearScreen = (color?: number) => {
fillRectRaw(0, 0, 128, 128, color ?? COLOR.BLACK); fillRectRaw(0, 0, 128, 128, color ?? COLOR.BLACK);
// allPixelColors.fill(0);
} }
export const frame = () => { export const frame = () => {

View File

@ -1,9 +1,9 @@
import { drawText} from "./builtins.ts"; import { drawText} from "../runtime/builtins.ts";
import { getKeysPressed, shiftKeyDown, shiftMap, K } from "./keyboard.ts"; import { getKeysPressed, shiftKeyDown, shiftMap, K } from "../io/keyboard.ts";
import { font } from "./font.ts"; import { font } from "../data/font.ts";
import { addToContext, evalCode } from "./runcode.ts"; import { addToContext, evalCode } from "../runtime/runcode.ts";
import { clearScreen, fillRect } from "./window.ts"; import { clearScreen, fillRect } from "../io/window.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
const lineHeight = 6; const lineHeight = 6;

View File

@ -8,15 +8,15 @@ outlineCircle,
fillEllipse, fillEllipse,
outlineEllipse, outlineEllipse,
setPixelColor, setPixelColor,
} from "./window.ts"; } from "../io/window.ts";
import { CHAR, Font, font } from "./font.ts"; import { CHAR, Font, font } from "../data/font.ts";
import { K, keyDown, keyPressed, keyReleased } from "./keyboard.ts"; import { K, keyDown, keyPressed, keyReleased } from "../io/keyboard.ts";
import { addToContext, runCode } from "./runcode.ts"; import { addToContext, runCode } from "./runcode.ts";
import { resetRepl } from "./repl.ts"; import { resetRepl } from "../repl/repl.ts";
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { getSheet, getCodeSheet, getMapSheet } from "./sheet.ts"; import { getSheet, getCodeSheet, getMapSheet } from "../io/sheet.ts";
import { saveCart, loadCart } from "./cart.ts"; import { saveCart, loadCart } from "../io/cart.ts";
import { outlineRect } from "./util.ts"; import { outlineRect } from "../util/util.ts";
let spritesheet: number | null = null; let spritesheet: number | null = null;
@ -127,12 +127,13 @@ const faux = {
} }
return getMapSheet(mapSheet).get(x, y)[1]; return getMapSheet(mapSheet).get(x, y)[1];
}, },
mset: (mapSheet: number, x: number, y: number, sprSheet: number, spr: number) => { // Temporarily removing mset, since it would overwrite static cart data
if (x < 0 || x >= 64 || y < 0 || y >= 64) { // mset: (mapSheet: number, x: number, y: number, sprSheet: number, spr: number) => {
return; // if (x < 0 || x >= 64 || y < 0 || y >= 64) {
} // return;
getMapSheet(mapSheet).set(x, y, [sprSheet, spr]); // }
}, // getMapSheet(mapSheet).set(x, y, [sprSheet, spr]);
// },
// Input // Input
[CHAR.UP]: K.ARROW_UP, [CHAR.UP]: K.ARROW_UP,
[CHAR.DOWN]: K.ARROW_DOWN, [CHAR.DOWN]: K.ARROW_DOWN,
@ -169,6 +170,8 @@ const faux = {
WeakSet, WeakSet,
isFinite, isFinite,
isNaN, isNaN,
parseFloat,
parseInt,
// Math // Math
max: Math.max, max: Math.max,
min: Math.min, min: Math.min,

View File

@ -1,9 +1,23 @@
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
const G: any = {
eval: eval,
};
// deno-lint-ignore no-explicit-any
const builtins: any = {}; const builtins: any = {};
// deno-lint-ignore no-explicit-any
const G: any = {};
// deno-lint-ignore no-explicit-any
export const addToContext = (name: string, value: any) => {
builtins[name] = value;
}
export const getBuiltins = () => {
return builtins;
}
// deno-lint-ignore no-explicit-any
const AsyncFunction = (async function () {}).constructor as any;
addToContext("eval", eval);
const context = new Proxy(G, { const context = new Proxy(G, {
get: (target, prop) => { get: (target, prop) => {
if (prop in builtins) { if (prop in builtins) {
@ -20,18 +34,18 @@ const context = new Proxy(G, {
}, },
}); });
export const runCode = (code: string) => { export const runCode = async (code: string) => {
try { try {
new Function(code); new AsyncFunction(code);
} catch (err) { } catch (err) {
throw err; throw err;
} }
const fn = new Function("context", ` const fn = new AsyncFunction("context", `
with (context) { with (context) {
${code} ${code}
} }
`); `);
return fn(context); return await fn(context);
} }
export const evalCode = (code: string) => { export const evalCode = (code: string) => {
@ -44,13 +58,4 @@ export const evalCode = (code: string) => {
throw err; throw err;
} }
} }
}
// deno-lint-ignore no-explicit-any
export const addToContext = (name: string, value: any) => {
builtins[name] = value;
}
export const getBuiltins = () => {
return builtins;
} }

View File

@ -1,5 +1,5 @@
import { COLOR } from "./colors.ts"; import { COLOR } from "../data/colors.ts";
import { fillRect, setPixelColor } from "./window.ts"; import { fillRect, setPixelColor } from "../io/window.ts";
export const inRect = (x: number, y: number, rectX: number, rectY: number, rectW: number, rectH: number) => { export const inRect = (x: number, y: number, rectX: number, rectY: number, rectW: number, rectH: number) => {
return ( return (