diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps index 8b4691d0..6d6d972e 100644 --- a/res_raw/atlas.tps +++ b/res_raw/atlas.tps @@ -256,10 +256,6 @@ sprites/buildings/rotater.png sprites/buildings/trash.png sprites/misc/wires_overlay_tile.png - sprites/wires/pin_negative_accept.png - sprites/wires/pin_negative_eject.png - sprites/wires/pin_positive_accept.png - sprites/wires/pin_positive_eject.png pivotPoint 0.5,0.5 @@ -358,19 +354,9 @@ sprites/blueprints/belt_left.png sprites/blueprints/belt_right.png sprites/blueprints/belt_top.png - sprites/blueprints/wire_crossings-merger.png - sprites/blueprints/wire_crossings.png - sprites/blueprints/wire_left.png - sprites/blueprints/wire_right.png - sprites/blueprints/wire_top.png sprites/buildings/belt_left.png sprites/buildings/belt_right.png sprites/buildings/belt_top.png - sprites/buildings/wire_crossings-merger.png - sprites/buildings/wire_crossings.png - sprites/buildings/wire_left.png - sprites/buildings/wire_right.png - sprites/buildings/wire_top.png pivotPoint 0.5,0.5 @@ -385,28 +371,6 @@ scale9FromFile - sprites/blueprints/advanced_processor.png - sprites/blueprints/energy_generator.png - sprites/blueprints/painter-double.png - sprites/blueprints/trash-storage.png - sprites/buildings/advanced_processor.png - sprites/buildings/energy_generator.png - sprites/buildings/painter-double.png - sprites/misc/energy_generator_overlay.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 96,96,192,192 - scale9Paddings - 96,96,192,192 - scale9FromFile - - sprites/blueprints/cutter-quad.png sprites/blueprints/painter-quad.png sprites/buildings/cutter-quad.png @@ -481,6 +445,23 @@ scale9FromFile + sprites/blueprints/painter-double.png + sprites/blueprints/trash-storage.png + sprites/buildings/painter-double.png + + pivotPoint + 0.5,0.5 + spriteScale + 1 + scale9Enabled + + scale9Borders + 96,96,192,192 + scale9Paddings + 96,96,192,192 + scale9FromFile + + sprites/buildings/cutter.png sprites/buildings/mixer.png sprites/buildings/painter.png @@ -583,27 +564,6 @@ scale9FromFile - sprites/wires/battery_empty.png - sprites/wires/battery_full.png - sprites/wires/battery_low.png - sprites/wires/battery_medium.png - sprites/wires/negative_energy.png - sprites/wires/positive_energy.png - sprites/wires/waste_piled.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 16,16,32,32 - scale9Paddings - 16,16,32,32 - scale9FromFile - - fileList diff --git a/src/css/common.scss b/src/css/common.scss index 5f599716..b8f02d40 100644 --- a/src/css/common.scss +++ b/src/css/common.scss @@ -318,7 +318,7 @@ input { canvas { pointer-events: all; - image-rendering: auto; + image-rendering: pixelated; // &.smoothed { // } // &.unsmoothed { diff --git a/src/js/core/buffer_maintainer.js b/src/js/core/buffer_maintainer.js index c92a92a5..c28c0ee5 100644 --- a/src/js/core/buffer_maintainer.js +++ b/src/js/core/buffer_maintainer.js @@ -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) { diff --git a/src/js/core/config.js b/src/js/core/config.js index 8f0f02e1..bdb73727 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -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; diff --git a/src/js/core/dpi_manager.js b/src/js/core/dpi_manager.js index 0388c5f9..b944d155 100644 --- a/src/js/core/dpi_manager.js +++ b/src/js/core/dpi_manager.js @@ -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) { diff --git a/src/js/game/buildings/belt_base.js b/src/js/game/buildings/belt_base.js index 7727a996..322c345e 100644 --- a/src/js/game/buildings/belt_base.js +++ b/src/js/game/buildings/belt_base.js @@ -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 diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index 17fccf46..1a9c97ff 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -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 diff --git a/src/js/game/buildings/underground_belt.js b/src/js/game/buildings/underground_belt.js index 2c4f6a1d..498b19a0 100644 --- a/src/js/game/buildings/underground_belt.js +++ b/src/js/game/buildings/underground_belt.js @@ -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 diff --git a/src/js/game/core.js b/src/js/game/core.js index 9ca99a8e..cf8fb19d 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -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 diff --git a/src/js/game/items/color_item.js b/src/js/game/items/color_item.js index d1b9a217..61dcfaf1 100644 --- a/src/js/game/items/color_item.js +++ b/src/js/game/items/color_item.js @@ -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); } /** diff --git a/src/js/game/map_chunk_view.js b/src/js/game/map_chunk_view.js index 80ffa12e..3b9f61a1 100644 --- a/src/js/game/map_chunk_view.js +++ b/src/js/game/map_chunk_view.js @@ -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 diff --git a/src/js/game/map_view.js b/src/js/game/map_view.js index f7b9a7b3..62039468 100644 --- a/src/js/game/map_view.js +++ b/src/js/game/map_view.js @@ -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) { diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index 08754cff..27c911b1 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -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|null} + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return null; + } + /** * Should return additional statistics about this building * @param {GameRoot} root diff --git a/src/js/game/shape_definition.js b/src/js/game/shape_definition.js index 8da82d80..a016d23e 100644 --- a/src/js/game/shape_definition.js +++ b/src/js/game/shape_definition.js @@ -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); } diff --git a/src/js/game/themes/dark.json b/src/js/game/themes/dark.json index 626efa19..85b29617 100644 --- a/src/js/game/themes/dark.json +++ b/src/js/game/themes/dark.json @@ -34,9 +34,7 @@ }, "wires": { - "pins": { - "energyEjector": "#c425d7" - } + "overlayColor": "rgba(97, 161, 152, 0.75)" } }, diff --git a/src/js/game/themes/light.json b/src/js/game/themes/light.json index 21599585..2bc7050a 100644 --- a/src/js/game/themes/light.json +++ b/src/js/game/themes/light.json @@ -35,9 +35,7 @@ }, "wires": { - "pins": { - "energyEjector": "#c425d7" - } + "overlayColor": "rgba(97, 161, 152, 0.75)" } }, diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js index 9fee5b3a..5754a8a2 100644 --- a/src/js/platform/wrapper.js +++ b/src/js/platform/wrapper.js @@ -66,7 +66,7 @@ export class PlatformWrapperInterface { * @returns {number} */ getMinimumZoom() { - return 0.2 * this.getScreenScale(); + return 0.1 * this.getScreenScale(); } /**