Jump to content
  • Advertisement
Sign in to follow this  
AGD

Cross platform code and windows procedure

This topic is 2834 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm having some difficulty trying to create a cross-platform base - the difficulty I'm having is with the windows procedure and its effect on the game loop.

I have a base class "Root" which will hold all subsystems (window, graphics etc). It also currently has the game loop in it. As it was originally written as a win32 project - the game loop is in the style (as a member function of root called/returned by main):

MSG message = {0};

while(message.message != WM_QUIT)
{
//check for messages and process them if required
if(PeekMessage( &message, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &message );
DispatchMessage( &message );
}
else
{
//no message left so update
update();
}
}

//quitting
return static_cast<int>(message.wParam);


I can put the windows procedure in the win32 window class and then use an abstract factory to provide me the correct window class to hide this but I'm not sure how best to do the same to the game loop itself. Obviously I could create a "game/game loop" class and then use an abstract factory to provide me with the correct platform-specific game loop but it doesn't seem ideal to start having different game loops for different platforms. It's just the forced mixing of input, message handling, and game loop that is annoying me with the win32 api! The ideal situation would be to completely decouple the game loop from anything else. Any help would be much appreciated.

Share this post


Link to post
Share on other sites
Advertisement
Hi,

You could try libsdl : http://www.libsdl.org/
It multiplatform already and very easy to use. That would probably solve your problem :)

Share this post


Link to post
Share on other sites

Hi,

You could try libsdl : http://www.libsdl.org/
It multiplatform already and very easy to use. That would probably solve your problem :)


Thanks but I'm trying to do this myself so I can learn - and I find it interesting too - so I don't really want to use a library...

Share this post


Link to post
Share on other sites
You can still download the SDL source code and see how they did it. Each platform has it's own way of managing messages, if you're going to ignore what's already been done and tested you might have to look for the development libraries help of each platform you plan to support and write (encapsulate) different code for each. In the case of Linux it'd most likely be XOrg/XFree/X11. I really can't speak for Mac and others..

Share this post


Link to post
Share on other sites

You can still download the SDL source code and see how they did it. Each platform has it's own way of managing messages, if you're going to ignore what's already been done and tested you might have to look for the development libraries help of each platform you plan to support and write (encapsulate) different code for each. In the case of Linux it'd most likely be XOrg/XFree/X11. I really can't speak for Mac and others..


Thanks, I don't want to ignore what's out there (I will look at the sdl source) but I just wanted to see how others here approach the problem - especially in an oop way.

Share this post


Link to post
Share on other sites
In Windows and X11 messages are managed quite alike using a message queue. You might want to look into delegates. I personally have a class with an update method that get's called each frame. This update method encapsulates the platform specific message switching and then invokes the proper delegate.

You have lot's of materials to digest to this point. Take it slow.

Share this post


Link to post
Share on other sites
Ok, what I've implemented is the following. I have Root which is passed the platform in its ctor in main. Based upon this argument, Root news the appropriate factory which provides the platform specific input and window instances - both of which inherit from an abc with a simple interface.

To separate the windows procedure from the game loop and window class itself I did the following: the input class has a member windows procedure function called by a static windows procedure function which is also part of the "Input" class. The Root class contains the gameloop which calls update on the input class instance to do the peekmessage etc. Hence, raw input events are completely controlled by the platform specific input instance. Everything seems (relatively) decoupled and remains potentially crossplatform - have I missed anything? Have I made some obvious noob error in my design?

Here's a short code snipped in case all the text above doesn't make sense!

Root::Root(Platform platform)
: factory(0),
input(0),
window(0),
isQuitting(false)
{
//init factory
switch( platform )
{
case Root::WINDOWS:
{
factory = new WindowsFactory;
}
}

//init subsystems using factory
input = factory->createInput(*this);
window = factory->createWindow(*this);

}

int Root::gameLoop()
{
while( !isQuitting )
{
update();
}

return 0;
}

void Root::update()
{
input->update();
}

void WindowsInput::update()
{
MSG message = {0};

if(message.message == WM_QUIT)
{
root.sendQuitMessage();
}

//check for messages and process them if required
if(PeekMessage( &message, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &message );
DispatchMessage( &message );
}

}

LRESULT CALLBACK WindowsInput::windowsProcedure(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
{
//handle important messages
switch( message )
{
//handle relevant cases here

default:
//forward other messages to default windows procedure
return DefWindowProc(windowHandle, message, wParam, lParam);
}

return 0;
}



Note: only one platform is implemented atm - windows, hence the rather bare switch statement!

Share this post


Link to post
Share on other sites
Think about this: You'll have to compile a different executable for each platform you want to support thus it would make sense to pick the platform specific code at compile time.
IMO Factories make sense in the case of libraries (ie: Direct3D, OpenGL) which you can actually pick among on the same platform (windows). In this case, linux specific code shouldn't exist at all in the windows version of the program.

Share this post


Link to post
Share on other sites

Think about this: You'll have to compile a different executable for each platform you want to support thus it would make sense to pick the platform specific code at compile time.
IMO Factories make sense in the case of libraries (ie: Direct3D, OpenGL) which you can actually pick among on the same platform (windows). In this case, linux specific code shouldn't exist at all in the windows version of the program.


Oh well, at least I learnt the abstract factory design pattern and got practise implementing it! :P

Thanks for the reply and helping me learn. I don't know much about libs but would it be right to assume that every subsystem which is platform specific e.g. input, graphics should be implemented as a static library which is linked at compile time into your exe depending on whatever preprocessor directives you provide. Each library could provide the same interface so that the core code would remain the same which gives behaviour somewhat analogous to abstract factories.

As you mentioned in cases where different options exist for the same platform there could be two alternatives - create 2 different static libs and choose one at compile time as per usual or provide one static lib which incorporates an abstract factory to provide the required option - e.g. in the windows graphics subsystem library, an abstract factory could be used to choose between Direct3D and openGL...

Am I understanding the situation correctly or am I way off again?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!