Permalink
Fetching contributors…
Cannot retrieve contributors at this time
1986 lines (1363 sloc) 71.2 KB
Sphere v2 Core API Reference
============================
As the successor to the original Sphere engine, miniSphere implements nearly
the entire Sphere v1 API. However, the v1 API is quite dated and, as of
miniSphere 4.0, has been deprecated in its entirety. It is not documented here
at all; while games using the legacy functions will continue to run, new code
should be written against the modern Sphere v2 API, documented here.
In order to ease migration of existing Sphere v1 codebases to Sphere v2, legacy
and modern API calls may be freely intermingled within the same codebase, and
that holds true even when the engine is running in compatibility mode.
JSON Game Manifest (`game.json`)
--------------------------------
To take full advantage of the Sphere v2 platform, a game package must include a
file named `game.json` in its root directory. This file holds metadata such as
the title and author, as well as some control information which affects how the
engine runs the game.
Here's a sample manifest:
{
"name": "Spectacles: Bruce's Story",
"version": 2,
"apiLevel": 1,
"saveID": "fatCerberus.spectacles",
"author": "Fat Cerberus",
"summary": "Follow Scott Starcross in his quest to stop the Primus.",
"resolution": "320x240",
"main": "@/bin/main.mjs"
}
JSON fields defined by the Sphere v2 specification are documented below.
Because the manifest format is JSON, as many additional fields may be added as
needed, and their values can be accessed from JavaScript through `Sphere.Game`.
"version" [default: 2]
The Sphere standards version the game was developed against. If this is
set to 2 (or is just not present) the game runs in Sphere v2 mode. In
Sphere v2 mode, the main script is run as a module, either CommonJS or
mJS depending on the file extension.
If this is set to 1, the game runs in Sphere 1.x compatibility mode. In
compatibility mode, the main module is executed as top-level program code,
and miniSphere calls the global `game()` function--if one is provided--to
begin game execution.
Note: Regardless of the version specified, both Sphere v1 and v2 APIs will
be available for use by game code. The standards version merely
tells the engine how to load the main module.
"apiLevel" [default: 1]
The minimum API level required to run the game.
"author" [default: none]
The name of the person or company who developed the game.
"fullScreen" [default: false]
The game's preferred fullscreen mode. If the engine is started without
passing either `--windowed` or `--fullscreen` on the command line, the
value of this property will decide whether to start in fullscreen mode or
not.
"main" [required]
The SphereFS path of the main JavaScript module (see below for more on
SphereFS). This is the script miniSphere will run when the game is
started. If no "main" field is present, the game will not start.
"name" [default: "Untitled"]
The title of the game. This field must be present; if it is not, the game
will not start.
"resolution" [required]
The default screen resolution of the game, expressed as a string of the
form "WxH", specifying the number of pixels across and down. For example,
720p resolution would be expressed as "1280x720".
Note: The resolution can be changed at runtime by calling screen.resize().
"sandbox" [default: "full"]
Specifies the SphereFS sandbox enforcement mode. This should have one of
the following values:
"full": Full enforcement. This is the default. Using an absolute
path is illegal and will throw an error, and all files and
directories except for those in `~/` (the game's save data
directory) are treated as read-only.
"relaxed": Allow read-only access to files named by an absolute path
and enable full write access to `@/`. This is useful during
development but not recommended for production, particulary
as your game may end up installed in a read-only location.
"none": NOT RECOMMENDED! This disables the sandbox entirely and allows
write access to all files, including those named by an absolute
path and everything under `#/`. Unless you know what you're
doing (and maybe even then), avoid this mode at all costs!
"saveID" [default: none]
A string usually of the form "authorID.titleID" uniquely identifying the
game for the purposes of save data management.
Note: While providing a save ID is optional, one must be defined before a
game can use its SphereFS save store (`~/`). Legacy games using
only an SGM manifest therefore can't take advantage of the save
store.
"summary" [default: none]
A short summary of the game. While there is no imposed length limit, it
is recommended to keep this short (150 characters or less) with no line
breaks.
SphereFS File System
--------------------
Sphere uses the SphereFS standard to interpret file paths. Under SphereFS,
when a relative path is used in an API call, it will be resolved relative to
the root of the game package (where `game.json` is located). To load files
from a different location, you can use one of the SphereFS prefixes:
@/: The root of the game's sandboxed file system. Usually redundant, but
can be useful to qualify filenames in situations where a bare SphereFS
filename will be ambiguous, for example in an `import` declaration.
This directory is read-only; trying to save or modify anything here
will cause a TypeError to be thrown.
$/: The directory containing the startup script. This is mostly provided
as a convenience for specifying module names in `import` declarations.
#/: The engine's system directory. This contains assets included with the
engine. As with `@/`, this is read-only to Sphere games.
~/: The current user's save data directory (note: requires a save ID; refer
to the section on `game.json` above). This is generally used to store
save data and such where the user can easily access it.
As an example, the following will create a FileStream which allows reading from
the file `EatyPig.bin` residing in the user's save data directory.
let file = new FileStream('~/EatyPig.bin', FileOp.Read);
Note: Absolute paths are forbidden, and any attempt to circumvent the sandbox
to break into the underlying file system, e.g. "@/../maggie.fat", will
be met with a sandbox violation error.
The Sphere Event Loop
---------------------
Sphere, like most JavaScript-based platforms, is built around the concept of a
central event loop that keeps the engine running and schedules JavaScript
execution. JavaScript operations cannot run indefinitely; the engine runs in
a single thread, so the game must yield to the event loop periodically to allow
other tasks to run. There are two ways this can be done: either by allowing
the current operation to run to completion, or by suspending execution using
the `await` operator.
The event loop begins running after all JavaScript modules have been loaded and
remains active as long as there is something for it to do. Each iteration of
the event loop represents one frame and consists of three phases:
Render: The Render phase calls jobs set up with `Dispatch.onRender()`.
This phase is unique in that it may be skipped entirely in order
to maintain the game's desired frame rate. Only drawing operations
should be performed during this phase. Immediately after the
Render phase, the contents of the backbuffer are flipped to the
screen and the backbuffer is cleared.
Update: The Update phase calls jobs set up with `Dispatch.onUpdate()`.
Updates are regulated by `Sphere.frameRate` (see below), which you
can take advantage of to simplify, e.g., animation code.
Dispatch: The Dispatch phase is a multi-purpose phase which calls one-off
jobs such as `Dispatch.now()` and settles promises. The Dispatch
phase runs until there are no more jobs to execute, ensuring
results which are available immediately aren't delayed until the
next frame.
API Levels
----------
The Sphere API is constantly evolving, and as such new functions and classes
are added often. When a new API feature is added, it will be designated as
"experimental" until the next API freeze. When an API freeze occurs, the
engine's supported API level will be incremented and some or all experimental
features will be assigned to the new level.
The maximum supported API level in this version of miniSphere is level 1.
The minimum API level required by a game is specified in its game manifest (see
above); if this value is not present it defaults to level 1. By default, all
API functions are available for use regardless of this value; however you can
start the engine using the `--retro` command line switch to have the engine
emulate the older API level, which disables all APIs introduced in a later
level as well as experimental features.
All class constructors, methods and properties listed below include the API
level they were introduced in (e.g. "[L1]") or else, for experimental features,
"[experimental]".
`Sphere` Namespace
------------------
The `Sphere` namespace hosts functions and properties that allow the game to
communicate with the underlying Sphere platform. The properties provide access
to the engine's name, version number, and API level, and there are several
methods for managing execution.
Sphere.Engine [read-only] [L1]
A string specifying the name and version number of the game engine. The
version number takes the form X.Y.Z, where X is the major version, Y is the
minor version, and Z is the patch level.
Sphere.Version [read-only] [L1]
Sphere.APILevel [read-only] [L1]
The Sphere API version and level supported by the engine, respectively.
`Version` indicates which version of the Sphere API is supported (e.g., 2),
while `APILevel` reflects the evolutionary stage. Whenever new classes,
methods, or properties are added to the Core API, the API level is
increased.
Sphere.Compiler [read-only] [L1]
A string specifying the name and version number of the compiler or build
tool used to make the game distribution. If no compiler information is
available for the current game, this evaluates to `undefined`.
Sphere.Game [non-replaceable] [L1]
An object whose properties describe the currently running game. The object
consists of everything in the JSON manifest plus any fields synthesized by
the engine.
Sphere.frameRate [read/write] [L1]
Gets or sets the frame rate. Set this to Infinity to disable the frame
limiter. The default is 60 FPS.
The frame rate is used to regulate the event loop. For example if this is
set to 60 (the default), the event loop will perform 60 iterations per
second, skipping renders as necessary to meet that goal.
Sphere.frameSkip [read/write] [L1]
Gets or sets the maximum number of frames the engine is allowed to skip in
order to maintain the desired frame rate.
Sphere.fullScreen [read/write] [L1]
Gets or sets whether the engine is running in fullscreen mode. Set this to
`true` for fullscreen, or `false` for windowed.
Note: If an SSj debugger instance is attached, the engine is forced into
windowed mode and any change to the value of `screen.fullScreen` will
be silently ignored.
Sphere.main [read-only] [L1]
Gets a reference to the game's main object, when the main module exports a
constructor or class. This object is created by the engine on startup by
instantiating the exported class using `new`.
Sphere.abort(message); [L1]
Aborts execution. This is effectively a forced crash: JavaScript execution
will cease immediately, and the exception screen will be shown displaying
`message`.
Note: Sphere.abort() bypasses all exception handling mechanisms, including
the debugger if it's attached. Be sure you know what you're doing!
Sphere.now(); [L1]
Returns the number of frames (including skipped frames) processed by the
engine since it started running. To measure wall clock time instead, use
`Date.now()`.
Note: This value will wrap around to zero after around 4.3 billion frames.
That typically isn't an issue: at 60 FPS, a game would need to run
continuously for *over 2 years* before the timer would roll over.
Sphere.restart(); [L1]
Restarts the engine. All in-flight Dispatch jobs are canceled so that once
control returns to the event loop, the engine will initiate a restart.
Note: This initiates an asynchronous shutdown. The game will restart ONLY
after control has returned to the event loop. Note that dispatching
new update or render jobs before then will cancel the request!
Sphere.setResolution(width, height); [L1]
Changes the game's resolution. This determines the width and height of
the backbuffer (see `Surface.Screen` below); higher resolutions allow you
to render more detail.
Note: This change is not persistent and lasts only until the engine is
closed.
Sphere.shutDown(); [L1]
Shuts down the engine. All in-flight Dispatch jobs are canceled so that
once control returns to the event loop, the engine will close.
Note: This initiates an asynchronous shutdown. The engine will close ONLY
after control has returned to the event loop. Note that dispatching
new update or render jobs before then will cancel the request!
Sphere.sleep(frames); [L1]
Returns a promise which resolves after the specified number of frames have
elapsed. Can be used with `await`. This is useful to delay execution of a
function without blocking the event loop.
`Color` Object
--------------
The `Color` object represents an RGB color value. It also has an alpha
component and can therefore represent translucent colors.
Color.Red [read-only] [L1]
Color.Green [read-only] [L1]
Color.Blue [read-only] [L1]
Color.Transparent [read-only] [L1]
etc...
Gets a copy of a predefined color. The entire X11 color set is provided,
giving you access to such colors as `DodgerBlue` and `Chartreuse` in
addition to the standard red, green, blue, yellow, etc.
Each of these is an accessor which returns a new Color object every time
it is invoked. This ensures that code like what's shown below won't cause
undesirable side effects:
let customColor = Color.Red;
customColor.blue = 255; // we needed magenta instead
The downside to this is that e.g. `Color.Red === Color.Red` evaluates to
false, but this is rarely an issue in practice.
Color.is(color1, color2); [L1]
Returns true if `color1` refers to the same physical color as `color2`
without regard to their alpha components. Otherwise returns false.
Note: This is not the same as comparing the color objects' .name properties
because Color#name encodes the alpha channel in addition to the
physical color.
Color.mix(color1, color2[, w1, w2]); [L1]
Calculates a weighted average of two colors. `w1` and `w2` are optional
and specify the relative weights of `color1` and `color2` respectively. If
the weights are omitted, the mix is 50/50.
Color.of(name); [L1]
Returns a Color object from `name`, which can either be the name of a
predefined X11 color without spaces (e.g. "chartreuse"), or an ARGB
signature such as "#800000FF". If `name` cannot be resolved to a color,
throws a TypeError.
new Color(red, green, blue[, alpha]); [L1]
Constructs a new Color object. Color objects are used to specify the color
of elements such as vertices and primitives. Color components should be in
the range [0.0,1.0]; out-of-range values are silently clamped. `alpha`
specifies the color's opacity and defaults to 1.0 if not provided.
Color#r [read/write] [L1]
Color#g [read/write] [L1]
Color#b [read/write] [L1]
Color#a [read/write] [L1]
Gets or sets the individual components of the color (red, green, blue, or
alpha). Range is [0.0,1.0]; while values outside this range are accepted,
HDR is not supported and the engine will automatically clamp such colors
when rendered.
Color#name [read-only] [L1]
Gets the name of the Color according to its component values such that
Color.of(color.name) will give back a Color with the same values. Useful
for saving and reading back colors from save files.
Color#clone(); [L1]
Returns a copy of this Color object. Changes to the clone will not affect
the original object.
Color#fadeTo(alpha_factor); [L1]
Scales this color's alpha channel by `alpha_factor`, between 0.0 and 1.0,
and returns the result. The red, green, and blue components are not
modified. One use for this is when you need to make a predefined color
translucent; for example:
let translucentBlue = Color.Blue.fadeTo(0.5);
`DirectoryStream` Object
------------------------
The `DirectoryStream` object allows you to read the contents of a directory.
This works a lot like reading data from a `FileStream` (see below) in that you
read directory entries one at a time. `DirectoryStream` also implements the
JavaScript ES6 iterator protocol, so you can use it in a `from()` query or
`for...of` loop.
new DirectoryStream(dir_name[, options]); [L1]
Constructs a new DirectoryStream which reads entries from `dir_name`. If
the directory named by `dir_name` doesn't exist, throws an error.
options.recursive [default: false] [experimental]
If `recursive` is true, the DirectoryStream will descend into
subdirectories to list files they contain. The output will not contain
any directory entries in this case, only file entries.
DirectoryStream#fileCount [read-only] [L1]
Gets the number of entries (both files and directories) in the directory
listing.
DirectoryStream#fileName [read-only] [L1]
Gets the full SphereFS pathname of the directory whose entries are being
enumerated.
Note: Under SphereFS canonicalization rules, the pathname of a directory
always ends in a slash (`/`).
DirectoryStream#position [read/write] [L1]
Gets or sets the position within the stream. This is an index into the
directory specifying which entry will be read next.
DirectoryStream#dispose(); [L1]
Disposes of the DirectoryStream object, closing the underlying directory.
Attempting to the object afterwards will throw an error.
Note: While it's not strictly necessary to call `dispose()` on stream
objects, it may take some time for the garbage collector to get to
them. If there's an active DirectoryStream for a given directory, an
error may be thrown if you try to construct another one.
DirectoryStream#next(); [L1]
Reads the next entry from the directory and advances the stream position.
This returns an object. If there are no entries remaining, the object's
`done` property is set to `true`; otherwise, `done` is `false` and `value`
is an object with the following properties:
value.isDirectory
`true` if the entry is for a subdirectory, otherwise `false`.
value.fileName
The file or directory name of the entry. Directory names always
end in a slash (`/`).
value.fullPath
The full SphereFS pathname of the entry. As with `value.fileName`,
directory paths end in a slash (`/`) per SphereFS canonicalization
rules.
Note: This method is compatible with the JavaScript ES6 iterator protocol,
allowing you to use the DirectoryStream as input to a `from()` query.
Refer to the Sphere Runtime API documentation for more information
about `from()`.
DirectoryStream#rewind(); [L1]
Rewinds the stream and resets the position to 0. If the directory contents
have changed, rewinding the DirectoryStream will allow you to enumerate the
new entries without creating a new stream.
`Dispatch` Namespace
--------------------
The Dispatch API is used to set up asynchronous function calls which are later
performed from a designated part of the Sphere event loop. This is like an
advanced version of Sphere v1's update and render scripts, but more tightly
integrated and available throughout the engine.
When queueing a job, a token is returned which allows you to manage the
in-flight job. See the documentation for `JobToken` below to find out what you
can do with the token.
Dispatch.cancelAll(); [L1]
Cancels all one-time jobs (except `onExit`) in the job queue. In order to
prevent mishaps, this does not cancel update, render and exit jobs. Those
must be cancelled individually.
Dispatch.later(num_frames, callback); [L1]
Sets up a one-time job to call `callback` from the event loop after
`num_frames` frames have passed.
Returns a `JobToken` you can use the manage the job.
Dispatch.now(callback); [L1]
Sets up a one-time job to call `callback` from the event loop during the
current frame. This is useful for performing operations that need to be
done from the event loop with minimal delay.
Returns a `JobToken` you can use to manage the job.
Note: Dispatch.now(fn) is *NOT* an alias for Dispatch.later(0, fn). The
latter runs at the beginning of the next frame; Dispatch.now() jobs
always run during the same frame they were issued.
Dispatch.onExit(callback); [experimental]
Sets up a one-time job to call `callback` after the event loop exits. This
is useful when you need to ensure something always runs before the engine
terminates; for example, automatically saving the game or finalizing a log
file.
Returns a `JobToken` you can use to manage the job.
Note: Try not to do anything too intensive in an `onExit()` job if you can
avoid it; the engine won't close until all exit jobs have finished
running, so excessive delays here are likely to frustrate the user.
Dispatch.onRender(fn[, options]); [L1]
Dispatch.onUpdate(fn[, options]); [L1]
Sets up a recurring job to call `fn` during a specified event loop phase.
For example, `onRender()` jobs are called before the backbuffer is flipped,
and `onUpdate()` jobs are called at the start of each frame.
Returns a `JobToken` you can use to manage the job.
Note: If you pass an `async` function to one of these and it takes multiple
frames to complete, the engine will await completion of the previous
invocation before invoking it again. Avoid using `await` in a render
handler as the function will resume at the end of a frame, after the
backbuffer has already been flipped.
options.inBackground [default: false]
If this is `true`, the job won't keep the event loop alive. This is
useful for screen overlays and the like that you want to run in the
background without preventing the game from exiting.
options.priority [default: 0.0]
Determines the order of calls when there is more than one job. Render
jobs are performed in ascending priority order, while update jobs are
performed in descending priority order. The priority can be negative,
and fractional priorities are honored: 8.12, for example, is considered
a higher priority than 8.0.
`FS` Namespace
--------------
The `FS` namespace allows your game to access asset and save files, create or
remove directories, etc. All file system operations are sandboxed to prevent
damage to the system.
FS.createDirectory(dir_name); [L1]
Creates a directory and any of its parent directories that don't already
exist. If the directory already exists, this function does nothing.
Note: As indicated above, `FS.createDirectory()` is safe to call even if
the specified directory already exists; no error will be thrown in
that case. This allows you to call it to ensure a directory exists
before you access it, without needing an explicit check beforehand.
FS.deleteFile(filename); [L1]
Deletes `filename` from the file system.
FS.directoryExists(dir_name); [L1]
Checks whether the specified directory exists and returns true if it does.
Otherwise, returns false.
FS.directoryOf(filename); [experimental]
Returns the full SphereFS path of the directory containing `filename`. The
filename is resolved via the usual SphereFS rules, so if no directory info
is present, this function will return "@/".
FS.evaluateScript(filename); [L1]
Executes a JavaScript file in the global scope and returns the result.
This is useful for executing scripts originally written for the Web, where
modules are not supported.
Note: Depending on the particular script being evaluated, this function
can--and likely will--create new global functions and variables. Be
sure you know what you're doing!
FS.fileExists(filename); [L1]
Checks whether the specified file exists and returns true if it does.
Otherwise, returns false.
FS.fileNameOf(filename); [experimental]
If `filename` contains a directory path, returns only the filename portion,
or `undefined` if there is no filename in the path.
FS.fullPath(filename[, base_dir]); [L1]
Resolves a filename (which may contain relative path components, or even be
relative itself) to its full, canonical SphereFS pathname. `base_dir` is
optional and specifies a base directory for relative paths. The file or
directory ultimately referred to doesn't need to exist.
If `fileName` begins with a SphereFS prefix, it's resolved normally,
without regard to `base_dir`. Otherwise, `fileName` is considered to be
relative to `base_dir`.
Note: If `filename` refers to a known directory, the path string returned
by this function will end in a forward slash (`/`) even if `filename`
did not.
FS.readFile(filename); [L1]
Reads an entire UTF-8 text file into a JavaScript string. This is a
convenience to avoid the need to explicitly construct a FileStream and
decode the file contents when all you want is to load a text file.
Note: This performs UTF-8 decoding, making it unsuitable for use with
binary data. To work with binary files, use a FileStream object
instead.
FS.relativePath(filename, base_dir); [L1]
Abbreviates a full SphereFS pathname by returning its path relative to
`base_dir`. This can be useful when logging filenames or displaying track
names, for example.
FS.removeDirectory(dir_name); [L1]
Deletes the specified directory. The directory must be empty or an error
will be thrown.
FS.rename(orig_name, new_name); [L1]
Renames the file named by `orig_name` to `new_name`, both of which are
assumed to be full paths. This can also be used to move a file between
directories; if so, the destination directory must already exist.
FS.writeFile(filename, string); [L1]
Writes a string out to a UTF-8 text file. If a file already exists with
the specified filename, it will be overwritten.
Note: This performs UTF-8 encoding, making it unsuitable for use with
binary data. To work with binary files, use a FileStream object
instead.
`FileStream` Object
-------------------
new FileStream(filename, file_op); [L1]
Constructs a FileStream that provides access to the contents of a specified
file. `file_op` specifies the file operation requested and must be one of
the following:
FileOp.Read
Read data from the file. The file must exist and will be opened in
read-only mode. Any attempt to write to the file will throw a
TypeError.
FileOp.Write
Write data to the file. Be careful: If the file already exists,
its contents will be overwritten. If that behavior is not desired,
use `FileOp.Update` instead.
FileOp.Update
Amend the file. If a file by the specified name doesn't exist, it
will be created. For convenience, the file pointer is initially
placed at the end of the file.
Requesting write access to a file residing in a read-only directory (e.g.,
the system directory `#/`) will throw a TypeError.
FileStream#dispose(); [L1]
Disposes of the FileStream object, closing the underlying file. Attempting
to the object afterwards will throw an error.
Note: While it's not strictly necessary to call `dispose()` on stream
objects, it may take some time for the garbage collector to get to
them. If there's an active FileStream for a given file, particularly
if the file is opened in write mode, an error may be thrown if you
try to construct another one.
FileStream#fileName [read-only] [L1]
Gets the full SphereFS pathname of the underlying file.
FileStream#fileSize [read-only] [L1]
Gets the size of the underlying file, in bytes.
FileStream#position [read/write] [L1]
Gets or sets the file position, which determines where in the file the next
read or write will start from. Expressed in bytes.
Note: For files opened for writing, it is valid to seek past the end of the
stream. In this case the next write will be at the new position and
the intervening space filled with NUL bytes.
FileStream#read(num_bytes); [L1]
Reads data from the file, up to the specified number of bytes, and returns
it as an ArrayBuffer. The file must be opened for reading.
FileStream#write(data); [L1]
Writes data to the file and advances the file pointer. `data` should be an
ArrayBuffer, TypedArray or DataView containing the data to be written.
`Font` Object
-------------
The `Font` object specifies a typeface that can be used when drawing text.
Sphere provides a default font which is the same for all games, or you can load
one from an RFN font file.
Font.Default [read-only] [L1]
Gets the default engine font. This is the font used for the FPS counter
and system messages.
new Font(filename); [L1]
Constructs a Font object from a font file. Currently only the Sphere RFN
font format is supported.
Font#fileName [read-only] [L1]
Gets the full SphereFS pathname of the file used to construct this Font
object.
Font#height [read-only] [L1]
Gets the line height, in pixels, for text rendered using this font.
Font#drawText(surface, x, y, text[, color[, wrap_width]]); [L1]
Renders `text` to the specified surface at (x,y). `color` defaults to
Color.White if not provided, and `wrap_width` specifies the width in which
to constrain the text. If `wrap_width` is not provided, no wrapping is
performed.
Font#getTextSize(text[, wrap_width]); [L1]
Gets the size, in pixels, of `text` if it were rendered by Font:drawText()
with the specified wrap width. Return value is an object with `width` and
`height` properties.
Note: If `wrap_width` is not provided, no word wrap processing will be
performed.
Font#wordWrap(text, wrap_width); [L1]
Wraps `text` as if it were drawn with Font#drawText() using the specified
wrap width. Returns an array of strings, representing the lines in the
wrapped text.
When drawing large amounts of word-wrapped text every frame, for example in
a text box, this function should be used to pre-wrap the text since
performing wrapping calculations every frame can get expensive.
`IndexList` Object
------------------
An `IndexList` contains indices into a vertex list which are stored on the GPU
for fast access at render time. Index lists can be useful if you want to store
all the vertices for a scene in a single `VertexList` and construct different
shapes from it. The index list specifies which vertices from the list to use
to create a shape.
new IndexList(indices); [L1]
Constructs a new index list from `indices`, an array of integers in the
range [0,65535]. If `indices` is not an array or any element is not a
number in the above range, an error will be thrown.
Note: The list of indices stored on the GPU can't be modified later. If
you want to upload a new set of indices, you must construct a new
`IndexList`.
`JobToken` Object
-----------------
A JobToken represents a job queued using one of the `Dispatch` functions above.
When queuing a job, you must keep a reference to the token if you want to be
able to manage the job later.
JobToken#cancel(); [L1]
Cancels the dispatch job associated with this token. If the job was queued
using either `Dispatch.now()` or `Dispatch.later()` and has already started
running, calling this has no effect.
JobToken#pause(); [experimental]
Pauses the job. Paused jobs will not run, but do keep the event loop alive
and can be resumed at any time without the need to dispatch a new job.
JobToken#resume(); [experimental]
Resumes the job associated with this token after it's been paused with
JobToken#pause(). If the job is not currently paused, this does nothing.
`Joystick` Object
-----------------
Joystick.Null [read-only] [L1]
Gets the null joystick. When polled, a null joystick returns neutral
values for all inputs. Joystick.Null can be used in place of a real
Joystick object to simplify input code.
Joystick.getDevices(); [L1]
Gets an array of Joystick objects, one for each connected gamepad or
joystick.
Joystick#name [read-only] [L1]
Gets the name of the device, as reported by the Allegro backend. Xbox
controllers are reported as "XInput Joystick <n>"
Joystick#numAxes [read-only] [L1]
Gets the number of analog axes supported by the device.
Joystick#numButtons [read-only] [L1]
Gets the number of buttons supported by the device.
Joystick#getPosition(axisID); [L1]
Polls the device and gets the current position along the specified analog
axis. To get the number of axes supported by a device, use the `numAxes`
property.
Note: Axes are numbered sequentially, starting from 0. Which physical axis
is associated with any given axis ID will vary from device to device.
For gamepads with analog sticks, though, it's generally a safe bet
that the primary analog stick will be mapped to the first two axes.
Joystick#isPressed(buttonID); [L1]
Polls the device and returns true if the specified button is currently
depressed. To get the number of buttons supported by a device, use the
`numButtons` property.
Note: Buttons are numbered sequentially, starting from 0. As with axes,
which physical button is associated with any given button ID will
vary from device to device.
`Keyboard` Object
-----------------
What would a game be without the ability for the player to control it? The
`Keyboard` object allows your game to accept input via the keyboard, the most
common input method for a PC game.
Key [enumeration] [L1]
Specifies a keyboard key. Can be one of the following:
Key.Alt
Key.AltGr
Key.Apostrophe
Key.Backslash
Key.Backspace
Key.CapsLock
Key.CloseBrace
Key.Comma
Key.Delete
Key.Down
Key.End
Key.Enter
Key.Equals
Key.Escape
Key.F1
Key.F2
Key.F3
Key.F4
Key.F5
Key.F6
Key.F7
Key.F8
Key.F9
Key.F10
Key.F11
Key.F12
Key.Home
Key.Hyphen
Key.Insert
Key.LCtrl
Key.LShift
Key.Left
Key.NumLock
Key.OpenBrace
Key.PageDown
Key.PageUp
Key.Period
Key.RCtrl
Key.RShift
Key.Right
Key.ScrollLock
Key.Semicolon
Key.Slash
Key.Space
Key.Tab
Key.Tilde
Key.Up
Key.A
Key.B
Key.C
Key.D
Key.E
Key.F
Key.G
Key.H
Key.I
Key.J
Key.K
Key.L
Key.M
Key.N
Key.O
Key.P
Key.Q
Key.R
Key.S
Key.T
Key.U
Key.V
Key.W
Key.X
Key.Y
Key.Z
Key.D1
Key.D2
Key.D3
Key.D4
Key.D5
Key.D6
Key.D7
Key.D8
Key.D9
Key.D0
Key.NumPad1
Key.NumPad2
Key.NumPad3
Key.NumPad4
Key.NumPad5
Key.NumPad6
Key.NumPad7
Key.NumPad8
Key.NumPad9
Key.NumPad0
Key.NumPadEnter
Key.Add
Key.Decimal
Key.Divide
Key.Multiply
Key.Subtract
Note: Keys D0-D9 refer to the row of numbers above the letter keys and
below the function keys, while NumPad0-NumPad9 refer to the numbers
on the numeric keypad.
Keyboard.Default [read-only] [L1]
Gets a `Keyboard` object for the default keyboard device.
Note: miniSphere currently only supports a single keyboard.
Keyboard#capsLock [read-only] [L1]
Keyboard#numLock [read-only] [L1]
Keyboard#scrollLock [read-only] [L1]
Gets the state of the corresponding lock key. true if the lock is on,
false if not.
Keyboard#charOf(key[, shifted]); [L1]
Gets the character(s) that would be generated if a specified key is pressed
on this keyboard. For example, Key.A becomes "a" (or "A" if shifted).
`shifted` specifies whether to act as if the Shift key is pressed and
defaults to `false`.
An empty string is returned if the specified key is not associated with a
character (a modifier key, for example).
Keyboard#clearQueue(); [L1]
Removes all keys from the keyboard queue. If another key is not pressed
in the interim, the next getKey() will return null.
Keyboard#getKey(); [L1]
Gets the next key in the keyboard queue, or null if the queue is empty.
Keyboard#isPressed(key); [L1]
Returns true if the user is currently pressing the specified key. `key`
should be a member of the Key enumeration.
`Mixer` Object
--------------
Mixers are used to group related audio together and adjust their parameters as
a class; this is useful, for example, for implementing global volume controls
in your game.
Mixer.Default [read-only] [L1]
Gets the default Audialis audio mixer. The default mixer outputs 44.1 kHz
16-bit stereo sound, i.e. CD quality.
new Mixer(frequency, bits[, channels]); [L1]
Constructs a new Mixer object. Any sounds played through the mixer will use
the format specified by the parameters above. `frequency` is the sample
rate, `bits` specifies the bit depth (allowed values are 8, 16 and 24), and
`channels` is the number of channels, ranging [1-7]. Channel counts of 5 or
higher imply an additional LFE channel (i.e. 5.1, 6.1, 7.1).
Do note that this creates a _hardware_ mixer. If the requested format is
not supported by the system, an error will be thrown ("unable to create
hardware voice").
Mixer#volume [read/write] [L1]
Gets or sets the output volume of the mixer. This will affect the volume
of any sounds played through the mixer.
`Model` Object
--------------
A `Model` represents a group of shapes, combined with a shader and transforms,
which are drawn to a surface as a single unit. Used well, this can improve
your game's rendering performance by grouping together operations using similar
parameters.
new Model(shapes[, shader]); [L1]
Constructs a Model out of the provided array of Shape objects. `shader` is
the Shader to use when rendering the model. See below for more information
on shaders.
When a Model is created, its transformation matrix is set to the
identity matrix. If `shader` is not provided, the default shader program
will be used (see `Shader.Default`).
Model#shader [read/write] [L1]
Gets or sets the Shader to use when drawing this model.
Model#transform [read/write] [L1]
Gets or sets the transformation matrix to use when drawing this model.
Model#draw([surface]); [L1]
Draws the model on `surface`, or the backbuffer if no surface is specified.
Any transformations defined for the model (see below) are applied as if all
the shapes comprising it were a single object.
`Mouse` Object
--------------
The `Mouse` object allows your game to accept input from a mouse, another
common input method for games. As with the `Keyboard` object, `Mouse` provides
an event queue which accumulates clicks and other events until the game is
ready to process them.
MouseKey [enumeration] [L1]
Specifies a mouse click or other event (such as a wheel movement). Can
be one of the following:
MouseKey.Left
MouseKey.Middle
MouseKey.Right
MouseKey.WheelUp
MouseKey.WheelDown
Mouse.Default [read-only] [L1]
Gets a `Mouse` object for the default mouse device.
Note: miniSphere currently only supports a single mouse.
Mouse#x [read-only] [L1]
Mouse#y [read-only] [L1]
Gets the immediate X and Y position of the mouse cursor relative to the
game's rendering area.
Mouse#clearQueue(); [L1]
Removes all events from this mouse's event queue. If another event is not
received in the interim, the next getEvent() will return null.
Mouse#getEvent(); [L1]
Gets the next event in this mouse's event queue. `null` is returned if the
queue is empty.
The object returned has the following properties:
event.key
A MouseKey value representing the type of the click or other event.
For example, a left mouse click is represented as MouseKey.Left.
event.x
event.y
The X and Y position of the mouse cursor relative to the rendering
area at the time the event was received.
Mouse#isPressed(key); [L1]
Gets whether the specified mouse button is currently pressed. `key` is one
of the MouseKey constants listed above.
Note: This function always returns false for virtual keys such as WheelUp
and WheelDown.
`RNG` Object
------------
Games often have need of a good psuedorandom number generator, particularly in
the case of RPGs. JavaScript provides a barebones generator in the form of
`Math.random()`. Sphere takes it one step further with the powerful `RNG`
object.
Sphere uses the xoroshiro128+ algorithm to generate high-quality random numbers
and allows manually seeding the generator, as well as saving and restoring the
exact state of the generator at any time. RNG state is often saved along with
other save data as a way to deter save scumming.
RNG.fromSeed(seed); [L1]
Constructs a new random number generator seeded using the specified value.
The specific sequence of numbers generated is entirely defined by the seed:
Two generators running in parallel, initialized with the same seed, will
always produce the same sequence.
`seed` is a number greater than zero. If the seed is fractional, only the
integer part is used; everything after the decimal point is ignored.
RNG.fromState(state); [L1]
Constructs a new random number generator which starts in the specified
state. See RNG#state for more information.
new RNG(); [L1]
Constructs a new random number generator seeded from the current system
time.
RNG#state [read/write] [L1]
Gets or sets the current state of this generator. State is encoded as
a 32-digit hexadecimal string which makes it easy to save and restore.
When setting `RNG#state`, the string given must be exactly 32 characters
and consist only of hexadecimal digits (0-9, A-F), otherwise a TypeError
will be thrown.
RNG#next(); [L1]
Generates the next random number in the sequence. This returns an object
whose `done` property is always false, and whose `value` property is a
number in the range [0,1).
Note: This method is compatible with the JavaScript ES6 iterator protocol,
allowing you to use the RNG object as input to a `from()` query.
Refer to the Sphere Runtime API documentation for more information
about `from()`.
`SSj` Namespace
---------------
The `SSj` namespace provides functions that aid debugging and allow your game
to communicate with an attached debugger such as SSj or SSj Blue. Note that
`SSj` methods only have an effect when called under SpheRun; in production they
do nothing.
SSj.flipScreen(); [L1]
Immediately flips the contents of the backbuffer to the screen. The
backbuffer is not cleared afterwards. Useful for debugging graphics code.
SSj.log(text_or_object); [L1]
Logs `text_or_object` to an attached SSj or SSj Blue session. If an object
is passed in, logs the result of calling `JSON.stringify()` on the object.
Note: If the game was started from the command line using SpheRun, the
item is logged to the terminal as well.
SSj.now(); [L1]
Returns the time in nanoseconds since some arbitrary point in time, useful
for benchmarking. In production, this will always be 0; use `Date.now()`
for in-game timing purposes.
Note: While the value returned is in nanoseconds, the actual precision of
the timer will almost certainly be less, typically in the microsecond
range. Don't assume this will be nanosecond precision.
SSj.profile(object, method_name[, description]); [L1]
Adds a method to be automatically profiled (timed) by SpheRun.
`description` is an optional string to name the function in the performance
report; if no description is given, the engine will use the name of the
function.
`object` is the object whose method is being profiled, and `method_name` is
the name of the method. Note that to profile a method for all instances of
a class, you can specify the prototype. For example, to profile all calls
to `Font#drawText()`:
SSj.profile(Font.prototype, 'drawText');
Note: SpheRun must be started with the `--performance` option to enable the
profiler. All `SSj.profile()` calls will be completely ignored if
the profiler is not enabled.
SSj.trace(text); [L1]
Logs `text` to an attached SSj or SSj Blue session. This is intended for
low-level, detailed logging; by default, traces will not be displayed, even
in the debugger, unless enabled by the user.
`Sample` Object
---------------
A `Sample` represents a sound effect. Multiple instances of a sample can be
played simultaneously, on any mixer. This is often more desirable than using a
`Sound` object, which only allows one instance to play at a time.
new Sample(filename); [L1]
Constructs a Sample from the specified audio file. The audio data is
loaded into memory in its entirety and multiple instances can be played
simultaneously with no latency, making this very useful for sound effects.
Supported formats are Ogg Vorbis (.ogg), WAV, and FLAC.
Note: Compressed formats like Vorbis will be decompressed during loading,
potentially using a large amount of RAM. It is therefore not
recommend to use `Sample` objects for, e.g., background music. Use a
`Sound` instead.
Sample#fileName [read-only] [L1]
Gets the full SphereFS pathname of the audio file used to construct this
Sample object.
Sample#play(mixer[, options]); [L1]
Plays the sample on the specified mixer. Each time this is called, a new
stream is started, allowing many instances of the sound to be playing
simultaneously.
`options`, if present, must be an object and can include the following
properties (all optional):
options.volume
The volume level to play the sound at. 1.0 is full volume, 0.0 is
silent. Volume levels higher than 1.0 will amplify the sound but
may cause distortion. Volume is 1.0 if not specified.
options.pan
A volume between -1.0 and 1.0 specifying the left/right balance.
-1.0 is full left, +1.0 is full right, and 0.0 is dead center. Pan
is 0.0 (center) if not specified.
options.speed
Playback speed, where 1.0 is normal speed. Also affects pitch.
Speed is 1.0x if not specified.
Sample#stopAll(); [L1]
Stops playback of all active instances of this sample.
`Server` Object
---------------
A `Server` represents a basic TCP server which listens for connections on a
specified port. Clients connecting to the server are placed in a backlog and
must be explicitly accepted by game code.
new Server(port[, backlog_size]); [L1]
Constructs a new server to listen for connections on the specified port.
`backlog_size` specifies the size of the backlog. If the backlog fills,
new connections will be dropped.
Server#accept(); [L1]
If one or more connections are waiting in the backlog, removes it from the
queue and returns a `Socket` object representing the connection; otherwise,
this returns `null`. This method should be called regularly to prevent the
backlog from filling up.
Server#close(); [L1]
Shuts down the server. Any connections in the backlog will be dropped and
no new connections can be made until a new server is started on the same
port.
`Shader` Object
---------------
A `Shader` is a program that runs on the system's graphics processor and
manipulates vertices and pixels as they are rendered to a surface. Shaders are
written in the GLSL shader programming language, which is beyond the scope of
this document.
Shader.Default [read-only] [L1]
Gets the default Galileo shader program. This is a very barebones shader
that performs only basic transformations and texture mapping.
new Shader(options); [L1]
Constructs a shader program from a set of GLSL shader sources. `options`
specifies the shader sources.
options.vertexFile [required]
The name of a file containing GLSL source code for the program's vertex
shader.
options.fragmentFile [required]
The name of a file containing GLSL source code for the program's
fragment shader.
Shader#clone(); [L1]
Creates a copy of this shader. The new shader is distinct from the first
and can have its own independent uniform values. As uniform values are
persistent, cloning a shader can sometimes be useful as an optimization.
Note: Uniform values are not copied; the cloned shader will be constructed
with all of its uniforms set to their default values.
Shader#setBoolean(name, value); [L1]
Sets the value of a GLSL boolean-valued (`bool`) uniform. `value` is
either `true` or `false`.
Shader#setColorVector(name, color); [L1]
Sets the value of a GLSL floating point 4-vector uniform (`vec4`) from the
components of a `Color` object. Order is assumed to be RGBA.
Shader#setFloat(name, value); [L1]
Shader#setInt(name, value); [L1]
Sets the value of a GLSL scalar uniform.
Note: Only `float` and `int` types are currently supported.
Shader#setFloatArray(name, values); [L1]
Shader#setIntArray(name, values); [L1]
Sets the values of a GLSL array uniform. `values` should be an array
containing a number of values equal to the size of the array, otherwise
the uniform will not be set.
Note: Only `float` and `int` types are currently supported.
Shader#setFloatVector(name, values); [L1]
Shader#setIntVector(name, values); [L1]
Sets the value of a GLSL vector uniform. `values` must be an array and
contain between 2 and 4 values, inclusive. If not, an error will be
thrown.
Note: Only `vecN` (float) and `ivecN` (integer) types are currently
supported.
Shader#setMatrix(name, transform); [L1]
Sets the value of 4x4 matrix uniform (`mat4`) using the underlying matrix
cells of a `Transform` object.
Note: Matrix types other than `mat4` are not currently supported.
`Shape` Object
--------------
A `Shape` represents a group of textured triangles, line segments, or points to
be drawn to a surface. Shapes can be drawn directly, or added to a `Model` to
group related rendering operations together.
ShapeType [enumeration] [L1]
Specifies the type of graphics primitive represented by a Shape object.
Can be one of the following:
ShapeType.Fan
ShapeType.Lines
ShapeType.LineLoop
ShapeType.LineStrip
ShapeType.Points
ShapeType.Triangles
ShapeType.TriStrip
Shape.drawImmediate([surface, ]type[, texture], vertices); [experimental]
Draws a shape to a surface in immediate mode (on-the-fly). Useful when
you need to create shapes on demand (procedural generation, for instance)
without incurring the expense of creating Shape and VertexList objects
every frame.
`type` should be one of the ShapeType constants above and `vertices` is an
array in the same format as for `new VertexList()` (see below). `texture`
can be either a Texture or Surface object.
Note: `.drawImmediate()` is significantly slower than drawing pre-made
Shapes. Keep this in mind when writing your rendering code as
immediate-mode rendering can very easily become a performance issue.
new Shape(type[, texture], vertexList[, indexList]); [L1]
Constructs a primitive shape from a vertex list and optional index list,
textured with a specified `Texture` image. `type` specifies the type of
primitive to draw (see `ShapeType` above).
`vertexList` is a `VertexList` containing vertices for the shape, while
`indexList`, if provided, is an `IndexList` specifying which vertices from
the vertex list will comprise the shape. If `indexList` is not specified,
all vertices from `vertexList` will be used.
Shape#indexList [read/write] [L1]
Gets or sets the index list used to select vertices for this shape. Set
this to `null` to use the entire vertex list.
Shape#texture [read/write] [L1]
The Image to use when texturing the shape. This can be null, in which case
the vertex colors alone will determine the shape's appearance.
Shape#vertexList [read/write] [L1]
Gets or sets the vertex list containing vertices for this shape.
Shape#draw([surface[, transform]]); [L1]
Draws the shape onto `surface`, or the backbuffer if no surface is
specified. `transform` is the Transform to use.
Note: If the shape's current index list is larger than its vertex list, a
RangeError will be thrown.
`Socket` Object
--------------
A `Socket` represents a TCP connection to another computer. Sockets can either
be created manually (if the game is initiating the connection), or returned by
`Server#accept()` to represent an incoming connection.
new Socket([hostname, port]); [L1]
Constructs a TCP socket object. If no arguments are provided, the socket
starts in a disconnected state, otherwise attempts to connect to `hostname`
on `port` and throws an error if the attempt fails. See the documentation
for `Socket#connectTo()` for more information on socket connections.
Socket#bytesPending [read-only] [L1]
Gets the number of bytes of data currently in this socket's receive buffer.
Call `Socket#read()` to retrieve this data.
Note: More data may be received between the time this is checked the time
a read is performed. It's recommended to poll this value from time
to time and perform reads in order to keep the size of the receive
buffer down.
Socket#connected [read-only] [L1]
Gets whether the connection has been established. As long as this is
false, you cannot call any other methods on the socket object. Doing so
will cause an error to be thrown.
Socket#remoteAddress [read-only] [L1]
Gets the IP address of the upstream end of the socket. Throws an error if
accessed before a connection has been established.
Socket#remotePort [read-only] [L1]
Gets the port that the remote machine is using for the connection.
Generally not a useful statistic, but it's there if you need it. Throws an
error if accessed before a connection is established.
Socket#close(); [L1]
Disconnects the socket. Note that any given Socket object is tied to a
specific session and so cannot be reused after it has been closed.
Socket#connectTo(hostname, port); [L1]
Connects the socket to `hostname` on `port` and throws an error if the
initial connection attempt fails. `hostname` can either be a domain name
(e.g. google.com) or IP address (e.g. 127.0.0.1). If this method succeeds,
you must poll `Socket#connected` to find out when the connection has been
established before attempting to read or write from the socket.
Note: A single socket can only be connected to one client at a time. If
the socket is already connected when `Socket#connectTo()` is called,
that connection will be closed.
Socket#read(num_bytes); [L1]
Reads up to `num_bytes` bytes from the socket and returns an ArrayBuffer
containing the data received. This method is non-blocking: If more bytes
are requested than are available, only the available data will be returned.
Socket#write(data); [L1]
Writes data to the socket, which can be read at the other end. `data` can
be either an ArrayBuffer, TypedArray view, or DataView.
`Sound` Object
--------------
A `Sound` represents a streaming audio file. Because the sound is streamed, it
remains compressed, saving RAM; however, only one instance of the sound can be
played at a time.
new Sound(filename); [L1]
Constructs a Sound object from the specified audio file. Supported sound
formats are Ogg Vorbis (.ogg), WAV, MOD, S3M, IT, and FLAC. Note that
unlike in Sphere 1.x, mp3 and MIDI formats are not supported.
Sound#fileName [read-only] [L1]
Gets the full SphereFS pathname of the file used to construct this Sound
object.
Sound#length [read-only] [L1]
Gets the length of the sound in microseconds.
Sound#pan [read/write] [L1]
Gets or sets the current pan (balance). 0.0 is dead center, -1.0 is full
left, and 1.0 is full right.
Sound#playing [read-only] [L1]
true if the sound is currently playing, false otherwise.
Sound#position [read/write] [L1]
Gets or sets the playback position within the sound, in seconds.
Sound#repeat [read/write] [L1]
Gets or sets whether the sound will automatically repeat when it reaches
the end.
Sound#speed [read/write] [L1]
Gets the current playback speed of the sound. 1.0 is normal, 2.0 is double
speed, etc. Note that changing the playback speed affects the pitch as
well.
Sound#volume [read/write] [L1]
Gets or sets the current volume of the sound. 0.0 is silent, 1.0 is full
volume. Higher values are allowed, but may introduce distortion due to
clipping.
Sound#pause(); [L1]
Pauses the sound. If it is already paused, this has no effect.
Sound#play([mixer]); [L1]
Begins or resumes sound playback. When called with no `mixer` argument,
Sound#play() will resume playback for a paused sound. Otherwise, the sound
is started from the beginning on the specified mixer.
Sound#stop(); [L1]
Stops the sound. Playback position will be reset to the beginning (0.0s),
even if the sound was not playing.
`SoundStream` Object
--------------------
A `SoundStream` represents a dynamic audio stream which can be used to play
arbitrary audio data, fed to the stream by your game in realtime. This can be
used to implement procedural audio, for example.
new SoundStream([frequency[, bits[, channels]]]); [L1]
Constructs an audio stream, which plays arbitrary sound data provided by
the game at runtime. This may be used, for example, to generate sound
procedurally or add support for an unsupported audio format in script.
`frequency` specifies the stream's sample rate and 'channels' the number of
audio channels, ranging [1-7]. Channel counts of 5 and higher imply an
additional LFE (subwoofer) channel.
The default stream format is 8-bit 22050Hz with 1 channel.
SoundStream#length [read-only] [L1]
Gets the amount of audio currently buffered into the stream, in seconds.
Playback will pause if the buffer is exhausted; To ensure skip-free
playback, you should monitor the stream and write more data before `length`
reaches zero.
SoundStream#pause(); [L1]
Pauses playback of the stream. Has no effect if the stream is already
paused.
SoundStream#play([mixer]); [L1]
Starts the stream playing, or if no mixer is specified, resumes a paused
stream. Before beginning playback, it is recommended to pre-buffer a few
seconds of audio into the stream (see SoundStream#write() below). This
will minimize the risk of a buffer underrun and subsequent skipping during
playback.
SoundStream#stop(); [L1]
Stops playback of the stream and frees its buffer. This should be called
when you are done using a stream. The stream may be reused after a stop()
call, but you will have to feed new audio data.
SoundStream#write(data); [L1]
Writes audio data to the stream buffer. `data` is an ArrayBuffer,
TypedArray or DataView containing the data to write. While a stream is
playing, audio data should be fed into it continuously to prevent skipping.
`Surface` Object
----------------
The `Surface` object represents a rendering target. Your game doesn't always
need to draw directly to the screen; it sometimes makes sense to compose
complex parts of a scene in advance, offscreen, so that you don't have to
redraw them every frame. A Surface object can be used anywhere a texture is
expected. This avoids the need to make a copy of the surface and additionally
enables render-to-texture effects to be implemented.
Note: Surfaces can only be used as textures under API level 2 or higher. When
targeting API level 1 you must call `.toTexture()` (see below) first.
Surface.Screen [non-replaceable] [L1]
A special Surface object representing the backbuffer. Anything drawn to
this surface will automatically become visible on the screen the next time
the event loop regains control.
new Surface(width, height[, content]); [L1]
Constructs a new Surface with the specified content. `width` and `height`
specify the size in pixels of the surface, and `content` is either a
`Color` (in which case the surface will be filled with that color) or a
buffer object holding the RGBA pixel data to use to initialize the image.
The pixel data should not be padded (i.e. stride equal to width).
If `content` is not specified, the surface will be filled with transparent
pixels (`Color.Transparent`).
Note: When passing a buffer for `content` and the buffer doesn't contain
enough pixel data to cover the entire surface, a RangeError will be
thrown.
new Surface(filename); [L1]
Constructs a new Surface whose initial contents are taken from the
specified image file.
Surface#blendOp [read/write] [experimental]
Gets or sets the blending operation for objects drawn to this surface. The
value specifies how the colors of the object being drawn will be combined
with the existing contents of the surface, and can be one of the following:
BlendOp.AlphaBlend
BlendOp.Add
BlendOp.Average
BlendOp.CopyAlpha
BlendOp.CopyRGB
BlendOp.Invert
BlendOp.Multiply
BlendOp.Replace
BlendOp.Subtract
The default is `BlendOp.AlphaBlend` which combines the source and
destination pixels using the source's alpha value as a weighting factor
(commonly referred to as "alpha blending").
Surface#transform [read/write] [L1]
Gets or sets a `Transform` representing the surface's projection matrix.
When rendering is done on the surface, the projection matrix is the last
one applied and affects the entire scene.
Note: The default projection matrix in Sphere is NOT an identity matrix.
When a surface is created, Sphere sets its transform to an
orthographic matrix suitable for pixel-perfect 2D rendering.
Surface#width [read-only] [L1]
Surface#height [read-only] [L1]
Gets the width and height of the surface, in pixels. For the screen, this
is the game's nominal resolution, i.e. the resolution it renders at.
Surface#clipTo(x, y, width, height); [L1]
Sets the surface's clipping rectangle. Values are expressed in pixels.
Anything drawn outside of the clipping rectangle won't be rendered.
Note: When setting the clipping rectangle for the screen, the effect only
lasts until the next frame.
Surface#toTexture(); [L1]
Returns a Texture created from the current contents of this Surface. Note
that drawing to the surface afterwards will not affect the texture, which
is read-only.
Note: It is not necessary to call this when targeting API level 2 or later;
as noted above, the surface itself can be used as a texture.
`Texture` Object
----------------
A `Texture` is an image which can used to as a texture for shapes drawn using
the Sphere v2 graphics API. Unlike in Sphere v1, you cannot draw an image
directly using the Core API; it must be used to texture a `Shape`.
new Texture(filename); [L1]
Constructs a new Texture object from an image file. Unlike images in
Sphere v1, these cannot be rendered directly but instead must be used to
texture a Shape object.
Note that Textures are read-only. If you need a writable image, you should
use a Surface object instead.
new Texture(width, height[, content]); [L1]
Constructs a new Texture with the specified content. `width` and `height`
specify the size in pixels of the texture, and `content` is either a
`Color` (in which case the texture will be filled with that color) or a
buffer object holding the RGBA pixel data to use to initialize the image.
The pixel data should not be padded (i.e. stride equal to width).
If `content` is not specified, the texture will be filled with transparent
pixels (`Color.Transparent`).
Note: When passing a buffer for `content` and the buffer doesn't contain
enough pixel data to cover the entire texture, a RangeError will be
thrown.
new Texture(surface); [L1]
Constructs a new Texture from the contents of `surface`, a Surface object.
Subsequent modifications to the surface will not affect the contents of the
new texture.
Texture#fileName [read-only] [L1]
Gets the full SphereFS pathname of the file used to construct this Texture
object. For synthesized textures, e.g. those created from a surface, this
is `null`.
Texture#width [read-only] [L1]
Texture#height [read-only] [L1]
Gets the width or height of the texture, in pixels.
Texture#download(); [experimental]
Downloads the 32-bit RGBA pixel data from the texture and returns it as a
new Uint8ClampedArray.
Note: Downloading data from the GPU is a rather slow operation and
shouldn't be done at render time if you can avoid it. Use a Surface
for render-to-texture effects if at all possible.
Texture#upload(content); [experimental]
Uploads 32-bit RGBA pixel data from `content` (an ArrayBuffer or typed
array) to the texture. Enough data must be provided to completely rewrite
the texture or a RangeError will be thrown.
`Transform` Object
------------------
A `Transform` represents a transformation matrix used to convert vertex
coordinates for shapes drawn to a surface.
new Transform(); [L1]
Constructs a transformation matrix. The object represents a 4x4 matrix
and is initialized to identity.
Transform#matrix [non-replacable]
Gets an object you can use to access the cells of the underlying matrix.
The object is used like a two-dimensional array:
cellValue = transform_obj.matrix[i][j];
transform_obj.matrix[i][j] = newValue;
Transform#identity(); [L1]
Re-initializes this matrix as an identity matrix.
Transform#compose(otherMatrix); [L1]
Composes this transform with another. `otherMatrix` is multiplied from the
left such that transformations are performed in the order you specify.
Transform#project2D(left, top, right, bottom[, near, far]); [L1]
Multiplies this transform's matrix with an orthographic (parallel)
projection.
Transform#project3D(fov, aspect, near, far); [L1]
Multiplies this transform's matrix with a 3D perspective projection. `fov`
is the size of the vertical field of view, in degrees. `aspect` should
match the aspect ratio of the game. For example, if the game resolution
is 1280x720, then `aspect` would usually be (16 / 9).
`near` and `far` define the distances in front of the "camera" beyond which
objects will be clipped. They must be nonzero and positive, or an error
will be thrown.
Transform#rotate(angle[, vx, vy, vz]); [L1]
Applies a rotation transformation to this matrix. `angle` is the amount of
rotation to apply, in degrees. (vx, vy, vz) is the vector to rotate about.
For example, the default is (0, 0, 1) which rotates about the Z axis.
Transform#scale(sx, sy[, sz]); [L1]
Applies a scaling transformation to this matrix. `sx`, `sy`, and `sz` are
the scaling factors for each axis. If `sz` is omitted, it defaults to 1.0
and the Z axis is not scaled.
Transform#translate(tx, ty[, tz]); [L1]
Applies a translation transformation to this matrix. `tx`, `ty`, and `tz`
are the amount of translation to apply along each axis. If `tz` is
omitted, it defaults to 0.0 and the Z axis is not translated.
`VertexList` Object
-------------------
A `VertexList` contains a collection of vertices for use when constructing a
`Shape`. The vertices in the vertex list are stored on the GPU for fast access
at render time.
new VertexList(vertices); [L1]
Constructs a new vertex list from `vertices`, an array of objects with the
following properties:
vertex.x, vertex.y
The location of the vertex. The final location of each vertex can
be modified by using a transformation matrix (see Matrix above).
vertex.u, vertex.v
The texture coordinates of the vertex. This is used to control
which part of the texture will be applied to this vertex. If u/v
is not provided for a vertex, it will be assumed to be have its u/v
at (0, 0).
vertex.color
The color of the vertex. The vertex colors will be multiplied with
texture pixels to determine the final color of each pixel in a
shape.
If `vertices` is not an array or any element is not a valid object as
described above, an error will be thrown.
Note: The list of vertices stored on the GPU can't be modified later. If
you want to upload a new set of vertices, you must construct a new
`VertexList`.
`Z` Namespace
-------------
The somewhat cryptically-named `Z` namespace hosts functions used for data
compression.
Z.deflate(data[, level]); [experimental]
Compresses the data in an ArrayBuffer or TypedArray using the DEFLATE
compression method. `level` specifies the compression level from
0 (no compression) to 9 (maximum), with 7 being the default. Returns an
ArrayBuffer containing the compressed data.
Z.inflate(data[, max_size]); [experimental]
Decompresses data in an ArrayBuffer or TypedArray which was previously
compressed using DEFLATE. `max_size` is optional and specifies an upper
limit on the size of the decompressed data, useful for preventing
"zip bomb" attacks. Returns an ArrayBuffer containing the decompressed
data.