Jump to content
  • Advertisement
Sign in to follow this  
Fire Lancer

Design Questions

This topic is 3658 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

1) For my main game loop, I plan to have a fixed update rate (eg 30 updates per second), with an independent frame rate. This means the game logic will always play out the same given the same random seed and input (eg replays, or keeping multiplayer in sync). I'll then get how long untill the next update (0.0 = last update, 1.0 = next update) to apply movement etc to the objects I'm rendering. Is this the best method or should I be doing it a diffrent way? 2) What is the "correct" way to handle user input? Idealiy I want to parse all input in one place, and to determin what this means (eg what a right click means would vary depending what the mouse is over, is somethings selected, etc), and if its valid (eg if its th eattack key, the selected object must be the players, and the target must be emeny), and then finaly pass the command onto the unit, or to the ui, etc. But I'm really not sure how to do this in a tidy way... 3) I want a system a bit like X2's/X3's scripts for my units. That is that each unit can be running its own virtual "thread" for carrying out commands such as attacking, or just simply moving, with a limited number of functions coded directly into the unit objects (basic stuff like MoveTowards). Basicly I find this design much easier to work with when it comes to programming the units to do stuff, since I can treat each command basicly as its own program eg to move to a position I could have something like:
this->SetAction(GetString("CMD_MOVE_POS", TargetX,TargetY));//gets the string with the given ID and sets it as the displayed action. the last arguments values are inserted in the string
while(this->MoveTowardsPosition(TargetX,TargetY,100))Break();//returns false once within 100 game units of target
return 1;
4) I'm planning on storeing all the strings in an associative array (likly std::map). These will be fected using ID's (eg CMD_MOVE_POS, MENU_MAIN_NEWGAME, etc). They will then be parsed for the insertion of varibles eg GetString("CMD_MOVE_POS", 500,750) Strings["CMD_MOVE_POS"] = "Moving to position ($1,$2)" so the string returned would be "Moving to position (600,700)" I can make this pretty easily, but would it be too slow/better way to do it? 5) Is it a good idea to use associative arrays with string id keys to keep track of ofvarious items, mainly "templates" for various objects, and resources. Templates are needed in the following conditions during gameplay: -Infomation is needed about the object type (eg cost) -An instance of that type is to be created Resource are needed in the following conditions: -An object is being created that uses the resource (eg a unit getting the pointer to it's texture) - on second thought, I might reduce this to just during loading/certain special events, seeing as the templates could store the pointer... String resources would be needed when the string is required (although I could cache strings having got them, so just needed when something changes to generate the new one.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Fire Lancer
For my main game loop, I plan to have a fixed update rate (eg 30 updates per second), with an independent frame rate.

This means the game logic will always play out the same given the same random seed and input (eg replays, or keeping multiplayer in sync). I'll then get how long untill the next update (0.0 = last update, 1.0 = next update) to apply movement etc to the objects I'm rendering.

Is this the best method or should I be doing it a diffrent way?
Sounds good to me. You're talking about interpolation, right? Be advised that it can either create lag or inaccuracy, as you either have to guess about what's going to be in the next frame or wait until you've calculated it, at which point you're rendering a frame behind.

You may want to move your rendering out to a separate thread to make it easier to maintain the rate-limited and rate-unlimited framerates separately.

Quote:
What is the "correct" way to handle user input?

Idealiy I want to parse all input in one place, and to determin what this means (eg what a right click means would vary depending what the mouse is over, is somethings selected, etc), and if its valid (eg if its th eattack key, the selected object must be the players, and the target must be emeny), and then finaly pass the command onto the unit, or to the ui, etc.

But I'm really not sure how to do this in a tidy way...
Sample input at as high a rate as possible (again, possibly on a separate thread), mark each input event with the percieved game-time at which it happened, and pack it into a buffer. Then, when updating, grab the whole buffer and process it; you've got all the input that happened since the previous frame and you know how far 'through' the frame it was to figure out exactly how much things have or should move since the input event.

From a design point of view, there aren't very many nice ways to process the input; inevitably you have to store some kind of state that tells you things like which units are currently selected, and then you process each input event accordingly. Validity can be determined by the target of the UI event; you don't have to do it separately - i.e. rather than trying to figure out whether 'attack' is valid given the currently selected unit, just tell the currently selected unit to 'attack' and then let it ignore it if it's not the player's unit.

Quote:

I want a system a bit like X2's/X3's scripts for my units. That is that each unit can be running its own virtual "thread" for carrying out commands such as attacking, or just simply moving, with a limited number of functions coded directly into the unit objects (basic stuff like MoveTowards).
You didn't ask a question here - what aspect of the design do you want to know about? If you're just asking for the best way of doing this then you might want to look into scripting languages like Python or Lua.

Quote:

I'm planning on storeing all the strings in an associative array (likly std::map). These will be fected using ID's (eg CMD_MOVE_POS, MENU_MAIN_NEWGAME, etc).

They will then be parsed for the insertion of varibles eg
GetString("CMD_MOVE_POS", 500,750)
Strings["CMD_MOVE_POS"] = "Moving to position ($1,$2)"
so the string returned would be "Moving to position (600,700)"

I can make this pretty easily, but would it be too slow/better way to do it?
You'll probably be better off using an enum instead of strings for your key, but otherwise, sure, this kind of thing is pretty common in commercial games - not least because you can quickly switch out one map for another when you want to change languages.

As far as formatting the strings goes, I'm pretty sure there are libraries around to do it for you, such as boost.

Quote:
Is it a good idea to use associative arrays with string id keys to keep track of ofvarious items, mainly "templates" for various objects, and resources.
Once objects have been created I'd recommend they keep references to the template used to create them so that you don't have to look it up again. Beyond that, it's fine, though if you find it to be slow then you may want to hash the keys before using them to look up. You can implement that later though; if you're only fetching templates at unit creation time, that's not terribly often.

Share this post


Link to post
Share on other sites
Quote:
Original post by superpig
Sounds good to me. You're talking about interpolation, right? Be advised that it can either create lag or inaccuracy, as you either have to guess about what's going to be in the next frame or wait until you've calculated it, at which point you're rendering a frame behind.

Can it create enough lag/inaccuracy for the player to actauly notice?

Quote:
Original post by superpig
You may want to move your rendering out to a separate thread to make it easier to maintain the rate-limited and rate-unlimited framerates separately.

Not sure how I'm meant to go about this, since then the render thread would be reading data the main thread is writing? Unless I lock it and make acopy at the render start/update end?

Quote:
Original post by superpig
Sample input at as high a rate as possible (again, possibly on a separate thread), mark each input event with the percieved game-time at which it happened, and pack it into a buffer. Then, when updating, grab the whole buffer and process it; you've got all the input that happened since the previous frame and you know how far 'through' the frame it was to figure out exactly how much things have or should move since the input event.

From a design point of view, there aren't very many nice ways to process the input; inevitably you have to store some kind of state that tells you things like which units are currently selected, and then you process each input event accordingly. Validity can be determined by the target of the UI event; you don't have to do it separately - i.e. rather than trying to figure out whether 'attack' is valid given the currently selected unit, just tell the currently selected unit to 'attack' and then let it ignore it if it's not the player's unit.

So would this be a good design?

Handle all the windows messages for input, filling a buffer as it goes.
Then at the start of the update step, use the input data to fill another buffer with pressed/released/held data.

Then I could use that to fill an action buffer (need a good way to do the key mappings here, since being able to use ctrl/shift/alt + something would be nice...), which the diffrent objects use during their own update stages to determin if their meant to do something or not.

Quote:
Original post by superpig
You didn't ask a question here - what aspect of the design do you want to know about? If you're just asking for the best way of doing this then you might want to look into scripting languages like Python or Lua.

Basicly how to go about doing it...

I'll check out those scripting languages, wasn't aware python could be integrated into a c++ program like that.

How do they go as far as speed (since every unit will be running various scripts to carry out their tasks) and ease of integration go for them?
Basicly I really want whatever I use to have the following:
-Be able to pause where I want and wait for the next update for its "parent" object
-Be able to destroy it, automaticly clearing up its resources (eg when the unit is destroyed)
-Be fast enough that I can have 1 or more (in the case of special objects, which have background stuff) per unit while keeping a high unit cap (wacthing an army fight is always more fun than just 2 small groups)

Original post by superpig
You'll probably be better off using an enum instead of strings for your key, but otherwise, sure, this kind of thing is pretty common in commercial games - not least because you can quickly switch out one map for another when you want to change languages.

How should I go about using an enum for this though? For UI and other static stuff thats fine, but what of the items that are dynamicly loaded (unit types for example), I still need a way to link them to the name/description strings

Quote:
Original post by superpig
Once objects have been created I'd recommend they keep references to the template used to create them so that you don't have to look it up again. Beyond that, it's fine, though if you find it to be slow then you may want to hash the keys before using them to look up. You can implement that later though; if you're only fetching templates at unit creation time, that's not terribly often.

That was the general plan, the use will be minimal.

For general creating (eg player building something), a pointer will already be avaible (eg a shipyard would maintan pointers to the templates for the galleon, small transport, etc). But in some cases the pointer will not be avaible (eg for a mission I might want to spawn a bunch of emeny units, but I can't know where the template will be at that point.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fire Lancer
Quote:
Original post by superpig
Sounds good to me. You're talking about interpolation, right? Be advised that it can either create lag or inaccuracy, as you either have to guess about what's going to be in the next frame or wait until you've calculated it, at which point you're rendering a frame behind.

Can it create enough lag/inaccuracy for the player to actauly notice?
It depends on the game. From the sound of it you're making an RTS? In that kind of game I'd say it's not a problem; certainly I know other games (such as Perimeter) that have done it this way.

Quote:
Quote:
Original post by superpig
You may want to move your rendering out to a separate thread to make it easier to maintain the rate-limited and rate-unlimited framerates separately.

Not sure how I'm meant to go about this, since then the render thread would be reading data the main thread is writing? Unless I lock it and make acopy at the render start/update end?
Use multiple buffers for your data. The 'previous' and 'current' frames both get kept around while the next frame is being generated; the renderer can then interpolate between them. For the most part it only takes updating a few pointers (which you may need to lock), and making sure that the render doesn't get too far behind the update.

Quote:

So would this be a good design?

Handle all the windows messages for input, filling a buffer as it goes.
Then at the start of the update step, use the input data to fill another buffer with pressed/released/held data.

Then I could use that to fill an action buffer (need a good way to do the key mappings here, since being able to use ctrl/shift/alt + something would be nice...), which the diffrent objects use during their own update stages to determin if their meant to do something or not.
That sounds reasonable. I'd recommend making sure that the buffer you fill with input isn't then held up by the rest of the game doing processing - double-buffering is the best way to allow your input-handler to keep on trucking.

Quote:

How do they go as far as speed (since every unit will be running various scripts to carry out their tasks) and ease of integration go for them?
Basicly I really want whatever I use to have the following:
-Be able to pause where I want and wait for the next update for its "parent" object
-Be able to destroy it, automaticly clearing up its resources (eg when the unit is destroyed)
-Be fast enough that I can have 1 or more (in the case of special objects, which have background stuff) per unit while keeping a high unit cap (wacthing an army fight is always more fun than just 2 small groups)
Ease of integration is pretty high if you use the right libraries.

Speed is pretty high, but you may want to look into the ability to suspend and resume script execution, or running the interpreter/VM for a limited number of "steps" (in whatever sense that makes for the interpreter/VM you use). The number-of-steps thing is interesting in that you could specify a different number of steps for different units, resulting in units that 'think faster' than others.

Quote:

How should I go about using an enum for this though? For UI and other static stuff thats fine, but what of the items that are dynamicly loaded (unit types for example), I still need a way to link them to the name/description strings
Have multiple maps. Each unit can have its own string map. While the number and type of units you load might vary, each one will carry at least mostly the same set of strings, right? You can encode the common string identifies as an enum, and then if a unit needs extra strings beyond that it can manage the necessary identifiers itself.

Quote:

For general creating (eg player building something), a pointer will already be avaible (eg a shipyard would maintan pointers to the templates for the galleon, small transport, etc). But in some cases the pointer will not be avaible (eg for a mission I might want to spawn a bunch of emeny units, but I can't know where the template will be at that point.
Really? Would the spawn points used for the enemies not hold a pointer to the template? I think it's unlikely that you really want to be spawning enemies completely from scratch in script or whatever - not least because setting their positions becomes a bit painful. I reckon you could probably get every required template associated with some object on the map, even if those objects are not yet 'activated.'

Share this post


Link to post
Share on other sites
Quote:

Use multiple buffers for your data. The 'previous' and 'current' frames both get kept around while the next frame is being generated; the renderer can then interpolate between them. For the most part it only takes updating a few pointers (which you may need to lock), and making sure that the render doesn't get too far behind the update.

Ok so I have 4 buffers, and at the start of each update it makes a copy of the previous buffer (since its easier for the update to read/write to the same place, for instance if 5 bullets hit the same unit at once)

1)2 steps old, render reads this
2)1 step old, render reads this
3)Working buffer for update
4)Spare buffer, so the update does not need to wait for the current frame to be rendered

Not really sure how to make this in a tidy way though? (eg, should each buffer hold a instance of each object that existed in that step, or should each object hold 4 sets of varibles?)


I looked at your scripting links, the second gave me an error so I just looked at Lua's homesite instead.

In both cases I couldn't see how my implmentation would work, for example the boost.python seemed more geared towards writing a c++ dll for python, or just calling python functions from c++ and getting the return value... I'm no0t seeing how to get the two way integration I need (eg the starting and stoping of the scripts at update/breaks, or the fact c++ neeeds to call the python script, but the script must also be able to call c++ functions, and class methods).

Havn't had a chance to look at Lua's c++ integration yet...

Share this post


Link to post
Share on other sites
Your 2nd question:

This may not be correct, but this is what I found for dealing with User Input on only one thread.

I fear my comment may be out of place, because my code is for logic code, (say, being an admin on the server side of the game with no graphics.) Yet this code might help.

In Standard C++ I've not found much info to multi-thread, but I've been able to write (what I feel is) dynamic code for multi-purpose on a single thread. Long wind short, this is what I've got for user input handling:

do { // main game loop
...
do{
InputCheck(); // put your continual checking stuff here
Target_Attack();
NPC_Movement();
...
} while(!kbhit()); // This allows for the system to keep going without interupts being used.
LineCommand(getch()); // this will parce admin's keystrokes as needed 1 key at a time

} while done!= to quit

return 0; // end code

--------------

I hope that helps relating to your second question.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fire Lancer
Quote:

Use multiple buffers for your data. The 'previous' and 'current' frames both get kept around while the next frame is being generated; the renderer can then interpolate between them. For the most part it only takes updating a few pointers (which you may need to lock), and making sure that the render doesn't get too far behind the update.

Ok so I have 4 buffers, and at the start of each update it makes a copy of the previous buffer (since its easier for the update to read/write to the same place, for instance if 5 bullets hit the same unit at once)

1)2 steps old, render reads this
2)1 step old, render reads this
3)Working buffer for update
4)Spare buffer, so the update does not need to wait for the current frame to be rendered
I don't think you need the 4th buffer. Remember, the unit will never need to wait for the the renderer to render the current frame as the renderer's always going to be one frame behind.

Quote:
Not really sure how to make this in a tidy way though? (eg, should each buffer hold a instance of each object that existed in that step, or should each object hold 4 sets of varibles?)
Well, you only need to fill the buffers with data relevant to rendering - it's likely that you can abstract that in a neat way (e.g. a Model object that stores the position/orientation/animation data). You could create a MultiBufferedModel object that wraps the concept of rotating the buffers (along with the necessary locks) and directs writes to the right place; inside that object, you could probably get away with just having four instances of Model. I agree that it's not hugely neat but when you're dealing with deliberately redundant data it's never going to be brilliant.

Quote:

In both cases I couldn't see how my implmentation would work, for example the boost.python seemed more geared towards writing a c++ dll for python, or just calling python functions from c++ and getting the return value... I'm no0t seeing how to get the two way integration I need (eg the starting and stoping of the scripts at update/breaks, or the fact c++ neeeds to call the python script, but the script must also be able to call c++ functions, and class methods).


Check out the code snippet in 'An overview of Lua' in this paper:


#include <stdio.h>
#include "lua.h" /* lua header file */
#include "lualib.h" /* extra libraries (optional) */

int main (int argc, char *argv[])
{
char line[BUFSIZ];
iolib_open(); /* opens I/O library (optional) */
strlib_open(); /* opens string lib (optional) */
mathlib_open(); /* opens math lib (optional) */
while (gets(line) != 0)
lua_dostring(line);
}


The code's not quite compilable, but you get the idea. It'd be easy enough to adjust a loop like that to only execute, say, 5 lines before returning (you'd want a separate LUA_State per unit). Yes, it's possible that some lines in the script would take longer than others; don't write your scripts like that [grin]

I'm not familiar enough with the Python Embedding API to know for sure, but I imagine there must be some similar pattern you could write using Python.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fire Lancer
1)
For my main game loop, I plan to have a fixed update rate (eg 30 updates per second), with an independent frame rate.

This means the game logic will always play out the same given the same random seed and input (eg replays, or keeping multiplayer in sync). I'll then get how long untill the next update (0.0 = last update, 1.0 = next update) to apply movement etc to the objects I'm rendering.

Is this the best method or should I be doing it a diffrent way?


Careful. The update loop is where you "apply movement". When you render, you can calculate an in-between position where the object will be drawn, but you must be careful that this calculation doesn't actually affect the state of the object. Otherwise, you basically lose all the benefits of separating updates from renders in the first place.

Quote:
2)
What is the "correct" way to handle user input?

Idealiy I want to parse all input in one place, and to determin what this means (eg what a right click means would vary depending what the mouse is over, is somethings selected, etc), and if its valid (eg if its th eattack key, the selected object must be the players, and the target must be emeny), and then finaly pass the command onto the unit, or to the ui, etc.

But I'm really not sure how to do this in a tidy way...


Read and store the input in one place, and determine its meaning in another.

A typical approach is something like this:


Objects of the KeyState class can:
.handleEvent(KeyEvent).

Objects of the GameState class can:
.update(KeyState) -> GameState:
# Do some logic, possibly .update Enemies and Players.
# Return the state that the game is now in.
.render():
# .render() each Enemy in the game.
# .render() each Player in the game.

Objects of the Enemy class can:
.update(AI).
.render().

Objects of the Player class can:
.update(Direction).
.render().

gstate: InitialState(). # derived from GameState
kstate: KeyState().
t: current time + 1 frame.
While gstate is valid: # maybe you use a NULL pointer to end the loop, or an
# instance of a special "end state" derived class, or an instance of the base, or...
for each KeyEvent ke in the event queue:
kstate.handleEvent(ke).
gstate.render().
while current time > t:
gstate: gstate.update(kstate).
t += 1 frame.


Quote:

4)
I'm planning on storeing all the strings in an associative array (likly std::map). These will be fected using ID's (eg CMD_MOVE_POS, MENU_MAIN_NEWGAME, etc).

They will then be parsed for the insertion of varibles eg
GetString("CMD_MOVE_POS", 500,750)
Strings["CMD_MOVE_POS"] = "Moving to position ($1,$2)"
so the string returned would be "Moving to position (600,700)"

I can make this pretty easily, but would it be too slow/better way to do it?


Don't implement the string interpolation yourself. Use boost::format.

Also, read the string data in from a file. That way, you gain the benefit of "internationalization": you can have the game translated by making a file that stores text equivalents for other languages. If it's all hard-coded, then you really aren't gaining much at all, and you're paying a lot in terms of complexity, versus just using string literals where you want them.

Quote:
5)
Is it a good idea to use associative arrays with string id keys to keep track of ofvarious items, mainly "templates" for various objects, and resources.

Templates are needed in the following conditions during gameplay:
-Infomation is needed about the object type (eg cost)
-An instance of that type is to be created


A better term might be "prototype" (especially if you want to search the Internet for more information), but such techniques are fairly common, yes.

Share this post


Link to post
Share on other sites
Quote:
Don't implement the string interpolation yourself. Use boost::format.

Also, read the string data in from a file. That way, you gain the benefit of "internationalization": you can have the game translated by making a file that stores text equivalents for other languages. If it's all hard-coded, then you really aren't gaining much at all, and you're paying a lot in terms of complexity, versus just using string literals where you want them.


That was the general idea, personaly I hate having "data" in my source files anyways :)

I'll check out the other stuff (eg boost::format) after work tommorw.

Share this post


Link to post
Share on other sites
Quote:
Original post by superpig
Quote:
Original post by Fire Lancer
Quote:

Use multiple buffers for your data. The 'previous' and 'current' frames both get kept around while the next frame is being generated; the renderer can then interpolate between them. For the most part it only takes updating a few pointers (which you may need to lock), and making sure that the render doesn't get too far behind the update.

Ok so I have 4 buffers, and at the start of each update it makes a copy of the previous buffer (since its easier for the update to read/write to the same place, for instance if 5 bullets hit the same unit at once)

1)2 steps old, render reads this
2)1 step old, render reads this
3)Working buffer for update
4)Spare buffer, so the update does not need to wait for the current frame to be rendered

I don't think you need the 4th buffer. Remember, the unit will never need to wait for the the renderer to render the current frame as the renderer's always going to be one frame behind.


OK Ive been thinking about how to do this, but I can't see a way to do it without copying everything from the last buffer to the current one.
I could read from the old one, and then write to the new one but then theres the problem with multiple events effecting the same data.

eg say 5 bullets impact an object in the same step.

Bullet Read hp damage Write hp
1 500 200 300
2 500 10 490
3 500 50 450
4 500 20 480
5 500 100 400

But the ending hp should actauly be 120 not 400...
This wouldn't happen if it read and wrote the same data, but that means making a massive copy :(

EDIT:
Ok ive had an idea. What if I just had one single update buffer, and used it to create a new render buffer each step, thats much less data(eg only need to do most of it in the players "area", not the entire game. So mayby if theres 2000 objects, only 200 are in/near the players screen, so need to be rendered.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!