Add "interactive" tutorial for first level

This commit is contained in:
tobspr 2020-06-01 21:14:12 +02:00
parent 91351d2f79
commit cef07dec56
21 changed files with 274 additions and 22 deletions

View file

@ -5,7 +5,7 @@
transform: translateX(-50%);
color: #333;
z-index: 9999;
background: rgba(0, 10, 20, 0.5);
background: $ingameHudBg;
@include S(padding, 5px);
display: flex;
flex-direction: column;

View file

@ -10,7 +10,7 @@
@include S(width, 240px);
@include S(grid-column-gap, 5px);
background: rgba(#333438, 0.8);
background: $ingameHudBg;
grid-template-columns: 1fr auto;
grid-template-rows: auto 1fr;
@ -108,7 +108,8 @@
.variant {
grid-row: 2 / 3;
@include S(border-radius, $globalBorderRadius);
background: rgba(0, 10, 20, 0.2);
background: rgba($ingameHudBg, 0.3);
opacity: 0.5;
display: inline-flex;
vertical-align: top;
position: relative;
@ -117,7 +118,8 @@
@include S(grid-gap, 10px);
&.active {
background-color: rgba(74, 163, 223, 0.6);
opacity: 1;
background-color: rgba($colorBlueBright, 0.8);
}
$iconSize: 25px;

View file

@ -1,8 +1,9 @@
#ingame_HUD_DebugInfo {
position: absolute;
@include S(bottom, 5px);
@include S(left, 5px);
@include S(right, 5px);
text-align: right;
font-size: 15px;
display: flex;
line-height: 15px;

View file

@ -0,0 +1,50 @@
#ingame_HUD_InteractiveTutorial {
position: absolute;
@include S(left, 10px);
@include S(bottom, 10px);
@include StyleBelowWidth(1430px) {
@include S(bottom, 10px + 40px);
}
@include S(width, 150px);
background: $ingameHudBg;
@include S(padding, 4px);
color: #eee;
display: flex;
flex-direction: column;
@include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) {
0% {
}
50% {
transform: translateX(-100%);
}
100% {
}
}
.title {
color: #fff;
opacity: 0.5;
@include SuperSmallText;
text-transform: uppercase;
}
.desc {
@include SuperSmallText;
strong {
color: $colorBlueBright;
font-weight: bold;
}
}
.helperGif {
@include S(margin-top, 5px);
@include S(height, 150px);
background: center center / contain no-repeat;
}
}

View file

@ -3,8 +3,7 @@
@include S(top, 50px);
left: 50%;
transform: translateX(-50%);
background: rgba(lighten(#f77, 5), 0.95);
@include S(border-radius, $globalBorderRadius);
background: $ingameHudBg;
@include S(padding, 6px, 10px);
@include SuperSmallText;
color: #fff;

View file

@ -66,7 +66,7 @@
}
&.enlarged {
background: rgba(50, 60, 70, 0.9);
background: $ingameHudBg;
left: 50%;
bottom: 50%;
transform: translate(-50%, 50%);
@ -81,7 +81,7 @@
bottom: -1000px;
z-index: 0;
background: rgba(50, 60, 70, 0.3);
background: rgba($ingameHudBg, 0.3);
}
.header {

View file

@ -49,6 +49,7 @@
@import "ingame_hud/watermark";
@import "ingame_hud/blueprint_placer";
@import "ingame_hud/waypoints";
@import "ingame_hud/interactive_tutorial";
// prettier-ignore
$elements:
@ -69,6 +70,7 @@ ingame_HUD_Notifications,
ingame_HUD_MassSelector,
ingame_HUD_DebugInfo,
ingame_HUD_EntityDebugger,
ingame_HUD_InteractiveTutorial,
ingame_HUD_TutorialHints,
ingame_HUD_buildings_toolbar,
ingame_HUD_BlueprintPlacer,
@ -79,9 +81,9 @@ ingame_HUD_Watermark,
ingame_HUD_BetaOverlay,
// Dialogs
ingame_HUD_UnlockNotification,
ingame_HUD_Shop,
ingame_HUD_Statistics,
ingame_HUD_UnlockNotification,
ingame_HUD_SettingsMenu,
ingame_HUD_ModalDialogs;

View file

@ -34,8 +34,7 @@ $colorGreenBright: #66bb6a;
$colorBlueBright: rgb(74, 163, 223);
$colorRedBright: #ef5072;
$themeColor: #393747;
$ingameHudBg: rgba($accentColorBright, 0.1);
$ingameHudBorder: #{D(1.5px)} solid $accentColorDark;
$ingameHudBg: rgba(#333438, 0.9);
$text3dColor: #f4ffff;

View file

@ -10,7 +10,10 @@ import { AtlasDefinition, atlasFiles } from "./atlas_definitions";
const logger = createLogger("background_loader");
const essentialMainMenuSprites = ["logo.png", ...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/"))];
const essentialMainMenuSprites = [
"logo.png",
...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0),
];
const essentialMainMenuSounds = [
SOUNDS.uiClick,
SOUNDS.uiError,
@ -21,7 +24,7 @@ const essentialMainMenuSounds = [
];
const essentialBareGameAtlases = atlasFiles;
const essentialBareGameSprites = G_ALL_UI_IMAGES;
const essentialBareGameSprites = G_ALL_UI_IMAGES.filter(src => src.indexOf(".gif") < 0);
const essentialBareGameSounds = [MUSIC.theme];
const additionalGameSprites = [];

View file

@ -31,6 +31,7 @@ import { HUDWaypoints } from "./parts/waypoints";
/* dev:start */
import { TrailerMaker } from "./trailer_maker";
import { HUDInteractiveTutorial } from "./parts/interactive_tutorial";
/* dev:end */
export class GameHUD {
@ -87,6 +88,7 @@ export class GameHUD {
}
if (this.root.app.settings.getAllSettings().offerHints) {
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
}
const frag = document.createDocumentFragment();

View file

@ -0,0 +1,81 @@
import { BaseHUDPart } from "../base_hud_part";
import { makeDiv } from "../../../core/utils";
import { GameRoot } from "../../root";
import { MinerComponent } from "../../components/miner";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { TrackedState } from "../../../core/tracked_state";
import { cachebust } from "../../../core/cachebust";
import { T } from "../../../translations";
const tutorialsByLevel = [
// Level 1
[
// 1.1. place an extractor
{
id: "1_1_extractor",
condition: /** @param {GameRoot} root */ root => {
return root.entityMgr.getAllWithComponent(MinerComponent).length === 0;
},
},
// 1.2. connect to hub
{
id: "1_2_conveyor",
condition: /** @param {GameRoot} root */ root => {
return root.hubGoals.getCurrentGoalDelivered() === 0;
},
},
// 1.3 wait for completion
{
id: "1_3_expand",
condition: () => true,
},
],
];
export class HUDInteractiveTutorial extends BaseHUDPart {
createElements(parent) {
this.element = makeDiv(
parent,
"ingame_HUD_InteractiveTutorial",
["animEven"],
`
<strong class="title">Tutorial</strong>
`
);
this.elementDescription = makeDiv(this.element, null, ["desc"]);
this.elementGif = makeDiv(this.element, null, ["helperGif"]);
}
initialize() {
this.domAttach = new DynamicDomAttach(this.root, this.element);
this.currentHintId = new TrackedState(this.onHintChanged, this);
}
onHintChanged(hintId) {
this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId];
this.elementGif.style.backgroundImage =
"url('" + cachebust("res/ui/interactive_tutorial.noinline/" + hintId + ".gif") + "')";
this.element.classList.toggle("animEven");
this.element.classList.toggle("animOdd");
}
update() {
// Compute current hint
const thisLevelHints = tutorialsByLevel[this.root.hubGoals.level - 1];
let targetHintId = null;
if (thisLevelHints) {
for (let i = 0; i < thisLevelHints.length; ++i) {
const hint = thisLevelHints[i];
if (hint.condition(this.root)) {
targetHintId = hint.id;
break;
}
}
}
this.currentHintId.set(targetHintId);
this.domAttach.update(!!targetHintId);
}
}

View file

@ -1,4 +1,3 @@
import { cachebust } from "../../../core/cachebust";
import { InputReceiver } from "../../../core/input_receiver";
import { TrackedState } from "../../../core/tracked_state";
import { makeDiv } from "../../../core/utils";
@ -6,9 +5,8 @@ import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { T } from "../../../translations";
import { globalConfig } from "../../../core/config";
const tutorialVideos = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11];
const tutorialVideos = [2, 3, 4, 5, 6, 7, 9, 10, 11];
export class HUDPartTutorialHints extends BaseHUDPart {
createElements(parent) {

View file

@ -35,7 +35,7 @@ export const tutorialGoals = [
// Circle
{
shape: "CuCuCuCu", // belts t1
required: 20,
required: 40,
reward: enumHubGoalRewards.reward_cutter_and_trash,
},