mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Fix rendering bug
This commit is contained in:
parent
93f9d7ae23
commit
cda31732b1
@ -277,6 +277,11 @@
|
|||||||
<key type="filename">sprites/blueprints/underground_belt_entry.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_entry.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/virtual_processor-analyzer.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/virtual_processor-rotater.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/virtual_processor-shapecompare.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/virtual_processor.png</key>
|
||||||
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
|
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
|
||||||
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
||||||
<key type="filename">sprites/buildings/constant_signal.png</key>
|
<key type="filename">sprites/buildings/constant_signal.png</key>
|
||||||
@ -296,6 +301,11 @@
|
|||||||
<key type="filename">sprites/buildings/underground_belt_entry.png</key>
|
<key type="filename">sprites/buildings/underground_belt_entry.png</key>
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
|
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
||||||
|
<key type="filename">sprites/buildings/virtual_processor-analyzer.png</key>
|
||||||
|
<key type="filename">sprites/buildings/virtual_processor-rotater.png</key>
|
||||||
|
<key type="filename">sprites/buildings/virtual_processor-shapecompare.png</key>
|
||||||
|
<key type="filename">sprites/buildings/virtual_processor-unstacker.png</key>
|
||||||
|
<key type="filename">sprites/buildings/virtual_processor.png</key>
|
||||||
<key type="filename">sprites/buildings/wire_tunnel-coating.png</key>
|
<key type="filename">sprites/buildings/wire_tunnel-coating.png</key>
|
||||||
<key type="filename">sprites/buildings/wire_tunnel.png</key>
|
<key type="filename">sprites/buildings/wire_tunnel.png</key>
|
||||||
<key type="filename">sprites/wires/lever_on.png</key>
|
<key type="filename">sprites/wires/lever_on.png</key>
|
||||||
|
@ -1,274 +1,281 @@
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { getBuildingDataFromCode } from "./building_codes";
|
import { getBuildingDataFromCode } from "./building_codes";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
import { MapChunk } from "./map_chunk";
|
import { MapChunk } from "./map_chunk";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { THEME } from "./theme";
|
import { THEME } from "./theme";
|
||||||
import { drawSpriteClipped } from "../core/draw_utils";
|
import { drawSpriteClipped } from "../core/draw_utils";
|
||||||
|
|
||||||
export const CHUNK_OVERLAY_RES = 3;
|
export const CHUNK_OVERLAY_RES = 3;
|
||||||
|
|
||||||
export class MapChunkView extends MapChunk {
|
export class MapChunkView extends MapChunk {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @param {number} x
|
* @param {number} x
|
||||||
* @param {number} y
|
* @param {number} y
|
||||||
*/
|
*/
|
||||||
constructor(root, x, y) {
|
constructor(root, x, y) {
|
||||||
super(root, x, y);
|
super(root, x, y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whenever something changes, we increase this number - so we know we need to redraw
|
* Whenever something changes, we increase this number - so we know we need to redraw
|
||||||
*/
|
*/
|
||||||
this.renderIteration = 0;
|
this.renderIteration = 0;
|
||||||
|
|
||||||
this.markDirty();
|
this.markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks this chunk as dirty, rerendering all caches
|
* Marks this chunk as dirty, rerendering all caches
|
||||||
*/
|
*/
|
||||||
markDirty() {
|
markDirty() {
|
||||||
++this.renderIteration;
|
++this.renderIteration;
|
||||||
this.renderKey = this.x + "/" + this.y + "@" + this.renderIteration;
|
this.renderKey = this.x + "/" + this.y + "@" + this.renderIteration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the background layer
|
* Draws the background layer
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
*/
|
*/
|
||||||
drawBackgroundLayer(parameters) {
|
drawBackgroundLayer(parameters) {
|
||||||
const systems = this.root.systemMgr.systems;
|
const systems = this.root.systemMgr.systems;
|
||||||
systems.mapResources.drawChunk(parameters, this);
|
systems.mapResources.drawChunk(parameters, this);
|
||||||
systems.beltUnderlays.drawChunk(parameters, this);
|
systems.beltUnderlays.drawChunk(parameters, this);
|
||||||
systems.belt.drawChunk(parameters, this);
|
systems.belt.drawChunk(parameters, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the foreground layer
|
* Draws the dynamic foreground layer
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
*/
|
*/
|
||||||
drawForegroundLayer(parameters) {
|
drawForegroundDynamicLayer(parameters) {
|
||||||
const systems = this.root.systemMgr.systems;
|
const systems = this.root.systemMgr.systems;
|
||||||
|
|
||||||
systems.itemEjector.drawChunk(parameters, this);
|
systems.itemEjector.drawChunk(parameters, this);
|
||||||
systems.itemAcceptor.drawChunk(parameters, this);
|
systems.itemAcceptor.drawChunk(parameters, this);
|
||||||
|
systems.miner.drawChunk(parameters, this);
|
||||||
systems.miner.drawChunk(parameters, this);
|
}
|
||||||
|
|
||||||
systems.staticMapEntities.drawChunk(parameters, this);
|
/**
|
||||||
systems.lever.drawChunk(parameters, this);
|
* Draws the static foreground layer
|
||||||
systems.display.drawChunk(parameters, this);
|
* @param {DrawParameters} parameters
|
||||||
systems.storage.drawChunk(parameters, this);
|
*/
|
||||||
}
|
drawForegroundStaticLayer(parameters) {
|
||||||
|
const systems = this.root.systemMgr.systems;
|
||||||
/**
|
|
||||||
* Overlay
|
systems.staticMapEntities.drawChunk(parameters, this);
|
||||||
* @param {DrawParameters} parameters
|
systems.lever.drawChunk(parameters, this);
|
||||||
*/
|
systems.display.drawChunk(parameters, this);
|
||||||
drawOverlay(parameters) {
|
systems.storage.drawChunk(parameters, this);
|
||||||
const overlaySize = globalConfig.mapChunkSize * CHUNK_OVERLAY_RES;
|
}
|
||||||
const sprite = this.root.buffers.getForKey({
|
|
||||||
key: "chunk@" + this.root.currentLayer,
|
/**
|
||||||
subKey: this.renderKey,
|
* Overlay
|
||||||
w: overlaySize,
|
* @param {DrawParameters} parameters
|
||||||
h: overlaySize,
|
*/
|
||||||
dpi: 1,
|
drawOverlay(parameters) {
|
||||||
redrawMethod: this.generateOverlayBuffer.bind(this),
|
const overlaySize = globalConfig.mapChunkSize * CHUNK_OVERLAY_RES;
|
||||||
});
|
const sprite = this.root.buffers.getForKey({
|
||||||
|
key: "chunk@" + this.root.currentLayer,
|
||||||
const dims = globalConfig.mapChunkWorldSize;
|
subKey: this.renderKey,
|
||||||
|
w: overlaySize,
|
||||||
// Draw chunk "pixel" art
|
h: overlaySize,
|
||||||
parameters.context.imageSmoothingEnabled = false;
|
dpi: 1,
|
||||||
drawSpriteClipped({
|
redrawMethod: this.generateOverlayBuffer.bind(this),
|
||||||
parameters,
|
});
|
||||||
sprite,
|
|
||||||
x: this.x * dims,
|
const dims = globalConfig.mapChunkWorldSize;
|
||||||
y: this.y * dims,
|
|
||||||
w: dims,
|
// Draw chunk "pixel" art
|
||||||
h: dims,
|
parameters.context.imageSmoothingEnabled = false;
|
||||||
originalW: overlaySize,
|
drawSpriteClipped({
|
||||||
originalH: overlaySize,
|
parameters,
|
||||||
});
|
sprite,
|
||||||
|
x: this.x * dims,
|
||||||
parameters.context.imageSmoothingEnabled = true;
|
y: this.y * dims,
|
||||||
|
w: dims,
|
||||||
// Draw patch items
|
h: dims,
|
||||||
if (this.root.currentLayer === "regular") {
|
originalW: overlaySize,
|
||||||
for (let i = 0; i < this.patches.length; ++i) {
|
originalH: overlaySize,
|
||||||
const patch = this.patches[i];
|
});
|
||||||
|
|
||||||
const destX = this.x * dims + patch.pos.x * globalConfig.tileSize;
|
parameters.context.imageSmoothingEnabled = true;
|
||||||
const destY = this.y * dims + patch.pos.y * globalConfig.tileSize;
|
|
||||||
const diameter = Math.min(80, 30 / parameters.zoomLevel);
|
// Draw patch items
|
||||||
|
if (this.root.currentLayer === "regular") {
|
||||||
patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter);
|
for (let i = 0; i < this.patches.length; ++i) {
|
||||||
}
|
const patch = this.patches[i];
|
||||||
}
|
|
||||||
}
|
const destX = this.x * dims + patch.pos.x * globalConfig.tileSize;
|
||||||
|
const destY = this.y * dims + patch.pos.y * globalConfig.tileSize;
|
||||||
/**
|
const diameter = Math.min(80, 30 / parameters.zoomLevel);
|
||||||
*
|
|
||||||
* @param {HTMLCanvasElement} canvas
|
patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter);
|
||||||
* @param {CanvasRenderingContext2D} context
|
}
|
||||||
* @param {number} w
|
}
|
||||||
* @param {number} h
|
}
|
||||||
* @param {number} dpi
|
|
||||||
*/
|
/**
|
||||||
generateOverlayBuffer(canvas, context, w, h, dpi) {
|
*
|
||||||
context.fillStyle =
|
* @param {HTMLCanvasElement} canvas
|
||||||
this.containedEntities.length > 0
|
* @param {CanvasRenderingContext2D} context
|
||||||
? THEME.map.chunkOverview.filled
|
* @param {number} w
|
||||||
: THEME.map.chunkOverview.empty;
|
* @param {number} h
|
||||||
context.fillRect(0, 0, w, h);
|
* @param {number} dpi
|
||||||
|
*/
|
||||||
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
generateOverlayBuffer(canvas, context, w, h, dpi) {
|
||||||
const lowerArray = this.lowerLayer[x];
|
context.fillStyle =
|
||||||
const upperArray = this.contents[x];
|
this.containedEntities.length > 0
|
||||||
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
|
? THEME.map.chunkOverview.filled
|
||||||
const upperContent = upperArray[y];
|
: THEME.map.chunkOverview.empty;
|
||||||
if (upperContent) {
|
context.fillRect(0, 0, w, h);
|
||||||
const staticComp = upperContent.components.StaticMapEntity;
|
|
||||||
const data = getBuildingDataFromCode(staticComp.code);
|
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
||||||
const metaBuilding = data.metaInstance;
|
const lowerArray = this.lowerLayer[x];
|
||||||
|
const upperArray = this.contents[x];
|
||||||
const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix(
|
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
|
||||||
staticComp.rotation,
|
const upperContent = upperArray[y];
|
||||||
data.rotationVariant,
|
if (upperContent) {
|
||||||
data.variant,
|
const staticComp = upperContent.components.StaticMapEntity;
|
||||||
upperContent
|
const data = getBuildingDataFromCode(staticComp.code);
|
||||||
);
|
const metaBuilding = data.metaInstance;
|
||||||
|
|
||||||
if (overlayMatrix) {
|
const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix(
|
||||||
// Draw lower content first since it "shines" through
|
staticComp.rotation,
|
||||||
const lowerContent = lowerArray[y];
|
data.rotationVariant,
|
||||||
if (lowerContent) {
|
data.variant,
|
||||||
context.fillStyle = lowerContent.getBackgroundColorAsResource();
|
upperContent
|
||||||
context.fillRect(
|
);
|
||||||
x * CHUNK_OVERLAY_RES,
|
|
||||||
y * CHUNK_OVERLAY_RES,
|
if (overlayMatrix) {
|
||||||
CHUNK_OVERLAY_RES,
|
// Draw lower content first since it "shines" through
|
||||||
CHUNK_OVERLAY_RES
|
const lowerContent = lowerArray[y];
|
||||||
);
|
if (lowerContent) {
|
||||||
}
|
context.fillStyle = lowerContent.getBackgroundColorAsResource();
|
||||||
|
context.fillRect(
|
||||||
context.fillStyle = metaBuilding.getSilhouetteColor();
|
x * CHUNK_OVERLAY_RES,
|
||||||
for (let dx = 0; dx < 3; ++dx) {
|
y * CHUNK_OVERLAY_RES,
|
||||||
for (let dy = 0; dy < 3; ++dy) {
|
CHUNK_OVERLAY_RES,
|
||||||
const isFilled = overlayMatrix[dx + dy * 3];
|
CHUNK_OVERLAY_RES
|
||||||
if (isFilled) {
|
);
|
||||||
context.fillRect(
|
}
|
||||||
x * CHUNK_OVERLAY_RES + dx,
|
|
||||||
y * CHUNK_OVERLAY_RES + dy,
|
context.fillStyle = metaBuilding.getSilhouetteColor();
|
||||||
1,
|
for (let dx = 0; dx < 3; ++dx) {
|
||||||
1
|
for (let dy = 0; dy < 3; ++dy) {
|
||||||
);
|
const isFilled = overlayMatrix[dx + dy * 3];
|
||||||
}
|
if (isFilled) {
|
||||||
}
|
context.fillRect(
|
||||||
}
|
x * CHUNK_OVERLAY_RES + dx,
|
||||||
|
y * CHUNK_OVERLAY_RES + dy,
|
||||||
continue;
|
1,
|
||||||
} else {
|
1
|
||||||
context.fillStyle = metaBuilding.getSilhouetteColor();
|
);
|
||||||
context.fillRect(
|
}
|
||||||
x * CHUNK_OVERLAY_RES,
|
}
|
||||||
y * CHUNK_OVERLAY_RES,
|
}
|
||||||
CHUNK_OVERLAY_RES,
|
|
||||||
CHUNK_OVERLAY_RES
|
continue;
|
||||||
);
|
} else {
|
||||||
|
context.fillStyle = metaBuilding.getSilhouetteColor();
|
||||||
continue;
|
context.fillRect(
|
||||||
}
|
x * CHUNK_OVERLAY_RES,
|
||||||
}
|
y * CHUNK_OVERLAY_RES,
|
||||||
|
CHUNK_OVERLAY_RES,
|
||||||
const lowerContent = lowerArray[y];
|
CHUNK_OVERLAY_RES
|
||||||
if (lowerContent) {
|
);
|
||||||
context.fillStyle = lowerContent.getBackgroundColorAsResource();
|
|
||||||
context.fillRect(
|
continue;
|
||||||
x * CHUNK_OVERLAY_RES,
|
}
|
||||||
y * CHUNK_OVERLAY_RES,
|
}
|
||||||
CHUNK_OVERLAY_RES,
|
|
||||||
CHUNK_OVERLAY_RES
|
const lowerContent = lowerArray[y];
|
||||||
);
|
if (lowerContent) {
|
||||||
}
|
context.fillStyle = lowerContent.getBackgroundColorAsResource();
|
||||||
}
|
context.fillRect(
|
||||||
}
|
x * CHUNK_OVERLAY_RES,
|
||||||
|
y * CHUNK_OVERLAY_RES,
|
||||||
if (this.root.currentLayer === "wires") {
|
CHUNK_OVERLAY_RES,
|
||||||
// Draw wires overlay
|
CHUNK_OVERLAY_RES
|
||||||
|
);
|
||||||
context.fillStyle = THEME.map.wires.overlayColor;
|
}
|
||||||
context.fillRect(0, 0, w, h);
|
}
|
||||||
|
}
|
||||||
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
|
||||||
const wiresArray = this.wireContents[x];
|
if (this.root.currentLayer === "wires") {
|
||||||
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
|
// Draw wires overlay
|
||||||
const content = wiresArray[y];
|
|
||||||
if (!content) {
|
context.fillStyle = THEME.map.wires.overlayColor;
|
||||||
continue;
|
context.fillRect(0, 0, w, h);
|
||||||
}
|
|
||||||
MapChunkView.drawSingleWiresOverviewTile({
|
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
|
||||||
context,
|
const wiresArray = this.wireContents[x];
|
||||||
x: x * CHUNK_OVERLAY_RES,
|
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
|
||||||
y: y * CHUNK_OVERLAY_RES,
|
const content = wiresArray[y];
|
||||||
entity: content,
|
if (!content) {
|
||||||
tileSizePixels: CHUNK_OVERLAY_RES,
|
continue;
|
||||||
});
|
}
|
||||||
}
|
MapChunkView.drawSingleWiresOverviewTile({
|
||||||
}
|
context,
|
||||||
}
|
x: x * CHUNK_OVERLAY_RES,
|
||||||
}
|
y: y * CHUNK_OVERLAY_RES,
|
||||||
|
entity: content,
|
||||||
/**
|
tileSizePixels: CHUNK_OVERLAY_RES,
|
||||||
* @param {object} param0
|
});
|
||||||
* @param {CanvasRenderingContext2D} param0.context
|
}
|
||||||
* @param {number} param0.x
|
}
|
||||||
* @param {number} param0.y
|
}
|
||||||
* @param {Entity} param0.entity
|
}
|
||||||
* @param {number} param0.tileSizePixels
|
|
||||||
* @param {string=} param0.overrideColor Optionally override the color to be rendered
|
/**
|
||||||
*/
|
* @param {object} param0
|
||||||
static drawSingleWiresOverviewTile({ context, x, y, entity, tileSizePixels, overrideColor = null }) {
|
* @param {CanvasRenderingContext2D} param0.context
|
||||||
const staticComp = entity.components.StaticMapEntity;
|
* @param {number} param0.x
|
||||||
const data = getBuildingDataFromCode(staticComp.code);
|
* @param {number} param0.y
|
||||||
const metaBuilding = data.metaInstance;
|
* @param {Entity} param0.entity
|
||||||
const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix(
|
* @param {number} param0.tileSizePixels
|
||||||
staticComp.rotation,
|
* @param {string=} param0.overrideColor Optionally override the color to be rendered
|
||||||
data.rotationVariant,
|
*/
|
||||||
data.variant,
|
static drawSingleWiresOverviewTile({ context, x, y, entity, tileSizePixels, overrideColor = null }) {
|
||||||
entity
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
);
|
const data = getBuildingDataFromCode(staticComp.code);
|
||||||
context.fillStyle = overrideColor || metaBuilding.getSilhouetteColor();
|
const metaBuilding = data.metaInstance;
|
||||||
if (overlayMatrix) {
|
const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix(
|
||||||
for (let dx = 0; dx < 3; ++dx) {
|
staticComp.rotation,
|
||||||
for (let dy = 0; dy < 3; ++dy) {
|
data.rotationVariant,
|
||||||
const isFilled = overlayMatrix[dx + dy * 3];
|
data.variant,
|
||||||
if (isFilled) {
|
entity
|
||||||
context.fillRect(
|
);
|
||||||
x + (dx * tileSizePixels) / CHUNK_OVERLAY_RES,
|
context.fillStyle = overrideColor || metaBuilding.getSilhouetteColor();
|
||||||
y + (dy * tileSizePixels) / CHUNK_OVERLAY_RES,
|
if (overlayMatrix) {
|
||||||
tileSizePixels / CHUNK_OVERLAY_RES,
|
for (let dx = 0; dx < 3; ++dx) {
|
||||||
tileSizePixels / CHUNK_OVERLAY_RES
|
for (let dy = 0; dy < 3; ++dy) {
|
||||||
);
|
const isFilled = overlayMatrix[dx + dy * 3];
|
||||||
}
|
if (isFilled) {
|
||||||
}
|
context.fillRect(
|
||||||
}
|
x + (dx * tileSizePixels) / CHUNK_OVERLAY_RES,
|
||||||
} else {
|
y + (dy * tileSizePixels) / CHUNK_OVERLAY_RES,
|
||||||
context.fillRect(x, y, tileSizePixels, tileSizePixels);
|
tileSizePixels / CHUNK_OVERLAY_RES,
|
||||||
}
|
tileSizePixels / CHUNK_OVERLAY_RES
|
||||||
}
|
);
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* Draws the wires layer
|
}
|
||||||
* @param {DrawParameters} parameters
|
} else {
|
||||||
*/
|
context.fillRect(x, y, tileSizePixels, tileSizePixels);
|
||||||
drawWiresForegroundLayer(parameters) {
|
}
|
||||||
const systems = this.root.systemMgr.systems;
|
}
|
||||||
systems.wire.drawChunk(parameters, this);
|
|
||||||
systems.staticMapEntities.drawWiresChunk(parameters, this);
|
/**
|
||||||
systems.wiredPins.drawChunk(parameters, this);
|
* Draws the wires layer
|
||||||
}
|
* @param {DrawParameters} parameters
|
||||||
}
|
*/
|
||||||
|
drawWiresForegroundLayer(parameters) {
|
||||||
|
const systems = this.root.systemMgr.systems;
|
||||||
|
systems.wire.drawChunk(parameters, this);
|
||||||
|
systems.staticMapEntities.drawWiresChunk(parameters, this);
|
||||||
|
systems.wiredPins.drawChunk(parameters, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,252 +1,253 @@
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { BaseMap } from "./map";
|
import { BaseMap } from "./map";
|
||||||
import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils";
|
import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
import { THEME } from "./theme";
|
import { THEME } from "./theme";
|
||||||
import { MapChunkView } from "./map_chunk_view";
|
import { MapChunkView } from "./map_chunk_view";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the view of the map, it extends the map which is the raw model and allows
|
* This is the view of the map, it extends the map which is the raw model and allows
|
||||||
* to draw it
|
* to draw it
|
||||||
*/
|
*/
|
||||||
export class MapView extends BaseMap {
|
export class MapView extends BaseMap {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root);
|
super(root);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DPI of the background cache images, required in some places
|
* DPI of the background cache images, required in some places
|
||||||
*/
|
*/
|
||||||
this.backgroundCacheDPI = 2;
|
this.backgroundCacheDPI = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cached background sprite, containing the flat background
|
* The cached background sprite, containing the flat background
|
||||||
* @type {HTMLCanvasElement} */
|
* @type {HTMLCanvasElement} */
|
||||||
this.cachedBackgroundCanvas = null;
|
this.cachedBackgroundCanvas = null;
|
||||||
|
|
||||||
/** @type {CanvasRenderingContext2D} */
|
/** @type {CanvasRenderingContext2D} */
|
||||||
this.cachedBackgroundContext = null;
|
this.cachedBackgroundContext = null;
|
||||||
/**
|
/**
|
||||||
* Cached pattern of the stripes background
|
* Cached pattern of the stripes background
|
||||||
* @type {CanvasPattern} */
|
* @type {CanvasPattern} */
|
||||||
this.cachedBackgroundPattern = null;
|
this.cachedBackgroundPattern = null;
|
||||||
|
|
||||||
this.internalInitializeCachedBackgroundCanvases();
|
this.internalInitializeCachedBackgroundCanvases();
|
||||||
this.root.signals.aboutToDestruct.add(this.cleanup, this);
|
this.root.signals.aboutToDestruct.add(this.cleanup, this);
|
||||||
|
|
||||||
this.root.signals.entityAdded.add(this.onEntityChanged, this);
|
this.root.signals.entityAdded.add(this.onEntityChanged, this);
|
||||||
this.root.signals.entityDestroyed.add(this.onEntityChanged, this);
|
this.root.signals.entityDestroyed.add(this.onEntityChanged, this);
|
||||||
this.root.signals.entityChanged.add(this.onEntityChanged, this);
|
this.root.signals.entityChanged.add(this.onEntityChanged, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
freeCanvas(this.cachedBackgroundCanvas);
|
freeCanvas(this.cachedBackgroundCanvas);
|
||||||
this.cachedBackgroundCanvas = null;
|
this.cachedBackgroundCanvas = null;
|
||||||
this.cachedBackgroundPattern = null;
|
this.cachedBackgroundPattern = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an entity was added, removed or changed
|
* Called when an entity was added, removed or changed
|
||||||
* @param {Entity} entity
|
* @param {Entity} entity
|
||||||
*/
|
*/
|
||||||
onEntityChanged(entity) {
|
onEntityChanged(entity) {
|
||||||
const staticComp = entity.components.StaticMapEntity;
|
const staticComp = entity.components.StaticMapEntity;
|
||||||
if (staticComp) {
|
if (staticComp) {
|
||||||
const rect = staticComp.getTileSpaceBounds();
|
const rect = staticComp.getTileSpaceBounds();
|
||||||
for (let x = rect.x; x <= rect.right(); ++x) {
|
for (let x = rect.x; x <= rect.right(); ++x) {
|
||||||
for (let y = rect.y; y <= rect.bottom(); ++y) {
|
for (let y = rect.y; y <= rect.bottom(); ++y) {
|
||||||
this.root.map.getOrCreateChunkAtTile(x, y).markDirty();
|
this.root.map.getOrCreateChunkAtTile(x, y).markDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws all static entities like buildings etc.
|
* Draws all static entities like buildings etc.
|
||||||
* @param {DrawParameters} drawParameters
|
* @param {DrawParameters} drawParameters
|
||||||
*/
|
*/
|
||||||
drawStaticEntityDebugOverlays(drawParameters) {
|
drawStaticEntityDebugOverlays(drawParameters) {
|
||||||
const cullRange = drawParameters.visibleRect.toTileCullRectangle();
|
const cullRange = drawParameters.visibleRect.toTileCullRectangle();
|
||||||
const top = cullRange.top();
|
const top = cullRange.top();
|
||||||
const right = cullRange.right();
|
const right = cullRange.right();
|
||||||
const bottom = cullRange.bottom();
|
const bottom = cullRange.bottom();
|
||||||
const left = cullRange.left();
|
const left = cullRange.left();
|
||||||
|
|
||||||
const border = 1;
|
const border = 1;
|
||||||
|
|
||||||
const minY = top - border;
|
const minY = top - border;
|
||||||
const maxY = bottom + border;
|
const maxY = bottom + border;
|
||||||
const minX = left - border;
|
const minX = left - border;
|
||||||
const maxX = right + border - 1;
|
const maxX = right + border - 1;
|
||||||
|
|
||||||
// Render y from top down for proper blending
|
// Render y from top down for proper blending
|
||||||
for (let y = minY; y <= maxY; ++y) {
|
for (let y = minY; y <= maxY; ++y) {
|
||||||
for (let x = minX; x <= maxX; ++x) {
|
for (let x = minX; x <= maxX; ++x) {
|
||||||
// const content = this.tiles[x][y];
|
// const content = this.tiles[x][y];
|
||||||
const chunk = this.getChunkAtTileOrNull(x, y);
|
const chunk = this.getChunkAtTileOrNull(x, y);
|
||||||
if (!chunk) {
|
if (!chunk) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const content = chunk.getTileContentFromWorldCoords(x, y);
|
const content = chunk.getTileContentFromWorldCoords(x, y);
|
||||||
if (content) {
|
if (content) {
|
||||||
let isBorder = x <= left - 1 || x >= right + 1 || y <= top - 1 || y >= bottom + 1;
|
let isBorder = x <= left - 1 || x >= right + 1 || y <= top - 1 || y >= bottom + 1;
|
||||||
if (!isBorder) {
|
if (!isBorder) {
|
||||||
content.drawDebugOverlays(drawParameters);
|
content.drawDebugOverlays(drawParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all canvases used for background rendering
|
* Initializes all canvases used for background rendering
|
||||||
*/
|
*/
|
||||||
internalInitializeCachedBackgroundCanvases() {
|
internalInitializeCachedBackgroundCanvases() {
|
||||||
// Background canvas
|
// Background canvas
|
||||||
const dims = globalConfig.tileSize;
|
const dims = globalConfig.tileSize;
|
||||||
const dpi = this.backgroundCacheDPI;
|
const dpi = this.backgroundCacheDPI;
|
||||||
const [canvas, context] = makeOffscreenBuffer(dims * dpi, dims * dpi, {
|
const [canvas, context] = makeOffscreenBuffer(dims * dpi, dims * dpi, {
|
||||||
smooth: false,
|
smooth: false,
|
||||||
label: "map-cached-bg",
|
label: "map-cached-bg",
|
||||||
});
|
});
|
||||||
context.scale(dpi, dpi);
|
context.scale(dpi, dpi);
|
||||||
|
|
||||||
context.fillStyle = THEME.map.background;
|
context.fillStyle = THEME.map.background;
|
||||||
context.fillRect(0, 0, dims, dims);
|
context.fillRect(0, 0, dims, dims);
|
||||||
|
|
||||||
const borderWidth = THEME.map.gridLineWidth;
|
const borderWidth = THEME.map.gridLineWidth;
|
||||||
context.fillStyle = THEME.map.grid;
|
context.fillStyle = THEME.map.grid;
|
||||||
context.fillRect(0, 0, dims, borderWidth);
|
context.fillRect(0, 0, dims, borderWidth);
|
||||||
context.fillRect(0, borderWidth, borderWidth, dims);
|
context.fillRect(0, borderWidth, borderWidth, dims);
|
||||||
|
|
||||||
context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth);
|
context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth);
|
||||||
context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth);
|
context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth);
|
||||||
|
|
||||||
this.cachedBackgroundCanvas = canvas;
|
this.cachedBackgroundCanvas = canvas;
|
||||||
this.cachedBackgroundContext = context;
|
this.cachedBackgroundContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the maps foreground
|
* Draws the maps foreground
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
*/
|
*/
|
||||||
drawForeground(parameters) {
|
drawForeground(parameters) {
|
||||||
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawForegroundLayer);
|
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawForegroundDynamicLayer);
|
||||||
}
|
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawForegroundStaticLayer);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Calls a given method on all given chunks
|
/**
|
||||||
* @param {DrawParameters} parameters
|
* Calls a given method on all given chunks
|
||||||
* @param {function} method
|
* @param {DrawParameters} parameters
|
||||||
*/
|
* @param {function} method
|
||||||
drawVisibleChunks(parameters, method) {
|
*/
|
||||||
const cullRange = parameters.visibleRect.allScaled(1 / globalConfig.tileSize);
|
drawVisibleChunks(parameters, method) {
|
||||||
const top = cullRange.top();
|
const cullRange = parameters.visibleRect.allScaled(1 / globalConfig.tileSize);
|
||||||
const right = cullRange.right();
|
const top = cullRange.top();
|
||||||
const bottom = cullRange.bottom();
|
const right = cullRange.right();
|
||||||
const left = cullRange.left();
|
const bottom = cullRange.bottom();
|
||||||
|
const left = cullRange.left();
|
||||||
const border = 0;
|
|
||||||
const minY = top - border;
|
const border = 0;
|
||||||
const maxY = bottom + border;
|
const minY = top - border;
|
||||||
const minX = left - border;
|
const maxY = bottom + border;
|
||||||
const maxX = right + border;
|
const minX = left - border;
|
||||||
|
const maxX = right + border;
|
||||||
const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize);
|
|
||||||
const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize);
|
const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize);
|
||||||
|
const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize);
|
||||||
const chunkEndX = Math.floor(maxX / globalConfig.mapChunkSize);
|
|
||||||
const chunkEndY = Math.floor(maxY / globalConfig.mapChunkSize);
|
const chunkEndX = Math.floor(maxX / globalConfig.mapChunkSize);
|
||||||
|
const chunkEndY = Math.floor(maxY / globalConfig.mapChunkSize);
|
||||||
// Render y from top down for proper blending
|
|
||||||
for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) {
|
// Render y from top down for proper blending
|
||||||
for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) {
|
for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) {
|
||||||
const chunk = this.root.map.getChunk(chunkX, chunkY, true);
|
for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) {
|
||||||
method.call(chunk, parameters);
|
const chunk = this.root.map.getChunk(chunkX, chunkY, true);
|
||||||
}
|
method.call(chunk, parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Draws the wires foreground
|
/**
|
||||||
* @param {DrawParameters} parameters
|
* Draws the wires foreground
|
||||||
*/
|
* @param {DrawParameters} parameters
|
||||||
drawWiresForegroundLayer(parameters) {
|
*/
|
||||||
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresForegroundLayer);
|
drawWiresForegroundLayer(parameters) {
|
||||||
}
|
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresForegroundLayer);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Draws the map overlay
|
/**
|
||||||
* @param {DrawParameters} parameters
|
* Draws the map overlay
|
||||||
*/
|
* @param {DrawParameters} parameters
|
||||||
drawOverlay(parameters) {
|
*/
|
||||||
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawOverlay);
|
drawOverlay(parameters) {
|
||||||
}
|
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawOverlay);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Draws the map background
|
/**
|
||||||
* @param {DrawParameters} parameters
|
* Draws the map background
|
||||||
*/
|
* @param {DrawParameters} parameters
|
||||||
drawBackground(parameters) {
|
*/
|
||||||
if (!this.cachedBackgroundPattern) {
|
drawBackground(parameters) {
|
||||||
this.cachedBackgroundPattern = parameters.context.createPattern(
|
if (!this.cachedBackgroundPattern) {
|
||||||
this.cachedBackgroundCanvas,
|
this.cachedBackgroundPattern = parameters.context.createPattern(
|
||||||
"repeat"
|
this.cachedBackgroundCanvas,
|
||||||
);
|
"repeat"
|
||||||
}
|
);
|
||||||
|
}
|
||||||
if (!this.root.app.settings.getAllSettings().disableTileGrid) {
|
|
||||||
const dpi = this.backgroundCacheDPI;
|
if (!this.root.app.settings.getAllSettings().disableTileGrid) {
|
||||||
parameters.context.scale(1 / dpi, 1 / dpi);
|
const dpi = this.backgroundCacheDPI;
|
||||||
|
parameters.context.scale(1 / dpi, 1 / dpi);
|
||||||
parameters.context.fillStyle = this.cachedBackgroundPattern;
|
|
||||||
parameters.context.fillRect(
|
parameters.context.fillStyle = this.cachedBackgroundPattern;
|
||||||
parameters.visibleRect.x * dpi,
|
parameters.context.fillRect(
|
||||||
parameters.visibleRect.y * dpi,
|
parameters.visibleRect.x * dpi,
|
||||||
parameters.visibleRect.w * dpi,
|
parameters.visibleRect.y * dpi,
|
||||||
parameters.visibleRect.h * dpi
|
parameters.visibleRect.w * dpi,
|
||||||
);
|
parameters.visibleRect.h * dpi
|
||||||
parameters.context.scale(dpi, dpi);
|
);
|
||||||
}
|
parameters.context.scale(dpi, dpi);
|
||||||
|
}
|
||||||
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawBackgroundLayer);
|
|
||||||
|
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawBackgroundLayer);
|
||||||
if (G_IS_DEV && globalConfig.debug.showChunkBorders) {
|
|
||||||
const cullRange = parameters.visibleRect.toTileCullRectangle();
|
if (G_IS_DEV && globalConfig.debug.showChunkBorders) {
|
||||||
const top = cullRange.top();
|
const cullRange = parameters.visibleRect.toTileCullRectangle();
|
||||||
const right = cullRange.right();
|
const top = cullRange.top();
|
||||||
const bottom = cullRange.bottom();
|
const right = cullRange.right();
|
||||||
const left = cullRange.left();
|
const bottom = cullRange.bottom();
|
||||||
|
const left = cullRange.left();
|
||||||
const border = 1;
|
|
||||||
const minY = top - border;
|
const border = 1;
|
||||||
const maxY = bottom + border;
|
const minY = top - border;
|
||||||
const minX = left - border;
|
const maxY = bottom + border;
|
||||||
const maxX = right + border - 1;
|
const minX = left - border;
|
||||||
|
const maxX = right + border - 1;
|
||||||
const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize);
|
|
||||||
const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize);
|
const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize);
|
||||||
|
const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize);
|
||||||
const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize);
|
|
||||||
const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize);
|
const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize);
|
||||||
|
const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize);
|
||||||
for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) {
|
|
||||||
for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) {
|
for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) {
|
||||||
parameters.context.fillStyle = "#ffaaaa";
|
for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) {
|
||||||
parameters.context.fillRect(
|
parameters.context.fillStyle = "#ffaaaa";
|
||||||
chunkX * globalConfig.mapChunkWorldSize,
|
parameters.context.fillRect(
|
||||||
chunkY * globalConfig.mapChunkWorldSize,
|
chunkX * globalConfig.mapChunkWorldSize,
|
||||||
globalConfig.mapChunkWorldSize,
|
chunkY * globalConfig.mapChunkWorldSize,
|
||||||
3
|
globalConfig.mapChunkWorldSize,
|
||||||
);
|
3
|
||||||
parameters.context.fillRect(
|
);
|
||||||
chunkX * globalConfig.mapChunkWorldSize,
|
parameters.context.fillRect(
|
||||||
chunkY * globalConfig.mapChunkWorldSize,
|
chunkX * globalConfig.mapChunkWorldSize,
|
||||||
3,
|
chunkY * globalConfig.mapChunkWorldSize,
|
||||||
globalConfig.mapChunkWorldSize
|
3,
|
||||||
);
|
globalConfig.mapChunkWorldSize
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user