Skip to content

Commit

Permalink
Remove .ready and .whenReady() APIs
Browse files Browse the repository at this point in the history
These added a lot of complexity to the API implementation for very
little gain. It's just as easy to call, e.g., `Texture.fromFile()` and
hold off on awaiting the promise until later on.
  • Loading branch information
fatcerberus committed Jan 25, 2022
1 parent 95cce9f commit 8babcf7
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 222 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Since Last Release
------------------

* Adds support for games that use `Task` instead of `Thread`.
* Removes the background-loading support for assets and the corresponding APIs
added in the previous release.


v0.5.0 - January 5, 2022
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "oozaru",
"version": "0.6-WiP",
"version": "0.5.0+",
"description": "JavaScript game engine for the Web",
"main": "index.js",
"scripts": {
Expand Down
91 changes: 32 additions & 59 deletions src/audialis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,50 @@ class Mixer
this.panner.connect(this.context.destination);
}

get pan() { return this.panner.pan.value; }
set pan(value) { this.panner.pan.value = value; }
get pan()
{
return this.panner.pan.value;
}
set pan(value)
{
this.panner.pan.value = value;
}

get volume() { return this.gainer.gain.value; }
set volume(value) { this.gainer.gain.value = value; }
get volume()
{
return this.gainer.gain.value;
}
set volume(value)
{
this.gainer.gain.value = value;
}
}

export
class Sound
{
static fromFile(fileName: string)
static async fromFile(fileName: string)
{
return new Sound(fileName).whenReady();
const url = Game.urlOf(fileName);
const audioElement = new Audio();
await new Promise<void>((resolve, reject) => {
audioElement.onloadedmetadata = () => {
resolve();
}
audioElement.onerror = () => {
reject(Error(`Couldn't load audio file '${url}'.`));
};
audioElement.src = url;
});
const sound = new Sound(audioElement);
sound.fileName = Game.fullPath(fileName);
return sound;
}

audioNode: MediaElementAudioSourceNode | null = null;
complete = false;
currentMixer: Mixer | null = null;
element: HTMLAudioElement;
exception: unknown;
fileName: string | undefined;
promise: Promise<void> | null = null;

constructor(source: HTMLAudioElement | string)
{
Expand All @@ -98,21 +120,7 @@ class Sound
this.element.loop = true;
}
else if (typeof source === 'string') {
const url = Game.urlOf(source);
this.fileName = source;
this.element = new Audio();
this.element.loop = true;
this.promise = new Promise<void>((resolve) => {
this.element.onloadedmetadata = () => {
this.complete = true;
resolve();
}
this.element.onerror = () => {
this.exception = Error(`Couldn't load audio file '${url}'.`);
resolve();
};
this.element.src = url;
});
throw Error("'new Sound' with filename is not supported under Oozaru.");
}
else {
throw TypeError(`Invalid value '${source}' passed for 'Sound' source`);
Expand All @@ -121,31 +129,19 @@ class Sound

get length()
{
this.checkIfReady();
return this.element.duration;
}

get playing()
{
this.checkIfReady();
return !this.element.paused;
}

get position()
{
this.checkIfReady();
return this.element.currentTime;
}

get ready()
{
if (this.exception !== undefined)
throw this.exception;
if (this.complete)
this.promise = null;
return this.complete;
}

get repeat()
{
return this.element.loop;
Expand All @@ -163,7 +159,6 @@ class Sound

set position(value)
{
this.checkIfReady();
this.element.currentTime = value;
}

Expand All @@ -182,21 +177,13 @@ class Sound
this.element.volume = value;
}

checkIfReady()
{
if (this.promise !== null)
throw Error(`Sound loaded from file '${this.fileName}' was used without a ready check.`);
}

pause()
{
this.checkIfReady();
this.element.pause();
}

play(mixer = Mixer.Default)
{
this.checkIfReady();
if (mixer !== this.currentMixer) {
this.currentMixer = mixer;
if (this.audioNode !== null)
Expand All @@ -210,23 +197,9 @@ class Sound

stop()
{
this.checkIfReady();
this.element.pause();
this.element.currentTime = 0.0;
}

async whenReady()
{
if (this.exception !== undefined)
throw this.exception;
if (this.promise !== null) {
await this.promise;
if (this.exception !== undefined)
throw this.exception;
this.promise = null;
}
return this;
}
}

export
Expand Down
74 changes: 22 additions & 52 deletions src/fontso.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

import { DataStream } from './data-stream.js';
import Fido from './fido.js';
import { Color, Shape, ShapeType, Size, Surface, Texture, Vertex } from './galileo.js';
import { Color, Shape, ShapeType, type Size, type Surface, Texture, type Vertex } from './galileo.js';
import Game from './game.js';

interface Glyph
Expand Down Expand Up @@ -63,28 +63,32 @@ class Font
return defaultFont;
}

static fromFile(fileName: string)
static async fromFile(fileName: string)
{
return new Font(fileName).whenReady();
const fontURL = Game.urlOf(fileName);
const fileData = await Fido.fetchData(fontURL);
const font = new Font(fileData);
font.fileName = Game.fullPath(fileName);
return font;
}

atlas!: Texture;
complete = false;
exception: unknown;
fileName: string;
fileName: string | undefined;
glyphs: Glyph[] = [];
lineHeight = 0;
maxWidth = 0;
numGlyphs = 0;
promise: Promise<void> | null = null;
stride!: number;

constructor(fileName: string)
constructor(...args: | [ ArrayBuffer ]
| [ string ])
{
this.fileName = Game.urlOf(fileName);
this.promise = Fido.fetchData(this.fileName).then((data) => {
let stream = new DataStream(data);
let rfn = stream.readStruct({
if (typeof args[0] === 'string') {
throw Error("'new Font' with filename is not supported in Oozaru.");
}
else if (args[0] instanceof ArrayBuffer) {
let dataStream = new DataStream(args[0]);
let rfn = dataStream.readStruct({
signature: 'string/4',
version: 'uint16-le',
numGlyphs: 'uint16-le',
Expand All @@ -99,14 +103,14 @@ class Font
const numAcross = Math.ceil(Math.sqrt(rfn.numGlyphs));
this.stride = 1.0 / numAcross;
for (let i = 0; i < rfn.numGlyphs; ++i) {
let charInfo = stream.readStruct({
let charInfo = dataStream.readStruct({
width: 'uint16-le',
height: 'uint16-le',
reserved: 'reserve/28',
});
this.lineHeight = Math.max(this.lineHeight, charInfo.height);
this.maxWidth = Math.max(this.maxWidth, charInfo.width);
const pixelData = stream.readBytes(charInfo.width * charInfo.height * 4);
const pixelData = dataStream.readBytes(charInfo.width * charInfo.height * 4);
this.glyphs.push({
width: charInfo.width,
height: charInfo.height,
Expand All @@ -123,36 +127,19 @@ class Font
const y = Math.floor(i / numAcross) * this.lineHeight;
this.atlas.upload(glyph.pixelData, x, y, glyph.width, glyph.height);
}
this.complete = true;
}, (error) => {
this.exception = error;
})
}
else {
throw RangeError("Invalid argument(s) passed to 'new Font'.");
}
}

get height()
{
this.checkIfReady();
return this.lineHeight;
}

get ready()
{
if (this.exception !== undefined)
throw this.exception;
if (this.complete)
this.promise = null;
return this.complete;
}

checkIfReady()
{
if (this.promise !== null)
throw Error(`Font from file ${this.fileName} was used without a ready check.`);
}

drawText(surface: Surface, x: number, y: number, text: string | number | boolean, color = Color.White, wrapWidth?: number)
{
this.checkIfReady();
text = text.toString();
if (wrapWidth !== undefined) {
const lines = this.wordWrap(text, wrapWidth);
Expand All @@ -166,7 +153,6 @@ class Font

getTextSize(text: string | number | boolean, wrapWidth?: number): Size
{
this.checkIfReady();
text = text.toString();
if (wrapWidth !== undefined) {
const lines = this.wordWrap(text, wrapWidth);
Expand All @@ -185,7 +171,6 @@ class Font

heightOf(text: string | number | boolean, wrapWidth?: number)
{
this.checkIfReady();
return this.getTextSize(text, wrapWidth).height;
}

Expand Down Expand Up @@ -225,22 +210,8 @@ class Font
Shape.drawImmediate(surface, ShapeType.Triangles, this.atlas, vertices);
}

async whenReady()
{
if (this.exception !== undefined)
throw this.exception;
if (this.promise !== null) {
await this.promise;
if (this.exception !== undefined)
throw this.exception;
this.promise = null;
}
return this;
}

widthOf(text: string | number | boolean)
{
this.checkIfReady();
text = text.toString();
let cp: number | undefined;
let ptr = 0;
Expand All @@ -258,7 +229,6 @@ class Font

wordWrap(text: string | number | boolean, wrapWidth: number)
{
this.checkIfReady();
text = text.toString();
const lines: string[] = [];
let codepoints: number[] = [];
Expand Down
Loading

0 comments on commit 8babcf7

Please sign in to comment.