tutorial hints initial implementation

This commit is contained in:
austin 2024-06-22 20:09:49 -04:00
parent a676d8ddca
commit 9bbdafb43d
9 changed files with 255 additions and 30 deletions

View File

@ -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": ""

View File

@ -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.

View File

@ -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

View File

@ -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 {

View File

@ -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<CreatureType> readCreatureTypeFile(String filename){
List<CreatureType> typeList = new LinkedList<CreatureType>();
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<CreatureType> 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<ObjectData> readObjectTypeFile(String filename){
List<ObjectData> typeList = new LinkedList<ObjectData>();
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<ObjectData> 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;
}
}

View File

@ -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<TutorialHint> hints;
/**
* Gets the list of all available tutorial hints
* @return the list
*/
public List<TutorialHint> 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;
}
}

View File

@ -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;
}
}

View File

@ -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";
}

View File

@ -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);
}
}