Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - MrDoomMaster

Pages: [1] 2
1
Feature requests / sfml equivalent of GetMessage()
« on: November 04, 2008, 10:09:06 pm »
I have what I believe is a fairly solid argument in regards to the issue of PeekMessage() vs GetMessage().

Let's assume we have a specific goal: When the user minimizes the game, we want the game to consume 0% CPU. By 0% I mean time spent in our application/game code. This does not include the processing time the operating system spends managing our process. Let's keep it simple.

Below I've outlined 2 scenarios. Scenario 1 doesn't reach our goal at all, however it reflects the current design that SFML imposes on the user. Scenario 1 is being presented because I want to express how SFML could not possibly fulfill this very simple but very important design goal in its current state (architecture).

Scenario 2 will indeed solve the problem, however it utilizes an architectural design that is completely different/incompatible with SFML. This is basically the design that kfriddle is pushing for.


Scenario 1


Suppose the following game loop implementation (Forgive/Ignore any over-simplifications, subtle bugs, or other anomalies, this code has not been compiled):
Code: [Select]

int main()
{
MSG msg;

while( true )
{
if( PeekMessage( &msg, NULL, NULL, NULL, 0 ) )
{
if( msg.message == WM_QUIT )
{
break;
}

TranslateMessage( &msg );
DispatchMessage( &msg );
}

TickGame();
DrawGame();
}

return 0;
}


The above code represents an over-simplified version of your typical "main game loop". This is basically the thing that feeds your entire game and provides it continuous processing. When the user minimizes the application, there is no way to suspend the application. In other words, the while( true ) loop above will never end except for when the application is terminated by the user.

Because this while loop never ends except under the previously noted circumstances, the game will always push to consume as much CPU as possible regardless of the state of the application, such as being minimized.

You may say, "Well let's just do this:"
Code: [Select]

int main()
{
MSG msg;

while( true )
{
if( PeekMessage( &msg, NULL, NULL, NULL, 0 ) )
{
if( msg.message == WM_QUIT )
{
break;
}

TranslateMessage( &msg );
DispatchMessage( &msg );
}

if( bMinimized )
{
Sleep( 1 );
}
else
{
TickGame();
DrawGame();
}
}

return 0;
}


I would then proceed to say you're evil. This is not solving the problem. Sleeping here does not solve the problem since you have no idea how long the user will keep the application in the minimized state. For the entire duration the application is minimized, there should be absolutely 0 iterations of this while loop. No physical code that we control in the application should be getting processed. Any processing happening at application level code is considered wasteful.


Scenario 2


The code for this can get fairly extensive, so I'll only cover the most fundamental and important parts. In one thread (Thread #1), you would have this continuously running:
Code: [Select]
MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}


Obviously the window would have been constructed in the same thread processing the above loop. As far as where the message procedure is, let's also assume it is in the same thread for the purposes of this example.

In a completely different thread (Thread #2) you would have the following loop running:
Code: [Select]

while( true )
{
WaitForSingleObject( .... ); // This would suspend the thread if game processing is not currently needed.

TickGame();
DrawGame();
}


Again, I do apologize for the over-simplifications. Bear with me. This is mainly pseudo-code. The above code continues to process the game normally until a request from another thread comes in to tell it to PAUSE or RESUME (hence the WaitForSingleObject() call). If this thread is told to PAUSE, no game processing will occur until a matching RESUME request is given.

So let's tie all of this together. Typically I would use a sequence diagram to properly document the flow of all of this, so once again do bear with me while I try to use a bullet point list to describe the sequence of the application:

[list=1]
  • The application starts and Thread #1 is executed, which results in the message pump being processed.
  • When the user minimizes the application, a WM_MINIMIZED event occurs, which Thread #1 handles by atomically telling Thread #2 to PAUSE.
  • During this time, the application is in the minimized state consuming 0% CPU because the game loop in Thread #2 is not running, nor is Thread #1 continuously spamming calls to PeekMessage().
  • When the user restores/maximizes the window, the respective message is handled and results in a RESUME request being sent to Thread #2, which causes the game loop to continue processing.[/list:o]


    Conclusion


    As kfriddle has been saying all along, the design SFML utilizes (Scenario 1) is antiquated. I won't go over his arguments since they were well spoken. I'm simply giving a detailed side-by-side example to make his points a bit more realized. There is no sense in justifying memory leaks, many have already told you this is just plain EVIL in every sense of the word. There is also no sense in justifying usage of polling, as it greatly limits the conservativeness of the application as I've just explained in detail.

2
Feature requests / sfml equivalent of GetMessage()
« on: November 04, 2008, 01:26:13 am »
Another great book he should get is Patterns for Parallel Programming

3
Graphics / GL_INVALID_ENUM in renderwindow.cpp
« on: April 27, 2008, 05:40:22 am »
@tno

Please do not spam random people through PM's and direct them to your threads for help. This is not appropriate behavior.

4
General / Relative Cursor Movement
« on: April 21, 2008, 02:42:31 am »
Quote from: "Laurent"
Done ;)

As I couldn't find any reliable way to do it directly at the OS level, I added some simple code to sf::Window to discard MouseMoved events generated by SetCursorPosition.


Great! Thanks :)

Do you have a release date for SFML 1.3 (I'm assuming 1.3 is the next)?

5
General / Relative Cursor Movement
« on: April 18, 2008, 10:37:10 pm »
Laurent,

Did you ever figure out this issue? Right now I think SetCursorPosition is still generating WM_MOUSEMOVE events, which cause me to get additional redundant MouseMove messages.

6
Hi,

In Visual Studio 9, I setup my application to statically link to the MSVC libraries via "Multithreaded Debug" instead of "Multithreaded Debug DLL". When I do so, simply having "sfml-window-s-d.lib" in my additional libraries causes the linker to spit out the following errors (these are only just a few of many):
Code: [Select]
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) already defined in libcpmtd.lib(stdthrow.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __thiscall std::_Container_base_secure::_Orphan_all(void)const " (?_Orphan_all@_Container_base_secure@std@@QBEXXZ) already defined in InputRegistry.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Container_base_secure::~_Container_base_secure(void)" (??1_Container_base_secure@std@@QAE@XZ) already defined in InputRegistry.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) already defined in libcpmtd.lib(xlock.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) already defined in libcpmtd.lib(xlock.obj)
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in InputRegistry.obj
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) already defined in InputRegistry.obj

7
Window / sf::Key::Code::Count issue
« on: February 06, 2008, 05:59:12 pm »
Quote from: "Laurent"
In fact, the only reason is to map characters code to their ASCII code (sf::Key::A == 'a').

As the value of 'a' and all other characters can't be known (it could be 97 with ASCII, or something else with EBCDIC), I just can't fill the gaps with other codes and need to restart from a safe upper bound for the other values of the enum, which is 256 (I guess I could use 128 as well).


Why not allow your key code enumerations to be automatically numbered by the compiler? Is there actually a specific reason to assign the ASCII values?

8
Window / sf::Key::Code::Count issue
« on: February 05, 2008, 06:11:03 pm »
Quote from: "Laurent"
Yep, this is actually just an upper bound, not the exact count of keys. It's mostly used when you want to define an array of keys.


Yes, but it is inconsistent and misleading. I was using it to generate an array of key presses. Normally a "count" member in an enumeration is a count of all physical members in the enumeration. A prerequisite of this is that all of the enumerated members be numbered in ascending order starting from 0.

If you take a look at the other enumerations in the same file, you'll notice that the 'count' member actually does represent the physical count of enumeration members.

Now that you've explained the purpose of the Count member in Key::Code I understand that it isn't a bug. However it might be a good idea to create a detailed comment for that member. It deserves some textual explanation since, as I've pointed out, it is inconsistent.

I'm also curious why you even explicitly assign values to the enumerations. SFML is supposedly portable, so I don't think you are mapping them to Microsoft Virtual Key Codes. It also seems like SFML supports other key inputs that aren't explicitly defined in the Key::Code enumeration (I'm judging this by the implementation of the enum, it skips large ranges of numbers).

Thanks for your feedback. If you could address my few other questions I don't believe this would be an issue for me anymore.

9
Feature requests / Resize events
« on: February 04, 2008, 11:55:12 pm »
Quote from: "T.T.H."
Sorry, didn't want to hijack your thread, but I think the answers to those two questions probably are very close together in the code when they'll be implemented. Anyway, you go first.


True, they probably are. I wanted the main focus to be that there is a backlog of messages in the queue. However, now that you've mentioned it, if the loop doesn't block when you resize I guess it would make sense to constantly be receiving resize events. At least in that case you would dynamically see elements resizing.

So having said that, I agree that the synchronicity of the event loop is probably the essence of both of our problems.

10
Feature requests / Resize events
« on: February 04, 2008, 09:39:47 pm »
Quote from: "T.T.H."
MrDoomMaster's question: how to avoid getting a big amount of redundant Resized events in the first frame after the resizing is completed?

My question: how to avoid that blocking so that I can actually redraw my window during the resizing? (and not only having those ugly gray lines)


Seems like this needs to be in a new thread :)

11
Window / sf::Key::Code::Count issue
« on: February 04, 2008, 08:17:40 pm »
Hi,

I may be completely misunderstanding something, but the sf::Key::Code::Count enumerated member doesn't seem valid. For most of the enumerations in sf::Key::Code, they've been given explicit values. Thus, the 'count' member actually gives a number over 300, when there are only about 60+ enumerations.

This seems like an error and I thought I'd bring it up.

12
Feature requests / Automatic key repeat
« on: February 04, 2008, 07:57:03 pm »
Hi,

I would like to request a method off of sf::Window that provides the user the ability to enable or disable automatic key repeat. When a key is held down, the user constantly receives KeyPressed messages. I would like an option to disable the automatic generation of these messages.

For now I have to have an external array of booleans representing which key is already held down, and ignore the message if that key is held down. This isn't an ideal solution, as I believe SFML could (and should) handle this better.

From a design standpoint having such an option would be more efficient as well, since the messages wouldn't need to travel as far before being ignored.

Thanks!

13
Feature requests / Resize events
« on: February 04, 2008, 05:38:05 pm »
Quote from: "Mindiell"
Quote from: "MrDoomMaster"
Currently I do that. But it's a hack, not a solution. The (light) performance overhead of the 100-200 needless iterations of my event loop still exists. It needs to be fixed properly.

Quote from: "MrDoomMaster"
In my specific application utilizing SFML, my themes are set in such a way that the size of the window updates dynamically as the user drags an edge

I'm sorry, but SFML is doing its job, it's your application which updates dynamically as the user drags an edge. Maybe you have to change this ?

Quote from: "MrDoomMaster"
Due to the way the sizing works, clicking and holding an edge causes the ProcessEvents() function to block until it is released.

If you want to keep this way, the flag is a solution I think, and not just a hack ;)


I don't think you understand what I'm saying. My message loop is an exact copy of some of the sample apps using SFML. SFML is so simple, it's pretty much impossible to screw something up like this.

Below is the code I'm using to process messages:
Code: [Select]

bool ProcessEvents( Game& game, sf::RenderWindow& gameWindow )
{
bool closed = false;

// hack to overcome the bug in SFML that causes
// a continuous flood of Event::Resized messages.
// We're only interested in the last one.
unsigned int x,y;
bool resized = false;

sf::Event evt;
while( gameWindow.GetEvent( evt ) )
{
switch( evt.Type )
{
case  sf::Event::Closed:
{
closed = true;
break;
}

case sf::Event::KeyPressed:
{
OnKeyDown( evt, true );
break;
}

case sf::Event::KeyReleased:
{
OnKeyDown( evt, false );
break;
}

case sf::Event::MouseButtonPressed:
{
OnMouseButton( evt, true );
break;
}

case sf::Event::MouseButtonReleased:
{
OnMouseButton( evt, false );
break;
}

case sf::Event::MouseWheelMoved:
{
OnMouseWheel( evt );
break;
}

case sf::Event::MouseMoved:
{
OnCursorMotion( evt );
break;
}

case sf::Event::Resized:
{
x = evt.Size.Width;
y = evt.Size.Height;
resized = true;
break;
}
}
}

if( resized )
{
game.ResizeViewport( x, y );
}

return closed;
}


As you can see, I have placed a hack in to temporarily work around the resize bug. This still seems like an SFML issue. If you see anything wrong with the code above please let me know. Otherwise, I'll be looking forward to this being fixed properly in the SFML library.

Thanks.

14
General discussions / Adding SFML vs2008 projects to my solution...
« on: January 31, 2008, 08:11:42 pm »
Quote from: "Laurent"
I don't commit anything until the code has been completed and tested.

Well, the way I see it, there are only 2 reasons why I would make a branch to backup changes that require a week or so to complete:
1) For the purposes of backup & ability to revert. Keeping changes checked into the server is always better than keeping it modified on your working copy. If your machine's HDD fails, at least you can sleep at night knowing your code has been safely checked into your branch, even if it doesn't compile! It doesn't matter what the code looks like or how it functions, that's why it's in a branch!
2) Multiple developers. If I have a partner working on the same branch and helping me with a feature, it's pretty much a requirement to make sure your changes are checked into the branch so your partner can access those changes.

I personally don't like keeping things modified for too long on my working copy just because I'm paranoid about my hard drive failing at any time. If a feature I'm working on takes more than a day or two, I create a temporary branch for backup purposes.

I'm probably stating the obvious here, however I'm not trying to educate you. I'm just expressing how I use SVN for my personal needs. I would hate for you, too, to lose your work if your hard drive fails :(

Thanks for your prompt feedback. Again, you have a great library. Keep up the most excellent work you're doing!

15
Feature requests / Resize events
« on: January 31, 2008, 06:06:59 pm »
Quote from: "Mindiell"
What don't you simply put a flag on when getting a resize event ?
After your event loop, you have just to see if the flag is set and do your resizing.


Currently I do that. But it's a hack, not a solution. The (light) performance overhead of the 100-200 needless iterations of my event loop still exists. It needs to be fixed properly.

Pages: [1] 2