Vamos a ver: los objetos de un engine como los haceis, con variables globales, con Singletons, ...?
Lo suyo esque estos elementos, Managers, Renders, y otros se puedan acceder desde cualquier parte del codigo. A mi manera de verlo seria tener
una clase Engine que se encarga de crear el resto de Interfaces (Managers, Render,..)
main.cpp
--------------
#include "engine.h"
main()
{
engine.init();
engine.end();
}
myGame.cpp
---------------
#include "engine.h"
....
IRender.clearScreen();
IInput.update();
IRender.swapBuffers();
...
mas o menos. Y si no es asi como es es??????
Pues depende del objeto que de cada cosa y de cómo pienses programar; si es orientado a objetos, si no..
Yo lo que tengo es una clase unica para gestionar la escena (CScene.. original eh? :P) y ella es la que se encarga de manejar todo lo que se ve y lo que tiene que ser renderizado o no.
Luego están las camaras que son punteros a objetos (en c++) facilmente referenciables e intercamviables y todo lo que se pueda ocurrer.
Para los manejadores (mala traduccion del inglés, que pasa) de texturas y de entidades si que utilizo clases "singleton" porque a ella acceden todas las entidades que se crean.
El main de la aplicacion es simplemente para el Loop del juego.
Hay por internete muchas discusiones sobre esto y libros específicos, así que te recomiendes que mires cositas y luego te pongas a discurrir lo que sería mejor en cada caso. Yo lo que suelo hacer cuando tengo que aprender algo es ponerme a progrmar y luego mirar otras cosas a ver cómo lo hacen los demas, para aprender, y no suele ser tan diferente que mis propios razonamientos.
Un saludor!
Yo, a la hora de comenzar con un motor nuevo, que ya van unas pocas de veces (nooo) , lo primero que suelo hacer es dividirlo todo en namespaces, con los tipicos: kernel (parte central), video, audio, net, input, net y util (esto seria como un cajon desastre).
Las clases que ayudan con piezas unicas (como tarjeta de video, sonido, o la propia aplicacion), suelo hacerlas singletones, pero sin usar templates que luego dan problemas, al estilo de esto:
//////////////////////////////////////////////////////////////////////////////
/// \class iScene
/// \brief escena
/// \author Martin B.R.
//////////////////////////////////////////////////////////////////////////////
class ZGE_API iScene : public iBase
{
public:
////////////////////////////////////////////////////////////////////////////
/// \brief Obtiene una instancia unica al sistema de escena
/// \param
/// \return Instancia unica
/// \author Martin B.R.
////////////////////////////////////////////////////////////////////////////
static iScene *Instance();
private:
static iScene *m_pInstance;
};
donde iScene::Instance() es
iScene *iScene::Instance()
{
if (!m_pInstance)
m_pInstance = (iScene*)new cScene();
return m_pInstance;
}
La clase kernel, que tu llamas Engine, se encargaria de crear inicialmente todos los sistemas, manejar el tiempo, tareas, eventos de aplicacion etc etc.
La aplicacion seria algo asi como:
//////////////////////////////////////////////////////////////////////////////
/// \class iApplication
/// \brief Aplicacion de ZGE
//////////////////////////////////////////////////////////////////////////////
class ZGE_API iApplication : public iBase
{
public:
////////////////////////////////////////////////////////////////////////////
/// \brief Constructor
/// \param
/// \return
////////////////////////////////////////////////////////////////////////////
iApplication();
////////////////////////////////////////////////////////////////////////////
/// \brief Cosas que hacer cuando se crea la aplicacion
/// \param
/// \return Exito
////////////////////////////////////////////////////////////////////////////
virtual HRESULT OnInitialize() { return S_OK; }
////////////////////////////////////////////////////////////////////////////
/// \brief Actualizacion de la aplicacion
/// \param fDeltaTime Tiempo (en segundos) desde la ultima llamada
/// \return Exito
////////////////////////////////////////////////////////////////////////////
virtual HRESULT OnUpdate(float fDeltaTime) { return S_OK; }
////////////////////////////////////////////////////////////////////////////
/// \brief Cosas que hacer en el tiempo de render
/// \param fDeltaTime Tiempo (en segundos) desde la ultima llamada
/// \return Exito
////////////////////////////////////////////////////////////////////////////
virtual HRESULT OnRender(float fDeltaTime) { return S_OK; }
////////////////////////////////////////////////////////////////////////////
/// \brief Cosas que hacer en Denver cuando estas muerto XD
/// \param
/// \return
////////////////////////////////////////////////////////////////////////////
virtual void OnRelease() { }
////////////////////////////////////////////////////////////////////////////
/// \brief Fin de la ejecucion
/// \param
/// \return
////////////////////////////////////////////////////////////////////////////
void Exit();
};
Todo esto esta sacado de un un pequeño engine que empeze hace poco, en esta direccion
Z Game Engine tienes algo de codigo, documentacion y algunos ejemplos (por ahora es todo muy basico).
La verdad esque cuando he puesto este tema esque estoy ya cansado de intentar hacer un engine pero al final nunca doy con la clave. Orientado a objetos claro esta.
Astat, eso es justo lo que yo buscaba, por lo menos el estilo de la estrutura
lo que pasa esque yo usaba 'class Cclass : public Singleton' y al heredar tenia problemas.
Si me aconsejas que lo haga con static Cclass* m_class; te hare caso.
Astat: a ver que te parece esto,
class Capplication
{
public:
/// METODOS ///
virtual ~Capplication();
Capplication();
virtual bool init()=0;
virtual void run();
virtual void end()=0;
virtual void update()=0;
bool m_bRun, m_bActive;
}
void
Capplication::run()
{
while (m_bRun)
{
if (m_bActive)
{
update();
}
}
}
class CwinApplication : public Capplication
void
CwinApplication::update()
{
catchMessages()
// otras cosas
}
void
CwinApplication::catchMessages()
{
if (PeekMessage(&m_uMsg,0,0,0,PM_REMOVE))
{
if (m_uMsg.message==WM_QUIT)
{
m_bRun = false;
}
else
{
TranslateMessage(&m_uMsg);
DispatchMessage(&m_uMsg);
}
}
}
lo que pasa esque te obliga a hacer esto
WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR lpCmdLine,int)
{
CwinApplication App;
if (App.init())
App.run();
App.end();
...
y tener que meter todo el codigo del bucle principal en la funcion CwinApplication::update()
Yo lo tengo hecho asi.
Voy a ver si lo replanteo un poco para hacerlo con 'variables globales' static Cclass* y te envio los fuentes a ver que te parece (esta todo bien clarito).
Otra cosa, lo de los namespace que funcion tienen?
CitarSi me aconsejas que lo haga con static Cclass* m_class; te hare caso.
Al heredar siempre te daran problemas. Yo lo hago con statics y listo.
Citar
/// METODOS ///
virtual ~Capplication();
Capplication();
Asi permites que un usuario (por usuario me refiero al programador que usa tu motor (normamente es la misma persona :P )) pueda crear y borrar la clase cuando quiera. Quizas es demasiada libertad. Ocultalos si puedes y usa para borrar Release().
Lo demas lo veo bien, hay mil formas de hacerlo. Quizas si lo quieres hacer multiplataforma, tendras que pensarlo un poco mas.
CitarOtra cosa, lo de los namespace que funcion tienen?
Basicamente para definir ambitos. Osea:
namespace uno
{
int var = 5;
}
namespace dos
{
double var = 3.1416;
}
Definiendo dos namespaces no hay problema porque una variable se llame igual. Para usarlas, solo tendrias que poner su ambito delante: uno::var o dos::var. Es un buen sistema para separar cosas distintas dentro de algo grande (como es un motor).
Los namespaces se utilizan tambien en .Net y supongo q en muchos mas lenguajes.
Son una forma de tener jerarquizadas y agrupadas las clases y como bien dice Astat de esta forma no chocan las clases q se llaman igual.
Por ejemplo podriamos tener las clases
MiAplicacion.Datos.MiEntidad
MiAplicacion.Negocio.MiEntidad
MiAplicacion.Presentacion.MiEntidad
Serian 3 clases distintas, cada una dentro de un namespace diferente. Habria un namespace llamado MiAplicacion y dentro de el 3 namespaces (datos, negocio y presentacion) y dentro de cada uno de ellos la clase MiEntidad (y podria haber muchas mas)
Saludos