Salvation Prophecy: A Space Epic

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

kulik wrote:Very brave of you to delve into Falagard without visual tools.
I'm watching your work on CEED (Official Unified CEGUI Editor Tool) very closely. :)
CABAListic wrote:It's always amazing what a single person can accomplish. Great work! :)
Thanks! Just to clarify that, I've contracted out most of the artwork, music, and voice acting. But everything else (code, design, content, audio) is a one man (or should I say one very burnt out man) show. But even that's not true, without the help of Ogre, CEGUI, Ogitor, ParticleUniverse, PagedGeometry, Gorilla, and a few other libs, my game would look more like Atari asteroids. :) I think you need to be at least mid-thirties to get that joke.

Image

Image
Image
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

JoJoBo wrote:Do you have your own map editor or how do you generated the worlds ?
The landscapes are built with Ogitor Scene Builder
JoJoBo wrote:How do you manage enemy movement and obstacle avoidance ? for example with structures or trees ?
Do you use some special library or terrain map navigation or something else ?
I went old-school with my pathing. I use a path-node based approach. I'll describe this in a little more detail. But before I go on, path-node pathing is generally considered inferior to the more modern nav-mesh pathing, such as that implemented by recast detour. However, A* path-node pathing worked pretty well for me, and I was more comfortable working with this, given my limited time to devote to it.

So, first I construct my path map:
1. Every quad on the landscape is assigned a path node.
2. I determine if a path node is walkable by checking the slope of the terrain at that point, and also check to see if anything (like a rock) is obstructing that path node.
3. I solve paths using micropather, which is just an A* path solver, but it's very fast.

But A* path-node pathing is really just the start. It will tell you how to get from point A to point B, but it probably won't look good, as your AI characters zig-zag from path node to path node. So there are a ton of optimizations over the basic path-node chasing.
Examples:
  • if the AI character passes a "line of sight" check to its target (using a physics raycast query). then I just run directly towards it. (It's actually a little more complicated than this, but that's the general idea).
  • i detect if the AI character gets stuck (say on another AI character) by checking if the AI is trying to move, but remains in the same general position for too long. If stuck, I go into a separate "get unstuck" pathing routine.
  • the AI troops will do other things than just chase after their target. For example, AIs are aware of cover positions, which they may try to stand behind and use to their advantage, as a player would.
  • you don't always want to path to your exact target's position, but sometimes somewhere nearby to shoot at it.
Code-wise, I arrange all my basic pathing functions in a single system called the PathSystem. Then, I have AI tactic code which calls into this path system, depending on what it's trying to do.
My AI tactics have names like:

Code: Select all

   MeleeMonster_TacticSequenceType,
   ChargeTarget_TacticSequenceType,
   TakeCoverAndAttack_TacticSequenceType,
   PursueAndAttack_TacticSequenceType,
   StandAndFire_TacticSequenceType,
   StandAndMelee_TacticSequenceType,
   StrafeAndFire_TacticSequenceType,
   Flee_TacticSequenceType,
   ShootRocket_TacticSequenceType,
   ThrowBomb_TacticSequenceType,
   UseStim_TacticSequenceType,
   UseShieldGun_TacticSequenceType,
   ConstructTurret_TacticSequenceType,
   MechLaunchRocket_TacticSequenceType,
And just for anyone with way too much time on their hands, here's my PathSystem.h API, so you can see generally how I structure things. My game is closed source, but I don't mind talking about how I did things. No anti-singleton rants, please. ;)

Code: Select all

// Copyright (c) 2011 Firedance Games Inc
#ifndef __PATH_SYSTEM_H__
#define __PATH_SYSTEM_H__

// base class
#include "micropather/micropather.h"
#include "XML.h"

// ogre
#include "OgrePrerequisites.h"
using namespace Ogre;

// std
#include <map>
#include <vector>

// game
#include "ActionType.h"
#include "ChaseResultType.h"
#include "FactionType.h"
#include "MID.h"
#include "PathResultType.h"

// prototype
class ActorUserData;
class Decor;
class Landscape;
class Mobile;
class NxActor;
class Person;
class Ship;


// The PathSystem is the sister system of the FlightSystem.
// - The PathSystem is used for traditional pathing on a terrain.
// - The FlightSystem is used for 3D maneuvering in space.
// - See IndoorClassSystem.h for pathing inside a space station or other indoor structure.
//
// Pathing consists of 2 primary techniques:
//
// 1. "Straight Chase" Pathing
//
// - When there is a direct line of walkable terrain between the AI and its 
//   target, we will walk that direct line.
//
// - This is the preferred technique, because it's cheaper, and looks better.
//
// - If the target goes temporarily out of "straight chase" visibility, we
//   don't immediately give up the straight chase.  Instead, we remember where 
//   our last good "straight chase" target position, and move towards
//   that instead.  This is a very good optimization - it often allows the AI
//   to catch up with the target and re-achieve "straight chase" visibility.
//
// 2.  A* Pathing
// 
// - we use some middleware called "MicroPather" to implement our A* solver.
//
// - Good things about MicroPather:
//   * simple:  one include file, one cpp file, no external libs/dlls
//   * flexible:  it allows you to implement your own graph data structure.
//     This worked out well with how I used terrain heightmap data to form a 
//     graph out of walkable surfaces.
//   * focused:  written and optimized specifically for real time path planning
//     in games.  
//   * I also looked at the boost graph lib.  It was a highly templated generic
//     solution for all sorts of graph problems.  It would have been much more
//     tricky to integrate, harder to debug, and possibly slower due to the
//     way it was written to support many different graph problems.
//
// The PathSystem works very closely with:
// - class PathData:  Pathing data which gets cached on an AI (e.g. the path nodes leading to a target.)
// - class PathMap:  The graph of walkable terrain, owned by class Landscape.
// See discussion in PathData.h and PathMap.h
//
class PathSystem : public micropather::Graph, public XML
{
   //
   // System Singleton
   //
public:
   PathSystem();
   ~PathSystem();

   // Create the singleton instance
   static void Create();
   static PathSystem* GetSingleton() { return s_pSingleton; }

private:
   // There can only be one instance of a singleton
   static PathSystem* s_pSingleton;


   //
   // Lifecycle
   //
public:
   void Init();
   void Tick( float i_fSecFrame );


   //
   // Loading and Saving Game State
   //
public:
   // Loads data from a savegame file.
   // Savegame files are XML, and we are passed an XMLNode pointing to the data for this system.
   // This function is called either when we begin a new game, or the user loads a saved game.
   void LoadGameState( XMLNode& i_node );
   // Writes data for a savegame file.
   // Savegame files are in XML format, so we return an XMLNode containing all game state data for this system.
   // This function is called whenever the player saves the game.
   XMLNode SaveGameState( const char* i_szNodeName ) const;
   // Reinitializes all data back to the initial state of the system, to make sure that no data "leaks through"
   // (persists) from a previous game to the new game.
   // This should only ever be called by the LoadSaveSystem when we're loading a game.
   void ClearGameState();


   //
   // AI Calls
   //
public:
   // This is the high level API you want to use to make an AI pursue a target.
   ChaseResultType ChaseTarget( Person* i_pChaser, Mobile* i_pTarget, float i_fDistFound, float i_fSecFrame, ActionType i_eMoveAction = Walk_ActionType, ActionType i_eAvoidAction = Walk_ActionType, Degree i_degMoveThreshold = Degree( 45.f ) );
   // Alternate API for chasing a position rather than a target.
   ChaseResultType ChasePosition( Person* i_pChaser, const Vector3& i_posTarget, float i_fDistFound, float i_fSecFrame, ActionType i_eMoveAction = Walk_ActionType, ActionType i_eAvoidAction = Walk_ActionType, Degree i_degMoveThreshold = Degree( 45.f ) );
   // Strafing
   // You can just call this every tick and everything will work out.
   // Returns true if we're strafing
   bool DoStrafeIfTakingDamage( Person* i_pStrafer ) const;
   // A routine to make i_pPerson walk around mostly aimlessly.
   void Wander( Person* i_pPerson, const Vector3& i_posHome = Vector3::ZERO, float i_fDistLeash = -1 ) const;


   //
   // ChaseTarget Helper Functions
   //
private:
   // The position we should path towards isn't always the exact position of our target.
   // Examples:
   // - If the target is in an unwalkable position, we should pick a nearby walkable position
   // - if the target is huge, we should pick a point somewhere on its periphery.
   Vector3 GetChasePosition( Person* i_pChaser, const Mobile* i_pTarget );
   // For small objects, this just returns i_pTarget's position.
   // For some large objects, such as buildings, this will return a point on i_pTarget's periphery.
   //
   // The reason for this is because when pathing towards a large target, we will not be able to path
   // to it's center, because that point will be blocked by the object's physics.  So instead we
   // need to find a clear point around the edge of the target to path to.
   Vector3 GetLargeObjectPeripheryPoint( Person* i_pChaser, const Mobile* i_pTarget );
   // Helper for GetNearestPosition
   bool InqWalkablePeripheryPoint( Person* i_pChaser, const Mobile* i_pTarget, float i_fRadius, Vector3& o_posNearestPeriphery );
   Vector3 GetNearestUnobstructedWalkablePosition( const Vector3& i_pos );


   //
   // Strafing Helper Functions
   //
private:
   ActionType GetCurrentStrafeDirection( Person* i_pStrafer ) const;
   ActionType PickRandomStrafeAction() const;
   ActionType GetOppositeStrafeAction( ActionType i_eStrafe ) const;
   bool CanStrafe( Person* i_pStrafer, ActionType i_eStrafe ) const;


   //
   // Obstructions
   //
public:
   // If i_pMobile has been set as an obstacle (Mobile::m_bPathMapObstacle), then
   // it will be added to the PathMap.
   void RegisterObstacle( Mobile* i_pMobile );
   // This must be called when an obstacle is destroyed or removed from the scene, otherwise
   // AIs will keep pathing around the no longer existing obstacle.
   void UnregisterObstacle( Mobile* i_pMobile );

   // Same as above, except for decor objects.
   // Currently, we are not planning on making decor objects destructable, so there is no 
   // corresponding unregister call.
   void RegisterObstacle( Landscape* i_pLandscape, Decor* i_pDecor );

   // General code shared between all the RegisterObstacle public API functions.
   // - actually we now call this directly from outside the PathSystem for our PagedGeometry entities.
   void RegisterObstacle( Landscape* i_pLandscape, NxActor* i_pActor, MID i_mid );


   //
   // Pathing Techniques
   //
private:
   // 1. "Straight Chase" Pathing
   //
   // Note:  I pass in i_fDistTarget because usually the caller needs to calculate it anyways,
   //        and there's no sense in calculating it twice.
   //
   // Returns true if there is a straight-line chase path to our target.
   bool AttemptStraightChaseToTarget( Person* i_pChaser, Mobile* i_pTarget, Vector3 i_posChase, float i_fSecFrame, ActionType i_eMoveAction, ActionType i_eAvoidAction, Degree i_degMoveThreshold, bool i_bForceDetectAttempt = false ) const;

   // 2.  A* Pathing
   //
   // An A* path solver between two points on the terrain.
   PathResultType AttemptPathToTarget( Person* i_pChaser, const Vector3& i_posTarget, float i_fSecFrame, ActionType i_eMoveAction );


   //
   // Low Level Pathing Helper Functions
   //
public:
   // A low level function for turning to face the specified direction.
   // Note:  i_dirTarget must be localized to i_pChaser.
   // Note:  i_dirTarget is not const because we normalise it.
   void TurnTowardsLocalDirection( Person* i_pChaser, Vector3& i_dirTarget, float i_fSecFrame, bool i_bLimitDirectionSwitch = true ) const;
   // Alternate API which takes an absolute position to turn towards.
   void TurnTowardsPosition( Person* i_pChaser, const Vector3& i_posTarget, float i_fSecFrame, bool i_bLimitDirectionSwitch = true ) const;
   // Helper for TurnTowardsDirection
   // This keeps us from gyrating left and right while approximately being aimed at the target.
   bool HoneInOnDirection( Person* i_pChaser, Vector3& i_dirTarget, float i_fSecFrame ) const;
   // A low level function for moving directly towards the specified position
   void MoveTowardsPosition( Person* i_pChaser, const Vector3& i_posTarget, float i_fSecFrame, ActionType i_eMoveAction = Walk_ActionType ) const;
   // Returns true if i_pChaser is trying to move, but has been stuck in the same position for a while.
   bool IsStuck( Person* i_pChaser ) const;
   // Spin and jump to try to escape the stuck position.
   void TryToGetUnstuck( Person* i_pChaser ) const;
   // As simple as it sounds - a handy function to check if i_pPerson is walking or running.
   // If you want to count strafing as walking or running, set i_bIncludeStrafe to true.
   bool IsWalkingOrRunning( Person* i_pPerson, bool i_bIncludeStrafe = false ) const;
   // Does an LOS check and turns to avoid any obstacles in front of me.
   // Simple avoidance logic only - not powerful enough to handle complex paths!
   bool AvoidObstacles( Person* i_pPerson, const Mobile* i_pTarget, const Vector3& i_posDestination, float i_fSecFrame, ActionType i_eMoveAction = Walk_ActionType ) const;
   // Implements our logic to strafe left or right in response to a collided obstacle.
   // See header comments for PathData::SetCollidedPhysicsActor(..)
   bool StrafeAroundCollidedObstacle( Person* i_pPerson ) const;
   // Helper function for AvoidObstacles
   void RaycastForObstacles( Person* i_pPerson, const Mobile* i_pTarget, const Vector3& i_posDestination ) const;


   //
   // Terrain Queries
   //
public:
   // Returns true if the given position on the terrain is walkable.
   bool IsPositionWalkable( const Person* i_pPerson, const Vector3& i_pos ) const;
   // Returns true if the given path node on the terrain is walkable.
   // Path nodes are of type void* because of MicroPather integration.  
   // See PathMap.h, micropather.h, and especially MicroPather docs for more info.
   bool IsPathNodeWalkable( const Person* i_pPerson, void* i_pPathNode ) const;
   // Returns true if the straight line between the start and end positions can be walked over.
   // Parameter i_bNoNeighboringObstacles : See discussion in function body
   bool IsStraightLineWalkable( const Person* i_pPerson, const Vector3& i_posStart, const Vector3& i_posEnd, bool i_bNoNeighboringObstacles = false ) const;
   // Returns true if there is an adjacent walkable position to i_posStart.  If true, returns the adjacent
   // position in o_posAdjacent.
   bool InqAdjacentWalkablePosition( const Person* i_pChaser, Vector3& io_pos ) const;
   // Returns the walkable position if found.
   // Returns i_posUnwalkable if not found.
   Vector3 SearchForNearbyWalkablePosition( Person* i_pChaser, const Vector3& i_posUnwalkable ) const;
   // Returns true if i_pos is adjacent to an obstructed position.
   bool IsPathNodeAdjacentToObstacle( int i_iPathNode ) const;
   // Returns the number of adjacent obstructed path nodes.
   int GetNumAdjacentObstacles( int i_iPathNode ) const;
   // Returns the number of adjacent unwalkable path nodes.
   int GetNumAdjacentUnwalkables( int i_iPathNode ) const;
   // Returns true if this distance is within chasing range.
   // Returns false if this distance is too far away, and all pathing activities should cease.
   bool IsInPathingRange( float i_fDistTarget ) const;


   //
   // Cover
   //
public:
   void RegisterCover( const Vector3& i_pos );
   void RemoveAllCoverPositions();
   std::vector<Vector3> FindCoverPositions( const Vector3& i_pos, float i_fRadius ) const;
   Vector3 AssessThreatDirection( FactionType i_eFaction, const Vector3& i_pos, float i_fRadius, const Person* i_pPerson = 0) const;
   bool InqBestCoverPosition( const Person* i_pPerson, const std::vector<Vector3>& i_vecCoverPos, Vector3& o_posBestCover );
   void SetUsingCover( const Vector3& i_posCover, MID i_midPerson );
   void ClearCover( const Vector3& i_posCover, MID i_midPerson );
   bool IsCoverOwned( const Vector3& i_posCover ) const;


private:
   std::vector< Vector3 > m_vecPosCover;
   std::map< MID, Vector3 > m_mapCoverOwnedBy;


   //
   // Inherited Graph Functions, from micropather.h
   //
public:
   // Note:  *** THIS IS NOT MEANT AS A PUBLIC API ***
   //
   // These are all internal helper functions that you don't need to worry about as 
   // a user of this system.  But they must be public because of callbacks made from micropather
   // into this system.

   // PERF:  Consider inlining a bunch of these pathing functions?

   // From micropather.h:
   // Return the least possible cost between 2 states. For example, if your pathfinding 
	// is based on distance, this is simply the straight distance between 2 points on the 
   //	map. If you pathfinding is based on minimum time, it is the minimal travel time 
	//	between 2 points given the best possible terrain.
   float LeastCostEstimate( void* i_pPathNodeStart, void* i_pPathNodeEnd );

   // From micropather.h:
   // Return the exact cost from the given state to all its neighboring states. This
   // may be called multiple times, or cached by the solver. It *must* return the same
   // exact values for every call to MicroPather::Solve(). It should generally be a simple,
   // fast function with no callbacks into the pather.
	void AdjacentCost( void* i_pPathNode, std::vector< micropather::StateCost >* i_pAdjacent );

   // From micropather.h:
   // This function is only used in DEBUG mode - it dumps output to stdout. Since void* 
   // aren't really human readable, normally you print out some concise info (like "(1,2)") 
   // without an ending newline.
   void PrintStateInfo( void* i_pPathNode );

   // To convert from a position to a micropather "state" (i.e. PathNode).
   // See the micropather docs for more info on states.  A state is basically just a unique representation of a position.
   void* PositionToPathNode( const Vector3& i_pos ) const;

   // To convert from a micropather "state" to a position.
   // See the micropather docs for more info on states.  A state is basically just a unique representation of a position.
   // 
   // Note:  This only returns a 2D position because the state is a 2D x,y coordinate on the heightmap.
   // We could return a 3D position if needed.  To achieve this, we'd want to cache the absolute heights of all the
   // path nodes within Landscape::m_vecPathMap
   Vector2 PathNodeToPosition( const void* i_pPathNode ) const;

private:
   // We need to record who the chaser is before we call micropather::Solve.
   // This is because the graph functions called by micropather::Solve (such as AdjacentCost) 
   // need to take into account the GetMaxWalkableHeightDistance of the chaser.  But, since 
   // the graph APIs are defined by micropather, we can't pass in the chaser.
   // So, we'll just record it in a system variable, then query it from the graph functions.
   void SetCurrentChaser( const Person* i_pChaser );
   const Person* GetCurrentChaser() const;
   const Person* m_pCurrentChaser;


   //
   // Micropather solver
   //
public:
   // Not meant as a public API, but leaving this function public, so the ConsoleSystem can access it for testing.
   //
   // parameter:  o_path is an array of pathnode indexes, outlining the path from start to finish.
   //             Unfortunately, you will have to cast the void* vector values to integer pathnode indexes.
   //             This is a rough edge with the micropather API.
   //             See Landscape.h for more info on pathnode indexes.
   PathResultType SolvePath( const Person* i_pChaser,
                             const Vector3& i_posStart,
                             const Vector3& i_posEnd,
                             std::vector< void* >& o_vecPathNode,
                             float& o_fTotalCost );

   // For path debugging
   void DisplayPathNodes( std::vector<void*>& i_vecPath ) const;
   void DisplayPathMap( const Person* i_pPerson, const Vector3& i_posCenter, int i_nNodesPerEdge );

   // If we change the PathMap in any way (i.e. costs between path nodes change),
   // we need to reset the cached data stored by m_pPathSolver.
   // Example:  when we add obstacles to the path map.
   // See the MicroPather docs for more info on resetting the cache.
   void ResetPathCache();

private:
   // This gets set by SetActiveLandscape.
   // It will be deleted and re-newed as different landscapes are activated.
   //
   // TODO:  It's not going to work to have only one solver, with multiple
   // creatures of different PathData:;GetMaxWalkableHeightDifference().  The cache
   // will get all messed up.  
   // This is yet another reason to revisit this cache, and potentially disable it completely.
   // Or maybe maintain multiple path solvers for creatures of different height ranges.
   micropather::MicroPather* m_pPathSolver;
   

   //
   // Active Landscape
   //
public:
   void SetActiveLandscape( Landscape* i_pLandscape );
   void ClearActiveLandscape();

private:
   // Cache a pointer to the current Landscape Scene.
   // This prevents us having to constantly do a dynamic_cast<Landscape*> operation inside the performance critical
   // A* pathing functions.
   Landscape* m_pActiveLandscape;


};


// Syntactic convenience function.
inline PathSystem* PathSys()
{
   return PathSystem::GetSingleton();
}

#endif // __PATH_SYSTEM_H__
Image
JoJoBo
Gnoblar
Posts: 7
Joined: Mon Jul 16, 2007 12:06 am

Re: Salvation Prophecy: A Space Epic

Post by JoJoBo »

@Jabberwocky : Thanks for the overall description :)
I'm not skilled programmer, but i'll perhaps incorporate some ways and ideas you use in your game.

Some last question for target cover, how do you determine if the monster is covering well ? Do you use the bouding box ?
Caus if you use only the physic ray intersection going from player weapon laser or shotgun to ennemy body center,
the ennemy will cover but you will be able t ohit the arms for example that won't be covered ?

Or is ray collision enough when in game finally ?

Crysis game uses some sort of covert points that are placed on models or in the scene editor, they are just 3D positions around a 3D model like 4 positions for example, and the AI will use them to cover.
that's predifined cover positions, but it works pretty well, specially when playing the game.
User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia
x 81

Re: Salvation Prophecy: A Space Epic

Post by Mind Calamity »

Hey Jabberwocky, can you recommend me/us some resources on gameplay programming, and the basic concepts of gameplay development, since I have basically not idea how to put the gameplay mechanics (fighting, world interaction, etc...) together, at all...

Any books/articles/whatever you've read that you can recommend ?
Last edited by Mind Calamity on Sat Sep 24, 2011 3:58 pm, edited 1 time in total.
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
dudeabot
Gnome
Posts: 334
Joined: Thu Jun 28, 2007 2:12 pm
Location: Brazil
x 5
Contact:

Re: Salvation Prophecy: A Space Epic

Post by dudeabot »

hummm i guess there are some worlds, so how are you doing the transitions from world to the another?

have you separeted it into zones, or is there some type of seamless integration?
User avatar
DanielSefton
Ogre Magi
Posts: 1235
Joined: Fri Oct 26, 2007 12:36 am
Location: Mountain View, CA
x 10
Contact:

Re: Salvation Prophecy: A Space Epic

Post by DanielSefton »

Awesome work. I'm sure most people would give up pretty fast on such an ambitious project, but you just keep going and going! I hope it does well :)
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

JoJoBo wrote:Some last question for target cover, how do you determine if the monster is covering well ? Do you use the bouding box ?
I don't hand-pick my cover positions. Although that's certainly a good technique, especially for complex indoor levels.
But my fighting occurs on landscapes, and I automatically calculate my cover positions.

It works something like this:

1. Cover List
Keep a list of all possible things you can hide behind.
For example, for one of my scene.xml files, I have this list of cover:

Code: Select all

   <mesh_name_cover>ThreeLeafTreeSmall.mesh</mesh_name_cover>
   <mesh_name_cover>ThreeLeafTreeMedium.mesh</mesh_name_cover>
   <mesh_name_cover>LightBulbPlant.mesh</mesh_name_cover>
   <mesh_name_cover>rockround1.mesh</mesh_name_cover>
   <mesh_name_cover>rockround2.mesh</mesh_name_cover>
This means that any of these 5 meshes are possible things an NPC can find cover behind.
If each mesh was placed on the landscape 20 times, that would make 5 * 20 = 100 potential cover objects.

2. Pick one of these cover objects

If an NPC wants to go into cover, I query what cover objects are nearby, and pick one.

3. Assess the threat direction

I look at where the enemies are relative to the cover object.
Example, let'say the cover object is at position (100,10,100) and is 2 meters wide.
And there are three nearby enemies at positions (200,10,100), (250,10,50), (150,10,150)
Then:

Code: Select all

average_enemy_position = (200,10,100) + (250,10,50) + (150,10,150) / 3 = (200, 10, 100)
cover_object_position = (100,10,100)
enemy_direction = normalize ( average_enemy_position - cover_position ) = (1,0,0)  
cover_object_radius = 2
4. Calculate the cover position
The rest is simple, I look at which side the threat is coming from, and take cover on the other side.

Code: Select all

cover_position = cover_object_position - enemy_direction * cover_object_radius;
Possible improvements:
- rank each nearby cover position to see which one provides the best cover from all nearby enemies based on the calculated cover_position, and choose that one.
- only consider enemies who are actively shooting at you.
Mind Calamity wrote:can you recommend me/us some resources on gameplay programming

Sorry I didn't get back to you on this sooner. It looks like you already got some good feedback in this thread. I browsed through some of the content on amazon, and they look pretty good.
dudeabot wrote:how are you doing the transitions from world to the another?
Yep, zones. Seamless transitions are very cool, but are a lot of hard work. A person could easily spend years working on this stuff, and I wanted to make a game instead of new technology. Not that there's anything wrong with creating new tech, it just wasn't my goal.
Image
JoJoBo
Gnoblar
Posts: 7
Joined: Mon Jul 16, 2007 12:06 am

Re: Salvation Prophecy: A Space Epic

Post by JoJoBo »

Thanks a lot , i'm inspired now, to try making some similar system !
I think precise cover is needed on "ultra realistic" FPS games where we don't want to be able to kill ennemies throught some
cover having holes and see the ennemy not reacting caus the AI is limited ; but for your game style it's perfect (as this is not ultrarealistic FPS game) .
For the Zones , i'm also in this state of thinking , i want more to make a game than waste years on technology without delivering any game.

I 've seen old versions of your game and the progress in 3D assets is really big, they are now very polished, but the old version
was not that bad and showed already gameplay.
Have you taken a 3D artist to make the 3D assets like interior rooms and stuff ? or it's you that have refined the models and texwtures ? Caus the progression is amazing between new and old version.

I think you will be successfull with your game :)
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Salvation Prophecy: A Space Epic

Post by jacmoe »

Its simply amazing! :D
It was mindbending the last time it was showcased, but now..
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

JoJoBo wrote:I think precise cover is needed on "ultra realistic" FPS games...
Agreed. This was written very specifically for the kind of game I am creating.
JoJoBo wrote:Have you taken a 3D artist to make the 3D assets like interior rooms and stuff ? (...) Cause the progression is amazing between new and old version.
Yes, most of what you see now is contracted artwork. Although I have gotten very good at modeling rocks myself. ;)

When I started the project, I bought a few basic textures and models. I also learned the basics of 3ds max, and built a few things myself.

This gave me enough art to implement things like character control, animations, combat, physics, shaders, and my content pipeline for building planets and stations. So when I started buying art later on, I knew exactly what I needed. And I was also able to integrate artwork immediately, and detect if there were any problems. Plus, the artists got feedback for seeing their stuff in-game more quickly.
JoJoBo wrote:I think you will be successfull with your game :)
Thanks! I hope so.
I'm a little worried about being finished at approximately the same time as Star Wars: The Old Republic. You know, just one of the most anticipated Science Fiction games of all time. :shock:
But since Salvation Prophecy is single player, and SW:TOR is an MMO, maybe we appeal to different crowds.
Image
JoJoBo
Gnoblar
Posts: 7
Joined: Mon Jul 16, 2007 12:06 am

Re: Salvation Prophecy: A Space Epic

Post by JoJoBo »

I'm a little worried about being finished at approximately the same time as Star Wars: The Old Republic
Well you can delay your game about 2 or 3 months after the game this mmo is arriving ? perhaps you could polish some things or add new extra content ?
Anyway if your price is not 60 Euros and more indie price this is not a problem, and your game have is own universe and design, it's not something
we all know, it's original and polished, no need to pay each month to play, so you don't need to worry.
What will matter is the popularity the game will encounter and some advertising :)
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Salvation Prophecy: A Space Epic

Post by jacmoe »

I wouldn't worry too much. :)

Personally, I loathe everything "MMO-ish", and I am (probably) not alone.
Well, maybe that's an exaggeration, but I read books and play games and really appreciate that experience - single-player engrossment (if there is such a word). :wink:
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

Thanks, I hope you're right. :)
But I agree, there's definitely a lot of folks who won't go anywhere near an MMO.
It'll cost significantly less than a regular full priced game, although I haven't settled on an exact price yet.
Image
User avatar
DavlexDesign
Orc
Posts: 400
Joined: Thu Apr 23, 2009 7:23 am
Location: Australia
x 19
Contact:

Re: Salvation Prophecy: A Space Epic

Post by DavlexDesign »

G'day Jabberwocky,

I hope it all goes well for you mate, definitely looks good.
I know I'll be buying it when it comes out.

Alex
Nems
Gnoblar
Posts: 3
Joined: Mon Jan 19, 2009 5:17 pm

Re: Salvation Prophecy: A Space Epic

Post by Nems »

Niice ! The gameplay AND the graphic look very good.
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: Salvation Prophecy: A Space Epic

Post by duststorm »

I'm really impressed. Your detailed descriptions are really interesting, thanks for sharing them with us.
Hats off for the massive amount of work you did on your own, the result is something to behold.
How long is this project in development?
Developer @ MakeHuman.org
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

Hey Duststorm,

I've been working on Salvation Prophecy for 0ver 4 years now. If I'd known it'd take so long, I might have done something easier. ;)
Image
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: Salvation Prophecy: A Space Epic

Post by duststorm »

I see what you mean, and have a feeling that a lot of people on these forums are in the same boat in some way. :)
Even though the time I put into my project is still far less (about two years on and off in my spare time), these things really take their time.
Sometimes I think you need to be a little nuts to keep going at it, or be really devoted. ;)
Developer @ MakeHuman.org
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

Yeah, insanity is the secret ingredient for sure. ;)

________

I just wrote up a blog on gamasutra (a game developer news site) called Challenges of Designing a Space Sim for anyone who is interested in that sort of thing.
Image
User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia
x 81

Re: Salvation Prophecy: A Space Epic

Post by Mind Calamity »

Nice job on the Gamasutra article, Jabberwocky, it should help anyone who decides to make their first game a space simulation.

Maybe this is not a thing you'd want to share, so I might sound a bit nosy or rude, but I'm going to ask it anyway.

Can you please share which libraries you used in combination with OGRE, and if possible post the list of the source and header file names (stupid question, but it's going to help anyone like me who's lost at how to structure a game source code) ?
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

HOW DARE YOU ASK ABOUT MY HEADER FILES YOU BASTARD!!!! :shock:

heh, just kidding. :lol:

Are you asking about the entire list of source/header file names for my project? Or just the ones related to the libs I use? I'm fine with sharing either.

As for libraries:
  • Graphics: Ogre
  • UI: CEGUI
  • Physics: PhysX
  • Sound: FMOD
  • Input: OIS
  • Particles: Particle Universe
  • Landscape Editor: Ogitor
  • Mesh exporting and station interior editor: OgreMax + 3dsmax
  • Mesh viewing: OgreMeshy
Image
User avatar
spacegaier
OGRE Team Member
OGRE Team Member
Posts: 4304
Joined: Mon Feb 04, 2008 2:02 pm
Location: Germany
x 135
Contact:

Re: Salvation Prophecy: A Space Epic

Post by spacegaier »

[OT]
Jabberwocky wrote:HOW DARE YOU ASK ABOUT MY HEADER FILES YOU BASTARD!!!! :shock:
Damn, you frightended me :D ! When I first glanced at that post I only had one thought in my mind:

WTF?!?!?!

[/OT]
Ogre Admin [Admin, Dev, PR, Finance, Wiki, etc.] | BasicOgreFramework | AdvancedOgreFramework
Don't know what to do in your spare time? Help the Ogre wiki grow! Or squash a bug...
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Salvation Prophecy: A Space Epic

Post by Jabberwocky »

Hehe, another victim of my twisted sense of humor. :twisted:
Image
User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia
x 81

Re: Salvation Prophecy: A Space Epic

Post by Mind Calamity »

@"twisted" joke: Same reaction as spacegaier to be honest. :D

Well... Both would be very helpful, especially the former...

Now that I think about it, you and this thread gave me more knowledge than any book I've scrolled-through. (I never read books completely :D )

Thanks for the list of libraries, and a question related to that - I wonder why you chose FMOD over any of the open-source/free alternatives, any specific reasons ?

Also, did you use Byatis or Cthugha ?

BTW - Are you planning on releasing a demo too ? Because for now I have no way of buying games, so I have to get by with demos.
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
Post Reply