Jump to content

  • Log In with Google      Sign In   
  • Create Account


SeiryuEnder

Member Since 02 Dec 2008
Offline Last Active Jun 28 2014 04:27 PM

#4945953 Main game loop design

Posted by SeiryuEnder on 03 June 2012 - 05:34 PM

  • what would you have HandleInput() do within an individual Object::Update?


That depends on the object.. Generally you have an ObjectManager that contains a list of Object*.
Then you have other objects that derive from the parent object and do different things.

Something like this (untested code):
class Animal
{
public: virtual void Talk() = 0;
};

class Cat : public Animal
{
public: void Talk() { say( "Meow" ); }
};

class Dog : public Animal
{
public: void Talk() { say( "Woof" ); }
};

class Bird : public Animal
{
public: void Talk() { say( "Chirp" ); }
};

class AnimalManager
{
public:
	 Add( Animal* _animal ) { m_Animals.push_back( _animal ); }
	 AllTalk()
	 {
		  for( int i = 0; i < m_Animals.size(); ++i )
			   m_Animals[i]->Talk();
	 }

private:
	 std::vector<Animal*> m_Animals;
};

int main()
{
	 Cat cat;
	 Dog dog;
	 Bird bird;
	 AnimalManager mgr;

	 mgr.Add(&cat);
	 mgr.Add(&dog);
	 mgr.Add(&bird);

	 mgr.AllTalk();

	 return 0;
}

  • what are some examples of what m_Events.Update() might include?


Simple Event System

  • If opjects are being moved one at a time, where would collisions be handled? Would that be within m_ObjectManager.Update after all the individual Object::Update methods have been called?


Different people handle it different ways. Some people move the collision check out of the object and make it part of the object manager. Some people do it through events, and keep track of objects they've collided with that frame so that they don't multiply collide. There are other solutions as well. Do a little Googling and find a solution that works for you.


#4945930 Main game loop design

Posted by SeiryuEnder on 03 June 2012 - 04:21 PM

That's a highly procedural approach.
Generally my update loop will go something like (this is complete pseudocode mind you...):

void Game::Update( float _delta )
{
	 m_Input.Update();
	 m_ObjectManager.Update( _delta );
	 m_Sound.Update();
	 m_Render.Update(); // <== Does the actual rendering
	 m_Events.Update();
}

void Object::Update( float _delta )
{
	 HandleInput();
	 UpdateAI( _delta );
	 UpdatePhysics( _delta );
	 UpdateRenderInfo(); // <== Update render information, doesn't actually render the object
}

Bear in mind there's a really good chance I'm missing something, but the logic behind this ordering is as follows:
Update Input first, as Input may raise events and needs to be readily accessible to other systems.
Update Objects second, they may create/play/stop audio assets and have to tell the renderer what to do.
Update Events last so that any events raised by other systems can be handled.

If I could offer some advice though... Don't worry about throttling yet. Worry about optimization once you get things working.


#4945915 What Order To Code In?

Posted by SeiryuEnder on 03 June 2012 - 03:28 PM

I couldn't agree more with JTippetts. Game programming is going to really challenge your self discipline; there's an uncountable number of projects scrapped because of lost interest. If you're not constrained by milestones and deadlines, do whatever motivates you at the time. Don't leave unfinished code - wrap up whatever you're working on - but generally it's a bad idea to keep working on something if you're deadlocked or just really disinterested.

The biggest thing to keep in mind about the UI is that it is purely about FEEDBACK. It is 100% INFORMATIVE.
I typically open a console (will add some code for that below) and make that last until many of the core systems are in place/functional.

As for the UI, the most critical thing you can do is sit down and DRAW OUT YOUR UI ON PAPER!!
Seriously, don't skip this step. Draw it a few times. Make changes on paper. It will save you so much time.
You will almost certainly go through several revisions, but you want to be as prepared as possible.

Generally speaking, for every hour you spend designing you will spend 10 fewer hours implementing.


-edit

Almost forgot to add the console code.
There's a couple ways of doing this. The easiest (if you're using visual studio) is to go to:
Project Properties -> Linker -> System and set your subsystem to console. In the older version of MSVC that would allow you to open a console window while running an application.

If you have trouble with that or it's not an option for you, you can also add this code to your WinMain:

#if defined(_DEBUG)
// Open a debug console window
    HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
    int hCrt = _open_osfhandle((long) handle_out, _O_TEXT);
    FILE* hf_out = _fdopen(hCrt, "w");
    setvbuf(hf_out, NULL, _IONBF, 1);
    *stdout = *hf_out;

    HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
    hCrt = _open_osfhandle((long) handle_in, _O_TEXT);
    FILE* hf_in = _fdopen(hCrt, "r");
    setvbuf(hf_in, NULL, _IONBF, 128);
    *stdin = *hf_in;
#endif


From there, you should be able to use std::cout to print to the console


#4945696 What Order To Code In?

Posted by SeiryuEnder on 02 June 2012 - 06:54 PM

I'm not familiar with CoronaSDK, but usually my dev cycle is something like:
  • Barebones world (just some land)
  • Console output, relevant debug text
  • Simple collision/Input
  • More complex UI
  • Refine World
  • Refine UI
  • Repeat 5-6 until gold
'World' refers to general features like rendering or audio.
In a production environment normally you have a set of features you're responsible for, so knowing what to work on is rarely an issue (esp. with publishers Posted Image)

The advantage of working indie is that once things are working on a very basic level, you can decide what you want to do when you want to do it.
If I could offer some advice though, try not to be too jumpy between systems. Lots of bugs happen that way.


#4945671 Any video formats that are free to use?

Posted by SeiryuEnder on 02 June 2012 - 04:38 PM

I didn't realize this was such a tumultuous legal issue... I knew generalized patent laws were out of hand but this is just absurd.
I'm surprised someone hasn't patented breathing. We can only hope that big-business money mongers will eventually realize
that inhibiting progress like this is just shooting themselves in the feet.

FYI: Bink is really easy to implement, I recommend it if you've got the $8,500 in your budget.


#4936927 Rotating a Sprite Around Its Center Directx11

Posted by SeiryuEnder on 02 May 2012 - 07:20 PM

It's been a while since I've done work with matrices but...

Try changing:
		return translation * rotationZ * scale;

To:
		return rotationZ * translation *  scale;


It seems like you're rotating then translating in the direction of the rotation.
You want to translate it to its intended position first, then rotate it to the desired orientation.

Could be wrong, but it's pretty quick to test... I'm also not sure about the ordering on the scalar matrix. It might be fine where it is, I'd have to dig up some old code to verify.


#4915602 Organizing and managing code?

Posted by SeiryuEnder on 22 February 2012 - 01:06 PM

I'm not sure what IDE you're using, I'm going to assume MS Visual Studio since it's arguably the most commonly used.


Debugging:

If your applications are closing on errors, you're probably running under release or have debugging disabled for some reason. When an error occurs under debug in MSVC, it will set a breakpoint at the line that crashes. This may be in your code or (commonly) inside a function whose source you may not have access to. Simply find your stack and follow it up until you find familiar code, step through and make sure you don't have any bad values. There are a lot of different techniques for debugging, you really need to find a good book on it.


Memory Management:

I am actually not a fan of "smart pointers", I feel like too much reliance on them signifies a weak architecture. However, they are still a common and useful utility. It's a good idea to get familiar with them. You should also look into memory pools and resource management. There are a lot of ways to manage memory, the most correct method depends on your needs for that specific project. You absolutely do need to use some sort of memory profiling. There are many free solutions. At the very least, you should check out this MSDN topic for simple leak detection.


#4913552 OOD- Abusing States?

Posted by SeiryuEnder on 15 February 2012 - 09:04 PM

It really depends on the scope of your project. If you know 100% that your player file won't get very complex, you're probably
best off defining a simple enumerated state and maybe defining some transition functions. If your player may get expansive,
I'd suggest using a more complex state system.

This prompted me to look up some of my old game source, in one of my games I found a polymorphic state machine.
Knowing what I know now, I would probably expand the state machine to use these states like a map, strictly defining
possible state transitions. In this example code, states transition themselves. I would maintain that behavior, but restrict
it to sibling nodes.

Using states like these are a great way to switch from hard-coded to scripted behavior. Instead of defining an object for
every state, you can have a ScriptedState object with a loaded script reference.

The global state defines character interactions with the world regardless of what state they are in.
You may be better off omitting this state and maintaining that behavior within the player class, it's up to you.

BaseObject.h
template <class ENTITY_TYPE>
class IBaseObjectState
{
	 public:
	 IBaseObjectState(){}
	 virtual ~IBaseObjectState(){}

	 virtual void Begin(ENTITY_TYPE*)=0;
	 virtual void Execute(ENTITY_TYPE*)=0;
	 virtual void End(ENTITY_TYPE*)=0;
};

CharacterStateIdle.h

class CharacterStateIdle : public IBaseObjectState<PlayerObject>
{
	 private:
	 float m_fTimeSpent;  // The time we've been idle (to trigger the "waiting" animation)
	 SCTimer *m_pTimer;

	 // Constructor List
	 CharacterStateIdle();
	 ~CharacterStateIdle();
	 CharacterStateIdle(const CharacterStateIdle &ref);
	 CharacterStateIdle &operator=(const CharacterStateIdle &ref);

public:
	 void Begin(PlayerObject *pOwner);
	 void Execute(PlayerObject *pOwner);
	 void End(PlayerObject *pOwner);
};

IObjectStateMachine.h
template <class ENTITY_TYPE>
class IObjectStateMachine
{
private:
	 ENTITY_TYPE* m_pOwner;
	 IBaseObjectState<ENTITY_TYPE>* m_pCurrentState;
	 IBaseObjectState<ENTITY_TYPE>* m_pPreviousState;
	 IBaseObjectState<ENTITY_TYPE>* m_pGlobalState;

public:
	 IObjectStateMachine(ENTITY_TYPE* owner) : m_pOwner(owner), m_pCurrentState(0),
						 m_pPreviousState(0), m_pGlobalState(0);

	 void SetCurrentState(IBaseObjectState<ENTITY_TYPE>* s){m_pCurrentState = s;}
	 void SetGlobalState(IBaseObjectState<ENTITY_TYPE>* s) {m_pGlobalState = s;}
	 void SetPreviousState(IBaseObjectState<ENTITY_TYPE>* s){m_pPreviousState = s;}

	 void Update() const
	 {
		  if (m_pGlobalState)   m_pGlobalState->Execute(m_pOwner);
		  if (m_pCurrentState) m_pCurrentState->Execute(m_pOwner);
	 }

	 void ChangeState(IBaseObjectState<ENTITY_TYPE>* pNewState)
	 {
		  if (pNewState == m_pCurrentState) return;
		  m_pPreviousState = m_pCurrentState;
		  m_pCurrentState->End(m_pOwner);
		  m_pCurrentState = pNewState;
		  m_pCurrentState->Begin(m_pOwner);
	 }

	 void  RevertState() { ChangeState(m_pPreviousState); }

	 IBaseObjectState<ENTITY_TYPE>*  CurrentState()  const{return m_pCurrentState;}
	 IBaseObjectState<ENTITY_TYPE>*  GlobalState()   const{return m_pGlobalState;}
	 IBaseObjectState<ENTITY_TYPE>*  PreviousState() const{return m_pPreviousState;}
	 bool  isInState(const IBaseObjectState<ENTITY_TYPE>& st) const;
};



#4913314 Help with tiled maps

Posted by SeiryuEnder on 15 February 2012 - 06:16 AM

I'm not sure what your language, OS, or scripting interface is; so I'm going to answer as if you're in Windows C++.
It's been several years since I've made a tile-based game, so bear with me. These are the highlights that I remember.

Tile maps:
The key thing to realize is that tile maps can have multiple "layers".
Primary layer: where your character runs around.
Foreground layers: objects 'in front' of your character, usually scrolls faster than primary layer
Background layers: objects 'behind' your character (IE scenery), usually scrolls slower than primary layer
Collision layer: non-visible areas where the character will 'collide' with the world. May define several types of collision, such as slopes or different terrain (ice)
Trigger layer: Areas that cause an event when something enters them (player, enemy, etc)

Refer to TehOwn's post for more information about tile collision.



Mouse Input & bullet firing:
You really want your input to be hardware accelerated, but to get things going quickly you can use the windows function GetCursorPos(LPPOINT).
This returns a point in screen space, you need to convert it to client space.

PSEUDOCODE

void Player::UpdateGun()
{
	 // This buffers the input, so we aren't shooting a bullet
	 // every frame the left mouse button is held
	 static bool bMouseWasClicked = false;

	 // Check if the left mouse button is pressed
	 if( GetAsyncKeyState( VK_LBUTTON ) && !bMouseWasClicked )
	 {
		  POINT mousePos;
		  float bulletDirX, bulletDirY;
		  bMouseWasClicked = true;

		  // Get current position of mouse
		  GetCursorPos( &mousePos );
		  ScreenToClient( hWindow, &mousePos );

		  // Get a vector from the gun to the mouse
		  bulletDir.x = mousePos.x - m_Gun.x;
		  bulletDir.y = mousePos.y - m_Gun.y;

		  // Normalize the direction vector
		  float mag= sqrt( bulletDirX * bulletDirX + bulletDirY * bulletDirY );
		  if( mag == 0.0f ) mag = 1.0f;
		  bulletDirX /= mag;
		  bulletDirY /= mag;

		  // Tell the gun which way to fire
		  m_Gun.Fire( bulletDirX, bulletDirY );
	 }
	 else
	 {
		  bMouseWasClicked = false;
	 }
}


This is completely untested code, but that's the general idea.


#4913308 Java or C++?

Posted by SeiryuEnder on 15 February 2012 - 05:44 AM

As some of the other posts stated, game development techniques are typically language independent.

There are plenty of very successful games that are made using languages other than C++.
These are usually web-based or mobile games, where platform-independent languages/IDEs really shine.
If those are the types of games you want to work on, you're fine with Java.

If you aspire to work on console or big PC titles, you will need to learn C++ at some point.
Much of the example code you find for various techniques will be written in C++, so a rudimentary knowledge couldn't hurt.
Personally, C++ is my favorite language. It has an admittedly steep learning curve, but it's well worth the effort.

You will probably wind up learning several programming languages, they are each useful for different things.

Best of luck!


#4907630 Looking For Programmers

Posted by SeiryuEnder on 30 January 2012 - 08:29 AM

If I may offer you some advice, you really need to slow down and take smaller steps.

Your ambition to make games is great. It's good that you realize making games takes a lot of work.
However, without a background in making games you're simply taking on too big of a challenge.

Think about it this way, when you start a game you normally don't face the final boss immediately, right?
You have to build up your character/party, gain a lot of experience, and get the proper tools.

Try making a top-down shooter or small beat-em-up. Simple arcade games have their own challenges
that may surprise you.


#4907626 Play mp3 sound files in C++

Posted by SeiryuEnder on 30 January 2012 - 08:15 AM

Just to build on this response a bit, here are some common sound APIs I've run into:

FMOD
WWISE
DirectSound
OpenAL


In my experience, FMOD is the easiest sound library to get up and running as a programmer.

WWISE is the API of choice for most audio engineers.
It gives them a lot of flexibility but will require a lot more patience to set up in code.
Fortunately, it's pretty well documented.

My knowledge on DirectSound and OpenAL are somewhat limited.
I remember OpenAL's documentation was poor and I'm not sure if it is still supported.


PARTNERS