Skip to content

Commit 45feddf

Browse files
committed
chore: implement TileMapRenderer and & some engine updates
1 parent 3a9b4b1 commit 45feddf

File tree

13 files changed

+1031
-44
lines changed

13 files changed

+1031
-44
lines changed

packages/engine/src/audio/AudioBackground.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type AudioBackgroundSoundPath = `${string}.${string}`;
1313
export interface AudioBackgroundOptions {
1414
playlists: AudioBackgroundPlaylist[];
1515
autoPlay?: boolean | AudioBackgroundSoundPath | AudioBackgroundSoundIndex;
16+
onError?: (error: Error) => void;
1617
}
1718

1819
export interface AudioBackgroundPlaylist {
@@ -43,26 +44,32 @@ export class AudioBackground {
4344
playlists: AudioBackgroundPlaylist[] = [];
4445
audio: null | THREE.Audio = null;
4546

47+
#onError: (error: Error) => void;
4648
#buffers = new Map<string, AudioBuffer>();
4749
#currentIndex: AudioBackgroundSoundIndex | null = null;
4850

4951
constructor(
5052
gameInstance: GameInstance,
5153
options: AudioBackgroundOptions
5254
) {
53-
const { playlists, autoPlay = false } = options;
55+
const {
56+
playlists,
57+
autoPlay = false,
58+
onError = (err) => console.error(err)
59+
} = options;
5460

5561
this.gameInstance = gameInstance;
5662
this.playlists = playlists;
63+
this.#onError = onError;
5764
if (autoPlay) {
5865
this.play(typeof autoPlay === "boolean" ? [0, 0] : autoPlay)
59-
.catch(console.error);
66+
.catch(this.#onError);
6067
}
6168
}
6269

6370
async preload(): Promise<void> {
6471
await Promise.all(
65-
this.playlists.flatMap((playlist) => playlist.tracks.map((track) => this.#loadAudioTrackBuffer(track)))
72+
this.playlists.flatMap((playlist) => playlist.tracks.map((track) => this.#loadAudioBuffer(track)))
6673
);
6774
}
6875

@@ -115,23 +122,25 @@ export class AudioBackground {
115122
return playlist && playlist.tracks.length > 0 ? playlist : null;
116123
}
117124

118-
async #loadAudioTrackBuffer(
125+
async #loadAudioBuffer(
119126
track: AudioBackgroundTrack
120127
): Promise<AudioBuffer> {
121128
if (this.#buffers.has(track.assetPath)) {
122129
return this.#buffers.get(track.assetPath)!;
123130
}
124131

125-
const buffer = await this.gameInstance.loader.audio.loadAsync(track.assetPath);
132+
const buffer = await this.gameInstance.loader.audio.loadAsync(
133+
track.assetPath
134+
);
126135
this.#buffers.set(track.assetPath, buffer);
127136

128137
return buffer;
129138
}
130139

131-
async #loadAudioTrack(
140+
async #createAudioFromTrack(
132141
track: AudioBackgroundTrack
133142
): Promise<THREE.Audio> {
134-
const buffer = await this.#loadAudioTrackBuffer(track);
143+
const buffer = await this.#loadAudioBuffer(track);
135144

136145
const { name, volume = 1 } = track;
137146
const sound = new THREE.Audio(this.gameInstance.audio.listener);
@@ -159,10 +168,6 @@ export class AudioBackground {
159168
return this.#getTrackByIndex(this.#currentIndex);
160169
}
161170

162-
/**
163-
* Plays a sound from the audio background.
164-
* @param pathOrIndex - The path in the format "playlistName.trackName" or an index in the format [playlistIndex, trackIndex].
165-
*/
166171
async play(
167172
pathOrIndex: AudioBackgroundSoundPath | AudioBackgroundSoundIndex | undefined
168173
) {
@@ -179,21 +184,16 @@ export class AudioBackground {
179184
throw new Error(`Track not found: ${pathOrIndex}`);
180185
}
181186

187+
this.#currentIndex = typeof pathOrIndex === "string"
188+
? this.#getTrackIndexFromPath(pathOrIndex)
189+
: pathOrIndex;
190+
182191
if (this.audio) {
183192
this.stop();
184193
}
185-
186-
const audio = await this.#loadAudioTrack(track);
187-
audio.onEnded = () => {
188-
this.playNext().catch(console.error);
189-
};
190-
191-
this.audio = audio;
192-
this.#currentIndex = typeof pathOrIndex === "string" ?
193-
this.#getTrackIndexFromPath(pathOrIndex) :
194-
pathOrIndex;
195-
196-
audio.play();
194+
this.audio = await this.#createAudioFromTrack(track);
195+
this.audio.onEnded = () => this.playNext().catch(this.#onError);
196+
this.audio.play();
197197
}
198198

199199
async playNext() {

packages/engine/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from "./controls/Input.class.js";
88
export * from "./Timer.js";
99
export * from "./audio/Audio.js";
1010
export * from "./audio/AudioBackground.js";
11+
export * as pathUtils from "./utils/path.js";
10.8 KB
Loading
8.3 KB
Loading
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{ "compressionlevel":-1,
2+
"height":20,
3+
"infinite":false,
4+
"layers":[
5+
{
6+
"data":[1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 1, 1, 1, 2, 3, 4, 2, 3, 4, 4, 3, 4, 1,
7+
1, 2, 3, 4, 1, 9, 9, 10, 11, 12, 9, 10, 11, 12, 10, 11, 12, 1, 1, 1, 2, 3, 4, 10, 11, 12, 12, 11, 12, 1,
8+
9, 10, 11, 12, 1, 17, 17, 18, 19, 20, 17, 18, 19, 20, 18, 19, 20, 1, 1, 2, 3, 4, 12, 18, 19, 20, 30, 19, 20, 1,
9+
17, 18, 19, 20, 1, 25, 25, 30, 27, 28, 25, 26, 27, 28, 26, 27, 1, 2, 1, 2, 3, 4, 20, 26, 27, 28, 28, 27, 28, 1,
10+
25, 26, 27, 28, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 9, 10, 9, 10, 1, 2, 3, 4, 1, 2, 1, 2, 3, 4,
11+
9, 10, 11, 12, 9, 10, 11, 12, 9, 10, 11, 12, 9, 10, 11, 12, 17, 18, 17, 18, 9, 10, 11, 12, 9, 10, 9, 10, 11, 12,
12+
17, 18, 19, 20, 17, 18, 19, 20, 17, 18, 19, 20, 17, 18, 19, 20, 25, 26, 25, 26, 17, 18, 19, 20, 17, 18, 17, 18, 19, 20,
13+
25, 26, 27, 28, 25, 26, 27, 28, 25, 26, 27, 28, 25, 26, 27, 28, 25, 26, 27, 28, 25, 26, 27, 28, 25, 26, 25, 30, 27, 28,
14+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
15+
34, 57, 34, 34, 34, 34, 34, 49, 34, 34, 53, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 58, 34, 34, 34, 34,
16+
34, 34, 34, 34, 60, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 58, 34, 34, 34, 34, 34, 34, 34, 62, 34,
17+
1, 2, 3, 1, 1, 2, 3, 4, 1, 2, 3, 4, 1, 1, 1, 1, 2, 3, 4, 1, 1, 1, 2, 3, 4, 4, 1, 1, 1, 1,
18+
9, 10, 11, 9, 9, 10, 11, 12, 9, 10, 11, 12, 22, 1, 1, 9, 1, 2, 3, 4, 1, 9, 10, 11, 12, 12, 1, 1, 1, 1,
19+
17, 18, 19, 17, 17, 1, 2, 3, 4, 18, 19, 20, 10, 10, 1, 17, 9, 10, 11, 12, 1, 17, 18, 19, 20, 20, 1, 1, 1, 1,
20+
1, 2, 3, 4, 25, 9, 10, 11, 12, 26, 27, 28, 1, 2, 3, 4, 17, 18, 19, 20, 2, 25, 26, 27, 28, 28, 1, 1, 2, 3,
21+
9, 1, 2, 3, 4, 30, 18, 19, 20, 1, 1, 2, 1, 2, 3, 4, 25, 1, 2, 3, 4, 11, 12, 1, 1, 1, 9, 9, 10, 11,
22+
17, 9, 10, 11, 12, 25, 26, 27, 28, 1, 9, 10, 9, 10, 1, 2, 3, 4, 10, 11, 1, 1, 1, 1, 9, 9, 17, 17, 18, 19,
23+
25, 17, 18, 19, 20, 10, 11, 12, 12, 1, 17, 18, 17, 18, 9, 10, 11, 12, 18, 19, 9, 9, 30, 9, 17, 17, 25, 25, 26, 27,
24+
17, 25, 26, 27, 28, 18, 19, 20, 20, 1, 25, 26, 25, 26, 17, 18, 19, 20, 26, 27, 17, 17, 17, 17, 25, 25, 26, 27, 28, 1,
25+
25, 26, 27, 28, 25, 26, 27, 28, 28, 1, 25, 26, 27, 28, 25, 26, 27, 28, 1, 1, 25, 25, 25, 25, 25, 26, 27, 28, 1, 1],
26+
"height":20,
27+
"id":1,
28+
"name":"Terrain",
29+
"opacity":1,
30+
"type":"tilelayer",
31+
"visible":true,
32+
"width":30,
33+
"x":0,
34+
"y":0
35+
},
36+
{
37+
"data":[92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
38+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
39+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
40+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
41+
92, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 92,
42+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
43+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
44+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
45+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
46+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
47+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
48+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
49+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
50+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
51+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
52+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 0, 92,
53+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
54+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
55+
92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
56+
92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92],
57+
"height":20,
58+
"id":2,
59+
"name":"Mur",
60+
"opacity":1,
61+
"type":"tilelayer",
62+
"visible":true,
63+
"width":30,
64+
"x":0,
65+
"y":0
66+
},
67+
{
68+
"draworder":"topdown",
69+
"id":3,
70+
"name":"Entities",
71+
"objects":[
72+
{
73+
"height":62.71,
74+
"id":3,
75+
"name":"spawn",
76+
"rotation":0,
77+
"type":"",
78+
"visible":true,
79+
"width":96.7525,
80+
"x":414.782,
81+
"y":285.778
82+
}],
83+
"opacity":1,
84+
"type":"objectgroup",
85+
"visible":true,
86+
"x":0,
87+
"y":0
88+
}],
89+
"nextlayerid":4,
90+
"nextobjectid":4,
91+
"orientation":"orthogonal",
92+
"renderorder":"left-down",
93+
"tiledversion":"1.11.2",
94+
"tileheight":32,
95+
"tilesets":[
96+
{
97+
"firstgid": 1,
98+
"tilewidth":32,
99+
"tileheight": 32,
100+
"tilecount": 64,
101+
"columns": 8,
102+
"source":"TX Tileset Grass.tsx"
103+
},
104+
{
105+
"firstgid":65,
106+
"tilewidth":32,
107+
"tileheight": 32,
108+
"tilecount": 64,
109+
"columns": 8,
110+
"source":"TX Tileset Stone Ground.tsx"
111+
}],
112+
"tilewidth":32,
113+
"type":"map",
114+
"version":"1.10",
115+
"width":30
116+
}

packages/experimental/src/components/SpriteAnimation.class.ts renamed to packages/experimental/src/components/sprite/SpriteAnimation.class.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Import Third-party Dependencies
22
import * as THREE from "three";
3-
// import { type Component } from "@jolly-pixel/engine";
43

54
export interface SpriteAnimationRange {
65
from: number;

packages/experimental/src/components/SpriteRenderer.class.ts renamed to packages/experimental/src/components/sprite/SpriteRenderer.class.ts

File renamed without changes.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Import Third-party Dependencies
2+
import * as THREE from "three";
3+
4+
// Import Internal Dependencies
5+
import type {
6+
TiledMap,
7+
TiledTileLayer
8+
} from "./types.js";
9+
10+
export class TileLayer {
11+
static* fromTileMap(
12+
map: TiledMap
13+
) {
14+
let zId = 0;
15+
for (const layer of map.layers) {
16+
if (layer.type === "tilelayer") {
17+
yield new TileLayer(layer, zId);
18+
zId++;
19+
}
20+
}
21+
}
22+
23+
layer: TiledTileLayer;
24+
zIndex: number;
25+
26+
constructor(
27+
layer: TiledTileLayer,
28+
zIndex = 0
29+
) {
30+
this.layer = layer;
31+
this.zIndex = zIndex;
32+
}
33+
34+
* [Symbol.iterator]() {
35+
for (let x = 0; x < this.layer.width; x++) {
36+
for (let y = 0; y < this.layer.height; y++) {
37+
const tileIndex = (y * this.layer.width) + x;
38+
const tileId = Number(this.layer.data[tileIndex]);
39+
40+
if (tileId !== 0) {
41+
yield {
42+
tileId,
43+
position: new THREE.Vector3(x, y, this.zIndex)
44+
};
45+
}
46+
}
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)