The SDL renderer seems to be working very well, thanks to Joel Longanecker's SDL tutorials. I like dealing with SDL actually, I've never used it before except as a launching pad for OpenGL apps. I'm writing to the screen buffer and doing all the stuff I used to have to think about in 'the old days' of game coding. It's nice to see I'm not too rusty with it all! I'm concerned about the whole 'clear screen/redraw' approach I'm taking right now (thanks, OpenGL!) and the affect it might have on framerate later on.
And to respond to yesterday's comments:-
Quote:Original post by rick_appleton
Theoretically, this setup would allow me to compile for each and every platform with the same makefile (assuming it builds the to-build list from directory contents), but only changing a single, or possibly two defines.
I took a leaf out of your book and removed all the platform/API specific cpp files from my build process and instead included them with the help of a few defines. I was already defining my platform, so it wasn't a major change. It seems to be working nicely - thanks for the tip - it saves me building many different makefiles now :)
The following is a response to Jack's idea mentioned in my last entry...
An interesting approach for plugins... In theory, it's possible provided you supply a global ISystem class for each system to register to.
For example:
class ISystem;class IPlugin{public: explicit IPlugin( ISystem *a_system ) { // hash name setHashedName( GetName() ); } virtual ~IPlugin() { } virtual const char *GetName() const = 0; unsigned int GetSystemHandle() const; void SetSystemHandle(unsigned int a_systemHandle); unsigned int GetHashedName() const;protected: ISystem *m_system; unsigned int m_hashedName; unsigned int m_systemHandle; void setHashedName( unsigned int a_hash ) { //generate a hash of 'name' and store; }};class ISystem{public: virtual ~ISystem() { } virtual IPlugin *LoadPlugin( const char *a_name ) = 0; virtual void ReleasePlugin( IPlugin *a_plugin ) = 0; virtual IPlugin *GetPlugin( const char *a_name ) = 0;};class System : public ISystem{public: virtual ~System() { } protected: void registerPlugin( IPlugin *a_plugin ) { // store in map for later retreival by name } // map of plugins, key is a hash of plugin name std::map< int, IPlugin *> m_plugins;};class Win32System : public System{public: IPlugin *LoadPlugin( const char *a_name ) { // Load module (a_name + .dll), look for 'CreatePlugin' function in DLL - store it in *p IPlugin *plg = (*p)( this ); plg->SetSystemHandle( // hmodule handle ); registerPlugin( plg ); return plg; }; void ReleasePlugin( IPlugin *a_plugin ) { // get system handle from IPlugin, release it }};
Or something along those lines. To use the system, you'd have to implement the plugin interface in your DLL:-
class HelloPlugin : public IPlugin{public: explicit HelloPlugin( ISystem *a_system ); virtual ~HelloPlugin() { } const char *GetName() const { return "hello"; }};// export__declspec(__dllexport) IPlugin *CreatePlugin( ISystem *a_system ) { return new HelloPlugin( a_system ); }
Then to consume the plugin you'd do something like:
int main(){#if defined( __WIN__ ) Win32System sys;#elif defined( __LINUX__ ) LinuxSystem sys;#else #error "Unsupported platform"#end IPlugin *plg = sys.LoadPlugin( "hello" ); // If you know what type of plugin to expect (eg: graphics, sound, etc) // you can probably cast HelloPlugin *hello = 0; if ( ::stricmp( "hello", plg.GetName() ) == 0 ) { hello = reinterpret_cast< HelloPlugin* >(plg); // do stuff with hello... }};
If you don't like the idea of casting on an assumption of name, you could probably have a set of standard "OnLoaded", "OnExecute", "OnReleased" type virtual event handlers to allow a certain amount of genericity (is that a word?). An extension of this would be to define a set of plugin 'types' in an enum - each of these types would have an associated interface:
Eg:
enum { PLGT_UNKNOWN = 0, PLGT_UTILITY, PLGT_GRAPHICS, PLGT_SOUND, PLGT_SCRIPTING, // etc};// Then the baseclasses:class IPlugin;class IUtilityPlugin : public IPlugin; // Contains a generic utility interfaceclass IGraphicsPlugin : public IPlugin; // Contains a generic graphics interfaceclass ISoundPlugin : public IPlugin; // A generic sound interfaceclass IScriptingPlugin : public IPlugin; // A generic script binding interface
The plugin would export its own class/typeid which would then let you (more) safely assume the baseclass for a plugin and cast to that.
Eg:
IPlugin *plg = sys.LoadPLugin( "glRenderer" );if (plg.GetType() != PLGT_GRAPHICS) // Error, we were expecting this to be a graphics pluginIGraphicsPlugin *gfx = reinterpret_cast(plg);// then later on:-gfx->ClearScreen();gfx->BeginRender();// etc
Of course, this would require the engine and the plugins to always be in sync, but would allow for them to know 'something' about each other for inter-plugin/system communication.
I got it from the Loki libraries I think.