Tweaked the layout

This commit is contained in:
2023-07-22 19:10:22 +10:00
committed by GitHub
parent 13bfaaf91e
commit e935061b0e
6 changed files with 68 additions and 66 deletions

View File

@@ -6,26 +6,27 @@ The about library can usually be accessed with the `import` keyword:
```
import about;
import about as about; //can easily be aliased
import about as about; //can be aliased
```
## major
## Defined Variables
### major
This variable is the major version number of Toy at the time of compilation.
## minor
### minor
This variable is the minor version number of Toy at the time of compilation.
## patch
### patch
This variable is the patch version number of Toy at the time of compilation.
## build
### build
This variable is a string representing the date and time that the interpreter was compiled.
## author
### author
This variable contains the name of Toy's lead author, and his game studio.

View File

@@ -1,127 +0,0 @@
# Game Engine
The Toy programming langauge was designed from the beginning as an embedded scripting language for some kind of game engine. Different iterations have existed with different implementations, some of which could charitably be said to function. The current version, and the most stable and feature complete so far, has reached a point where it needs some kind of concrete engine to improve any further.
Currently, the engine exists under the `Box/` directory within the "airport" repository, and builds as part of that program - this will be packaged as a separate repo soon.
[https://github.com/Ratstail91/airport](https://github.com/Ratstail91/airport)
NOTE: This documentation page is a rushjob, and will be expanded into it's own subsection eventually.
## Engine Structure
The engine is invoked with just three lifecycle functions called directly from `main()`:
```c
#define SDL_MAIN_HANDLED
#include "box_engine.h"
int main(int argc, char* argv[]) {
//the real main() has some extra junk, but this is all that's needed for the engine
Box_initEngine();
Box_execEngine();
Box_freeEngine();
return 0;
}
```
The engine proper holds the following elements:
* SDL2 window and renderer
* Framerate controls
* Toy interpreter
* Input keyboard mapping dictionaries
* The root node
Input and rendering in the game engine are handled by SDL2 - this allows for the game to, in theory, be built on multiple platforms. For the time being, however, we're just targeting Windows due to a lack of testing machines.
The engine is calibrated to run at 60 FPS - if the "simulation time" falls too far behind the real time, then frame rendering is skipped in favour of speeding up the game logic. Likewise, if the simulation time runs too fast, then the simulation step is skipped instead and an extra frame is drawn. This process can lead to multiple skips in a row, in both directions.
The Toy interpreter is the core of the scripting system. Other interpreters may be generated and cleared during Toy's internal processes, but this one lasts for the duration of the program.
The keyboard inputs can be remapped using API functions - these mappings are stored and accessed within a pair of Toy dictionaries that have simply been embedded directly into the engine for easy access.
The nodes form a deep tree-like structure, with the "root node" at it's base.
## Node Structure
The fundemental building block of the engine's logic is the node - nodes can represent anything within the game world, from entities to abstract global systems. You can think of entities as having a 1:1 mapping to Toy scripts, as each one is given bytecode on initialization that fills its internals.
A node holds the following elements:
* A reference to it's parent
* An array of references to its children, and bookkeeping variables for tracking them
* A dictionary of functions defined in the Toy script
* A single SDL texture reference, and controls for rendering it (including as an animated spritesheet)
The nodes are deeply integrated with Toy scripts, while Toy was written specifically for this purpose. The tree-like structure of the nodes all exist entirely within the computer's heap memory as a result of Toy's memory model - this comes with performance drawbacks and cleanup requirements. Child nodes should never be referenced directly, as they may be `NULL` references that have been released - the internal array doesn't shrink, and the tombstones don't get reused.
The rules of execution for scripts and functions is as follows:
* The script is executed during node initialization
* All functions (regardless of name) are stored within the node - effectively preserving the scope of the script as a whole
* These functions can now be invoked from elsewhere in the program
* Certian function names (listed below) are invoked at specific times during the game loop throughout the entire node tree
* If the specially named functions do not exist, the node is simply skipped
* Every function, which is intended to be called through `callNodeFn()` or at specific times in the loop must take the `opaque` node as its first argument
## Special Function Names
The following functions, which are defined within the node scripts, are invoked at specific times within the game loop. Note that if you want code to execute *during* node creation, place it within the script's root scope. Variables that you want to persist between calls should also be placed in the script's root.
* `onLoad(node: opaque)`
* `onInit(node: opaque)`
* `onStep(node: opaque)`
* `onFree(node: opaque)`
* `onDraw(node: opaque)`
* `onKeyDown(node: opaque, event: string)`
* `onKeyUp(node: opaque, event: string)`
* `onMouseMotion(node: opaque, x: int, y: int, xrel: int, yrel: int)`
* `onMouseButtonDown(node: opaque, x: int, y: int, button: string)`
* `onMouseButtonUp(node: opaque, x: int, y: int, button: string)`
* `onMouseWheel(node: opaque, xrel: int, yrel: int)`
These may change or expand as more input devices are added, and the engine matures.
NOTE: `onLoad()` is invoked every time a node is loaded - but `onInit()` is only invoked once by the engine. After that, `initNode()` must be called manually on any node children that are loaded later.
# Engine Libraries
A series of libraries are provided to allow Toy to interface and control the engine. In addition, the libraries stored within Toy's `repl/` directory are also available (see the main page for the list).
During startup, the script named `init.toy` in the root of the scripts directory is executed. This file can be used to configure input mappings, as well as initializing the window and node tree.
TODO: Complete the rest of this page
# Engine API
The engine API is for controlling the core of the engine directly.
## initWindow(caption: string, width: int, height: int, fullscreen: bool)
This function initializes the game's window, as well as specifying it's dimensions and properties. There is only one window - calling this multiple times is a fatal error. Also, the game's loop will simply not run if the window hasn't been initialized.
## loadRootNode(fname: string)
TODO
## getRootNode(): opaque
TODO
# Node API
The node API is for controlling individual nodes.
TODO
# Input API
The input API is for mapping different interface devices to different "event" names - currently only the keyboard inputs can be mapped this way, but more devices may be added in the future - thus, the input API was separated into a separate library from the engine proper.
TODO
# Box C API
TODO

View File

@@ -13,19 +13,22 @@ var generator: opaque = createRandomGenerator(clock().hash());
The current implementation is minimal in nature, and will be expanded or replaced in future.
## createRandomGenerator(seed: int)
## Defined Functions
### createRandomGenerator(seed: int): opaque
This function creates a new generator opaque based on the given seed. The same seed will produce the same sequence of pseudorandom outputs from different generators using `generateRandomNumber`.
Every generator must also be freed with `freeRandomGenerator`.
## generateRandomNumber(self: opaque)
### generateRandomNumber(self: opaque): int
This function takes in a generator opaque, and returns a pseudorandom integer value.
This function also mutates the generator's internal state.
## freeRandomGenerator(self: opaque)
### freeRandomGenerator(self: opaque)
This function frees an existing generator opaque.
This function must be called on all generators before the program ends.

View File

@@ -10,7 +10,9 @@ The runner library can usually be accessed with the `import` keyword:
import runner;
```
## loadScript(path: string)
## Defined Functions
### loadScript(path: string): opaque
This is used to load an external script into an opaque variable.
@@ -22,7 +24,7 @@ This function does a lot of work:
* It constructs and intializes an Interpreter
* It packages it all into an opaque variable and returns it
## loadScriptBytecode(path: string)
### loadScriptBytecode(path: string): opaque
This is used to load an external bytecode file into an opaque variable.
@@ -34,11 +36,11 @@ This function does a lot of work:
Note: This function resembles `loadScript()`, but skips the compilation step.
## runScript(self: opaque)
### runScript(self: opaque)
This function executes an external script, which must first be loaded into an opaque variable with either `loadScript()` or `loadScriptBytecode()`.
## getScriptVar(self: opaque, name: string)
### getScriptVar(self: opaque, name: string): any
This function retrieves a variable from the top level of a script's environment.
@@ -46,15 +48,14 @@ This function retrieves a variable from the top level of a script's environment.
This function retrieves a function from the top level of a script's environment, and calls it with `rest` as the argument list.
## resetScript(self: opaque)
### resetScript(self: opaque)
This function resets the script so that it is no longer in a "dirty" state, and can be re-run using `runScript()`.
## freeScript(self: opaque)
### freeScript(self: opaque)
This function frees a script's resources, cleaning up any memory that is no longer needed. Failing to call this will result in a memory leak.
## checkScriptDirty(self: opaque)
### checkScriptDirty(self: opaque): bool
This function returns true of the script is "dirty", otherwise it returns false.

View File

@@ -8,14 +8,13 @@ The standard library can usually be accessed with the `import` keyword:
import standard;
```
# Misc. Utilities
<hr />
## Defined Misc. Functions
## clock()
### clock(): string
This function returns a string representation of the current timestamp.
## hash(self)
### hash(self: any): int
This function returns a hashed value of `self`.
@@ -28,53 +27,51 @@ This function uses the internal literal hashing algorithms. As such, the followi
Any attempt to hash these will return -1, except `null` which returns 0.
# Maths Utilities
<hr />
## Defined Maths Functions
## abs(self)
### abs(self): any
This function returns the absolute value of any integer or float passed in.
## ceil(self): int
### ceil(self): int
This function returns the value of any integer or float passed in, rounded up.
## floor(self): int
### floor(self): int
This function returns the value of any integer or float passed in, rounded down.
## max(...)
### max(...): any
This function returns the value of the highest integer or float passed in. It can take any number of arguments.
## min(...)
### min(...): any
This function returns the value of the lowest integer or float passed in. It can take any number of arguments.
## round(self): int
### round(self): int
This function returns the value of any integer or float passed in, rounded to the nearest whole number.
# Compound Utilities
<hr />
## Defined Compound Functions
## concat(self, other)
### concat(self, other): any
This function only works when self and other are matching compounds (both arrays, dictionaries or strings). It returns a new compound of that kind, with the content of `other` appended to the content of `self`.
## containsKey(self: dictionary, key)
### containsKey(self: dictionary, key): bool
This function returns `true` if `self` contains the given `key`, otherwise it returns false.
## containsValue(self, value)
### containsValue(self, value): bool
This function returns `true` if `self` contains the given `value`, otherwise it returns false.
## every(self, func: fn)
### every(self, func: fn): bool
This function takes either an array or a dictionary as the `self` argument, and a function as `func`. The argument `func` must take two arguments - the first is the index/key of the array/dictionary, and the second is the value. The contents of `self` are passed into `func`, one element at a time, until `func` returns `false`, at which point this function returns `false`. Otherwise this function returns `true`.
## forEach(self, func: fn)
### forEach(self, func: fn)
This function takes either an array or a dictionary as the `self` argument, and a function as `func`. The argument `func` must take two arguments - the first is the index/key of the array/dictionary, and the second is the value. The contents of `self` are passed into `func`, one element at a time.
@@ -90,23 +87,23 @@ var a = [1, 3, 5];
a.forEach(p); //prints 1, 3, and 5 to stdout
```
## filter(self, func: fn)
### filter(self, func: fn): any
This function takes either an array or a dictionary as the `self` argument, and a function as `func`. The argument `func` must take two arguments - the first is the index/key of the array/dictionary, and the second is the value. The contents of `self` are passed into `func`, one element at a time, and the function returns a new compound for every element that `func` returned a truthy value for.
## getKeys(self: dictionary)
### getKeys(self: dictionary): [any]
This function returns an array of all non-null keys stored within the dictionary. The order is undefined.
## getValues(self: dictionary)
### getValues(self: dictionary): [any]
This function returns an array of all values with non-null keys stored within the dictionary. The order is undefined.
## indexOf(self: array, value)
### indexOf(self: array, value): int
This function returns the first index within `self` that is equal to `value`, or `null` if none are found.
## map(self, func: fn)
### map(self, func: fn): any
This function takes either an array or a dictionary as the `self` argument, and a function as `func`. The argument `func` must take two arguments - the first is the index/key of the array/dictionary, and the second is the value. It returns an array with the results of each call - the order of the results when called on a dictionary are undefined.
@@ -122,7 +119,7 @@ var a = [1, 2, 3];
print a.map(increment); //prints [2,3,4];
```
## reduce(self, default, func: fn)
### reduce(self, default: any, func: fn): any
This function takes either an array or a dictionary as the `self` argument, a default value, and a function as `func`. The argument `func` takes three arguments - the first is the accumulator, the second is the index/key and the third is the value. It applies the given function to every element of the array/dictionary, passing the result of each call as the accumulator to the next (the default value is used for the first call). Finally, the final value of the accumulator is returned to the caller.
@@ -138,13 +135,13 @@ var a = [1, 2, 3, 4];
print a.reduce(0, f); //prints "10"
```
## some(self, func: fn)
### some(self, func: fn): bool
This function takes either an array or a dictionary as the `self` argument, and a function as `func`. The argument `func` must take two arguments - the first is the index/key of the array/dictionary, and the second is the value. The contents of `self` are passed into `func`, one element at a time, until `func` returns `true`, at which point this function returns `true`. Otherwise this function returns `false`.
## sort(self: array, func: fn)
### sort(self: array, func: fn)
This function takes an array as the `self` argument, and a comparison function as `func`. The argument `func` must take two arguments, and return a truthy or falsy value. The contents of the array in `self` are sorted based on the results of `func`, as though function were the less comparison function.
This function takes an array as the `self` argument, and a comparison function as `func`. The argument `func` must take two arguments, and return a truthy or falsy value. The contents of the array in `self` are sorted based on the results of `func`, as though the function were the less comparator function.
```
import compound;
@@ -158,21 +155,21 @@ var a = [4, 1, 3, 2];
print a.sort(less); //prints "[1, 2, 3, 4]"
```
## toLower(self: string)
### toLower(self: string): string
This function returns a new string which is identical to the string `self`, except any uppercase letters are replaced with the corresponding lowercase letters.
## toString(self)
### toString(self): string
This function returns a string representation of `self`. This is intended for arrays and dictionaries, but can theoretically work on any printable value.
If the resulting string is longer than `TOY_MAX_STRING_LENGTH` - 1, then it is truncated.
## toUpper(self: string)
### toUpper(self: string):string
This function returns a new string which is identical to the string `self`, except any lowercase letters are replaced with the corresponding uppercase letters.
## trim(self: string, trimChars: string = " \t\n\r")
### trim(self: string, trimChars: string = " \t\n\r"): string
This function returns a new string which is identical to the string `self`, except any characters at the beginning or end of `self` which are present in the argument `trimChars` are removed. The argument `trimChars` is optional, and has the following characters as the default value:
@@ -183,11 +180,10 @@ This function returns a new string which is identical to the string `self`, exce
These characters used because they are the only control characters currently supported by Toy.
## trimBegin(self: string, trimChars: string = " \t\n\r")
### trimBegin(self: string, trimChars: string = " \t\n\r"): string
This function is identical to `trim(self, trimChars)`, except it is only applied to the beginning of the first argument.
## trimEnd(self: string, trimChars: string = " \t\n\r")
### trimEnd(self: string, trimChars: string = " \t\n\r"): string
This function is identical to `trim(self, trimChars)`, except it is only applied to the end of the first argument.