I'm developing a game using c++ and I don't know what's the better approach to my problem.
I have an array with gameObject objects, each one has an array with frames of animation that I loop through to show the animation in the game.
The animations are time based and I have to tell the objects how much time has passed since the last frame was displayed (deltaTime) to calculate what frame I will display in this iteration.
Everything ok until here.
Is it ok to feed the deltaTime to the objects with a setter method? Or would be better if I had a pointer in each object to a global variable? Or is there another even better approach here regarding performance and organization? Keep in mind that there'll be hundreds of objects.
Thank you for your time :)
In general, avoid global variables. Just loop over the objects, passing the deltaTime to each:
for (auto &gameObject : gameObjects)
{
gameObject.Update(deltaTime);
}
Storing the time within each object isn't recommended, since anything you think you might need it for "in the future", you should just do within Update.
Related
So, I have a 3d platformer. And I want to have a button that if you hold it it makes you "go back in time". Thankfully the game is rather simple and only has one entity so the only thing that would have to be saved for each frame is.
struct Coord {
float x;
float y;
float z;
}
structure Bool6 {
bool front;
bool back;
bool left;
bool right;
bool top;
bool bottom;
}
struct Player {
Coord Pos;
Coord Vel;
Bool6 Col;
}
But I fear that is a lot of data especially since my game theoretically runs somewhere around 60fps and it would be good to have 5 seconds or so (300 frames) of data saved that can be accessed when roll-backed. I have considered each frame doing something like this
Player Data[300];
for (int i = 299; i > 0; i--)
{
Data[i] = Data[(i-1)];
}
Data[0] = "THIS FRAMES DATA";
However that sounds like it means an outrageous amount of processing power is going just in storing each frame.
Is their a more efficient way to store this data keeping all of the data in order?
Also is their a way I can tell an array slot that it has nothing? So that their arent problems if the player tries to rollback before all of the array slots are filled or after rolling back? I believe in C# i would have set it equal to NULL... but that doesn't work in c++ probably because im using structures.
Thanks much!
However that sounds like it means an outrageous amount of processing power
Before making such a statement it can be useful to do the math. It seems the data you are concerned with is about 40 bytes, so 40*300 = 12 kB. This can easily fit in memory and is far from an "outrageous amount of processing power" on modern computers.
Is their a more efficient way to store this data keeping all of the data in order?
Yes. If your game is deterministic, all you have to store is the player's input and one game state 5 seconds ago. When rolling back, reset the game state and replay user inputs to recompute each frame data.
See this question for interesing discussion on how to design your own replay system on gamedev stackexchange.
I don't think an array of 300 relatively small elements will slow you down at all, have you tried profiling it yet?
That said you could store it in a vector and keep an iterator to the "current" and update that.
If you think storing 300 is a lot, store less, for example you can store 1/5 frames :
....|....|....|....|..*
* is your position, `/` the frames you will store and `....` other frames
and you don't have to copy all the saved data each time ... just delete the first and add one at the end, you can maybe use a std::list, you won't have to copy any data
in Every 5 frames you will call myList.pop_front(); the oldest frame and myList.push_back(); the newest
I don't think the storage requirement is THAT harsh - even with 300 frames this small object will take up much less memory than your average texture.
I suggest you avoid using a raw array and look at using a std::vector which is almost as efficient and will automatically resize as you need more buffer space (that way if you suddenly need 8 second or the fps goes up to 100 you aren't going to suddenly run out of buffer space). This also resolves your difficulty with unfilled 'slots' as the vector has a known size that you can efficiently access.
I also might suggest that you don't need to store every frame - games like Prince of Persia that do this trick if you watch them carefully are much less smooth when time runs backwards suggesting that they perhaps only store every few frames or something like twice a second as opposed to every frame.
Unless you're running on an MCU, data sizes (given the structures you've provided) will be negligible compared to the rest of your game (~10K, if I calculated it correctly, is nothing for modern PCs).
CPU-wise, moving data in a manner you've specified and on every frame, MIGHT be sub-optimal (it will move around 10K 60 times per second, or 600K per second, which MIGHT - though probably won't - be noticeable). IF it becomes a concern, I'd go for a circular buffer (for example, as in boost::circular_buffer), or for a std::deque or std::list (with deque probably being my first choice); all of them have O(1) insertion/deletion time, and insertion/deletion is what you need most of the time. Theoretically, there is also an option to use memmove() to speed things up without changing things much, but it is quite error-prone, and still has O(N) complexity, so I'd rather not do it.
Indeed, you could do less operations per frame to store the state.
You could use a std::vector. Then, at each frame, push_back() the new state and if(vector.size() > 300), then do a pop_front().
If you think it's not enough, just save less frequently (each half a second). When you roll back your info, you could do an interpolation between values.
Edit:
you're damn right Othman, vector doesn't have pop_front, so you can use vector.erase(vector.begin()) instead :) So you don't have to use linked lists.
Note: Although this question doesn't directly correlate to games, I've molded the context around game development in order to better visualize a scenario where this question is relevant.
tl;dr: Is rapidly creating objects of the same class memory intensive, inefficient, or is it common practice?
Say we have a "bullet" class - and an instance of said class is created every time the player 'shoots' - anywhere between 1 and 10 times every second. These instances may be destroyed (obviously) upon collision.
Would this be a terrible idea? Is general OOP okay here (i.e.: class Bullet { short x; short y; }, etc.) or is there a better way to do this? Is new and delete preferred?
Any input much appreciated. Thank you!
This sounds like a good use-case for techniques like memory-pools or Free-Lists. The idea in both is that you have memory for a certain number of elements pre-allocated. You can override the new operator of your class to use the pool/list or use placement new to instantiate your class in a retrieved address.
The advantages:
no memory fragmentation
pretty quick
The disadvantages:
you must know the maximum number of elements beforehand
Don't just constantly create and delete objects. Instead, an alternative is to have a constant, resizable array or list of object instances that you can reuse. For example, create an array of 100 bullets, they don't all have to be drawn, have a boolean that states whether they are "active" or not.
Then whenever you need a new bullet, "activate" an inactive bullet and set its position where you need it. Then whenever it is off screen, you can mark it inactive again and not have to delete it.
If you ever need more than 100 bullets, just expand the array.
Consider reading this article to learn more: Object Pool. It also has several other game pattern related topics.
The very very least that happens when you allocate an object is a function call (its constructor). If that allocation is dynamic, there is also the cost of memory management which at some point could get drastic due to fragmentation.
Would calling some function 10 times a second be really bad? No. Would creating and destroying many small objects dynamically 10 times a second be bad? Possibly. Should you be doing this? Absolutely not.
Even if the performance penalty is not "felt", it's not ok to have a suboptimal solution while an optimal one is immediately available.
So, instead of for example a std::list of objects that are dynamically added and removed, you can simply have a std::vector of bullets where addition of bullets means appending to the vector (which after it has reached a large enough size, shouldn't require any memory allocation anymore) and deleting means swapping the element being deleted with the last element and popping it from the vector (effectively just reducing the vector size variable).
Think that with every instantiation there is a place in the heap where it need to allocate memory and create a new instance. This may affect the performance. Try using collection and create an instance of that collection with how many bullets you want.
I am working on an OpenGL based game, and this problem arises in my search for a robust way to pass entity information to the rendering and networking functions.
Something like this:
vector <DynamicEntity> DynamicEntities;
vector <StaticEntity> StaticEntities;
vector <Entity> *Entities;
Entities.push_back(&DynamicEntities);
Entities.push_back(&StaticEnt);
Graphics.draw(Entities);
Server.bufferData(Entities);
The only information Graphics.draw and Server.bufferData need is contained by Entity, which both DynamicEntity and StaticEntity inherit from.
I know this would work:
vector <Entity*> Entities;
for(uint32_t iEntity=0;iEntity<iNumEntities;iEntity++)
{
Entities.push_back(&DynamicEntities[iEntity])
}
//(ad nauseam for other entity types)
but that seems awfully inefficient, and would have to account for changing numbers of entities as the game progresses. I know relatively little of the underpinnings of data structures; so this may be a stupid question, but I would appreciate some insight.
That copy operation in the for loop you show is likely to be so fast as to be unmeasurable as compared to the cost of drawing the graphics. You may be able to make it faster still by doing Entities.resize(...) before the loop and using array indexing in the loop.
The solution you propose in the first part of your question will not work, because the data layout for a vector<StaticEntity> likely differs from the layout for a vector<DynamicEntity>. Arrays of objects are not polymorphic, and the storage managed by vector<> is essentially an array with some dynamic management around it.
In fact, because the vector storage is array-like, if you replace push_back with array indexing, the body of for loop will compile to something resembling:
*p1++ = p2++;
which the compiler may even auto-vectorize!
I'm trying to figure out the best way to do this, but I'm getting a bit stuck in figuring out exactly what it is that I'm trying to do, so I'm going to explain what it is, what I'm thinking I want to do, and where I'm getting stuck.
I am working on a program that has a single array (Image really), which per frame can have a large number of objects placed on an image array. Each object is completely independent of all other objects. The only dependency is the output, in theory possible to have 2 of these objects placed on the same location on the array. I'm trying to increase the efficiency of placing the objects on the image, so that I can place more objects. In order to do that, I'm wanting to thread the problem.
The first step that I have taken towards threading it involves simply mutex protecting the array. All operations which place an object on the array will call the same function, so I only have to put the mutex lock in one place. So far, it is working, but it is not seeing the improvements that I would hope to have. I am hypothesizing that this is because most of the time, the limiting factor is the image write statement.
What I'm thinking I need to do next is to have multiple image buffers that I'm writing to, and to combine them when all of the operations are done. I should say that obscuration is not a problem, all that needs to be done is to simply add the pixel counts together. However, I'm struggling to figure out what mechanism I need to use in order to do this. I have looked at semaphores, but while I can see that they would limit a number of buffers, I can envision a situation in which two or more programs would be trying to write to the same buffer at the same time, potentially leading to inaccuracies.
I need a solution that does not involve any new non-standard libraries. I am more than willing to build the solution, but I would very much appreciate a few pointers in the right direction, as I'm currently just wandering around in the dark...
To help visualize this, imagine that I am told to place, say, balls at various locations on the image array. I am told to place the balls each frame, with a given brightness, location, and size. The exact location of the balls is dependent on the physics from the previous frame. All of the balls must be placed on a final image array, as quickly as they possibly can be. For the purpose of this example, if two balls are on top of each other, the brightness can simply be added together, thus there is no need to figure out if one is blocking the other. Also, no using GPU cards;-)
Psuedo-code would look like this: (Assuming that some logical object is given for location, brightness, and size). Also, assume, that isValidPoint simply finds if the point should be on the circle, given the location and radius of said circle.
global output_array[x_arrLimit*y_arrLimit)
void update_ball(int ball_num)
{
calc_ball_location(ball_num, *location, *brightness, *size); // location, brightness, size all set inside function
place_ball(location,brightness,size)
}
void place_ball(location,brighness,size)
{
get_bounds(location,size,*xlims,*ylims)
for (int x=xlims.min;x<xlims.max;y++)
{
for (int y=ylims.min;y<ylims.max;y++)
{
if (isValidPoint(location,size,x,y))
{
output_array(x,y)+=brightness;
}
}
}
}
The reason you're not seeing any speed up with the current design is that, with a single mutex for the entire buffer, you might as well not bother with threading, as all the objects have to be added serially anyway (unless there's significant processing being done to determine what to add, but it doesn't sound like that's the case). Depending on what it takes to "add an object to the buffer" (do you use scan-line algorithms, flood fill, or something else), you might consider having one mutex per row or a range of rows, or divide the image into rectangular tiles with one mutex per region or something. That would allow multiple threads to add to the image at the same time as long as they're not trying to update the same regions.
OK, you have an image member in some object. Add the, no doubt complex, code to add other image/objects to it. maipulate it, whatever. Aggregate in all the other objects that may be involved, add some command enun to tell threads what op to do and an 'OnCompletion' event to call when done.
Queue it to a pool of threads hanging on the end of a producer-consumer queue. Some thread will get the *object, perform the operation on the image/set and then call the event, (pass the completed *object as a parameter). In the event, you can do what you like, according to the needs of your app. Maybe you will add the processed images into a (thread-safe!!), vector or other container or queue them off to some other thread - whatever.
If the order of processing the images must be preserved, (eg. video stream), you could add an incrementing sequence-number to each object that is submitted to the pool, so enabling your 'OnComplete' handler to queue up 'later' images until all earlier ones have come in.
Since no two threads ever work on the same image, you need no locking while processing. The only locks you should, (may), need are those internal the queues, and they only lock for the time taken to push/pop object pointers to/from the queue - contention will be very rare.
This may be the wrong approach, but as I dig deeper into developing my game engine I have ran into a timing issue.
So lets say I have a set of statements like:
for(int i = 0; i < 400; i++)
{
engine->get2DObject("bullet")->Move(1, 0);
}
The bullet will move, however, on the screen there won't be any animation. It will basically "warp" from one part of the screen to the next.
So, I am thinking...create a vector of function pointers for each base object (which the user inherits from) and when they call "Move" I actually don't move the object until the next iteration of the game loop.
So something like:
while(game.running())
{
game.go();
}
go()
{
for(...)
2dobjs.at(i)->action.pop_back();
}
Or something like that, and this way it runs only a single action of each object during each iteration (of course I'll add in a check to see if there is actually "actions" to be ran).
And if that is a good idea, my question is how do I store the parameters. Since each object can do more than a single type of "action" rather than move (rotateby is one example), I think it would be nonsensical to create a struct similar in fashion to:
struct MoveAction {
MovePTR...;
int para1;
int para2;
};
Thoughts? Or is this the completely wrong direction?
Thoughts? Or is this the completely wrong direction?
It's the wrong direction.
Actually, the idea of being able to queue actions or orders has some merit. But usually this applies to things like AI and to more general tasks (like "proceed to location X", "attack anything you see", etc). So it usually doesn't cover the frame-by-frame movement issue that you're dealing with here.
For very simply entities like bullets, queuing tasks is rather overkill. After all, what else is a bullet going to do except move forward each time? It's also an awkward way to implement such simple motion. It brings up issues like, why only 400 steps forward? What if the area in front is longer? What if its shorter? What if some other object gets in the way after only say 50 steps? (Then 350 queued move actions were a waste.)
Another problem with this idea (at least in the simplistic way you've presented it) is that your bullets are going to move a fixed amount per each iteration of your game loop. But not all iterations are going to take the same amount of time. Some people's computers will obviously be able to run the code faster than others. And even disregarding that, sometimes the game loop may be doing considerably more work than other times (such as when many more entities are active in the game). So you would really want a way to factor in the time that each iteration is taking to adjust the movement and such so that the everything appears to move at a consistent speed to the user, regardless of how fast the game loop is running.
So instead of each movement action being "move X amount" they would be "move at X speed" and would then be multiplied by something like the time elapsed since the last iteration. And then you would really never know how many move actions to queue, because it would depend on how fast your game loop is running in that scenario. But again, this is another indication that queuing movement actions is an awkward solution to frame-by-frame movement.
The way most game engines do it is to simply call some sort of function on the each object each frame which evaluates its movement. Maybe a function like void ApplyMovement(float timeElapsedSinceLastFrame);. In the case of a bullet, it would multiply the speed at which a bullet should move per second by the passed in time since the last frame to determine the amount that the bullet should move this frame. For more complex objects you might want to do math with rotations, accelerations, decelerations, target-seeking, etc. But the general idea is the same: call a function each iteration of the game loop to evaluate what should happen for that iteration.
I don't think this is the right direction. After you store 400 moves in a vector of function pointers, you'll still need to pop and perform a move, redraw the screen, and repeat. Isn't it easier just to move(), redraw, and repeat?
I'd say your bullet is warping because it's moving 400 pixels/frame, not because you need to delay the move calculations.
But if this is the correct solution for your architecture, in C++ you should use classes rather than function pointers. For example:
class Action // an abstract interface for Actions
{
public:
virtual void execute() = 0; // pure virtual function
}
class MoveAction: public Action
{
public:
MoveAction(Point vel) : velocity(vel) {}
virtual void execute();
Point velocity;
...
}
std::vector<Action*> todo;
gameloop
{
...
todo.push_back(new MoveAction(Point(1,0))
...
}
So where does 400 come from? Why not just do it this way:
go()
{
engine->get2DObject("bullet")->Move(1, 0);
}
I think the general approach could be different to get what you want. I personally would prefer a setup where each go loop called functions to set the position for all objects including the bullet, then draw the scene. So each loop it would put the bullet where it should be right then.
If you do decide to go your route, you will likely have to do your struct idea. It's not pleasant, but until we get closures, you'll have to do.