Skip to content

Commit

Permalink
fix(tutorial): refined tutorial text and fixed controller input
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaminAmos committed Mar 12, 2023
1 parent 7690d6f commit eb91c0f
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 477 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,15 @@
import org.destinationsol.game.planet.PlanetManager;
import org.destinationsol.game.screens.GameScreens;
import org.destinationsol.game.ship.ShipBuilder;
import org.destinationsol.game.tutorial.NewTutorialManager;
import org.destinationsol.ui.TutorialManager;
import org.destinationsol.game.tutorial.TutorialManager;
import org.terasology.context.Lifetime;
import org.terasology.gestalt.di.ServiceRegistry;

public class SolGameServiceRegistry extends ServiceRegistry {
public SolGameServiceRegistry(boolean isTutorial) {
this.with(SolGame.class).lifetime(Lifetime.Singleton);
if (isTutorial) {
// this.with(TutorialManager.class).lifetime(Lifetime.Singleton);
this.with(NewTutorialManager.class).lifetime(Lifetime.Singleton);
this.with(TutorialManager.class).lifetime(Lifetime.Singleton);
}

this.with(EntitySystemManager.class);
Expand Down
11 changes: 3 additions & 8 deletions engine/src/main/java/org/destinationsol/game/SolGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,10 @@
import org.destinationsol.game.ship.ShipBuilder;
import org.destinationsol.game.ship.SloMo;
import org.destinationsol.game.ship.hulls.HullConfig;
import org.destinationsol.game.tutorial.NewTutorialManager;
import org.destinationsol.game.tutorial.TutorialManager;
import org.destinationsol.mercenary.MercenaryUtils;
import org.destinationsol.modules.ModuleManager;
import org.destinationsol.ui.DebugCollector;
import org.destinationsol.ui.TutorialManager;
import org.destinationsol.ui.UiDrawer;
import org.destinationsol.ui.Waypoint;
import org.destinationsol.ui.nui.screens.MainGameScreen;
Expand Down Expand Up @@ -140,8 +139,6 @@ public class SolGame {
@Inject
protected Optional<TutorialManager> tutorialManager;
@Inject
protected Optional<NewTutorialManager> newTutorialManager;
@Inject
protected BeanContext beanContext;
@Inject
protected GalaxyBuilder galaxyBuilder;
Expand Down Expand Up @@ -194,7 +191,6 @@ public void createUpdateSystems() {
updateSystems = new TreeMap<>();
List<UpdateAwareSystem> defaultSystems = new ArrayList<>(Arrays.asList(planetManager, solCam, chunkManager, mountDetectDrawer, objectManager, mapDrawer, soundManager, beaconHandler, drawableDebugger));
tutorialManager.ifPresent(defaultSystems::add);
newTutorialManager.ifPresent(defaultSystems::add);
updateSystems.put(0, defaultSystems);

List<UpdateAwareSystem> defaultPausedSystems = new ArrayList<UpdateAwareSystem>();
Expand Down Expand Up @@ -269,7 +265,6 @@ public void run() {
gameScreens.consoleScreen.init(this);
solApplication.getNuiManager().pushScreen(gameScreens.mainGameScreen);
tutorialManager.ifPresent(TutorialManager::start);
newTutorialManager.ifPresent(NewTutorialManager::start);
}

private void addObjectsToPlanetManager() {
Expand Down Expand Up @@ -343,7 +338,7 @@ public void onGameEnd(Context context) {
e.printStackTrace();
}
} else {
newTutorialManager.ifPresent(NewTutorialManager::onGameEnd);
tutorialManager.ifPresent(TutorialManager::onGameEnd);
}

// TODO: Remove this when context is reset after each game
Expand Down Expand Up @@ -639,7 +634,7 @@ public void setRespawnState() {
}

public boolean isTutorial() {
return tutorialManager.isPresent() || newTutorialManager.isPresent();
return tutorialManager.isPresent();
}

public SolApplication getSolApplication() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,13 @@
import org.destinationsol.game.tutorial.steps.SelectEquippedWeaponStep;
import org.destinationsol.game.tutorial.steps.SlowVelocityStep;
import org.destinationsol.game.tutorial.steps.ThrustForwardsStep;
import org.destinationsol.game.tutorial.steps.TravelThroughStarPortStep;
import org.destinationsol.game.tutorial.steps.TurnLeftRightStep;
import org.destinationsol.game.tutorial.steps.UseAbilityStep;
import org.destinationsol.game.tutorial.steps.WaitUntilFullyRepairedStep;
import org.destinationsol.ui.nui.NUIManager;
import org.destinationsol.ui.nui.screens.MainGameScreen;
import org.destinationsol.ui.nui.screens.TutorialScreen;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.context.exception.BeanNotFoundException;
import org.terasology.gestalt.di.BeanContext;

Expand All @@ -71,7 +70,7 @@
* instances.
* @see TutorialStep
*/
public class NewTutorialManager implements UpdateAwareSystem {
public class TutorialManager implements UpdateAwareSystem {
private final NUIManager nuiManager;
private final TutorialScreen tutorialScreen;
private final SolApplication solApplication;
Expand All @@ -81,7 +80,7 @@ public class NewTutorialManager implements UpdateAwareSystem {
private int stepNo;

@Inject
public NewTutorialManager(NUIManager nuiManager, SolApplication solApplication, Provider<SolGame> game, BeanContext beanContext) {
public TutorialManager(NUIManager nuiManager, SolApplication solApplication, Provider<SolGame> game, BeanContext beanContext) {
this.nuiManager = nuiManager;
this.tutorialScreen = (TutorialScreen) nuiManager.createScreen("engine:tutorialScreen");
this.solApplication = solApplication;
Expand All @@ -101,8 +100,7 @@ public void start() {
GameOptions gameOptions = solApplication.getOptions();
GameOptions.ControlType controlType = gameOptions.controlType;
boolean isMobile = solApplication.isMobile();
boolean usesKeyboard = !isMobile &&
(controlType != GameOptions.ControlType.MOUSE);
boolean usesKeyboard = !isMobile && (controlType != GameOptions.ControlType.MOUSE);

// A lot of input names will vary by control type. In some control types, the inputs are also hard-coded.
// Rather than a lot of messy conditional statements in-line with the step definitions, we'll set things up here.
Expand Down Expand Up @@ -220,7 +218,7 @@ public void start() {
isMobile ? "Open the map." : "Open the map (" + gameOptions.getKeyMapName() + ")."),
new ButtonPressStep(solGame.get().getScreens().mapScreen.getZoomInButton(), "Zoom In"),
new ButtonPressStep(solGame.get().getScreens().mapScreen.getZoomOutButton(), "Zoom Out"),
new MapDragStep("You can move around the map by clicking/tapping and dragging."),
new MapDragStep("You can drag the map to move around."),
new CreateWaypointStep("Create a waypoint near your ship."),
new CloseScreenStep(
solGame.get().getScreens().mapScreen.getCloseButton(),
Expand All @@ -237,11 +235,7 @@ public void start() {
new BuyMercenaryStep(1000,
usesKeyboard ? "Select Hire (" + gameOptions.getKeyHireShipMenuName() + ")." : "Select Hire.",
"Try hiring a mercenary."),
new MessageStep("Let's see how your mercenary fights."),
new DestroySpawnedShipsStep(1, "core:pirateSmall",
"core:blaster core:smallShield", "Destroy the targeted ship.",
"Enemy ships can be tough.\nOpen the pause menu and select Respawn."),
new MessageStep("Mercenaries will keep any money they collect as part of their payment."),
new MessageStep("Mercenaries will fight for you. They keep any money they collect as part of their payment."),
new MessageStep("Section 11 - Managing Mercenaries"),
new OpenScreenStep(
solGame.get().getScreens().mainGameScreen.getMercsButton(),
Expand All @@ -254,7 +248,8 @@ public void start() {
"Here you can manage your mercenary's equipment."),
new FlyToNearestStarPortStep("Fly to the marked star lane."),
new MessageStep("For a small fee, star lanes allow you to travel quickly between planets."),
new MessageStep("The tutorial is finished. You will be returned to the main menu.")
new TravelThroughStarPortStep("Fly into the centre to travel across the star lane."),
new MessageStep("That's it! The tutorial is finished. You will be returned to the main menu.")
));

for (TutorialStep step : steps) {
Expand Down Expand Up @@ -299,28 +294,28 @@ public void update(SolGame game, float timeStep) {
}

TutorialStep currentStep = steps.get(stepNo);
tutorialScreen.setTutorialText(currentStep.getTutorialText(), currentStep.getTutorialBoxPosition());
if (currentStep.getRequiredInput() != null) {
tutorialScreen.setInteractHintInput(currentStep.getTutorialBoxPosition(), currentStep.getRequiredInput());
tutorialScreen.setInteractEvent(currentStep.getTutorialBoxPosition(), currentStep.getInputHandler());
}
setUpTutorialBox(currentStep);
if (currentStep.checkComplete(timeStep)) {
stepNo++;
tutorialScreen.clearAllTutorialBoxes();
if (stepNo < steps.size()) {
TutorialStep newStep = steps.get(stepNo);
newStep.start();
tutorialScreen.setTutorialText(newStep.getTutorialText(), newStep.getTutorialBoxPosition());
if (newStep.getRequiredInput() != null) {
tutorialScreen.setInteractHintInput(newStep.getTutorialBoxPosition(), newStep.getRequiredInput());
tutorialScreen.setInteractEvent(newStep.getTutorialBoxPosition(), newStep.getInputHandler());
}
setUpTutorialBox(newStep);
} else {
solApplication.finishGame();
}
}
}

private void setUpTutorialBox(TutorialStep tutorialStep) {
tutorialScreen.setTutorialText(tutorialStep.getTutorialText(), tutorialStep.getTutorialBoxPosition());
if (tutorialStep.getRequiredInput() != null) {
tutorialScreen.setInteractHintInput(tutorialStep.getTutorialBoxPosition(), tutorialStep.getRequiredInput());
tutorialScreen.setInteractEvent(tutorialStep.getTutorialBoxPosition(), tutorialStep.getInputHandler());
}
}

/**
* This method should be called when either the game or the tutorial ends. It cleans-up the UI changes made for the tutorial.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.destinationsol.GameOptions;
import org.destinationsol.SolApplication;
import org.destinationsol.game.SolGame;
import org.destinationsol.game.tutorial.TutorialStep;
import org.terasology.input.ControllerInput;
import org.terasology.input.InputType;
Expand All @@ -35,6 +36,8 @@ public class MessageStep extends TutorialStep {
protected static final float MIN_STEP_DURATION = 0.5f;
@Inject
protected SolApplication solApplication;
@Inject
protected SolGame game;
protected final String message;
protected float stepTimer;
protected boolean interactComplete;
Expand Down Expand Up @@ -81,6 +84,11 @@ public void start() {

@Override
public boolean checkComplete(float timeStep) {
if (solApplication.getOptions().controlType == GameOptions.ControlType.CONTROLLER && game.getHero().getPilot().isShoot()) {
// TODO: NUI doesn't support controller input at the moment, so we detect completion here.
interactComplete = true;
}

stepTimer += timeStep;
return stepTimer >= MIN_STEP_DURATION && interactComplete;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2023 The Terasology Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.destinationsol.game.tutorial.steps;

import org.destinationsol.game.Hero;
import org.destinationsol.game.SolGame;
import org.destinationsol.game.tutorial.TutorialStep;

import javax.inject.Inject;

/**
* A tutorial step that completes once the player has travelled across a star lane.
*/
public class TravelThroughStarPortStep extends TutorialStep {
@Inject
protected SolGame game;
private final String message;
private boolean wasTranscendent;

@Inject
protected TravelThroughStarPortStep() {
throw new RuntimeException("Attempted to instantiate TutorialStep via DI. This is not supported.");
}

public TravelThroughStarPortStep(String message) {
this.message = message;
}

@Override
public void start() {
setTutorialText(message);
}

@Override
public boolean checkComplete(float timeStep) {
Hero hero = game.getHero();
if (wasTranscendent && !hero.isTranscendent()) {
return true;
}
wasTranscendent = hero.isTranscendent();
return false;
}
}
Loading

0 comments on commit eb91c0f

Please sign in to comment.