Improve map overlay rendering and raise zoom limit

pull/558/head
tobspr 4 years ago
parent c1b1564d76
commit b19b87a6c8

@ -256,10 +256,6 @@
<key type="filename">sprites/buildings/rotater.png</key>
<key type="filename">sprites/buildings/trash.png</key>
<key type="filename">sprites/misc/wires_overlay_tile.png</key>
<key type="filename">sprites/wires/pin_negative_accept.png</key>
<key type="filename">sprites/wires/pin_negative_eject.png</key>
<key type="filename">sprites/wires/pin_positive_accept.png</key>
<key type="filename">sprites/wires/pin_positive_eject.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
@ -358,19 +354,9 @@
<key type="filename">sprites/blueprints/belt_left.png</key>
<key type="filename">sprites/blueprints/belt_right.png</key>
<key type="filename">sprites/blueprints/belt_top.png</key>
<key type="filename">sprites/blueprints/wire_crossings-merger.png</key>
<key type="filename">sprites/blueprints/wire_crossings.png</key>
<key type="filename">sprites/blueprints/wire_left.png</key>
<key type="filename">sprites/blueprints/wire_right.png</key>
<key type="filename">sprites/blueprints/wire_top.png</key>
<key type="filename">sprites/buildings/belt_left.png</key>
<key type="filename">sprites/buildings/belt_right.png</key>
<key type="filename">sprites/buildings/belt_top.png</key>
<key type="filename">sprites/buildings/wire_crossings-merger.png</key>
<key type="filename">sprites/buildings/wire_crossings.png</key>
<key type="filename">sprites/buildings/wire_left.png</key>
<key type="filename">sprites/buildings/wire_right.png</key>
<key type="filename">sprites/buildings/wire_top.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
@ -385,28 +371,6 @@
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/blueprints/advanced_processor.png</key>
<key type="filename">sprites/blueprints/energy_generator.png</key>
<key type="filename">sprites/blueprints/painter-double.png</key>
<key type="filename">sprites/blueprints/trash-storage.png</key>
<key type="filename">sprites/buildings/advanced_processor.png</key>
<key type="filename">sprites/buildings/energy_generator.png</key>
<key type="filename">sprites/buildings/painter-double.png</key>
<key type="filename">sprites/misc/energy_generator_overlay.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>96,96,192,192</rect>
<key>scale9Paddings</key>
<rect>96,96,192,192</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/blueprints/cutter-quad.png</key>
<key type="filename">sprites/blueprints/painter-quad.png</key>
<key type="filename">sprites/buildings/cutter-quad.png</key>
@ -481,6 +445,23 @@
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/blueprints/painter-double.png</key>
<key type="filename">sprites/blueprints/trash-storage.png</key>
<key type="filename">sprites/buildings/painter-double.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>96,96,192,192</rect>
<key>scale9Paddings</key>
<rect>96,96,192,192</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/buildings/cutter.png</key>
<key type="filename">sprites/buildings/mixer.png</key>
<key type="filename">sprites/buildings/painter.png</key>
@ -583,27 +564,6 @@
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/wires/battery_empty.png</key>
<key type="filename">sprites/wires/battery_full.png</key>
<key type="filename">sprites/wires/battery_low.png</key>
<key type="filename">sprites/wires/battery_medium.png</key>
<key type="filename">sprites/wires/negative_energy.png</key>
<key type="filename">sprites/wires/positive_energy.png</key>
<key type="filename">sprites/wires/waste_piled.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>16,16,32,32</rect>
<key>scale9Paddings</key>
<rect>16,16,32,32</rect>
<key>scale9FromFile</key>
<false/>
</struct>
</map>
<key>fileList</key>
<array>

@ -318,7 +318,7 @@ input {
canvas {
pointer-events: all;
image-rendering: auto;
image-rendering: pixelated;
// &.smoothed {
// }
// &.unsmoothed {

@ -95,15 +95,18 @@ export class BufferMaintainer {
}
/**
*
* @param {string} key
* @param {string} subKey
* @param {function(HTMLCanvasElement, CanvasRenderingContext2D, number, number, number, object?) : void} redrawMethod
* @param {object=} additionalParams
* @param {object} param0
* @param {string} param0.key
* @param {string} param0.subKey
* @param {number} param0.w
* @param {number} param0.h
* @param {number} param0.dpi
* @param {function(HTMLCanvasElement, CanvasRenderingContext2D, number, number, number, object?) : void} param0.redrawMethod
* @param {object=} param0.additionalParams
* @returns {HTMLCanvasElement}
*
*/
getForKey(key, subKey, w, h, dpi, redrawMethod, additionalParams) {
getForKey({ key, subKey, w, h, dpi, redrawMethod, additionalParams }) {
// First, create parent key
let parent = this.cache.get(key);
if (!parent) {

@ -34,6 +34,7 @@ export const globalConfig = {
assetsDpi: 192 / 32,
assetsSharpness: 1.2,
shapesSharpness: 1.4,
mapChunkSharpness: 1.0,
// Production analytics
statisticsGraphDpi: 2.5,
@ -45,8 +46,7 @@ export const globalConfig = {
// Map
mapChunkSize: 16,
mapChunkPrerenderMinZoom: -1,
mapChunkOverviewMinZoom: 0.7,
mapChunkOverviewMinZoom: 0.9,
// Belt speeds
// NOTICE: Update webpack.production.config too!
@ -113,14 +113,12 @@ globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5
// Dynamic calculations
if (globalConfig.debug.disableMapOverview) {
globalConfig.mapChunkOverviewMinZoom = 0;
globalConfig.mapChunkPrerenderMinZoom = 0;
}
// Stuff for making the trailer
if (G_IS_DEV && globalConfig.debug.renderForTrailer) {
globalConfig.debug.framePausesBetweenTicks = 32;
// globalConfig.mapChunkOverviewMinZoom = 0.0;
// globalConfig.mapChunkPrerenderMinZoom = globalConfig.mapChunkOverviewMinZoom;
// globalConfig.debug.instantBelts = true;
// globalConfig.debug.instantProcessors = true;
// globalConfig.debug.instantMiners = true;

@ -15,8 +15,8 @@ export function getDeviceDPI() {
* @returns {number} Smoothed dpi
*/
export function smoothenDpi(dpi) {
if (dpi < 0.05) {
return 0.05;
if (dpi < 0.02) {
return 0.02;
} else if (dpi < 0.1) {
return round2Digits(dpi);
} else if (dpi < 1) {

@ -9,6 +9,29 @@ import { GameRoot } from "../root";
export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right];
const overlayMatrices = {
[enumDirection.top]: {
0: [0, 1, 0, 0, 1, 0, 0, 1, 0],
90: [0, 0, 0, 1, 1, 1, 0, 0, 0],
180: [0, 1, 0, 0, 1, 0, 0, 1, 0],
270: [0, 0, 0, 1, 1, 1, 0, 0, 0],
},
[enumDirection.left]: {
0: [0, 0, 0, 1, 1, 0, 0, 1, 0],
90: [0, 1, 0, 1, 1, 0, 0, 0, 0],
180: [0, 1, 0, 0, 1, 1, 0, 0, 0],
270: [0, 0, 0, 0, 1, 1, 0, 1, 0],
},
[enumDirection.right]: {
0: [0, 0, 0, 0, 1, 1, 0, 1, 0],
90: [0, 0, 0, 1, 1, 0, 0, 1, 0],
180: [0, 1, 0, 1, 1, 0, 0, 0, 0],
270: [0, 1, 0, 0, 1, 1, 0, 0, 0],
},
};
export class MetaBeltBaseBuilding extends MetaBuilding {
getHasDirectionLockAvailable() {
return true;
@ -44,6 +67,17 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
return true;
}
/**
*
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return overlayMatrices[entity.components.Belt.direction][rotation];
}
/**
* Creates the entity at the given location
* @param {Entity} entity

@ -11,6 +11,8 @@ import { formatItemsPerSecond } from "../../core/utils";
/** @enum {string} */
export const enumMinerVariants = { chainable: "chainable" };
const overlayMatrix = [1, 1, 1, 1, 0, 1, 1, 1, 1];
export class MetaMinerBuilding extends MetaBuilding {
constructor() {
super("miner");
@ -41,6 +43,16 @@ export class MetaMinerBuilding extends MetaBuilding {
return super.getAvailableVariants(root);
}
/**
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return overlayMatrix;
}
/**
* Creates the entity at the given location
* @param {Entity} entity

@ -25,13 +25,31 @@ export const enumUndergroundBeltVariantToTier = {
[enumUndergroundBeltVariants.tier2]: 1,
};
const overlayMatrices = [
// Sender
{
0: [1, 1, 1, 0, 1, 0, 0, 1, 0],
90: [0, 0, 0, 1, 1, 1, 0, 0, 0],
180: [0, 1, 0, 0, 1, 0, 0, 1, 0],
270: [0, 0, 0, 1, 1, 1, 0, 0, 0],
},
// Receiver
{
0: [0, 1, 0, 0, 1, 0, 1, 1, 1],
90: [0, 1, 0, 1, 1, 0, 0, 0, 0],
180: [0, 1, 0, 0, 1, 1, 0, 0, 0],
270: [0, 0, 0, 0, 1, 1, 0, 1, 0],
},
];
export class MetaUndergroundBeltBuilding extends MetaBuilding {
constructor() {
super("underground_belt");
}
getSilhouetteColor() {
return "#555";
return "#222";
}
getFlipOrientationAfterPlacement() {
@ -42,6 +60,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
return true;
}
/**
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return overlayMatrices[rotationVariant][rotation];
}
/**
* @param {GameRoot} root
* @param {string} variant

@ -349,8 +349,9 @@ export class GameCore {
// Gather context and save all state
const context = root.context;
context.save();
if (G_IS_DEV && globalConfig.debug.testClipping) {
context.clearRect(0, 0, window.innerWidth * 3, window.innerHeight * 3);
if (G_IS_DEV) {
context.fillStyle = "#a10000";
context.fillRect(0, 0, window.innerWidth * 3, window.innerHeight * 3);
}
// Compute optimal zoom level and atlas scale
@ -394,9 +395,9 @@ export class GameCore {
// -----
// BG / Map Resources / Belt Backgrounds
root.map.drawBackground(params);
if (!this.root.camera.getIsMapOverlayActive()) {
root.map.drawBackground(params);
// Underlays for splitters / balancers
systems.beltUnderlays.drawUnderlays(params);
@ -406,21 +407,21 @@ export class GameCore {
// Items being ejected / accepted currently (animations)
systems.itemEjector.draw(params);
systems.itemAcceptor.draw(params);
}
// Miner & Static map entities
root.map.drawForeground(params);
// Miner & Static map entities
root.map.drawForeground(params);
if (!this.root.camera.getIsMapOverlayActive()) {
// HUB Overlay
systems.hub.draw(params);
// Storage items
systems.storage.draw(params);
}
// Green wires overlay (not within the if because it can fade)
root.hud.parts.wiresOverlay.draw(params);
// Green wires overlay
root.hud.parts.wiresOverlay.draw(params);
} else {
root.map.drawOverlay(params);
}
if (this.root.currentLayer === enumLayer.wires && !this.root.camera.getIsMapOverlayActive()) {
// Static map entities

@ -54,14 +54,14 @@ export class ColorItem extends BaseItem {
const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel);
const key = size + "/" + dpi;
const canvas = parameters.root.buffers.getForKey(
const canvas = parameters.root.buffers.getForKey({
key,
this.color,
size,
size,
subKey: this.color,
w: size,
h: size,
dpi,
this.bufferGenerator
);
redrawMethod: this.bufferGenerator,
});
parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size);
}
/**

@ -1,6 +1,12 @@
import { MapChunk } from "./map_chunk";
import { GameRoot } from "./root";
import { GameRoot, enumLayer } from "./root";
import { DrawParameters } from "../core/draw_parameters";
import { smoothenDpi } from "../core/dpi_manager";
import { globalConfig } from "../core/config";
import { THEME } from "./theme";
import { getBuildingDataFromCode } from "./building_codes";
const CHUNK_OVERLAY_RES = 3;
export class MapChunkView extends MapChunk {
/**
@ -48,6 +54,134 @@ export class MapChunkView extends MapChunk {
systems.staticMapEntities.drawChunk(parameters, this);
}
/**
* Overlay
* @param {DrawParameters} parameters
*/
drawOverlay(parameters) {
const sprite = this.root.buffers.getForKey({
key: "chunk@" + this.root.currentLayer,
subKey: this.renderKey,
w: globalConfig.mapChunkSize * CHUNK_OVERLAY_RES,
h: globalConfig.mapChunkSize * CHUNK_OVERLAY_RES,
dpi: 1,
redrawMethod: this.generateOverlayBuffer.bind(this),
});
const dims = globalConfig.mapChunkSize * globalConfig.tileSize;
parameters.context.imageSmoothingEnabled = false;
parameters.context.drawImage(sprite, this.x * dims, this.y * dims, dims, dims);
parameters.context.imageSmoothingEnabled = true;
for (let i = 0; i < this.patches.length; ++i) {
const patch = this.patches[i];
patch.item.draw(
this.x * dims + patch.pos.x * globalConfig.tileSize,
this.y * dims + patch.pos.y * globalConfig.tileSize,
parameters,
Math.min(80, 30 / parameters.zoomLevel)
);
}
}
/**
*
* @param {HTMLCanvasElement} canvas
* @param {CanvasRenderingContext2D} context
* @param {number} w
* @param {number} h
* @param {number} dpi
*/
generateOverlayBuffer(canvas, context, w, h, dpi) {
context.fillStyle =
this.containedEntities.length > 0
? THEME.map.chunkOverview.filled
: THEME.map.chunkOverview.empty;
context.fillRect(0, 0, w, h);
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
const lowerArray = this.lowerLayer[x];
const upperArray = this.contents[x];
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
const upperContent = upperArray[y];
if (upperContent) {
const staticComp = upperContent.components.StaticMapEntity;
const data = getBuildingDataFromCode(staticComp.code);
const metaBuilding = data.metaInstance;
const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix(
staticComp.rotation,
data.rotationVariant,
data.variant,
upperContent
);
if (overlayMatrix) {
// Draw lower content first since it "shines" through
const lowerContent = lowerArray[y];
if (lowerContent) {
context.fillStyle = lowerContent.getBackgroundColorAsResource();
context.fillRect(
x * CHUNK_OVERLAY_RES,
y * CHUNK_OVERLAY_RES,
CHUNK_OVERLAY_RES,
CHUNK_OVERLAY_RES
);
}
context.fillStyle = metaBuilding.getSilhouetteColor();
for (let dx = 0; dx < 3; ++dx) {
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,
1,
1
);
}
}
}
continue;
} else {
context.fillStyle = metaBuilding.getSilhouetteColor();
context.fillRect(
x * CHUNK_OVERLAY_RES,
y * CHUNK_OVERLAY_RES,
CHUNK_OVERLAY_RES,
CHUNK_OVERLAY_RES
);
continue;
}
}
const lowerContent = lowerArray[y];
if (lowerContent) {
context.fillStyle = lowerContent.getBackgroundColorAsResource();
context.fillRect(
x * CHUNK_OVERLAY_RES,
y * CHUNK_OVERLAY_RES,
CHUNK_OVERLAY_RES,
CHUNK_OVERLAY_RES
);
}
}
}
if (this.root.currentLayer === enumLayer.wires) {
// Draw wires overlay
context.fillStyle = THEME.map.wires.overlayColor;
context.fillRect(0, 0, w, h);
}
}
/**
* Draws the wires layer
* @param {DrawParameters} parameters

@ -175,33 +175,38 @@ export class MapView extends BaseMap {
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresForegroundLayer);
}
/**
* Draws the map overlay
* @param {DrawParameters} parameters
*/
drawOverlay(parameters) {
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawOverlay);
}
/**
* Draws the map background
* @param {DrawParameters} parameters
*/
drawBackground(parameters) {
// If not using prerendered, draw background
if (parameters.zoomLevel > globalConfig.mapChunkPrerenderMinZoom) {
if (!this.cachedBackgroundPattern) {
this.cachedBackgroundPattern = parameters.context.createPattern(
this.cachedBackgroundCanvas,
"repeat"
);
}
const dpi = this.backgroundCacheDPI;
parameters.context.scale(1 / dpi, 1 / dpi);
parameters.context.fillStyle = this.cachedBackgroundPattern;
parameters.context.fillRect(
parameters.visibleRect.x * dpi,
parameters.visibleRect.y * dpi,
parameters.visibleRect.w * dpi,
parameters.visibleRect.h * dpi
if (!this.cachedBackgroundPattern) {
this.cachedBackgroundPattern = parameters.context.createPattern(
this.cachedBackgroundCanvas,
"repeat"
);
parameters.context.scale(dpi, dpi);
}
const dpi = this.backgroundCacheDPI;
parameters.context.scale(1 / dpi, 1 / dpi);
parameters.context.fillStyle = this.cachedBackgroundPattern;
parameters.context.fillRect(
parameters.visibleRect.x * dpi,
parameters.visibleRect.y * dpi,
parameters.visibleRect.w * dpi,
parameters.visibleRect.h * dpi
);
parameters.context.scale(dpi, dpi);
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawBackgroundLayer);
if (G_IS_DEV && globalConfig.debug.showChunkBorders) {

@ -54,6 +54,18 @@ export class MetaBuilding {
return false;
}
/**
* Can return a special interlaved 9 elements overlay matrix for rendering
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
* @returns {Array<number>|null}
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return null;
}
/**
* Should return additional statistics about this building
* @param {GameRoot} root

@ -289,14 +289,14 @@ export class ShapeDefinition extends BasicSerializableObject {
}
const key = size + "/" + dpi;
const canvas = parameters.root.buffers.getForKey(
const canvas = parameters.root.buffers.getForKey({
key,
this.cachedHash,
size,
size,
subKey: this.cachedHash,
w: size,
h: size,
dpi,
this.bufferGenerator
);
redrawMethod: this.bufferGenerator,
});
parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size);
}

@ -34,9 +34,7 @@
},
"wires": {
"pins": {
"energyEjector": "#c425d7"
}
"overlayColor": "rgba(97, 161, 152, 0.75)"
}
},

@ -35,9 +35,7 @@
},
"wires": {
"pins": {
"energyEjector": "#c425d7"
}
"overlayColor": "rgba(97, 161, 152, 0.75)"
}
},

@ -66,7 +66,7 @@ export class PlatformWrapperInterface {
* @returns {number}
*/
getMinimumZoom() {
return 0.2 * this.getScreenScale();
return 0.1 * this.getScreenScale();
}
/**

Loading…
Cancel
Save