From 9bbdafb43d1fd96e0ccd6c17085e4c3918003726 Mon Sep 17 00:00:00 2001 From: austin Date: Sat, 22 Jun 2024 20:09:49 -0400 Subject: [PATCH] tutorial hints initial implementation --- assets/Data/tutorial/hints.json | 2 +- docs/src/architecture/ui/tutorial.md | 4 + docs/src/progress/renderertodo.md | 14 ++-- .../engine/loadingthreads/ClientLoading.java | 17 ---- .../java/electrosphere/game/data/Config.java | 77 ++++++++++++++++++- .../game/data/tutorial/HintDefinition.java | 35 +++++++++ .../game/data/tutorial/TutorialHint.java | 52 +++++++++++++ .../electrosphere/menu/WindowStrings.java | 26 ++++++- .../menu/tutorial/TutorialMenus.java | 58 ++++++++++++++ 9 files changed, 255 insertions(+), 30 deletions(-) create mode 100644 docs/src/architecture/ui/tutorial.md create mode 100644 src/main/java/electrosphere/game/data/tutorial/HintDefinition.java create mode 100644 src/main/java/electrosphere/game/data/tutorial/TutorialHint.java create mode 100644 src/main/java/electrosphere/menu/tutorial/TutorialMenus.java diff --git a/assets/Data/tutorial/hints.json b/assets/Data/tutorial/hints.json index c6d5a846..0b6c2860 100644 --- a/assets/Data/tutorial/hints.json +++ b/assets/Data/tutorial/hints.json @@ -1,7 +1,7 @@ { "hints": [ { - "id": "Basic Navigation", + "id": "BasicNavigation", "titleString": "Navigation", "descriptionString": "You can move the mouse to move the camera around. Also, you can use the W, A, S, and D keys to move your character.", "image": "" diff --git a/docs/src/architecture/ui/tutorial.md b/docs/src/architecture/ui/tutorial.md new file mode 100644 index 00000000..3e72a5f5 --- /dev/null +++ b/docs/src/architecture/ui/tutorial.md @@ -0,0 +1,4 @@ +@page tutorial Tutorial UI + +The current implementation of tutorial hints is centered around calling a single function. +THe idea is to call `TutorialMenus.showTutorialHint` and it will show a popup with a hint in it. \ No newline at end of file diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 5cd58c9b..aef7c862 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -385,6 +385,7 @@ Transvoxel implementation Fix items falling below the ground Fix server always rotating entity to face client camera -- should only be changing movement vector +Probably some kind of tutorial text # TODO @@ -406,7 +407,6 @@ Sub menu on title screen that allows changing control mappings Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around) - Introduce block hitbox (blockbox) type Enemy AI -Probably some kind of tutorial text Network-able ui messages Ability to display video both on title screen as well as in game windows for tutorials better scaffolding for scriptig engine with hooks for equipping items, spawning entities, pausing/resuming play, etc @@ -416,6 +416,9 @@ Ability for private realms to have time start/stop based on the player's feedbac +BIG BIG BIG BIG IMMEDIATE TO DO: +always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible + @@ -433,14 +436,7 @@ Transvoxel implementation - - - -BIG BIG BIG BIG IMMEDIATE TO DO: -always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible - - - +Allow texture map to bind multiple model paths to a single set of mesh->textures diff --git a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java index 0aab804f..1f8c4312 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java @@ -1,38 +1,24 @@ package electrosphere.engine.loadingthreads; -import java.util.Random; import java.util.concurrent.TimeUnit; import org.joml.Quaterniond; -import org.joml.Vector3d; import org.joml.Vector3f; -import org.joml.Vector3i; -import electrosphere.audio.AudioUtils; -import electrosphere.audio.VirtualAudioSource; -import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType; import electrosphere.client.culling.ClientEntityCullingManager; import electrosphere.client.fluid.cells.FluidCellManager; import electrosphere.client.foliagemanager.ClientFoliageManager; import electrosphere.client.sim.ClientSimulation; import electrosphere.client.targeting.crosshair.Crosshair; -import electrosphere.client.terrain.cells.DrawCell; import electrosphere.client.terrain.cells.DrawCellManager; -import electrosphere.client.terrain.cells.DrawCell.DrawCellFace; -import electrosphere.collision.CollisionEngine; import electrosphere.controls.ControlHandler; import electrosphere.engine.Globals; -import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.DrawableUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityCreationUtils; -import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.state.movement.ApplyRotationTree; import electrosphere.entity.types.camera.CameraEntityUtils; -import electrosphere.entity.types.terrain.TerrainChunk; -import electrosphere.entity.types.tree.ProceduralTree; import electrosphere.logger.LoggerInterface; import electrosphere.menu.MenuGenerators; import electrosphere.menu.WindowStrings; @@ -40,10 +26,7 @@ import electrosphere.menu.WindowUtils; import electrosphere.menu.mainmenu.MenuGeneratorsMultiplayer; import electrosphere.net.NetUtils; import electrosphere.net.client.ClientNetworking; -import electrosphere.renderer.meshgen.TransvoxelModelGeneration.TransvoxelChunkData; import electrosphere.renderer.ui.elements.Window; -import electrosphere.server.datacell.EntityDataCellMapper; -import electrosphere.server.terrain.manager.ServerTerrainChunk; import electrosphere.util.MathUtils; public class ClientLoading { diff --git a/src/main/java/electrosphere/game/data/Config.java b/src/main/java/electrosphere/game/data/Config.java index 04d16b6b..ef960611 100644 --- a/src/main/java/electrosphere/game/data/Config.java +++ b/src/main/java/electrosphere/game/data/Config.java @@ -14,14 +14,14 @@ import electrosphere.game.data.object.type.model.ObjectTypeLoader; import electrosphere.game.data.object.type.model.ObjectTypeMap; import electrosphere.game.data.projectile.ProjectileTypeHolder; import electrosphere.game.data.structure.type.model.StructureTypeMap; +import electrosphere.game.data.tutorial.HintDefinition; import electrosphere.game.data.voxel.VoxelData; import electrosphere.game.server.race.model.RaceMap; import electrosphere.game.server.symbolism.model.SymbolMap; import electrosphere.util.FileUtils; /** - * - * @author amaterasu + * Current configuration for the data of the game */ public class Config { @@ -33,9 +33,17 @@ public class Config { SymbolMap symbolMap; RaceMap raceMap; ProjectileTypeHolder projectileTypeHolder; + //data about every voxel type VoxelData voxelData; + + //the hints that are defined + HintDefinition hintData; + /** + * Loads the default data + * @return The config + */ public static Config loadDefaultConfig(){ Config config = new Config(); config.creatureTypeLoader = loadCreatureTypes("Data/creatures.json"); @@ -47,10 +55,16 @@ public class Config { config.raceMap = FileUtils.loadObjectFromAssetPath("Data/races.json", RaceMap.class); config.voxelData = FileUtils.loadObjectFromAssetPath("Data/voxelTypes.json", VoxelData.class); config.projectileTypeHolder = FileUtils.loadObjectFromAssetPath("Data/projectile.json", ProjectileTypeHolder.class); + config.hintData = FileUtils.loadObjectFromAssetPath("Data/tutorial/hints.json", HintDefinition.class); config.projectileTypeHolder.init(); return config; } + /** + * Reads a child creature defintion file + * @param filename The filename + * @return The list of creatures in the file + */ static List readCreatureTypeFile(String filename){ List typeList = new LinkedList(); CreatureTypeMap typeMap = FileUtils.loadObjectFromAssetPath(filename, CreatureTypeMap.class); @@ -68,6 +82,11 @@ public class Config { return typeList; } + /** + * Loads all creature definition files recursively + * @param initialPath The initial path to recurse from + * @return The creature defintion interface + */ static CreatureTypeLoader loadCreatureTypes(String initialPath) { CreatureTypeLoader loader = new CreatureTypeLoader(); List typeList = readCreatureTypeFile(initialPath); @@ -86,6 +105,11 @@ public class Config { return loader; } + /** + * Read a file that define object entity types + * @param filename The filename to read + * @return The list of object definitions + */ static List readObjectTypeFile(String filename){ List typeList = new LinkedList(); ObjectTypeMap typeMap = FileUtils.loadObjectFromAssetPath(filename, ObjectTypeMap.class); @@ -103,6 +127,11 @@ public class Config { return typeList; } + /** + * Recursively reads files that define object entities + * @param initialPath The initial path to start recursing from + * @return The object entity interface + */ static ObjectTypeLoader loadObjectTypes(String initialPath) { ObjectTypeLoader loader = new ObjectTypeLoader(); List typeList = readObjectTypeFile(initialPath); @@ -112,40 +141,84 @@ public class Config { return loader; } + /** + * Gets the interface for creature definitions loaded into memory + * @return The interface + */ public CreatureTypeLoader getCreatureTypeLoader() { return creatureTypeLoader; } + /** + * Gets the data on all structure entities in memory + * @return The structure definitions + */ public StructureTypeMap getStructureTypeMap() { return structureTypeMap; } + /** + * Gets the data on all item types in memory + * @return the data on all items + */ public ItemTypeMap getItemMap() { return itemMap; } + /** + * Gets the data on all foliage types in memory + * @return The foliage data + */ public FoliageTypeMap getFoliageMap() { return foliageMap; } + /** + * Gets the symbolism map + * @return The symbolism map + */ public SymbolMap getSymbolMap() { return symbolMap; } + /** + * Gets the data that defines all creature races in the engine + * @return The data on all races + */ public RaceMap getRaceMap() { return raceMap; } + /** + * Gets the definitions of all object entities in memory + * @return The objects + */ public ObjectTypeLoader getObjectTypeLoader() { return objectTypeLoader; } + /** + * Gets the definitions all projectiles + * @return the projectile data + */ public ProjectileTypeHolder getProjectileMap(){ return projectileTypeHolder; } + /** + * Gets the voxel data + * @return The voxel data + */ public VoxelData getVoxelData(){ return voxelData; } + + /** + * The tutorial hints data + * @return The hints + */ + public HintDefinition getHintData(){ + return hintData; + } } diff --git a/src/main/java/electrosphere/game/data/tutorial/HintDefinition.java b/src/main/java/electrosphere/game/data/tutorial/HintDefinition.java new file mode 100644 index 00000000..ae4a9464 --- /dev/null +++ b/src/main/java/electrosphere/game/data/tutorial/HintDefinition.java @@ -0,0 +1,35 @@ +package electrosphere.game.data.tutorial; + +import java.util.List; + +/** + * A file that defines tutorial hints + */ +public class HintDefinition { + + //the list of all tutorial hints + List hints; + + /** + * Gets the list of all available tutorial hints + * @return the list + */ + public List getHints(){ + return hints; + } + + /** + * Gets a hint by its id + * @param id the id of the hint + * @return The hint if it exists, null otherwise + */ + public TutorialHint getHintById(String id){ + for(TutorialHint hint : hints){ + if(hint.id.equals(id)){ + return hint; + } + } + return null; + } + +} diff --git a/src/main/java/electrosphere/game/data/tutorial/TutorialHint.java b/src/main/java/electrosphere/game/data/tutorial/TutorialHint.java new file mode 100644 index 00000000..14de7ff2 --- /dev/null +++ b/src/main/java/electrosphere/game/data/tutorial/TutorialHint.java @@ -0,0 +1,52 @@ +package electrosphere.game.data.tutorial; + +/** + * A hint that can be shown as a popup in game + */ +public class TutorialHint { + + //the id of the hint + String id; + + //the title + String titleString; + + //the description paired with the title + String descriptionString; + + //the image to display + String image; + + /** + * Gets the id of the hint + * @return the hint's id + */ + public String getId(){ + return id; + } + + /** + * Gets the string for the title of the hint + * @return The title + */ + public String getTitleString(){ + return titleString; + } + + /** + * Gets the string for the description of the hint + * @return The description + */ + public String getDescriptionString(){ + return descriptionString; + } + + /** + * Gets the string for the path to the image associated with the hint + * @return The image path + */ + public String getImage(){ + return image; + } + +} diff --git a/src/main/java/electrosphere/menu/WindowStrings.java b/src/main/java/electrosphere/menu/WindowStrings.java index 6ab7b6fb..b03c24ab 100644 --- a/src/main/java/electrosphere/menu/WindowStrings.java +++ b/src/main/java/electrosphere/menu/WindowStrings.java @@ -1,17 +1,41 @@ package electrosphere.menu; +/** + * Strings that identify different windows + */ public class WindowStrings { - + //the main menu public static final String WINDOW_MENU_MAIN = "windowMenuMain"; + + //the ingame main menu public static final String WINDOW_MENU_INGAME_MAIN = "windowMenuInGameMain"; + + //the string used to generate inventory menus public static final String WINDOW_MENU_INVENTORY = "windowMenuInventory"; + + //a window that shows the text 'loading' public static final String WINDOW_LOADING = "windowLoading"; + + //the window used to receive drag events for dropping items public static final String WINDDOW_ITEM_DROP = "itemDrop"; + + //the window used as a container for item icons for drawing dragging them around the screen public static final String WINDOW_ITEM_DRAG_CONTAINER = "itemDragContainer"; + + //the window for displaying information about the character public static final String WINDOW_CHARACTER = "windowCharacter"; + + //the debug menu public static final String WINDOW_DEBUG = "windowDebug"; + + //the level editor menu public static final String LEVEL_EDTIOR_SIDE_PANEL = "levelEditor"; + + //the voxel type selection menu public static final String VOXEL_TYPE_SELECTION = "voxelTypeSelection"; + //the tutorial popup + public static final String TUTORIAL_POPUP = "tutorialPopup"; + } diff --git a/src/main/java/electrosphere/menu/tutorial/TutorialMenus.java b/src/main/java/electrosphere/menu/tutorial/TutorialMenus.java new file mode 100644 index 00000000..835b3314 --- /dev/null +++ b/src/main/java/electrosphere/menu/tutorial/TutorialMenus.java @@ -0,0 +1,58 @@ +package electrosphere.menu.tutorial; + +import org.lwjgl.util.yoga.Yoga; + +import electrosphere.engine.Globals; +import electrosphere.game.data.tutorial.TutorialHint; +import electrosphere.menu.WindowStrings; +import electrosphere.menu.WindowUtils; +import electrosphere.renderer.ui.elements.Button; +import electrosphere.renderer.ui.elements.Label; +import electrosphere.renderer.ui.elements.Window; +import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback; +import electrosphere.renderer.ui.events.ClickEvent; + +/** + * Generates in game tutorial windows + */ +public class TutorialMenus { + + /** + * Shows a tutorial hint + * @param hint the hint + */ + public static void showTutorialHint(TutorialHint hint){ + + //Get the window + Window windowEl; + if(Globals.elementManager.containsWindow(WindowStrings.TUTORIAL_POPUP)){ + windowEl = (Window)Globals.elementManager.getWindow(WindowStrings.TUTORIAL_POPUP); + } else { + //create the window + windowEl = new Window(50,50,500,500,true); + windowEl.setParentAlignContent(Yoga.YGAlignCenter); + windowEl.setParentJustifyContent(Yoga.YGJustifyCenter); + windowEl.setFlexDirection(Yoga.YGFlexDirectionColumn); + Globals.elementManager.registerWindow(WindowStrings.TUTORIAL_POPUP, windowEl); + } + + //clear previous content + windowEl.clearChildren(); + + //create tutorial elements + windowEl.addChild(Label.createLabel(hint.getTitleString())); + windowEl.addChild(Label.createLabel(hint.getDescriptionString())); + windowEl.addChild(Button.createButton("Close", new ClickEventCallback() { + @Override + public boolean execute(ClickEvent event) { + WindowUtils.recursiveSetVisible(windowEl, true); + return false; + } + })); + + //show the window + WindowUtils.recursiveSetVisible(windowEl, true); + + } + +}