diff --git a/.vscode/settings.json b/.vscode/settings.json index 335f886a..c476e951 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.rulers": [ + 110 + ], } \ No newline at end of file diff --git a/src/js/game/buildings/counter.js b/src/js/game/buildings/counter.js index ce2c2f6a..da7fdb21 100644 --- a/src/js/game/buildings/counter.js +++ b/src/js/game/buildings/counter.js @@ -14,8 +14,11 @@ export class MetaCounterBuilding extends MetaBuilding { super("counter"); } + /** + * @returns {string} Colour used to represent this building when zoomed out. + */ getSilhouetteColor() { - return "#7dc6cd"; + return "#444e81"; // Dark Blue } /** @@ -24,15 +27,19 @@ export class MetaCounterBuilding extends MetaBuilding { * @returns {Array<[string, string]>} */ getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getBeltBaseSpeed(); + const speed = root.hubGoals.getBeltBaseSpeed("regular"); return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; } /** + * The counter is unlocked once the belt speed reaches 20 (items/s). This is around the time when items on + * a belt begin to blurr. It is also late enough in the game that a player would understand and appreciate + * this building. * @param {GameRoot} root */ getIsUnlocked(root) { - return true; //root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater); + const beltSpeed = root.hubGoals.getBeltBaseSpeed("regular"); + return beltSpeed >= 20; } /** @@ -53,7 +60,6 @@ export class MetaCounterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, }, ], }) diff --git a/src/js/game/component_registry.js b/src/js/game/component_registry.js index 5a019923..c18ef379 100644 --- a/src/js/game/component_registry.js +++ b/src/js/game/component_registry.js @@ -39,7 +39,7 @@ export function initComponentRegistry() { assert( // @ts-ignore require.context("./components", false, /.*\.js/i).keys().length === - gComponentRegistry.getNumEntries(), + gComponentRegistry.getNumEntries(), "Not all components are registered" ); diff --git a/src/js/game/components/counter.js b/src/js/game/components/counter.js index a0148179..32fa223b 100644 --- a/src/js/game/components/counter.js +++ b/src/js/game/components/counter.js @@ -1,3 +1,8 @@ +/** @typedef {object} TickCount + * @property {number} gameTimeSeconds + * @property {number} count + */ + import { types } from "../../savegame/serialization"; import { Component } from "../component"; import { BaseItem } from "../base_item"; @@ -33,22 +38,24 @@ export class ItemCounterComponent extends Component { */ this.inputSlots = []; + /** @type {number} a count of items that have passed through the component since the last tick */ this.currentCount = 0; - this.lastResetTime = 0; - - /** @typedef {object} TickCount - * @property {number} gameTimeSeconds - * @property {number} count + /** + * Maintained every game tick, this aray contains the item counts for every tick in the past 1 second. + * @type {TickCount[]} */ - /** @type {TickCount[]} */ this.tickHistory = []; + /** @type {number} Calculated and set every second. This is a read only property. */ this.averageItemsPerSecond = 0; + + /** @type {number} - Last time the averageItemsPerSecond property was reset. */ + this.lastResetTime = 0; } /** - * Called every time an item leaves the counter + * Called every time an item leaves the counter building */ countNewItem() { this.currentCount++; @@ -60,6 +67,7 @@ export class ItemCounterComponent extends Component { */ tick(gameTime) { const count = this.currentCount; + // Reset the count this.currentCount = 0; this.tickHistory.push({ @@ -68,6 +76,8 @@ export class ItemCounterComponent extends Component { }); // Only keep history for the last second. + // TODO: Possible optimisation to replace with a for loop. Unsure if the logic within the loop will + // counteract any speed gained by not using .filter this.tickHistory = this.tickHistory.filter(tick => gameTime.timeSeconds - tick.gameTimeSeconds <= 1); const delta = gameTime.timeSeconds - this.lastResetTime; diff --git a/src/js/game/core.js b/src/js/game/core.js index ef3387de..b4bf8c2b 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -424,6 +424,7 @@ export class GameCore { // Energy consumer (Battery icons) systems.energyConsumer.draw(params); + // Items per second overlay systems.counter.draw(params); } diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index 41df709b..00e5ba7d 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -4,7 +4,6 @@ import { MetaEnergyGenerator } from "../../buildings/energy_generator"; import { MetaMinerBuilding } from "../../buildings/miner"; import { MetaMixerBuilding } from "../../buildings/mixer"; import { MetaPainterBuilding } from "../../buildings/painter"; -import { MetaCounterBuilding } from "../../buildings/counter"; import { MetaRotaterBuilding } from "../../buildings/rotater"; import { MetaSplitterBuilding } from "../../buildings/splitter"; import { MetaStackerBuilding } from "../../buildings/stacker"; @@ -13,6 +12,7 @@ import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; import { enumLayer } from "../../root"; import { HUDBaseToolbar } from "./base_toolbar"; import { MetaAdvancedProcessorBuilding } from "../../buildings/advanced_processor"; +import { MetaCounterBuilding } from "../../buildings/counter"; const supportedBuildings = [ MetaBeltBaseBuilding, @@ -20,12 +20,12 @@ const supportedBuildings = [ MetaUndergroundBeltBuilding, MetaMinerBuilding, MetaCutterBuilding, - MetaCounterBuilding, MetaRotaterBuilding, MetaStackerBuilding, MetaMixerBuilding, MetaPainterBuilding, MetaTrashBuilding, + MetaCounterBuilding, MetaEnergyGenerator, MetaAdvancedProcessorBuilding, diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 090d6066..67101a80 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -49,7 +49,6 @@ export const KEYMAPPINGS = { underground_belt: { keyCode: key("3") }, miner: { keyCode: key("4") }, cutter: { keyCode: key("5") }, - counter: { keyCode: key("~") }, rotater: { keyCode: key("6") }, stacker: { keyCode: key("7") }, mixer: { keyCode: key("8") }, @@ -57,6 +56,7 @@ export const KEYMAPPINGS = { trash: { keyCode: key("0") }, energy_generator: { keyCode: key("O") }, advanced_processor: { keyCode: key("P") }, + counter: { keyCode: key("J") }, // Wires layer wire: { keyCode: key("1") }, diff --git a/src/js/game/systems/counter.js b/src/js/game/systems/counter.js index 8c866d16..a238efec 100644 --- a/src/js/game/systems/counter.js +++ b/src/js/game/systems/counter.js @@ -3,13 +3,11 @@ import { ItemCounterComponent } from "../components/counter"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { ShapeItem } from "../items/shape_item"; -import { Loader } from "../../core/loader"; +import { ColorItem } from "../items/color_item"; export class CounterSystem extends GameSystemWithFilter { constructor(root) { super(root, [ItemCounterComponent]); - - this.storageOverlaySprite = Loader.getSprite("sprites/misc/storage_overlay.png"); } update() { @@ -23,8 +21,7 @@ export class CounterSystem extends GameSystemWithFilter { let outItem = null; if (items.length > 0) { - const inputItem = /** @type {ShapeItem} */ (items[0].item); - assert(inputItem instanceof ShapeItem, "Input for counting is not a shape"); + const inputItem = /** @type {ShapeItem|ColorItem} */ (items[0].item); outItem = inputItem; let slot = ejectorComp.getFirstFreeSlot(entity.layer); @@ -43,6 +40,7 @@ export class CounterSystem extends GameSystemWithFilter { } } + // Only render the items/s overlay if the entity is on screen draw(parameters) { this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); } @@ -67,7 +65,7 @@ export class CounterSystem extends GameSystemWithFilter { context.font = "bold 8.5px GameFont"; context.textAlign = "center"; context.fillStyle = "#64666e"; - context.fillText(counterComp.averageItemsPerSecond, center.x, center.y + 3); + context.fillText(counterComp.averageItemsPerSecond.toString(), center.x, center.y + 3); context.textAlign = "left"; context.globalAlpha = 1; diff --git a/src/js/game/systems/item_ejector.js b/src/js/game/systems/item_ejector.js index 97a45749..6cb7b925 100644 --- a/src/js/game/systems/item_ejector.js +++ b/src/js/game/systems/item_ejector.js @@ -219,9 +219,9 @@ export class ItemEjectorSystem extends GameSystemWithFilter { sourceSlot.progress = Math.min( 1, sourceSlot.progress + - progressGrowth * - this.root.hubGoals.getBeltBaseSpeed(sourceSlot.layer) * - globalConfig.beltItemSpacingByLayer[sourceSlot.layer] + progressGrowth * + this.root.hubGoals.getBeltBaseSpeed(sourceSlot.layer) * + globalConfig.beltItemSpacingByLayer[sourceSlot.layer] ); // Check if we are still in the process of ejecting, can't proceed then diff --git a/translations/base-en.yaml b/translations/base-en.yaml index f3bab4f1..010ddfde 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -507,7 +507,7 @@ buildings: counter: default: name: &counter Counter - description: COUNTER + description: Displays a count of items that passed by in the last second. stacker: default: