diff --git a/demos/demo3-foodthrowing/src/food_scene.cpp b/demos/demo3-foodthrowing/src/food_scene.cpp index 089bdbf..d2369eb 100644 --- a/demos/demo3-foodthrowing/src/food_scene.cpp +++ b/demos/demo3-foodthrowing/src/food_scene.cpp @@ -36,6 +36,7 @@ std::vector FoodScene::sprites() { } void FoodScene::removeBulletsOffScreen() { + // TODO this is VERY ineffective, but it's a nice example of how C++11 remove_if works. bullets.erase( std::remove_if(bullets.begin(), bullets.end(), [](std::unique_ptr &s) { return s->isOffScreen(); }), bullets.end()); @@ -55,6 +56,7 @@ void FoodScene::tick(u16 keys) { TextStream::instance().setText(std::to_string(counter) + std::string(" frames/5sec"), 5, 1); TextStream::instance().setText(std::string(engine->getTimer()->to_string()), 6, 1); + avatar->animateToFrame(0); bool allowedToShoot = false; int oldBulletSize = bullets.size(); @@ -66,11 +68,6 @@ void FoodScene::tick(u16 keys) { } removeBulletsOffScreen(); - TextStream::instance().setText(std::string("bullets: ") + std::to_string(bullets.size()), 1, 1); - TextStream::instance().setText(std::string("cooldown: ") + std::to_string(bulletCooldown), 2, 1); - - TextStream::instance().setText(std::string("angle pa/pb: ") + std::to_string(avatar->getMatrix()->pa) + std::string("/") + std::to_string(avatar->getMatrix()->pb), 3, 1); - TextStream::instance().setText(std::string("angle pc/pd: ") + std::to_string(avatar->getMatrix()->pc) + std::string("/") + std::to_string(avatar->getMatrix()->pd), 4, 1); if(keys & KEY_LEFT) { avatarRotation -= AVATAR_ROTATION_DIFF; @@ -92,6 +89,7 @@ void FoodScene::tick(u16 keys) { } avatar->rotate(avatarRotation); + if(oldBulletSize != bullets.size()) { engine.get()->updateSpritesInScene(); } @@ -132,18 +130,5 @@ 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)); - } - } - }*/ - engine->getTimer()->start(); } \ No newline at end of file diff --git a/engine/include/libgba-sprite-engine/sprites/sprite.h b/engine/include/libgba-sprite-engine/sprites/sprite.h index 6a18da5..e3d6adc 100644 --- a/engine/include/libgba-sprite-engine/sprites/sprite.h +++ b/engine/include/libgba-sprite-engine/sprites/sprite.h @@ -58,10 +58,9 @@ protected: bool stayWithinBounds; u32 imageSize, tileIndex; SpriteSize spriteSize; - u32 animationDelay, numberOfFrames, beginFrame, currentFrame, animationCounter; + u8 animationDelay, numberOfFrames, beginFrame, currentFrame, previousFrame, animationCounter; bool animating; - - std::unique_ptr oam; + OBJ_ATTR oam; void syncAnimation(); virtual void syncOam(); diff --git a/engine/src/sprites/affine_sprite.cpp b/engine/src/sprites/affine_sprite.cpp index 7020e78..65710c3 100644 --- a/engine/src/sprites/affine_sprite.cpp +++ b/engine/src/sprites/affine_sprite.cpp @@ -38,7 +38,7 @@ void AffineSprite::setTransformationMatrix(OBJ_AFFINE *matrix) { } void AffineSprite::rebuildOamAttr1ForAffineIndex() { - this->oam->attr1 = this->x | + oam.attr1 = this->x | ATTR1_AFF_ID(affIndex) | (HORIZONTAL_FLIP_FLAG << 12) | (VERTICAL_FLIP_FLAG << 13) | @@ -47,7 +47,7 @@ void AffineSprite::rebuildOamAttr1ForAffineIndex() { void AffineSprite::buildOam(int tileIndex) { Sprite::buildOam(tileIndex); - this->oam->attr0 = ATTR0_Y(this->y) | + oam.attr0 = ATTR0_Y(this->y) | ATTR0_MODE(1) | (GFX_MODE << 10) | (MOSAIC_MODE << 12) | diff --git a/engine/src/sprites/sprite.cpp b/engine/src/sprites/sprite.cpp index 80e1a6d..0b20ac0 100644 --- a/engine/src/sprites/sprite.cpp +++ b/engine/src/sprites/sprite.cpp @@ -29,9 +29,7 @@ void Sprite::moveTo(VECTOR location) { void Sprite::moveTo(int x, int y) { this->x = x; this->y = y; - if(oam) { - syncOam(); - } + syncOam(); } bool Sprite::isOffScreen() { @@ -40,25 +38,20 @@ bool Sprite::isOffScreen() { void Sprite::flipHorizontally(bool flip) { if(flip) { - oam->attr1 |= ATTR1_HFLIP; + oam.attr1 |= ATTR1_HFLIP; } else { - oam->attr1 &= FLIP_HORIZONTAL_CLEAR; + oam.attr1 &= FLIP_HORIZONTAL_CLEAR; } } void Sprite::flipVertically(bool flip) { if(flip) { - oam->attr1 |= ATTR1_VFLIP; + oam.attr1 |= ATTR1_VFLIP; } else { - oam->attr1 &= FLIP_VERTICAL_CLEAR; + oam.attr1 &= FLIP_VERTICAL_CLEAR; } } -void Sprite::syncVelocity() { - oam->attr0 = (oam->attr0 & ~ATTR0_Y_MASK) | (y & ATTR0_Y_MASK); - oam->attr1 = (oam->attr1 & ~ATTR1_X_MASK) | (x & ATTR1_X_MASK); -} - void Sprite::makeAnimated(int beginFrame, int numberOfFrames, int animationDelay) { setBeginFrame(beginFrame); animateToFrame(beginFrame); @@ -67,10 +60,17 @@ void Sprite::makeAnimated(int beginFrame, int numberOfFrames, int animationDelay animate(); } +void Sprite::syncVelocity() { + oam.attr0 = (oam.attr0 & ~ATTR0_Y_MASK) | (y & ATTR0_Y_MASK); + oam.attr1 = (oam.attr1 & ~ATTR1_X_MASK) | (x & ATTR1_X_MASK); +} + void Sprite::syncAnimation() { + if(previousFrame == currentFrame) return; + int newTileIndex = this->tileIndex + (currentFrame * (this->animation_offset * 2)); - oam->attr2 &= OAM_TILE_OFFSET_CLEAR; - oam->attr2 |= (newTileIndex & OAM_TILE_OFFSET_NEW); + oam.attr2 &= OAM_TILE_OFFSET_CLEAR; + oam.attr2 |= (newTileIndex & OAM_TILE_OFFSET_NEW); } void Sprite::syncOam() { @@ -96,6 +96,7 @@ void Sprite::updateAnimation() { if(!animating) return; animationCounter++; + previousFrame = currentFrame; if(animationCounter > animationDelay) { currentFrame++; if(currentFrame > (numberOfFrames - 1) + beginFrame) { @@ -148,23 +149,19 @@ bool Sprite::collidesWith(Sprite &s2) { void Sprite::buildOam(int tileIndex) { this->tileIndex = tileIndex; - if(!oam) { - this->oam = std::unique_ptr(new OBJ_ATTR()); + oam.attr0 = ATTR0_Y(this->y & 0x00FF) | + ATTR0_MODE(0) | + (GFX_MODE << 10) | + (MOSAIC_MODE << 12) | + (COLOR_MODE_256 << 13) | + (this->shape_bits << 14); + oam.attr1 = (this->x & 0x01FF) | + (AFFINE_FLAG_NONE_SET_YET << 9) | + (HORIZONTAL_FLIP_FLAG << 12) | + (VERTICAL_FLIP_FLAG << 13) | + (this->size_bits << 14); - this->oam->attr0 = ATTR0_Y(this->y & 0x00FF) | - ATTR0_MODE(0) | - (GFX_MODE << 10) | - (MOSAIC_MODE << 12) | - (COLOR_MODE_256 << 13) | - (this->shape_bits << 14); - this->oam->attr1 = (this->x & 0x01FF) | - (AFFINE_FLAG_NONE_SET_YET << 9) | - (HORIZONTAL_FLIP_FLAG << 12) | - (VERTICAL_FLIP_FLAG << 13) | - (this->size_bits << 14); - } - - this->oam->attr2 = ATTR2_ID(tileIndex) | + oam.attr2 = ATTR2_ID(tileIndex) | ATTR2_PRIO(priority) | ATTR2_PALBANK(0); } diff --git a/engine/src/sprites/sprite_manager.cpp b/engine/src/sprites/sprite_manager.cpp index f106870..67dd4b1 100644 --- a/engine/src/sprites/sprite_manager.cpp +++ b/engine/src/sprites/sprite_manager.cpp @@ -45,8 +45,7 @@ void SpriteManager::copyOverSpriteOAMToVRAM() { for(auto sprite : this->sprites) { sprite->update(); - auto oam = sprite->oam.get(); - oam_mem[i] = *oam; + oam_mem[i] = sprite->oam; auto affine = dynamic_cast(sprite); if(affine) {