This commit is contained in:
Theis Pieter Hollebeek 2025-10-13 12:36:26 +02:00
parent 8c5f713501
commit 6663c46f71
7 changed files with 2408 additions and 0 deletions

View File

@ -3,5 +3,6 @@
"indentWidth": 4,
"lineWidth": 100
},
"exclude": ["./docs"],
"lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
}

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
-

11
docs/deno.jsonc Normal file
View File

@ -0,0 +1,11 @@
{
"fmt": {
"indentWidth": 4,
"lineWidth": 100
},
"imports": {
"@libs/markdown": "jsr:@libs/markdown@^2.0.4",
"@std/fs": "jsr:@std/fs@^1.0.19",
"@std/path": "jsr:@std/path@^1.1.2"
}
}

2073
docs/deno.lock generated Normal file

File diff suppressed because it is too large Load Diff

86
docs/render.ts Normal file
View File

@ -0,0 +1,86 @@
import { Renderer } from "@libs/markdown";
import HighlightPlugin from "@libs/markdown/plugins/highlighting";
import { walk } from "@std/fs";
import * as pathTools from "@std/path";
function injectIntoTemplate(name: string, rendered: string): string {
let content = [
"<!DOCTYPE html>",
"<html>",
"<head>",
[
`<title>${name}</title>`,
],
"</head>",
"<body>",
[
rendered,
"<script>",
[
"function slugify(elements) {",
`return elements
.map((element, i) => {
if (i === 0) return null;
const content = element.textContent.trim();
if (content.startsWith("lib.")) {
const [name] = content.match(/^lib\\.[^\(]+/);
return name.trim();
}
return content;
})
.filter(x => x !== null)
.join("-");`,
"}",
'const headers = document.querySelectorAll("h1,h2,h3,h4,h5,h6");',
"const ancestors = [];",
"for (const header of headers) {",
[
"const depth = parseInt(header.tagName.slice(1));",
"while (ancestors.length >= depth) {",
[
"ancestors.pop();",
],
"}",
"ancestors.push(header);",
"if (depth > 1) header.id = slugify(ancestors);",
],
"}",
],
"</script>",
],
"</body>",
"</html>",
];
while (content.some((x) => Array.isArray(x))) {
content = content.flat();
}
return content.join("");
}
async function main() {
const renderer = await Renderer.with({
plugins: [HighlightPlugin],
});
for await (
const entry of walk("src", {
exts: [".md"],
})
) {
const parsed = pathTools.parse(entry.path);
parsed.dir = parsed.dir.replace(/^src[\\/]?/, "");
parsed.dir = pathTools.join("-", parsed.dir);
parsed.ext = ".html";
parsed.base = `${parsed.name}${parsed.ext}`;
await Deno.mkdir(parsed.dir, { recursive: true });
const content = await renderer.render(await Deno.readTextFile(entry.path));
await Deno.writeTextFile(
pathTools.format(parsed),
injectIntoTemplate(parsed.name, content),
);
}
}
if (import.meta.main) {
main();
}

236
docs/src/gamelib.md Normal file
View File

@ -0,0 +1,236 @@
# Gamelib
## Models
### `Color`
A type of string.
Represents HTML colors. This includes
[named colors](https://developer.mozilla.org/en-US/docs/Web/CSS/named-color) such as `blue`, `red`,
`blanchedalmond`, `lavenderblush`, and rgb/hex when used with proper format. You can use
[`lib.rgb(r, g, b)`](#Lib-lib.rgb) to generate a properly formatted rgb color code.
Example:
```ts
lib.drawRect(0, 0, 100, 100, "blue");
lib.drawRect(100, 0, 100, 100, lib.rgb(192, 127, 172));
```
### `Key`
A type of string.
Represents JavaScript's `KeyboardEvent.key`
([link](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)) property.
Example:
```
"Enter": Enter was pressed.
"b": Lowercase 'b' was pressed.
"B": Uppercase 'B' was pressed (i.e. Shift + B)
" ": Spacebar was pressed.
```
/* todo: include a little html tool that listens to key events when focused and outputs what key was
pressed */
### `KeyEventFunc`
A function with no parameters that is called whenever the appropriate [`Key`](#Models-Key) is
pressed / released.
Works both as a named and anonymous function.
Example:
```ts
let playerX = 0;
// anonymous function
lib.onPress("a", function () {
playerX -= 20;
});
// named function
function dWasPressed() {
playerX += 20;
}
// note the lack of () after dWasPressed - we are not calling the function, we are referring to it as a variable
lib.onPress("a", dWasPressed);
```
### `LoopFunc`
A function with a single parameters (`deltaT`) that is called whenever a game tick should run -
usually about 1/60 times a second.
The `deltaT` parameter describes the time difference between the last tick and now, in seconds.
The name used for `deltaT` can be anything, it functions as any other function parameter. I.e.
`loopFunction(timeSinceLastCall)`, `loopFunction(fooBar)`, etc.
For example:
```
loopFunction is called at 12:00.24 - deltaT is 0
loopFunction is called at 12:00.75 - deltaT is .51
loopFunction is called at 12:01.52 - deltaT is .77
```
Works both as a named and anonymous function.
Example:
```ts
let playerX = 0;
// anonymous function
lib.startGameLoop(function (deltaT) {
playerX += 20 * deltaT;
});
// named function
function loopFunction(deltaTime) {
playerX += 20 * deltaTime;
}
// note the lack of () after loopFunction - we are not calling the function, we are using it as a variable
lib.startGameFunction(loopFunction);
```
## Lib
### `lib.println(msg: string) -> void`
Print a message the debug console.
Example:
```ts
lib.println("Hello world!");
lib.println("It is a thursday.");
```
```
[console]
Hello world!
It is a thursday.
```
### `lib.startGameLoop(loopFunction: LoopFunc) -> void`
Registers a gameloop function, that is called on every tick.
See also: [`Models.LoopFunc`](#Models-LoopFunc)
### `lib.isPressed(key: Key) -> bool`
Returns whether or not `key` is currently pressed.
See also: [`Models.Key`](#Models-Key)
Example:
```ts
let playerX = 0;
lib.startGameLoop(function (deltaT) {
if (lib.isPressed("a")) {
playerX -= 20 * deltaT;
}
if (lib.isPressed("d")) {
playerX -= 20 * deltaT;
}
});
```
### `lib.onPress(key: Key, handlerFunction: KeyEventFunc) -> void`
Calls `handlerFunction` whenever `key` is pressed.
See also: [`Models.Key`](#Models-Key), [`Models.KeyEventFunc`](#Models-KeyEventFunc)
Example:
```ts
let isJumping = false;
lib.onPress(" ", function () {
isJumping = true;
});
lib.onRelease(" ", function () {
isJumping = false;
});
```
### `lib.onRelease(key: Key, handlerFunction: KeyEventFunc) -> void`
The opposite of [`lib.onPress`](#Lib-lib.onPress)
### `lib.rgb(red: number, green: number, blue: number) -> Color`
Generates a correctly formatted [`Color`](#Models-Color) value based on `red`, `green` and `blue`
See also: [`Models.Color`](#Models-Color)
Example:
```ts
lib.drawRect(100, 0, 100, 100, lib.rgb(192, 127, 172));
```
### `lib.clear(color: Color) -> void`
Paints the entire screen `color`.
See also: [`Models.Color`](#Models-Color)
Example:
```ts
function drawClouds() {
/* some lib.drawRect(..) or lib.drawSprite(..) */
}
lib.startGameLoop(function () {
lib.clear("blue");
drawClouds();
});
```
### `lib.drawSprite(x: number, y: number, width: number, height: number, name: string) -> void`
Draws a sprite imported in the sprite editor.
/* todo: link to sprite editor docs */
Example:
```ts
lib.startGameLoop(function () {
lib.clear("blue");
lib.drawSprite(20, 30, 20, 10, "cloud.png");
});
```
### `lib.drawRect(x: number, y: number, width: number, height: number, color: Color) -> void`
Fills a rect with [`Color`](#Models-Color).
See also: [`Models.Color`](#Models-Color)
Example:
```ts
function drawCloud(x, y) {
lib.drawRect(x, y, 20, 10, "white");
}
lib.startGameLoop(function () {
lib.clear("blue");
drawCloud(20, 30);
drawCloud(50, 35);
});
```