Jump to content
  • Advertisement
Sign in to follow this  
Psilobe

Performance trouble when rendering (2d)

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

I've noticed in my small game that I get very low fps very quickly when multiple objects are on the screen.

The two objects that hogs performance are enemies and shots fired by either the player or the enemy.

After looping through a vector and moving all enemies I loop the vector again and renders each enemy.

Collapse
void renderEnemy(){
for (int i = 0;i<enemyVector.size();i++){
enemyVector.drawEnemy();
}
};

Collapse
void enemy::drawEnemy(){
const string playerFilename = "SmallMine.tif";
const int DROPS_X_FRAME_COUNT = 1;
const int DROPS_Y_FRAME_COUNT = 1;
VGCImage player = VGCDisplay::openImage(
playerFilename,
DROPS_X_FRAME_COUNT,
DROPS_Y_FRAME_COUNT
);
const VGCVector frameIndex = VGCVector(0, 0);
const VGCVector position = VGCVector(xPos, yPos);
const VGCAdjustment adjustment = VGCAdjustment(0.0, 0.0);
VGCDisplay::renderImage(player, frameIndex, position, adjustment);
VGCDisplay::closeImage(player);

};

As you can see drawEnemy gets called quite a lot which slows down my game but I'm not sure on how to avoid this function getting called so many times.

Share this post


Link to post
Share on other sites
Advertisement
void enemy::drawEnemy(){
const string playerFilename = "SmallMine.tif";
const int DROPS_X_FRAME_COUNT = 1;
const int DROPS_Y_FRAME_COUNT = 1;
VGCImage player = VGCDisplay::openImage(
playerFilename,
DROPS_X_FRAME_COUNT,
DROPS_Y_FRAME_COUNT
);
const VGCVector frameIndex = VGCVector(0, 0);
const VGCVector position = VGCVector(xPos, yPos);
const VGCAdjustment adjustment = VGCAdjustment(0.0, 0.0);
VGCDisplay::renderImage(player, frameIndex, position, adjustment);
VGCDisplay::closeImage(player);
};
What does VGCDisplay::openImage do? If it actually opens an image from disk then of course your code will be slow. You want to keep images in memory if they are used often.

Share this post


Link to post
Share on other sites
That is exactly what it does, and it is what I want to avoid. I got no clue on how to proceeed at the moment and how to keep the picture in the memory.

Share this post


Link to post
Share on other sites
You need to load the image in a different function and keep a copy of the image in memory. How are you loading the image? What API are you using?

Share this post


Link to post
Share on other sites
Quote:
Original post by Psilobe
That is exactly what it does, and it is what I want to avoid. I got no clue on how to proceeed at the moment and how to keep the picture in the memory.


Simple enough: You want to move the openImage out of drawEnemy and store the VGCImage it returns somewhere where drawEnemy can use it.

For example, we could turn it into a member variable, and use enemy's constructor and deconstructor to open/close it. This isn't all that great on it's own, but it is at least better:

class enemy {
VGCImage player;
public:
enemy();
~enemy();
...
};

enemy::enemy() {
const string playerFilename = "SmallMine.tif";
const int DROPS_X_FRAME_COUNT = 1;
const int DROPS_Y_FRAME_COUNT = 1;
player = VGCDisplay::openImage(
playerFilename,
DROPS_X_FRAME_COUNT,
DROPS_Y_FRAME_COUNT
);
}

enemy::~enemy() {
VGCDisplay::closeImage(player)
}

void enemy::drawEnemy() {
const VGCVector frameIndex = VGCVector(0, 0);
const VGCVector position = VGCVector(xPos, yPos);
const VGCAdjustment adjustment = VGCAdjustment(0.0, 0.0);
VGCDisplay::renderImage(player, frameIndex, position, adjustment);
}



A more efficient way would be to only load the image once for the entire program, rather than once per enemy. There are many different ways to do this:

- (ab)use the static keyword
- Have something else load the image, and then tell the enemies what to use by passing it a pointer or reference to the image
- Have something else load the image AND draw the enemies, having the enemy not care what images are used.

Experiment, and see what works well for you :). (And for future reference, wrap your code in [source] tags [/source] to make it nice and readable with indentation like above.)

Share this post


Link to post
Share on other sites
Many thanks, I think I'm starting to get how it should be done.

But if I load the iamge with one isntance of enemy can other instances of enemy draw the image if the draw function then jsut takes their coordinates and use the render part of the code?

Or do I ahce to point to that specific instance which loaded the image?

Share this post


Link to post
Share on other sites
Something like this is typically done statically.

-Add a static VGCImage variable to your enemy class.
-Add a static function to your enemy class that loads the image.
-call the static function when you are initializing things, such as the beginning of a level.

Just in case you aren't familiar with what static means, by declaring a variable static, it will be shared by all instances of the enemy class. This way, you only load the image once, and all enemies can access it.

Share this post


Link to post
Share on other sites
I think I'm closing in on this but I still dont think I got the hang of using statics.

This is what I came up with but I get linker erro LNK2001.

error LNK2001: unresolved external symbol "protected: static class VGCImage enemy::player" (?player@enemy@@1VVGCImage@@A) enemy.obj

And also LNK1120 1 unresolved external.

And I has no clue as to what's wrong.


void enemy::initImage(){
const string playerFilename = "SmallMine.tif";
const int DROPS_X_FRAME_COUNT = 1;
const int DROPS_Y_FRAME_COUNT = 1;
VGCImage player = VGCDisplay::openImage(
playerFilename,
DROPS_X_FRAME_COUNT,
DROPS_Y_FRAME_COUNT
);

};


void enemy::closeImage(){
VGCDisplay::closeImage(player);
};
void enemy::renderEnemy(){
const VGCVector frameIndex = VGCVector(0, 0);
const VGCVector position = VGCVector(xPos, yPos);
const VGCAdjustment adjustment = VGCAdjustment(0.0, 0.0);
VGCDisplay::renderImage(player, frameIndex, position, adjustment);
};


And the header:
class enemy {

public:
static void initImage();
static void closeImage();
void drawEnemy();
void initEnemy();
void moveEnemy();
void updateEnemy();
int getyPos();
int getxCent();
int getyCent();
void renderEnemy();

protected:
static VGCImage player;
int xPos;
int yPos;
};

Share this post


Link to post
Share on other sites
You declared the static variable but you didn't define it. Read more here

I should note that using a static member variable only makes sense if you expect all 'enemies' to have the same image. Otherwise you would want a regular member variable and assign an image in, for example, the constructor.

Share this post


Link to post
Share on other sites
The problem with defining my static variable is taht if I do it like this:

VGCImage enemy::player = VGCDisplay::openImage(
playerFilename,
DROPS_X_FRAME_COUNT,
DROPS_Y_FRAME_COUNT
);



It says it cant find PlayerFilename and Drops_X... and Drops_Y...

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!