Skip to content

Commit 4aa1853

Browse files
authored
Merge pull request #28 from Ragzouken/rendering
more modular rendering for ease of plugination
2 parents 9585209 + 851898b commit 4aa1853

File tree

2 files changed

+63
-35
lines changed

2 files changed

+63
-35
lines changed

docs/event-behaviors.md

+3
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,18 @@
6969
| image layer | meaning
7070
|--|--
7171
| background | below the room, events, and dialogue
72+
| midground | above the room, but below the events and dialogue
7273
| foreground | above the room and events, but below the dialogue
7374
| overlay | above the room, events, and dialogue
7475

7576
| name | type | meaning
7677
|--|--|--
7778
| background | text | show named image on background layer
79+
| midground | text | show named image on midground layer
7880
| foreground | text | show named image on foreground layer
7981
| overlay | text | show named image on overlay layer
8082
| clear-background | tag | clear image on background layer
83+
| clear-midground | tag | clear image on midground layer
8184
| clear-foreground | tag | clear image on foreground layer
8285
| clear-overlay | tag | clear image on overlay layer
8386

src/scripts/playback.js

+60-35
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,13 @@ if (backgrounds.length > 0) {
241241
HIDE_IMAGE("BACKGROUND");
242242
}
243243
244+
let midgrounds = FIELDS_OR_LIBRARY("midground");
245+
if (midgrounds.length > 0) {
246+
SHOW_IMAGE("MIDGROUND", midgrounds, 1, 0, 0);
247+
} else if (IS_TAGGED(EVENT, "clear-midground")) {
248+
HIDE_IMAGE("MIDGROUND");
249+
}
250+
244251
let foregrounds = FIELDS_OR_LIBRARY("foreground");
245252
if (foregrounds.length > 0) {
246253
SHOW_IMAGE("FOREGROUND", foregrounds, 2, 0, 0);
@@ -540,57 +547,75 @@ class BipsiPlayback extends EventTarget {
540547
this.render();
541548
}
542549

543-
render(frame=undefined) {
550+
addRoomToScene(scene, dest, frame) {
544551
// find avatar, current room, current palette
545552
const avatar = getEventById(this.data, this.avatarId);
546553
const room = roomFromEvent(this.data, avatar);
547554
const palette = this.getActivePalette();
548555
const tileset = this.stateManager.resources.get(this.data.tileset);
549556

550557
// find current animation frame for each tile
551-
frame = frame ?? this.frameCount;
552558
const tileToFrame = makeTileToFrameMap(this.data.tiles, frame);
553559

554-
// sort images
555-
const images = Array.from(this.images.values());
556-
images.sort((a, b) => a.layer - b.layer);
557-
const images_below_all = images.filter((image) => image.layer < 1);
558-
const images_below_events = images.filter((image) => image.layer >= 1 && image.layer < 2);
559-
const images_above_events = images.filter((image) => image.layer >= 2 && image.layer < 3);
560-
const images_above_all = images.filter((image) => image.layer >= 3);
560+
function upscaler(func) {
561+
return () => {
562+
fillRendering2D(TEMP_ROOM);
563+
func();
564+
dest.drawImage(TEMP_ROOM.canvas, 0, 0, 256, 256);
565+
};
566+
}
567+
568+
scene.push({ layer: 1, func: upscaler(() => drawTilemapLayer(TEMP_ROOM, tileset, tileToFrame, palette, room)) });
569+
scene.push({ layer: 2, func: upscaler(() => drawEventLayer(TEMP_ROOM, tileset, tileToFrame, palette, room.events)) });
570+
}
561571

572+
addImagesToScene(scene, dest, frame) {
562573
function drawImage({ image, x, y }) {
563-
TEMP_ROOM.drawImage(image[frame % image.length], x, y);
574+
dest.drawImage(image[frame % image.length], x, y);
564575
}
565576

566-
fillRendering2D(this.rendering);
567-
images_below_all.forEach(drawImage);
568-
drawTilemapLayer(TEMP_ROOM, tileset, tileToFrame, palette, room);
569-
images_below_events.forEach(drawImage);
570-
drawEventLayer(TEMP_ROOM, tileset, tileToFrame, palette, room.events);
571-
images_above_events.forEach(drawImage);
572-
573-
// upscale tilemaps to display area
574-
this.rendering.drawImage(TEMP_ROOM.canvas, 0, 0, 256, 256);
575-
576-
// render dialogue box if necessary
577-
if (!this.dialoguePlayback.empty) {
578-
// change default dialogue position based on avatar position
579-
const top = avatar.position[1] >= 8;
580-
this.dialoguePlayback.options.anchorY = top ? 0 : 1;
581-
582-
// redraw dialogue and copy to display area
583-
this.dialoguePlayback.render();
584-
this.rendering.drawImage(this.dialoguePlayback.dialogueRendering.canvas, 0, 0);
577+
const images = [...this.images.values()];
578+
const draws = images.map((image) => ({ layer: image.layer, func: () => drawImage(image) }));
579+
580+
scene.push(...draws);
581+
}
582+
583+
addDialogueToScene(scene, dest, frame) {
584+
if (this.dialoguePlayback.empty)
585+
return;
586+
587+
// change default dialogue position based on avatar position
588+
const avatar = getEventById(this.data, this.avatarId);
589+
const top = avatar.position[1] >= 8;
590+
this.dialoguePlayback.options.anchorY = top ? 0 : 1;
591+
592+
// redraw dialogue and copy to display area
593+
this.dialoguePlayback.render();
594+
scene.push({ layer: 3, func: () => dest.drawImage(this.dialoguePlayback.dialogueRendering.canvas, 0, 0) });
595+
}
596+
597+
addLayersToScene(scene, dest, frame) {
598+
if (!this.ended) {
599+
this.addRoomToScene(scene, dest, frame);
600+
this.addDialogueToScene(scene, dest, frame);
601+
this.addImagesToScene(scene, dest, frame);
585602
}
603+
}
604+
605+
render(frame=undefined) {
606+
frame = frame ?? this.frameCount;
607+
608+
const scene = [];
586609

587-
fillRendering2D(TEMP_ROOM);
588-
images_above_all.forEach(drawImage);
589-
this.rendering.drawImage(TEMP_ROOM.canvas, 0, 0, 256, 256);
610+
// add visual layers to scene
611+
this.addLayersToScene(scene, this.rendering, frame);
590612

591-
if (this.ended) {
592-
fillRendering2D(this.rendering);
593-
}
613+
// sort visual layers
614+
scene.sort((a, b) => a.layer - b.layer);
615+
616+
// clear and draw layers
617+
fillRendering2D(this.rendering);
618+
scene.forEach(({ func }) => func());
594619

595620
// signal, to anyone listening, that rendering happened
596621
this.dispatchEvent(new CustomEvent("render"));

0 commit comments

Comments
 (0)