diff --git a/artwork/itch.io/background.png b/artwork/itch.io/background.png deleted file mode 100644 index 674b7fab..00000000 Binary files a/artwork/itch.io/background.png and /dev/null differ diff --git a/artwork/itch.io/banner.png b/artwork/itch.io/banner.png index 05f4cfe3..17488ee2 100644 Binary files a/artwork/itch.io/banner.png and b/artwork/itch.io/banner.png differ diff --git a/artwork/itch.io/banner.psd b/artwork/itch.io/banner.psd index 6fb9ef3c..3743dd30 100644 Binary files a/artwork/itch.io/banner.psd and b/artwork/itch.io/banner.psd differ diff --git a/artwork/logo.png b/artwork/logo.png index 14141d58..75dd3a35 100644 Binary files a/artwork/logo.png and b/artwork/logo.png differ diff --git a/artwork/logo.psd b/artwork/logo.psd index 4638aa05..6e30b914 100644 Binary files a/artwork/logo.psd and b/artwork/logo.psd differ diff --git a/res/logo.png b/res/logo.png index 14141d58..75dd3a35 100644 Binary files a/res/logo.png and b/res/logo.png differ diff --git a/src/css/ingame_hud/unlock_notification.scss b/src/css/ingame_hud/unlock_notification.scss index 597b45f9..5f72909d 100644 --- a/src/css/ingame_hud/unlock_notification.scss +++ b/src/css/ingame_hud/unlock_notification.scss @@ -9,6 +9,7 @@ justify-content: center; align-items: center; pointer-events: all; + @include InlineAnimation(0.1s ease-in-out) { 0% { opacity: 0; @@ -16,7 +17,7 @@ } .dialog { - background: rgba(#222428, 0.5); + // background: rgba(#222428, 0.5); @include S(border-radius, $globalBorderRadius); @include S(padding, 30px); @@ -32,7 +33,7 @@ .subTitle { @include SuperHeading; text-transform: uppercase; - @include S(font-size, 50px); + @include S(font-size, 40px); @include InlineAnimation(0.5s ease-in-out) { 0% { @@ -48,11 +49,10 @@ } .subTitle { - @include Heading; - background: $colorGreenBright; + @include PlainText; display: inline-block; - @include S(padding, 1px, 6px); - @include S(margin, 20px, 0, 20px); + @include S(margin, 0px, 0, 20px); + color: $colorGreenBright; @include S(border-radius, $globalBorderRadius); @include InlineAnimation(0.5s ease-in-out) { @@ -82,14 +82,15 @@ transform: translateX(-2vw); } } - display: grid; - grid-template-columns: auto auto; + display: flex; + flex-direction: column; align-items: center; justify-content: center; @include S(grid-gap, 10px); - .reward { + .rewardName { grid-column: 1 / 3; + display: none; @include InlineAnimation(0.5s ease-in-out) { 0% { transform: translateX(200vw); @@ -104,29 +105,63 @@ } } - .buildingExplanation { - @include S(width, 200px); - @include S(height, 200px); - display: inline-block; - background-position: center center; - background-size: cover; - background-repeat: no-repeat; - @include S(border-radius, $globalBorderRadius); - box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15); + .rewardDesc { + grid-column: 1 / 3; + @include PlainText; + @include S(margin-bottom, 15px); + color: #aaacaf; + @include S(width, 400px); + text-align: left; + strong { + color: #fff; + } + } + + .images { + display: flex; + .buildingExplanation { + @include S(width, 200px); + @include S(height, 200px); + display: inline-block; + background-position: center center; + background-size: cover; + background-repeat: no-repeat; + @include S(border-radius, $globalBorderRadius); + box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15); + } } } button.close { border: 0; - @include InlineAnimation(2s ease-in-out) { - 0% { - opacity: 0; - } - 95% { - opacity: 0; + position: relative; + @include S(margin-top, 30px); + + &:not(.unlocked) { + pointer-events: none; + opacity: 0.8; + cursor: default; + } + + &::after { + content: " "; + display: inline-block; + position: absolute; + top: 0; + left: 100%; + right: 0; + bottom: 0; + background: rgba(0, 10, 20, 0.8); + + @include InlineAnimation(10s linear) { + 0% { + left: 0; + } + 100% { + left: 100%; + } } } - @include S(margin-top, 30px); } } } diff --git a/src/js/game/hud/parts/unlock_notification.js b/src/js/game/hud/parts/unlock_notification.js index 44fa7deb..20996ffa 100644 --- a/src/js/game/hud/parts/unlock_notification.js +++ b/src/js/game/hud/parts/unlock_notification.js @@ -2,18 +2,11 @@ import { globalConfig } from "../../../core/config"; import { gMetaBuildingRegistry } from "../../../core/global_registries"; import { makeDiv } from "../../../core/utils"; import { SOUNDS } from "../../../platform/sound"; -import { MetaCutterBuilding } from "../../buildings/cutter"; -import { MetaMixerBuilding } from "../../buildings/mixer"; -import { MetaPainterBuilding } from "../../buildings/painter"; -import { MetaRotaterBuilding } from "../../buildings/rotater"; -import { MetaSplitterBuilding } from "../../buildings/splitter"; -import { MetaStackerBuilding } from "../../buildings/stacker"; -import { MetaTrashBuilding } from "../../buildings/trash"; -import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; -import { enumHubGoalRewards } from "../../tutorial_goals"; +import { T } from "../../../translations"; +import { defaultBuildingVariant } from "../../meta_building"; +import { enumHubGoalRewards, enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals"; import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { T } from "../../../translations"; export class HUDUnlockNotification extends BaseHUDPart { initialize() { @@ -26,6 +19,8 @@ export class HUDUnlockNotification extends BaseHUDPart { if (!(G_IS_DEV && globalConfig.debug.disableUnlockDialog)) { this.root.signals.storyGoalCompleted.add(this.showForLevel, this); } + + this.buttonShowTimeout = null; } shouldPauseGame() { @@ -60,63 +55,50 @@ export class HUDUnlockNotification extends BaseHUDPart { ("" + level).padStart(2, "0") ); - const rewardText = T.storyRewards[reward]; + const rewardName = T.storyRewards[reward].title; - let html = - "" + - T.ingame.levelCompleteNotification.unlockText.replace("", rewardText) + - ""; + let html = ` +
+ ${T.ingame.levelCompleteNotification.unlockText.replace("", rewardName)} +
+ +
+ ${T.storyRewards[reward].desc} +
- const addBuildingExplanation = metaBuildingClass => { - const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); - html += `
`; - }; + `; - switch (reward) { - case enumHubGoalRewards.reward_cutter_and_trash: { - addBuildingExplanation(MetaCutterBuilding); - addBuildingExplanation(MetaTrashBuilding); - break; - } - case enumHubGoalRewards.reward_mixer: { - addBuildingExplanation(MetaMixerBuilding); - break; - } - - case enumHubGoalRewards.reward_painter: { - addBuildingExplanation(MetaPainterBuilding); - break; - } - - case enumHubGoalRewards.reward_rotater: { - addBuildingExplanation(MetaRotaterBuilding); - break; - } - - case enumHubGoalRewards.reward_splitter: { - addBuildingExplanation(MetaSplitterBuilding); - break; - } - - case enumHubGoalRewards.reward_stacker: { - addBuildingExplanation(MetaStackerBuilding); - break; - } - - case enumHubGoalRewards.reward_tunnel: { - addBuildingExplanation(MetaUndergroundBeltBuilding); - break; - } + html += "
"; + const gained = enumHubGoalRewardsToContentUnlocked[reward]; + if (gained) { + gained.forEach(([metaBuildingClass, variant]) => { + const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); + html += `
`; + }); } - - // addBuildingExplanation(MetaSplitterBuilding); - // addBuildingExplanation(MetaCutterBuilding); + html += "
"; this.elemContents.innerHTML = html; - this.visible = true; - this.root.soundProxy.playUi(SOUNDS.levelComplete); + + if (this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + } + + this.buttonShowTimeout = setTimeout( + () => this.element.querySelector("button.close").classList.add("unlocked"), + G_IS_DEV ? 1000 : 10000 + ); + } + + cleanup() { + if (this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + this.buttonShowTimeout = null; + } } requestClose() { @@ -126,10 +108,18 @@ export class HUDUnlockNotification extends BaseHUDPart { } close() { + if (this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + this.buttonShowTimeout = null; + } this.visible = false; } update() { this.domAttach.update(this.visible); + if (!this.visible && this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + this.buttonShowTimeout = null; + } } } diff --git a/src/js/game/systems/hub.js b/src/js/game/systems/hub.js index 93fbcb0d..b371de6e 100644 --- a/src/js/game/systems/hub.js +++ b/src/js/game/systems/hub.js @@ -88,7 +88,7 @@ export class HubSystem extends GameSystemWithFilter { context.font = "bold 11px GameFont"; context.fillStyle = "#fd0752"; context.textAlign = "center"; - context.fillText(T.storyRewards[goals.reward].toUpperCase(), pos.x, pos.y + 46); + context.fillText(T.storyRewards[goals.reward].title.toUpperCase(), pos.x, pos.y + 46); // Level context.font = "bold 11px GameFont"; diff --git a/src/js/game/tutorial_goals.js b/src/js/game/tutorial_goals.js index d22a72fe..1c957e6b 100644 --- a/src/js/game/tutorial_goals.js +++ b/src/js/game/tutorial_goals.js @@ -1,7 +1,18 @@ import { ShapeDefinition } from "./shape_definition"; import { finalGameShape } from "./upgrades"; +import { MetaBuilding, defaultBuildingVariant } from "./meta_building"; +import { MetaCutterBuilding, enumCutterVariants } from "./buildings/cutter"; +import { MetaRotaterBuilding, enumRotaterVariants } from "./buildings/rotater"; +import { MetaPainterBuilding, enumPainterVariants } from "./buildings/painter"; +import { MetaMixerBuilding } from "./buildings/mixer"; +import { MetaStackerBuilding } from "./buildings/stacker"; +import { MetaSplitterBuilding, enumSplitterVariants } from "./buildings/splitter"; +import { MetaUndergroundBeltBuilding, enumUndergroundBeltVariants } from "./buildings/underground_belt"; +import { MetaMinerBuilding, enumMinerVariants } from "./buildings/miner"; +import { MetaTrashBuilding, enumTrashVariants } from "./buildings/trash"; /** + * Don't forget to also update unlock_notification.js as well as the translations! * @enum {string} */ export const enumHubGoalRewards = { @@ -27,6 +38,44 @@ export const enumHubGoalRewards = { no_reward: "no_reward", }; +/** @typedef {Array<[typeof MetaBuilding, string]>} TutorialGoalReward */ + +/** + * Helper method for proper types + * @returns {TutorialGoalReward} + */ +const typed = x => x; + +/** + * Stores which reward unlocks what + * @enum {TutorialGoalReward?} + */ +export const enumHubGoalRewardsToContentUnlocked = { + [enumHubGoalRewards.reward_cutter_and_trash]: typed([[MetaCutterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_rotater]: typed([[MetaRotaterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_painter]: typed([[MetaPainterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_mixer]: typed([[MetaMixerBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_stacker]: typed([[MetaStackerBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_splitter]: typed([[MetaSplitterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]), + + [enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]), + [enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]), + [enumHubGoalRewards.reward_underground_belt_tier_2]: typed([ + [MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2], + ]), + [enumHubGoalRewards.reward_splitter_compact]: typed([ + [MetaSplitterBuilding, enumSplitterVariants.compact], + ]), + [enumHubGoalRewards.reward_cutter_quad]: typed([[MetaCutterBuilding, enumCutterVariants.quad]]), + [enumHubGoalRewards.reward_painter_double]: typed([[MetaPainterBuilding, enumPainterVariants.double]]), + [enumHubGoalRewards.reward_painter_quad]: typed([[MetaPainterBuilding, enumPainterVariants.quad]]), + [enumHubGoalRewards.reward_storage]: typed([[MetaTrashBuilding, enumTrashVariants.storage]]), + + [enumHubGoalRewards.reward_freeplay]: null, + [enumHubGoalRewards.no_reward]: null, +}; + export const tutorialGoals = [ // Circle { diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 450a3c9b..af13ec4b 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -352,27 +352,77 @@ buildings: storyRewards: # Those are the rewards gained from completing the store - reward_cutter_and_trash: Cutting Shapes - reward_rotater: Rotating - reward_painter: Painting - reward_mixer: Color Mixing - reward_stacker: Combiner - reward_splitter: Splitter/Merger - reward_tunnel: Tunnel + reward_cutter_and_trash: + title: Cutting Shapes + desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! - reward_rotater_ccw: CCW Rotating - reward_miner_chainable: Chaining Extractor - reward_underground_belt_tier_2: Tunnel Tier II - reward_splitter_compact: Compact Balancer - reward_cutter_quad: Quad Cutting - reward_painter_double: Double Painting - reward_painter_quad: Quad Painting - reward_storage: Storage Buffer + reward_rotater: + title: Rotating + desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - reward_freeplay: Freeplay + reward_painter: + title: Painting + desc: >- + The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, I'm working on a solution already! + + reward_mixer: + title: Color Mixing + desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + + reward_stacker: + title: Combiner + desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + + reward_splitter: + title: Splitter/Merger + desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ + reward_tunnel: + title: Tunnel + desc: The tunnel has been unlocked - You can now pipe items through belts and buildings with it! + + reward_rotater_ccw: + title: CCW Rotating + desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + + reward_miner_chainable: + title: Chaining Extractor + desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + + reward_underground_belt_tier_2: + title: Tunnel Tier II + desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + + reward_splitter_compact: + title: Compact Balancer + desc: >- + You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + + reward_cutter_quad: + title: Quad Cutting + desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + + reward_painter_double: + title: Double Painting + desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + + reward_painter_quad: + title: Quad Painting + desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + + reward_storage: + title: Storage Buffer + desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + + reward_freeplay: + title: Freeplay + desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) # Special reward, which is shown when there is no reward actually - no_reward: Next level + no_reward: + title: Next level + desc: >- + This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! settings: title: Settings