Begin and End Functions

Started by
6 comments, last by dukon 15 years, 9 months ago
Hi Everyone, This is just something fun to think about, but I am quite stumped on this. At my programming level now, I can't think of a way to program begin and end functions similar to those found in DirectX (BeginScene and EndScene). Here is an example. Begin(); // Do anything I want in here Sum = Add(5, 2); Print(Sum); End(); I came up with this idea while making my own simple game engine. I could get away without doing it this way, but I thought it would be fun to learn something new. The reason why I want to do this is to make my code a bit more modular. I have a class that handles the Windows API and I also want it to handle the message loop. The thing about this is that I won't be able to stick in my game code into the loop without breaking the modularity of the code. So my thought was to have the beginning and ending functions that mark a block of code that will run inside the message loop. I am not sure if I explained that clearly enough, but please tell me if you don't understand. So any ideas on how to do this if it is possible?
Advertisement
Do you mean you want to somehow mark the start and end of a scope? Here's an example of an idiomatic way to do that in C++.
#include <iostream>#include <stdexcept>class Scoper{public:  Scoper(int i): i_(i) { std::cerr << "Scoper " << i_ << " entry\n"; }  ~Scoper() { std::cerr << "Scoper " << i_ << " exit\n"; }private:  int i_;};void f(int i){  Scoper s(3);  if (i > 0)    return;  throw std::runtime_error("i is less than or equal to zero");}int main(){  Scoper s(0);  try  {    Scoper s(1);    f(10);    f(-1);  }  catch (std::exception& ex)  {    Scoper s(2);    std::cerr << "exception caught: " << ex.what() << "\n"  }}

Stephen M. Webb
Professional Free Software Developer

Quote:Original post by dukon
I came up with this idea while making my own simple game engine. I could get away without doing it this way, but I thought it would be fun to learn something new. The reason why I want to do this is to make my code a bit more modular. I have a class that handles the Windows API and I also want it to handle the message loop. The thing about this is that I won't be able to stick in my game code into the loop without breaking the modularity of the code. So my thought was to have the beginning and ending functions that mark a block of code that will run inside the message loop. I am not sure if I explained that clearly enough, but please tell me if you don't understand. So any ideas on how to do this if it is possible?


Maybe something like this would work:
void Run(){    //Handle message loop, draw code, etc...}void anywhereInMyCode(){   while(1)   {       Run();              doWhatever();       doMoreStuff();              if(timeToBreakFromTheLoop())           break;   }}


You could, if you wanted to, use a macro or two to create your own keywords for it. Other people might yell and throw things at you for doing it though. [grin]
#define BeginLoop while(1){BeginFunc(); #define EndLoop EndFunc();}void BeginFunc(){    //This function runs each loop, before your code.    //Handle message loops and whatever else, here.}void EndFunc(){    //This function runs each loop, after your code.    //Maybe do the graphic drawing here.}


You could use it like this:
BeginLoop{ //You don't need to use these { } here, they are optional.   DoWhatever();      for(int i = 0; i < 99; i++)      DoSomething(i);      if(TimeToExitTheLoop())       break;}EndLoop
Quote:Original post by dukon
I won't be able to stick in my game code into the loop without breaking the modularity of the code.

Have your loop call out to another function and put your game code into that function.
You could generalise that idea by passing a function object (functor) to your message loop and have the loop invoke the functor:

// run handles the message loop and calls a function called game_logic
run(std::ptr_fun(game_logic));
Bregma, I am quite new to C++, but I understand what is going on in your code. It is actually quite cool. I just learned something new :). I don't think it is what I am looking for though, but thank you.

Servant of the Lord, those macros are the right idea. It is what I am looking for, but since you said it is not a good idea, can you think of another way of doing the same thing?

dmatter, I thought of that before. It will certainly work, but I would like to try this method of using these two functions to define the scope.

To further explain with some pseudo code, I want...
/* Application file */typedef class App{ public:  bool CreateWindow();  void WindowsMessageLoop();  void Begin();  void End();} App;void App::WindowsMessageLoop(){ while(Message != WM_QUIT) {  if(PeekMessage())  {   ...  }  else  {   // I want Inp.GetInput() and Gfx.RenderScreen() to run here, but without calling the functions explicitly here.  } }}/* Main file */int WinMain(){ ... App.CreateWindow(); App.Begin(); Inp.GetInput(); Gfx.RenderScreen(); App.End(); ...}

Quote:Original post by dukon
Servant of the Lord, those macros are the right idea. It is what I am looking for, but since you said it is not a good idea, can you think of another way of doing the same thing?

It's pretty much the only way to do that, that I can tell. I'm not a really great programmer though. Or at least, not yet. [wink]

I'd personally use a callback function, like dmatter suggested, but my way gives you the syntax you are looking for. The only bad thing, is it uses macros with are generally frowned upon. It's still perfectly usable, however.

What DirectX does, I believe, is different from what you want your's to do. DirectX's BeginScene and EndScene, and OpenGL's glBegin and glEnd, are used to let DirectX/OpenGL setup some variables in the background, and then send all your drawing commands to the videocard and whatever else it needs to send it to. I've never used DirectX before, but I don't believe it loops between the BeginScene and EndScene.

Almost definitely (Says someone who never used DirectX, and isn't a experienced programmer) what's going on under DirectX's hood, is two separate threads; one polling the message queue, and one running whatever you, the programmer, write in the code.

Basically, all you are doing is with my macros is running a normal loop, like this:
//Start of macro 'Begin'while(1) //or for(;;) if you prefer...{    BeginFunc();    //End of macro 'Begin'        //Start of player's code.    {       DoWhatever();    }    //End of player's code.        //Start of macro 'End'    EndFunc();} //End of macro 'End'


It's not possible to have your program actually do two things at once, without using threads.

Your code wont implode if you use macros, it's just not always a acceptable programming practice, because macros, by their vary nature of replacing chunks of text with code, can cause errors that are often times hard to locate. So feel free to use the macro way, it's practically the only thing you can do in this situation (or at least, that I can see, given what you are requiring), just don't overuse macros any more than you can help, or your code will be harder to debug.
The best solution in this scenario is a callback function. (Or perhaps some real OOP-centric programmers might suggest a virtual function inherited from a base class of type 'App')

typedef void (*CALLBACK_FUNCTION)();/* Application file */typedef class App{ private:  CALLBACK_FUNCTION myCallbackFunction;   public:  bool CreateWindow();  void WindowsMessageLoop();  void RegisterCallbackFunction(CALLBACK_FUNCTION callback);} App;void App::WindowsMessageLoop(){ while(Message != WM_QUIT) {  if(PeekMessage())  {   ...  }  else  {     myCallbackFunction();  } }}/* Main file */int WinMain(){ ... App.CreateWindow(); App.RegisterCallback(&MyCallbackFunction); App.WindowsMessageLoop(); ...}void MyCallbackFunction(){   Inp.GetInput();   Gfx.RenderScreen();}


(Coding on the fly, so be sure to check up on the proper syntax for Function Pointers, because the above code is from memory)
From what I understand, the begin and end says that any drawing functions between them will draw to the back buffer. I don't know what really goes on, but now that I think about it, it probably just sets a variable to draw to the back buffer and then reinitialize it to what it was before. This is definitely not what I am looking for. I was probably hoping it would be more than it actually is.

I like your callback function and I think I will use that method. I was trying to do something similar by passing a class member function, but since it is a part of a class, the code is no longer independent.

Anyways, thanks a lot for the help. I appreciate it.

This topic is closed to new replies.

Advertisement