Skip to content

Commit

Permalink
Oozaru 0.5.1
Browse files Browse the repository at this point in the history
Adds `Task` alias for `Thread` and removes the `.whenReady()` APIs.
  • Loading branch information
fatcerberus committed Jan 27, 2022
1 parent 8babcf7 commit b1e583d
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 114 deletions.
9 changes: 4 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
Oozaru Changelog
================

Since Last Release
------------------
v0.5.1 - January 27, 2022
-------------------------

* 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.

* Removes background-loading support for assets and the corresponding APIs
(e.g. `whenReady`) added in the previous release.

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

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "oozaru",
"version": "0.5.0+",
"version": "0.5.1",
"description": "JavaScript game engine for the Web",
"main": "index.js",
"scripts": {
Expand All @@ -23,6 +23,6 @@
},
"homepage": "https://github.com/fatcerberus/oozaru#readme",
"devDependencies": {
"typescript": "^4.5.4"
"typescript": "^4.5.5"
}
}
151 changes: 78 additions & 73 deletions src/fontso.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ class Font
const fontURL = Game.urlOf(fileName);
const fileData = await Fido.fetchData(fontURL);
const font = new Font(fileData);
font.fileName = Game.fullPath(fileName);
font.#fileName = Game.fullPath(fileName);
return font;
}

atlas!: Texture;
fileName: string | undefined;
glyphs: Glyph[] = [];
lineHeight = 0;
maxWidth = 0;
numGlyphs = 0;
stride!: number;
#atlas: Texture;
#fileName: string | undefined;
#glyphs: Glyph[] = [];
#lineHeight = 0;
#maxWidth = 0;
#numGlyphs = 0;
#stride: number;

constructor(...args: | [ ArrayBuffer ]
| [ string ])
Expand All @@ -88,54 +88,59 @@ class Font
}
else if (args[0] instanceof ArrayBuffer) {
let dataStream = new DataStream(args[0]);
let rfn = dataStream.readStruct({
let rfnHeader = dataStream.readStruct({
signature: 'string/4',
version: 'uint16-le',
numGlyphs: 'uint16-le',
reserved: 'reserve/248',
});
if (rfn.signature !== '.rfn')
if (rfnHeader.signature !== '.rfn')
throw new Error(`Unable to load RFN font file`);
if (rfn.version < 2 || rfn.version > 2)
throw new Error(`Unsupported RFN version '${rfn.version}'`)
if (rfn.numGlyphs <= 0)
if (rfnHeader.version < 2 || rfnHeader.version > 2)
throw new Error(`Unsupported RFN version '${rfnHeader.version}'`)
if (rfnHeader.numGlyphs <= 0)
throw new Error(`Malformed RFN font (no glyphs)`);
const numAcross = Math.ceil(Math.sqrt(rfn.numGlyphs));
this.stride = 1.0 / numAcross;
for (let i = 0; i < rfn.numGlyphs; ++i) {
const numAcross = Math.ceil(Math.sqrt(rfnHeader.numGlyphs));
this.#stride = 1.0 / numAcross;
for (let i = 0; i < rfnHeader.numGlyphs; ++i) {
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);
this.#lineHeight = Math.max(this.#lineHeight, charInfo.height);
this.#maxWidth = Math.max(this.#maxWidth, charInfo.width);
const pixelData = dataStream.readBytes(charInfo.width * charInfo.height * 4);
this.glyphs.push({
this.#glyphs.push({
width: charInfo.width,
height: charInfo.height,
u: i % numAcross / numAcross,
v: 1.0 - Math.floor(i / numAcross) / numAcross,
pixelData,
});
}
this.atlas = new Texture(numAcross * this.maxWidth, numAcross * this.lineHeight);
this.numGlyphs = rfn.numGlyphs;
for (let i = 0; i < this.numGlyphs; ++i) {
const glyph = this.glyphs[i];
const x = i % numAcross * this.maxWidth;
const y = Math.floor(i / numAcross) * this.lineHeight;
this.atlas.upload(glyph.pixelData, x, y, glyph.width, glyph.height);
this.#atlas = new Texture(numAcross * this.#maxWidth, numAcross * this.#lineHeight);
this.#numGlyphs = rfnHeader.numGlyphs;
for (let i = 0; i < this.#numGlyphs; ++i) {
const glyph = this.#glyphs[i];
const x = i % numAcross * this.#maxWidth;
const y = Math.floor(i / numAcross) * this.#lineHeight;
this.#atlas.upload(glyph.pixelData, x, y, glyph.width, glyph.height);
}
}
else {
throw RangeError("Invalid argument(s) passed to 'new Font'.");
}
}

get fileName()
{
return this.#fileName;
}

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

drawText(surface: Surface, x: number, y: number, text: string | number | boolean, color = Color.White, wrapWidth?: number)
Expand All @@ -144,10 +149,10 @@ class Font
if (wrapWidth !== undefined) {
const lines = this.wordWrap(text, wrapWidth);
for (let i = 0, len = lines.length; i < len; ++i)
this.renderString(surface, x, y, lines[i], color);
this.#renderString(surface, x, y, lines[i], color);
}
else {
this.renderString(surface, x, y, text, color);
this.#renderString(surface, x, y, text, color);
}
}

Expand All @@ -158,13 +163,13 @@ class Font
const lines = this.wordWrap(text, wrapWidth);
return {
width: wrapWidth,
height: lines.length * this.lineHeight,
height: lines.length * this.#lineHeight,
};
}
else {
return {
width: this.widthOf(text),
height: this.lineHeight,
height: this.#lineHeight,
};
}
}
Expand All @@ -174,42 +179,6 @@ class Font
return this.getTextSize(text, wrapWidth).height;
}

renderString(surface: Surface, x: number, y: number, text: string, color: Color)
{
x = Math.trunc(x);
y = Math.trunc(y);
if (text === "")
return; // empty string, nothing to render
let cp: number | undefined;
let ptr = 0;
let xOffset = 0;
const vertices: Vertex[] = [];
while ((cp = text.codePointAt(ptr++)) !== undefined) {
if (cp > 0xFFFF) // surrogate pair?
++ptr;
cp = toCP1252(cp);
if (cp >= this.numGlyphs)
cp = 0x1A;
const glyph = this.glyphs[cp];
const x1 = x + xOffset, x2 = x1 + glyph.width;
const y1 = y, y2 = y1 + glyph.height;
const u1 = glyph.u;
const u2 = u1 + glyph.width / this.maxWidth * this.stride;
const v1 = glyph.v;
const v2 = v1 - glyph.height / this.lineHeight * this.stride;
vertices.push(
{ x: x1, y: y1, u: u1, v: v1, color },
{ x: x2, y: y1, u: u2, v: v1, color },
{ x: x1, y: y2, u: u1, v: v2, color },
{ x: x2, y: y1, u: u2, v: v1, color },
{ x: x1, y: y2, u: u1, v: v2, color },
{ x: x2, y: y2, u: u2, v: v2, color },
);
xOffset += glyph.width;
}
Shape.drawImmediate(surface, ShapeType.Triangles, this.atlas, vertices);
}

widthOf(text: string | number | boolean)
{
text = text.toString();
Expand All @@ -220,9 +189,9 @@ class Font
if (cp > 0xFFFF) // surrogate pair?
++ptr;
cp = toCP1252(cp);
if (cp >= this.numGlyphs)
if (cp >= this.#numGlyphs)
cp = 0x1A;
width += this.glyphs[cp].width;
width += this.#glyphs[cp].width;
}
return width;
}
Expand All @@ -231,7 +200,7 @@ class Font
{
text = text.toString();
const lines: string[] = [];
let codepoints: number[] = [];
const codepoints: number[] = [];
let currentLine = "";
let lineWidth = 0;
let lineFinished = false;
Expand All @@ -243,9 +212,9 @@ class Font
if (cp > 0xFFFF) // surrogate pair?
++ptr;
cp = toCP1252(cp);
if (cp >= this.numGlyphs)
if (cp >= this.#numGlyphs)
cp = 0x1A;
const glyph = this.glyphs[cp];
const glyph = this.#glyphs[cp];
switch (cp) {
case 13: case 10: // newline
if (cp === 13 && text.codePointAt(ptr) == 10)
Expand All @@ -254,7 +223,7 @@ class Font
break;
case 8: // tab
codepoints.push(cp);
wordWidth += this.glyphs[32].width * 3;
wordWidth += this.#glyphs[32].width * 3;
wordFinished = true;
break;
case 32: // space
Expand Down Expand Up @@ -286,6 +255,42 @@ class Font
lines.push(currentLine);
return lines;
}

#renderString(surface: Surface, x: number, y: number, text: string, color: Color)
{
x = Math.trunc(x);
y = Math.trunc(y);
if (text === "")
return; // empty string, nothing to render
let cp: number | undefined;
let ptr = 0;
let xOffset = 0;
const vertices: Vertex[] = [];
while ((cp = text.codePointAt(ptr++)) !== undefined) {
if (cp > 0xFFFF) // surrogate pair?
++ptr;
cp = toCP1252(cp);
if (cp >= this.#numGlyphs)
cp = 0x1A;
const glyph = this.#glyphs[cp];
const x1 = x + xOffset, x2 = x1 + glyph.width;
const y1 = y, y2 = y1 + glyph.height;
const u1 = glyph.u;
const u2 = u1 + glyph.width / this.#maxWidth * this.#stride;
const v1 = glyph.v;
const v2 = v1 - glyph.height / this.#lineHeight * this.#stride;
vertices.push(
{ x: x1, y: y1, u: u1, v: v1, color },
{ x: x2, y: y1, u: u2, v: v1, color },
{ x: x1, y: y2, u: u1, v: v2, color },
{ x: x2, y: y1, u: u2, v: v1, color },
{ x: x1, y: y2, u: u1, v: v2, color },
{ x: x2, y: y2, u: u2, v: v2, color },
);
xOffset += glyph.width;
}
Shape.drawImmediate(surface, ShapeType.Triangles, this.#atlas, vertices);
}
}

function toCP1252(codepoint: number)
Expand Down
19 changes: 8 additions & 11 deletions src/galileo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,17 +489,15 @@ class Model
{
return this.shader_;
}

get transform()
{
return this.transform_;
}

set shader(value)
{
this.shader_ = value;
}

get transform()
{
return this.transform_;
}
set transform(value)
{
this.transform_ = value;
Expand Down Expand Up @@ -1019,18 +1017,17 @@ class Surface extends Texture
return screenSurface;
}

static async fromFile(fileName: string)
static fromFile(fileName: string): Promise<Surface>
{
const url = Game.urlOf(fileName);
const image = await Fido.fetchImage(url);
return new Surface(image);
throw Error("'Surface.fromFile' is not supported in Oozaru.");
}

constructor(...args: | [ HTMLImageElement ]
| [ string ]
| [ number, number, (BufferSource | Color)? ])
{
if (typeof args[0] === 'string')
throw RangeError("new Surface() doesn't support background loading.");
throw Error("'new Surface' with filename is not supported in Oozaru.");

super(...args);

Expand Down
Loading

0 comments on commit b1e583d

Please sign in to comment.