Friday, February 15, 2013

Design of First Milestone

The first milestone will be the initial playable version of the game.  It will probably not be made publicly available since it’ll have a limited feature set (read as: nearly nothing :P ).  However, it’ll be a good starting point before I start putting in large maps, random map generator etc and get an actual release-able game.

I’d like the feature set to be:

  • Menu System:
    • Main Menu (Play, Load, Quit)
    • In-game menu (Continue, Save, Load, Quit to main menu)
  • Gameplay
    • WASD camera control, no zoom
    • One map, 100x100, can be entirely loaded at once
    • Trees, bushes, grass which are harvestable
      • Different graphic when exhausted
    • Resource nodes: stone, clay
    • Animals, no AI (ie. do not move)
      • Different graphic when killed
    • People, no reproduction
    • Structures, just your stash, no graphical rewards

This of course implies many technical developments in the Cultura code base.

  • InputManager
    • MainMenuInputManager
      • CEGUI Main Menu
    • InGameMenuInputManager
      • CEGUI In-game Menu
    • GameInputManager
      • Camera control
      • Selecting units, keeping track of selected units
      • Context-sensitive right-click
        • Resources imply mining actions
        • Animals imply hunting actions
        • Empty space implies movement action
  • TerrainManager
    • Store a map
    • Create a scene based on loaded map and save file information (eg. trees chopped down should have the tree invisible and the tree stump visible)
    • Update of map state (eg. trees are chopped or regrow)
    • Selective update of loaded scene (don’t want to recreate the scene every frame, just update certain entities in scene such as setting a tree invisible when it is cut down and then making the tree stump visible)
  • GameEngine
    • Main loop
      • Render graphics in vsync (60 fps for most people), no graphic setting options for now, not full screen
      • Update tick at standard interval
        • Move units that are moving
        • Objects being attacked lose health
        • Resources being mined lose resources, units mining gain those resources up to carry limit
      • Send buffered input to different InputManager depending on AppStateManager
  • AppStateManager
    • Serialisation
      • Save map
      • Save tree, bush, grass status
      • Save animal position and status
      • Save people position and status (including resources carried)
      • Save structure position and status (including resources stored)
    • State Stack
      • Push/pop states as needed (Main Menu -> Game -> In-Game Menu)
    • Input Translation
      • Send to correct InputManager depending on state
  • UIManager
    • Main Menu scheme
    • Game overlay (show selected unit status, show resources at top right)
    • In-Game Menu scheme

Here is the overall initial design:



The following classes exist and will have these definitions:

  • Main
  • GameEngine
  • AppStateManager
    • GameState
      • ResourceManager
      • TerrainManager
    • UIManager
    • InputManager
      • MainMenuHandler
      • GameInputHandler
      • InGameMenuHandler

Main
  • Main loop
    • Capture input (sends to GameEngine)
    • UpdateTick with time since last update
    • Render frame
    • Message pump

GameEngine
  • Delegate input to AppStateManager
  • UpdateTick on AppStateManager per amount of time since last update

AppStateManager
  • Delegate input to InputManager
  • Change state if requested
    • ChangeOverlay on UIManager if state is changing
    • ChangeInputHandler on InputManager if state is changing
  • UpdateTick on gameState if in game state

InputManager
  • If changing game state, call init on proper handler given window

MainMenuHandler
  • New Game, requests state game, init GameState for new game
  • Load Game, requests load game state
  • Quit, request shut down

InGameMenuHandler
  • Continue, request game state
  • Save Game, requests save game state
  • Load Game, requests load game state
  • Quit, requests main menu state

LoadGameMenuHandler
  • Load Game, init GameState with selected file then request game state
  • Back, request in game menu state

SaveGameMenuHandler
  • Save Game, serialise GameState to disk using selected file name then request game state
  • Back, request in game menu state

GameInputHandler
  • Mouse Press
    • if left-click Record location
    • If right-click and have friendly selected units
      • If on empty ground, clear action stack, push move action to all units
      • If on mineable resource, clear action stack, push move action to location, push harvest action
      • If killable non-friendly unit, clear action stack, push move action to location, push attack action, push harvest action
  • Mouse Release
    • If left-click...
      • Use location from mouse press, use this location, draw box
      • Select all units in box, all friendly, or if no friendly, first non-friendly
      • Update selected units
  • Keyboard Key Press
    • If camera movement key move camera position (check if edge reached)

UIManager
  • On request, SetGUISheet based on game state passed, load resources as needed

GameState
  • Init, tell ResourceManager to load resources (will have to optimise lazy loading later)
  • Save, given filename then serialise to disk
    • Save map with default filename based on seed
  • Load, given filename load data and populate member variables
    • Set seed on TerrainManager
    • Send to TerrainManager after loaded current gameState (for static objects, trees, bushes, grass and resource nodes)
    • Call TerrainManager load
  • UpdateTick
    • Go through all units
    • Based on action update unit
      • If move, move unit closer to location, update position in scene
        • If at location, pop action from actionStack
      • If attack, check ticks since last attack, if attack speed allows then damage target (if target too far, push moveToTarget command to unit position)
        • Check if target can react
        • Check if target dies, update scene
      • If harvest, check carry limit and resource node, harvest as much as possible, update resources in node and carried by unit (if target too far, push move command to unit)
        • Check if resource node is used up, send update to TerrainManager
        • Check if unit is full, update scene
      • If moveToTarget, update position with current position of target, then move unit closer to location, update position in scene
        • If at location pop action from actionStack
      • (For future) If attackmove, move toward location.  If attacked then push attackLimitDistance with current position and target is the attacker
      • (For future) If attackLimitDistance, check ticks since last attack, if attack speed allows then damage target (if target too far, push moveToTargetLimitDistance with current location and target unless current distance from original location exceeds threshold)
        • Check if target can react
        • Check if target dies, update scene
      • (For future) If hold position, do nothing.  If attacked then push attackLimitDistance with 0 distance threshold (meaning you do not move from location)
    • Units heal automagically
      • If unit is in an active attack action, do not heal
      • If ticks since last heal is high enough, heal unit for 1 hp, reset counter


    TerrainManager
    • Save, know own seed, write to disk based on that to generate filename
    • Load, given a seed load from disk or generate new map
    • CreateScene/ReloadScene, given location on map, if loaded then create staticGeometry as needed, then process gameState to set objects visible/invisible as needed (later optimisation: this should keep track of loaded chunks and load/unload as needed)
    • UpdateScene, check change stack, set objects visible/invisible as needed

    ResourceManager
    • Init, load resource directories into Ogre
    • LazyLoad, load meshes as they are needed (does Ogre do this?)

    1 comment:

    1. FASCINATING! GOOD LUCK WITH ALL YOUR FANCY CODE STUFF!

      ReplyDelete