major performance gain by optimizing GBAEngine::update()

This commit is contained in:
wgroeneveld 2018-12-15 19:34:47 +01:00
parent 5e1b40cf4b
commit b71e0fc130
4 changed files with 41 additions and 9 deletions

View File

@ -48,6 +48,7 @@ VECTOR FoodScene::rotateAround(VECTOR center, VECTOR point) {
void FoodScene::tick(u16 keys) {
avatar->animateToFrame(0);
bool allowedToShoot = false;
int oldBulletSize = bullets.size();
if(bulletCooldown > 0) {
bulletCooldown--;
@ -82,6 +83,9 @@ void FoodScene::tick(u16 keys) {
}
avatar->rotate(avatarRotation);
if(oldBulletSize != bullets.size()) {
engine.get()->updateSpritesInScene();
}
for(auto &b : bullets) {
b->tick();
@ -118,4 +122,19 @@ void FoodScene::load() {
// rotation of a point on a circle within the resolution means our radius should be big enough
defaultBulletTarget = { GBA_SCREEN_WIDTH / 2, GBA_SCREEN_HEIGHT + (GBA_SCREEN_WIDTH / 2) - avatar->getCenter().y + 40};
/*
for(int i = 0; i < 10; i++) {
for(int j = 0; j < 4; j++) {
bullets.push_back(createBullet());
auto &b = bullets.at(bullets.size() - 1);
b->getSprite()->moveTo(10 + (i * 20), 10 + (j * 20));
if(j >= 1) {
b->getSprite()->moveTo(10 + (i * 20), 100 + (j * 20));
}
}
}
*/
}

View File

@ -21,6 +21,7 @@ private:
public:
int getSpriteSize() { return sprites.size(); }
void hideAll();
void add(Sprite* sprite);
void set(std::vector<Sprite*> sprites);
void persist(); // copies over image and palette data to VRAM, modifies sprite OAM indiches

View File

@ -113,6 +113,8 @@ GBAEngine::GBAEngine() {
}
void GBAEngine::update() {
// main update loop, in while(true) {}.
// WARNING - keep amount of instructions as minimal as possible in here!
if(sceneToTransitionTo) {
currentEffectForTransition->update();
@ -122,12 +124,16 @@ void GBAEngine::update() {
}
u16 keys = readKeys();
// main scene update loop call. This *might* take a while.
currentScene->tick(keys);
if(currentScene->sprites().size() != spriteManager.getSpriteSize()) {
updateSpritesInScene();
}
// Intentionally commented out: asking the scene for sprites() rebuilds the vector each time
// Causing a big performance hit. Instead, you should call updateSpritesInScene() yourself!
// if(currentScene->sprites().size() != spriteManager.getSpriteSize()) {
// updateSpritesInScene();
// }
// TODO use software interrupt Vsyncing instead of 2 wasteful whiles
vsync();
spriteManager.render();
}
@ -156,6 +162,7 @@ void GBAEngine::setScene(Scene* scene) {
TextStream::instance().clear();
}
}
spriteManager.hideAll();
scene->load();
auto fgPalette = scene->getForegroundPalette();

View File

@ -29,6 +29,7 @@ void SpriteManager::add(Sprite* sprite) {
}
void SpriteManager::render() {
// WARNING - This is called every time in the main update loop; keep amount of instructions as minimal as possible in here!
if(!initialized) {
failure_gba(Cant_Render_Before_Init);
}
@ -37,7 +38,7 @@ void SpriteManager::render() {
}
void SpriteManager::persist() {
copyOverImageDataToVRAM();
copyOverImageDataToVRAM();
initialized = true;
}
@ -46,9 +47,6 @@ void SpriteManager::copyOverSpriteOAMToVRAM() {
int affineIndex = 0;
for(auto sprite : this->sprites) {
if(affineIndex > MAX_AFFINE_SIZE) {
failure_gba(MaxSpritesWithAffineReached);
}
sprite->update();
auto oam = sprite->oam.get();
@ -66,8 +64,15 @@ void SpriteManager::copyOverSpriteOAMToVRAM() {
i++;
}
for(int j = i; j < MAX_SPRITE_SIZE; j++) {
oam_mem[j].attr0 = ATTR0_HIDE;
if(affineIndex > MAX_AFFINE_SIZE) {
failure_gba(MaxSpritesWithAffineReached);
}
}
void SpriteManager::hideAll() {
for(int i = 0; i < MAX_SPRITE_SIZE; i++) {
oam_mem[i].attr0 = ATTR0_HIDE;
}
}