Register
Site Login
Site Search
Forums
Advertisement
Welcome to PocketMatrix. PocketMatrix is dedicated to providing the best online community for mobile device developers and enthusiests. What's new?

A question of technique


A question of technique

Postby Guest » Apr 18, 2006 @ 10:06pm

Hi, y'all,

I'm going to admit my serious lack of experience here, but I need some help. I'm trying to use the PocketFrog Game framework to write a simple game. Although this isn't my first project using PocketFrog, it is more complicated than any of my others and I'm having trouble figuring out how to organize my code.

I think I understand the basics: Most of my processing should be done in GameLoop and I write functions for ButtonDown, ButtonUP, StylusDown, etc that reacts to the various inputs. That's all well and good.

However - My game is going to have different modes. For instance: Main menu, Introduction screen, Map displays, Information displays, Next Turn prompts, etc. How do I keep track of what mode I'm in and what my game should be doing at any particular time? Let me try to explain myself with an example:

If the game is in the main menu mode and the stylus is pressed on the screen, the game will need to decide if it was pressed inside of a menu item and respond appropriately.

However, if the game is displaying the introduction and the stylus is pressed on the screen, the display will need to change to the next screen in the introduction.

How do I handle the different modes in this situation? For instance, how do I get my StylusDown function to act according to the current game mode? I have thought of two solutions.

Solution 1: Have a variable that keeps track of the current mode and put a switch statement in my StylusDown function. Have the switch statement call other functions (like MainMenuStylusDown, IntroScreenStylusDown, etc.) to execute mode-specific code.

Solution 2: Create a CMode class with a virtual StylusDown function. Then I could derive specialized child classes (CMainMenu, CIntroScreen, etc) for each mode. I could then create a CMode pointer that points to the current game mode object and dynamically create game mode objects as they're needed. Then (assuming my CMode pointer is called pCurrentMode) in my main StylusDown function, I could just call pCurrentMode->StylusDown () to execute mode-specific code.

Solution 1 seems more intuitive and less likely to cause memory errors, but could make organizing my code difficult. I would need to have a separate StylusDown function for each mode. Extending this to the other input functions (StylusMove, ButtonDown, etc), there could be a real problem.

Solution 2 makes code organization fairly simple. I can put each mode class in its own source file. However, is the overhead of virtual functions something I need to worry about? Is this solution introducing more problems than it's fixing?

I guess I just need advice from someone wiser than I. What do the rest of you do in your games? If any of you can make sense of what I'm trying to ask, please help me.

Thanks.
Guest
 


Postby BradK3 » Apr 18, 2006 @ 10:18pm

Not that it matters, but I forgot to login... :oops:
User avatar
BradK3
pm Member
 
Posts: 19
Joined: May 27, 2003 @ 7:34pm
Location: Clearfield, Utah


Postby Kzinti » Apr 18, 2006 @ 11:34pm

I would go with solution 2. I don't understand this fear of virtual functions that people seem to have around here. It's irrelevant. The cost of that virtual is no more (and probably less) then the cost of using a switch() statement.
Kzinti
pm Member
 
Posts: 3238
Joined: Jan 13, 2002 @ 5:23am


Postby Andy » Apr 19, 2006 @ 6:46am

In Sol'n 1, the switch statement will likely give you an indirection through a jump table. In Sol'n 2, you'll get an indirection via a vtable. You may get a few additional indirections because of other, related virtual functions, but that doesn't really matter here. These functions (eg InputHandlers) seem like they're called (at most) one time per iteration of the main loop.
Andy
<font color=red size=3>Troll++</font>
 
Posts: 1288
Joined: Nov 1, 2003 @ 7:36am


Postby jaguard » Apr 19, 2006 @ 8:32am

Use whatevery you like - it really doens't matter. I'm fond of solution1, but that's just because I don't like virtual functions much and avoiding them as far as I can.
Well, pretty successful avoiding - there's no single virtual function in Enslave, except for Gameloop()/GameInit()/etc.

PS: I also have each function in a separate file, and I don't see a problem here.
jaguard
pm Member
 
Posts: 230
Joined: Mar 2, 2004 @ 6:45pm


Postby BradK3 » Apr 19, 2006 @ 2:14pm

Thanks for the responses. I was leaning toward using virtual functions and I think I'll go that way. I appreciate the advice. It's nice to get feedback on things like this!
User avatar
BradK3
pm Member
 
Posts: 19
Joined: May 27, 2003 @ 7:34pm
Location: Clearfield, Utah


Postby ml » Apr 19, 2006 @ 2:30pm

Absolutely use virtual functions as you suggest - no-one has yet mentioned the mess you get trying to maintain a solution where you have to test for a whole series of possible states of the game before you can process a button-click. It may be 'slightly' quicker to build using method 1, but just try changing it later on, or adding a new state.

Encapsulating the states in classes inherited from the base CMode allows you to just forget all those checks, and work under the assumption that you've switched state correctly at the right time.
ml
pm Member
 
Posts: 30
Joined: Oct 7, 2005 @ 4:22pm


Postby fast_rx » Apr 20, 2006 @ 3:44am

why hasn't anyone mentioned keeping the stylusdown function simple:

virtual void StylusDown( Point stylus )
{
stylusinfo.down = true;
stylusinfo.firstdown = true;
stylusinfo.loc.x = stylus.x;
stylusinfo.loc.y = stylus.y;
}

and using a simple function pointer for game modes.
User avatar
fast_rx
pm Member
 
Posts: 660
Joined: Jun 10, 2003 @ 4:24pm


Postby Kzinti » Apr 20, 2006 @ 4:16am

fast_rx wrote:using a simple function pointer for game modes.


That's exactly what a virtual function is.
Kzinti
pm Member
 
Posts: 3238
Joined: Jan 13, 2002 @ 5:23am


Postby fast_rx » Apr 20, 2006 @ 4:47am

Kzinti wrote:
fast_rx wrote:using a simple function pointer for game modes.


That's exactly what a virtual function is.


I would've thought there would be a few extra lines of code here and there...
User avatar
fast_rx
pm Member
 
Posts: 660
Joined: Jun 10, 2003 @ 4:24pm


Postby fzammetti » Apr 20, 2006 @ 6:02am

Speaking as someone who has used both techniques, I definitely suggest option 2. Whatever cost there *may* be is well worth the return in code maintainability.

The last project I worked on used this approach, and all my main game loop contained was about 50 lines of code, just a switch based on the state of the current screen (loading, running, destroying, a few others) that called to the appropriate method of the current CScreen class. Same was true for the stylus/key events. Made for very clean code...

...and because of the nature of the game, I had to have the ability to plug in new screens with ease, and this allowed for that too. I personally wouldn't do it any other way at this point, not unless I had an especially good reason not to.
...and so I said to Mr. Gates: "$640 billion should be enough for anyone!"
User avatar
fzammetti
pm Insider
 
Posts: 1496
Joined: Jun 4, 2002 @ 6:21pm
Location: Omnytex Technologies


Postby InexorableTash » Apr 27, 2006 @ 5:33am

Agreed: Solution 2.

Extend this beyond events to rendering, and for added fun you can nest modules - for example, when a player pauses my game, the game keeps rendering in the background but time stops (it's not the active module) and a dialog appears on top. Once you have this sort of framework in place it's easy to add new module types for things line cinematics, menus, different level types, etc.

Note that you do have to be careful when switching modules: if you switch modules during an event handler (e.g. StylusDown) the framework code could get confused (e.g. m_pActiveModule changes in the middle of a call stack). I think I ended up deferring module switches until outside of any event handlers.

One of the Game Programming Gems has a framework for this pattern, BTW.
User avatar
InexorableTash
pm Member
 
Posts: 99
Joined: Sep 13, 2002 @ 6:14am


Postby Conan » Apr 27, 2006 @ 4:30pm

does anyone have a simple worked example? I have to admit to using 'method 1' and have not seen the virtual function approach in action so I'm not sure how it works.
What is Best in Life ?
User avatar
Conan
pm Member
 
Posts: 1309
Joined: Dec 24, 2001 @ 5:16am
Location: the Shades, Ankh-Morpock


Postby BradK3 » Apr 27, 2006 @ 7:14pm

Conan wrote:does anyone have a simple worked example? I have to admit to using 'method 1' and have not seen the virtual function approach in action so I'm not sure how it works.


Well, since starting this thread, I've made some good progress on my game using method 2, and, while I don't have a simple example to post, I'll take a shot at coming up with something 'on-the-fly'. I can't guarantee that this will work as-is, but it should give you an idea of what we're talking about:

As a simple example, say we want to write a game that displays a blue screen or red screen, depending on the game 'mode' (Not a terribly fun, game, I realize, but I'm not ambitious).

To use 'method 2', we must first create a base class for the modes we'll be using in the game.
Code: Select all






// CModeBase - Base class for all game modes
class CModeBase
{
public:
   virtual void Update (Display* pDisplay) = 0; // (The '= 0' makes this class 'pure virtual'
};
6 lines; 4 keywds; 1 nums; 9 ops; 0 strs; 2 coms    Syntactic Coloring v0.4 - Dan East  

Of course, with a real game, we would likely also include virtual functions for ButtonDown, StylusDown, etc, and maybe some member variables shared among the modes.

Then we can create specific mode classes derived from the base class. For instance, a 'CModeBlue' class that colors the screen blue and a 'CModeRed' to color it red.
Code: Select all









10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
// CModeBlue - Colors the screen blue
class CModeBlue : public CModeBase // derived from CModeBase
{
public:
   void Update (Display* pDisplay)
   {
      pDisplay->Clear (Color (0, 0, 255));
   }
};

// CModeRed - Colors the screen red
class CModeRed : public CModeBase // Also derived from CModeBase
{
public:
   void Update (Display* pDisplay)
   {
      pDisplay->Clear (Color (255, 0, 0));
   }
};
19 lines; 8 keywds; 6 nums; 38 ops; 0 strs; 4 coms    Syntactic Coloring v0.4 - Dan East  


Now let's assume that this game will be using PocketFrog's game framework. In our main game object, we need to include a CModeBase pointer as a member variable (or a global variable, I suppose...), like so:

Code: Select all








// Our game class 'CFunGame' (A bit of a misnomer)
class CFunGame : public Game
{
.
.  // Misc. function and variable definitions...
.
   CModeBase* m_pMode;
}
8 lines; 2 keywds; 0 nums; 8 ops; 0 strs; 2 coms    Syntactic Coloring v0.4 - Dan East  


Let's say we want to start out with a blue screen. In our GameInit function, we do the following:
Code: Select all




bool CFunGame::GameInit ()
{
   m_pMode = new CModeBlue;
}
4 lines; 2 keywds; 0 nums; 8 ops; 0 strs; 0 coms    Syntactic Coloring v0.4 - Dan East  


Now, believe it or not, most of the work's done. Thanks to C++'s polymorphism (I think) capability, anytime we need to update the screen (i.e. in the GameLoop function), we just call m_pMode->Update (pointer to the display); And a blue screen will be displayed. For instance:
Code: Select all






void CFunGame::GameLoop ()
{
   Display* pDisplay = GetDisplay ();
   m_pMode->Update (pDisplay); // Tells the current mode to update the screen
   pDisplay->Update (); // Updates the screen
}
6 lines; 1 keywds; 0 nums; 21 ops; 0 strs; 2 coms    Syntactic Coloring v0.4 - Dan East  


When you want the screen to change to red, do the following:
Code: Select all


delete m_pMode; // Get rid of the blue mode object
m_pMode = new CModeRed;
2 lines; 2 keywds; 0 nums; 3 ops; 0 strs; 1 coms    Syntactic Coloring v0.4 - Dan East  


Then, without changing our GameLoop function, the screen will be red! By changing the object pointed to by m_pMode, we can change back and forth between blue and red, blue and red, blue and red... makes one giddy just thinking about it!

Of course, this is just a simple example. This technique is, in fact, very powerful and quite versitile, as I'm learning. Why, with just a few changes, we could paint the screen green, yellow, purple or cyan, even!

Seriously, though, I'm glad the kind forum members here convinced me to go this route. There is quite a lot that you can do. For instance, in my game, I also pass button and stylus events to the current mode, so they're handled differently based on what the game is doing at the moment. Depending on the mode my game is currently in, pressing a hardware button may open a menu, advance to the next mode, or even quit the game abruptly (undocumented feature...).

Anyway, that's how I'm doing it. Hopefully, I haven't made too many errors. I'll be happy to clarify any points I've muddled, just ask. Perhaps someone more experienced than I can clarify or correct this, as needed.
User avatar
BradK3
pm Member
 
Posts: 19
Joined: May 27, 2003 @ 7:34pm
Location: Clearfield, Utah


Postby Kzinti » Apr 27, 2006 @ 9:18pm

I think you pretty much nailed down the idea behind method #2. This is extremely flexible as it allows you to change the framework depending on the current mode (context).
Kzinti
pm Member
 
Posts: 3238
Joined: Jan 13, 2002 @ 5:23am


Return to PocketFrog & PocketHAL


Sort


Forum Description

SDKs for fast and robust device-independent access to Pocket PC display hardware.

Moderators:

sponge, Kzinti

Forum permissions

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum