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.
Related
I'm creating a game engine using C++ and SFML. I have a class called character that will be the base for entities within the game. The physics class is also going to handle character movement.
My question is, is it faster to create a vector of pointers to the characters that move in a frame. Then, whenever a function moves a character it places it inside that vector. After the physics class is done handling the vector it gets cleared?
Or is it faster to have a bool variable that gets set to true whenever a function moves a character and then have an if statement inside my physics class that tests every character for movement?
EDIT:
Ok i've gone with a different approach where a function inside the Physics class is responsible for dealing with character movement. Immediately upon movement, it tests for collision detection. If collision happens it stops the movement in that direction.
Thanks for your help guys
Compared to all the other stuff that is going on in your program (physics, graphics), this will not make a difference. Use the method that makes programming easier because you will not notice a runtime difference at all.
If the total number of characters is relatively small, then you won't notice the difference between the approaches.
Else (the number of characters is large), if most of characters move during a frame, then the approach with flag inside a character seems more appropriate, because even with vector of moved characters, you'll traverse all of them and besides that you get additional overhead of maintaining the vector.
Else (the number of characters is large, but only few of them move during a frame), it may be better to use vector because it can save you time by not traversing characters which didn't move.
What is a small or large number, depends on your application. You should test under which conditions you get better performance using either of approaches.
This would be the right time to quote Hoare, but I'll abstain. Generally, however, you should profile before you optimize (if, and only if, the time budget is not enough on the minimum spec hardware -- if your game runs at 60fps on the target hardware you will do nothing whatsoever).
It is much more likely that the actual physics calculations will be the limiting factor, not doing the "is this unit moving?" check. Also, it is much more likely that submitting draw calls will bite you rather than checking a few hundred or so units.
As an "obvious" thing, it appears to be faster to hold a vector of object pointers and only process the units that are actually moving. However, the "obvious" is not always correct. Iterating linearly over a greater number of elements can very well be faster than jumping around (due to cache). Again, if this part of your game is identified as the bottleneck (very unlikely) then you will have to measure which is better.
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.
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.
Hey im programming a simple game using directX and C++ and i have hit a slight problem which im sure some genius can fix.
I currently have an array of 8 Aliens and i currently use this code to move them left to right and down a line.
bool turnaround=false;
if ((Aliens[0].pos.x<-5 & Aliens[0].vel.x<0)|(Aliens[3].pos.x>5&Aliens[3].vel.x>0))
{
turnaround=true;
if(Aliens[0].vel.x<0)
Aliens[0].animCtrl->SetTrackSpeed(0,1);
else
Aliens[0].animCtrl->SetTrackSpeed(0,-1);
}
However this currently stops them short if ones to the left or right have been destroyed (they are destroyed by a variable Aliens[i].dead = true
I was wondering if anyone can come up with the if statement or nested if's required to say if ones furthest left or right are destroyed go further across :/
Thanks :)
I presume from your question that you are constructing some sort of space invaders type game. Here would be one way to approach this that might be better than what you currently have (in a pseudo-code form):
For each alien:
If alien is currently on an odd row:
Set direction to left
If alien x position is near 0:
Set direction to down
Else
Set direction to right
If alien x position is near screen width:
Set direction to down
This should cause the aliens to move down towards the bottom of the screen row by row. (Of course there are many different formations aliens could take in this type of game, this is just one). You aren't clear about what sort of behaviour you want them to exhibit when they are killed ("go further across" is ambiguious, is this the player or some of the aliens, or what?), however, if you elaborate on that I may be able to lend further advice here.
I would also suggest you reconsider your design for a minute. You have what appears to be a fixed size array that holds the 8 aliens. While this may allow you to construct a particular level, it is likely to prove very restrictive. What if in another level you want 12 aliens? I suggest you turn your Aliens array into an std::vector, so you can add them to a level as you like at will. Even better, if you have different types of enemies that all share the same properties, you could create a superclass CEnemy that these enemies all inherit from. This is likely to make your design more robust and expandable.
Also, as has been stated by others already, use logical operators when you want to run an AND or OR operation, not bitwise. (That is, use || instead of |, etc) There is an important difference between the two.
By the way, you should get in the habit of using the logical operators (&& and ||) for things like this instead of bitwise operators. They should be more efficient because of short circuiting and prevent bugs later down the road.
I'm not sure if there's enough information to answer your real question. Why are you manually accessing the 0th and 3rd Alien? How do you want the aliens to behave, ideally?
EDIT 1:
Something like this should work:
Alien * furthestLeftAlien, * furthestRightAlien;
/** here loop through your Aliens array to find
the furthest left and furthest right aliens **/
if(furthestLeftAlien->dead || furthestRightAlien->dead)
{
goFurtherAcross():
}
You should really be using a different data structure altogether. C++ std library has several different container classes that can help you.
For instance, a std::deque allows you to easily remove items from either end.
You could remove dead aliens like:
while (!Aliens.empty() && Aliens.front().is_dead()) Aliens.pop_front();
while (!Aliens.empty() && Aliens.back().is_dead()) Aliens.pop_back();
And then your code above would go:
bool turnaround=false;
if ((Aliens.front().pos.x<-5 && Aliens.front().vel.x<0) || (Aliens.back().pos.x>5 && Aliens.back().vel.x>0))
{
turnaround=true;
if(Aliens.front().vel.x<0)
Aliens.front().animCtrl->SetTrackSpeed(0,1);
else
Aliens.front().animCtrl->SetTrackSpeed(0,-1);
}
Though to be honest, I'm not sure how the code here is meant to turn around the whole row of aliens. Instead of using a turnaround variable, why not just turn the aliens around inside the if statement?
I don't really have any problems with the way I'm rendering now, but I don't feel like it's a very good way of handling rendering. I'm using SDL.
It boils down to this I have some abstract class
class Renderable
With two functions.
virtual void update() = 0;
virtual void doRender(SDL_Surface* surface) = 0;
I have another class
class RenderManager
With 1 std::vector
std::vector<Renderable*> _world;
and 2 std::queue
std::queue<Renderable*> _addQueue;
std::queue<Renderable*> _delQueue;
The two queues hold the renderables that need to be added in the next tick and the ones that need to be removed. Doing everything in one shot gave me problems and now that I think about it, it makes sense (at least the way I did it).
Renderables can add and remove themselves from the RenderManager statically.
Here's more or less the function handling everything.
void renderAll() {
std::vector<Renderable*>::iterator begin, end;
begin = _world.begin();
end = _world.end();
for (;begin != end; ++begin) {
(*begin)->update();
(*begin)->doRender(_mainWindow); // _mainWindow is the screen of course
}
begin = world.begin();
if (_delQueue.size() > 0) {
for (unsigned int i = 0; i < _delQueue.size(); i++) {
std::vector<Renderable*>::iterator del;
del = std::find(begin, end, _delQueue.front());
if (del != end) {
delete *del;
_world.erase(del);
}
_delQueue.pop();
}
}
if (_addQueue.size() > 0) {
for (unsigned int i = 0; i < _addQueue.size(); i++) {
Renderable* front = _addQueue.front();
// _placement is a property of Renderable calculated by RenderManager
// where they can choose the level they want to be rendered on.
_world.insert(begin + front->_placement, front);
_addQueue.pop();
}
}
}
I'm kinda sorta newish to C++, but I think I know my way around it on an average scale at least. I'm even newer to SDL, but it seems pretty simple and easy to learn. I'm concerned because I have 3 big loops together. I tried one shotting it but I was having problems with _world resizing during the loop causing massive amounts of destruction. But I'm not claiming I did it right! :)
I was thinking maybe something involving threads?
EDIT:
Ahh, sorry for the ambiguity. By "cleaner" I mean more efficient. Also there is no "problem" with my approach, I just feel there's a more efficient way.
Firstly, I'd say don't fix something which isn't broken. Are you experiencing performance issues? Unless you're adding and removing 'renderables' in huge quantities every frame, I can't see a huge problem with what you have. Of course, in terms of an overall application it could be a clumsy design, but you haven't stated what sort of application this is for, so it's hard, if not impossible to judge.
However, I can guess and say that because you're using SDL, there's a chance you're developing a game. Personally I've always rendered game objects by having a render method for each active object and use an object manager to cycle through pointers to each object every tick and call this render method. Because constantly removing an item from the middle of a vector can cause slowdowns due to internal copying of memory (vectors guarantee contiguous memory), you could have a flag in every object which is set when it is meant to be removed, and periodically the object manager performs 'garbage collection', removing all objects with this flag set at the same time, hence reducing the amount of copying that needs to be done. In the mean time before garbage collection occurs, the manager simply ignores the flagged object, not calling its render method each tick - it's as if it has gone. It's actually not too dissimilar to what you have here with your queue system, in fact if game objects are derived from your 'renderable' class it could be deemed the same.
By the way is there any reason you're querying the queue sizes before accessing their elements? If size() is 0, the for loops won't operate anyway.