~ndiddy/libremo

091f47350772b587924523d512be5c207a3bd95c — Nathan Misner 2 years ago cbb57c6
fixed issues with fade-out code
7 files changed, 323 insertions(+), 313 deletions(-)

M ball.h
M block.cpp
M block.h
M game.cpp
M level.cpp
M level.h
M stage.cpp
M ball.h => ball.h +1 -1
@@ 50,7 50,7 @@
#define BALL_STATE_INIT (0)
#define BALL_STATE_NORMAL (1)
#define BALL_SPAWN_XOFFSET ((SHIP_WIDTH / 2) - (BALL_WIDTH / 2))
#define BALL_SPAWN_YOFFSET (-2)
#define BALL_SPAWN_YOFFSET (2)

extern int ballMode;


M block.cpp => block.cpp +6 -8
@@ 160,14 160,6 @@ int Block::collide(int power) {
    }
}

void Block::setAlpha(uint8_t alpha) {
    // small optimization so i can call this function every frame in level.cpp
    if (alpha != this->alpha) {
        printf("old: %u new: %u\n", alpha, this->alpha);
        printf("result: %d\n", SDL_SetTextureAlphaMod(texture, alpha));
    }
}

void Block_Init() {
    blockTextures = Sprite_LoadPak("block.pak");
    tutorialBlockTextures = Sprite_LoadPak("tutorialblock.pak");


@@ 175,4 167,10 @@ void Block_Init() {
    blockRect.y = 0;
    blockRect.w = BLOCK_WIDTH;
    blockRect.h = BLOCK_HEIGHT;
}

void Block_SetAlpha(uint8_t alpha) {
    for (auto &pak : blockTextures) {
        SDL_SetTextureAlphaMod(pak->texture, alpha);
    }
}
\ No newline at end of file

M block.h => block.h +5 -2
@@ 79,8 79,11 @@ public:
    Block(float xPos, float yPos, int type, int mode, Level *parent);
    int shouldBounce(int power);
    int collide(int power);
    // makes the block partially transparent. alpha should be between 0 and 255
    void setAlpha(uint8_t alpha);
};

// should be run before creating any Block objects
void Block_Init();

// sets alpha transparency for all displayed Blocks with BLOCK_MODE_NORMAL
void Block_SetAlpha(uint8_t alpha);


M game.cpp => game.cpp +308 -284
@@ 22,6 22,7 @@

#include "ball.h"
#include "barrier.h"
#include "block.h"
#include "capsule.h"
#include "enemy.h"
#include "fade.h"


@@ 38,10 39,11 @@

typedef enum {
    STATE_GAME_FADEIN,
    STATE_SHIP_SPAWN,
    STATE_GAME_PLAY,
    STATE_GAME_PAUSE,
    STATE_GAME_LOSS,
    STATE_GAME_FADELEVEL,
    STATE_GAME_LOSS,
    STATE_GAME_CENTERSHIP,
    STATE_GAME_FLYUP,
    STATE_GAME_FLYDOWN,


@@ 231,23 233,17 @@ void Game_Init(int level, int numLevels) {
    gameLevelNum = level;
    gameLevelMax = level + numLevels;

    // make sure blocks are opaque
    Block_SetAlpha(255);
    gameLevel = std::make_unique<Level>(LEFT_WALL, TOP_WALL, gameLevelNum, BLOCK_MODE_NORMAL);

    state = STATE_GAME_FADEIN;
}


// ship flies in from bottom of the screen and transforms into a paddle
static void Game_ShipAnim() {
    // ship animation stuff (keeping it stateless helps simplify things)
    // move ship when it spawns
    if (shipSprite.y > SHIP_POS) {
        shipSprite.y -= (3 * Speed_Multiplier());
    }
    else {
        shipSprite.y = SHIP_POS;
    }
    // animate ship
// ship flies in from bottom of the screen and transforms into a paddle.
// returns 1 if the transformation animation is done
static int Game_ShipAnim() {
    shipFrames += Speed_Multiplier();
    if (shipFrames >= SHIP_TIMING) {
        shipFrames = 0;


@@ 255,6 251,7 @@ static void Game_ShipAnim() {
        // if we're still doing the ship transformation animation
        if (shipSprite.source.y < SHIP_SPRITESHEET_LAST) {
            shipSprite.source.y += SHIP_HEIGHT;
            return 0;
        }

        // otherwise, animate the barrels


@@ 264,8 261,11 @@ static void Game_ShipAnim() {
            if (barrelSprite.source.y >= (BARREL_FRAMES * BARREL_SIZE)) {
                barrelSprite.source.y = 0;
            }
            return 1;
        }
    }

    return 0;
}

static void Game_ShipCollapseAnim() {


@@ 290,10 290,13 @@ static void Game_BitAnim() {
    }
}

// flame that comes out of the ship at the end of a level
static void Game_FlameRun(int start, int end) {
    static float frameCount = 0;

    frameCount += Speed_Multiplier();
    // change frames every other frame, subtraction is so rounding will cancel
    // out any error if frame rate isn't a multiple of 60
    if (frameCount >= 2) {
        frameCount -= 2;
        flameFrame += FLAME_SIZE;


@@ 397,318 400,335 @@ int Game_Run() {
    float speed;

    switch (state) {
        case STATE_GAME_FADEIN:
            frames += Speed_Multiplier();
            if (frames > 60) {
                Hud_ChipSet(STATE_CHIP_HAND);
                frames = 0;
                state = STATE_GAME_PLAY;
            }
            break;
        
        case STATE_GAME_PLAY:
            //handle input
            speed = SHIP_SPEED;
            if ((padDataE & PAD_LASER)) {
                Laser_Add(shipSprite.x + SHIP_GUNX, shipSprite.y + SHIP_GUNY);
                // sound_play(SOUND_LASER);
            }
    case STATE_GAME_FADEIN:
        frames += Speed_Multiplier();
        if (frames > 60) {
            Hud_ChipSet(STATE_CHIP_HAND);
            frames = 0;
            state = STATE_SHIP_SPAWN;
        }
        break;

            if ((padData & PAD_UP) || (padData & PAD_TURBO)) {
                speed += turbo;
            }
    case STATE_SHIP_SPAWN:
        shipSprite.y -= (3 * Speed_Multiplier());
        if (shipSprite.y <= SHIP_POS) {
            shipSprite.y = SHIP_POS;
        }
        if (Game_ShipAnim()) {
            state = STATE_GAME_PLAY;
        }
        break;

            if (padDataE & PAD_DBG1) {
                Game_IncPowerUp();
            }
    
    case STATE_GAME_PLAY:
        //handle input
        speed = SHIP_SPEED;
        if ((padDataE & PAD_LASER)) {
            Laser_Add(shipSprite.x + SHIP_GUNX, shipSprite.y + SHIP_GUNY);
            // sound_play(SOUND_LASER);
        }

            // update shipSpeed so other files know what direction the ship is going
            shipSpeed = 0;
            if (padData & PAD_LEFT) { shipSpeed -= (speed * Speed_Multiplier()); }
            if (padData & PAD_RIGHT) { shipSpeed += (speed * Speed_Multiplier()); }
            shipSprite.x += shipSpeed;
        if ((padData & PAD_UP) || (padData & PAD_TURBO)) {
            speed += turbo;
        }

            // --- wall collision detection ---
            while (1) {
                // bit powerup gives ship extra width
                if (bitShip) {
                    bitLeft = shipSprite.x - BIT_WIDTH;
                    bitRight = shipSprite.x + SHIP_WIDTH;
                    shipLeft = bitLeft;
                    shipRight = bitRight + BIT_WIDTH;
                }
                else {
                    shipLeft = shipSprite.x;
                    shipRight = shipSprite.x + SHIP_WIDTH;
                }
        if (padDataE & PAD_DBG1) {
            Game_IncPowerUp();
        }

                //ship boundaries
                if (shipLeft < LEFT_WALL) {
                    shipSprite.x += 1;
                }
                else if (shipRight > RIGHT_WALL) {
                    shipSprite.x -= 1;
                }
                else {
                    break;
                }
        // update shipSpeed so other files know what direction the ship is going
        shipSpeed = 0;
        if (padData & PAD_LEFT) { shipSpeed -= (speed * Speed_Multiplier()); }
        if (padData & PAD_RIGHT) { shipSpeed += (speed * Speed_Multiplier()); }
        shipSprite.x += shipSpeed;

        // --- wall collision detection ---
        while (1) {
            // bit powerup gives ship extra width
            if (bitShip) {
                bitLeft = shipSprite.x - BIT_WIDTH;
                bitRight = shipSprite.x + SHIP_WIDTH;
                shipLeft = bitLeft;
                shipRight = bitRight + BIT_WIDTH;
            }

            // trail for illusion powerup
            illusionArr[illusionCursor].x = shipSprite.x;
            illusionArr[illusionCursor].y = shipSprite.y;
            illusionCursor++;
            if (illusionCursor >= ILLUSION_ARRLEN) {
                illusionCursor = 0;
            else {
                shipLeft = shipSprite.x;
                shipRight = shipSprite.x + SHIP_WIDTH;
            }
            // calculate array indexes for each trailing ship, as well as "true" shipLeft/shipRight
            if (illusion) {
                int topIndex = illusionCursor - ILLUSION_FRAMEDELAY; // top
                if (topIndex < 0) { topIndex += ILLUSION_ARRLEN; }
                int midIndex = topIndex - ILLUSION_FRAMEDELAY;       // middle
                if (midIndex < 0) { midIndex += ILLUSION_ARRLEN; }
                int botIndex = midIndex - ILLUSION_FRAMEDELAY;       // bottom
                if (botIndex < 0) { botIndex += ILLUSION_ARRLEN; }
                // left
                shipLeft = MIN(shipLeft, illusionArr[topIndex].x);
                shipLeft = MIN(shipLeft, illusionArr[midIndex].x);
                shipLeft = MIN(shipLeft, illusionArr[botIndex].x);
                // right
                shipRight = MAX(shipRight, illusionArr[topIndex].x + SHIP_WIDTH);
                shipRight = MAX(shipRight, illusionArr[midIndex].x + SHIP_WIDTH);
                shipRight = MAX(shipRight, illusionArr[botIndex].x + SHIP_WIDTH);

            //ship boundaries
            if (shipLeft < LEFT_WALL) {
                shipSprite.x += 1;
            }
            // animate the barrier
            Barrier_Move();
            // animate the ship
            Game_ShipAnim();
            
            // if all the blocks from the current level are gone, move to the new level.
            // if there's no more letters, show the coming soon text.
            if ((padDataE & PAD_DBG2) || (gameLevel->doneLoad() && !gameLevel->blocksLeft())) {
                // remove all balls
                Ball_RemoveAll();
                // remove all capsules
                Capsule_RemoveAll();
                // remove all lasers
                Laser_RemoveAll();
                // remove all enemies
                Enemy_RemoveAll();

                gameLevelNum++;
                // show the "ship flying off the screen" animation
                if (gameLevelNum >= gameLevelMax) {
                    frames = 0;
                    state = STATE_GAME_FADELEVEL;
                    break;
                }

                // load new level
                gameLevel = std::make_unique<Level>(LEFT_WALL, TOP_WALL, gameLevelNum, BLOCK_MODE_NORMAL);
                // add a new ball for the ship
                Ball_Add(shipSprite.x, shipSprite.y, 45);

            else if (shipRight > RIGHT_WALL) {
                shipSprite.x -= 1;
            }

            // handle pause (last so nothing else can set an animation, etc)
            if (padDataE & PAD_PAUSE) {
                state = STATE_GAME_PAUSE;
                Sound_StopMusic();
                Sound_PlayVGM("01 Login Check.vgz");
                Hud_ChipSet(STATE_CHIP_SLEEP);
            else {
                break;
            }
            break;
        }

        // chip is tired and she needs a nap
        case STATE_GAME_PAUSE:
            if (padDataE & PAD_PAUSE) {
                state = STATE_GAME_PLAY;
                Sound_StopMusic();
                Sound_PlayVGM("12 Stage 1.vgz");
                Hud_ChipSet(STATE_CHIP_NONE);
            }
            break;
        // trail for illusion powerup
        illusionArr[illusionCursor].x = shipSprite.x;
        illusionArr[illusionCursor].y = shipSprite.y;
        illusionCursor++;
        if (illusionCursor >= ILLUSION_ARRLEN) {
            illusionCursor = 0;
        }
        // calculate array indexes for each trailing ship, as well as "true" shipLeft/shipRight
        if (illusion) {
            int topIndex = illusionCursor - ILLUSION_FRAMEDELAY; // top
            if (topIndex < 0) { topIndex += ILLUSION_ARRLEN; }
            int midIndex = topIndex - ILLUSION_FRAMEDELAY;       // middle
            if (midIndex < 0) { midIndex += ILLUSION_ARRLEN; }
            int botIndex = midIndex - ILLUSION_FRAMEDELAY;       // bottom
            if (botIndex < 0) { botIndex += ILLUSION_ARRLEN; }
            // left
            shipLeft = MIN(shipLeft, illusionArr[topIndex].x);
            shipLeft = MIN(shipLeft, illusionArr[midIndex].x);
            shipLeft = MIN(shipLeft, illusionArr[botIndex].x);
            // right
            shipRight = MAX(shipRight, illusionArr[topIndex].x + SHIP_WIDTH);
            shipRight = MAX(shipRight, illusionArr[midIndex].x + SHIP_WIDTH);
            shipRight = MAX(shipRight, illusionArr[botIndex].x + SHIP_WIDTH);

        }
        // animate the barrier
        Barrier_Move();
        // animate the ship
        Game_ShipAnim();
        
        // when player has lost, show burnt chip for a second
        // in order to make the player think about what he's done
        case STATE_GAME_LOSS:
            frames += Speed_Multiplier();
            if (frames >= 60) {
                lives--;
                if (lives < 0) {
                    frames = 0;
                    //todo play "game over" music
                    // sound_vgm_play();
                    state = STATE_GAME_OVER;
                    break;
                }
                Hud_ChipSet(STATE_CHIP_NONE);
                shipSprite.source.y = SHIP_SPRITESHEET_FIRST;
                shipSprite.y = SHIP_STARTY;
                shipState = SHIP_STATE_INIT;
                Ball_Add(shipSprite.x, shipSprite.y, 135);
                state = STATE_GAME_PLAY;
            }
            break;
        // if all the blocks from the current level are gone, move to the new level.
        // if there's no more letters, show the coming soon text.
        if ((padDataE & PAD_DBG2) || (gameLevel->doneLoad() && !gameLevel->blocksLeft())) {
            // remove all balls
            Ball_RemoveAll();
            // remove all capsules
            Capsule_RemoveAll();
            // remove all lasers
            Laser_RemoveAll();
            // remove all enemies
            Enemy_RemoveAll();

            frames = 0;
            state = STATE_GAME_FADELEVEL;
        }

        // beginning of "ship flying out"
        case STATE_GAME_FADELEVEL:
            if (frames < 60) {
                frames += Speed_Multiplier();
                gameLevel->setAlpha((uint8_t)((255.0 / 60.0) * (60.0 - frames)));
            }
            else {
        // handle pause (last so nothing else can set an animation, etc)
        if (padDataE & PAD_PAUSE) {
            state = STATE_GAME_PAUSE;
            Sound_StopMusic();
            Sound_PlayVGM("01 Login Check.vgz");
            Hud_ChipSet(STATE_CHIP_SLEEP);
        }
        break;

    // chip is tired and she needs a nap
    case STATE_GAME_PAUSE:
        if (padDataE & PAD_PAUSE) {
            state = STATE_GAME_PLAY;
            Sound_StopMusic();
            Sound_PlayVGM("12 Stage 1.vgz");
            Hud_ChipSet(STATE_CHIP_NONE);
        }
        break;

    // fade out the remaining blocks in preparation for showing the next level
    case STATE_GAME_FADELEVEL:
        if (frames < 60) {
            frames += Speed_Multiplier();
            Block_SetAlpha((uint8_t)((255.0 / 60.0) * (60.0 - frames)));
        }
        else {
            gameLevelNum++;
            // show the "ship flying off the screen" animation
            if (gameLevelNum >= gameLevelMax) {
                frames = 0;
                state = STATE_GAME_CENTERSHIP;
                break;
            }
            break;

        case STATE_GAME_CENTERSHIP:
            if (shipSprite.x < SHIP_STARTX) {
                shipSprite.x += 3;
                if (shipSprite.x > SHIP_STARTX) {
                    shipSprite.x = SHIP_STARTX;
                }
            // load new level
            Block_SetAlpha(255);
            gameLevel = std::make_unique<Level>(LEFT_WALL, TOP_WALL, gameLevelNum, BLOCK_MODE_NORMAL);
            // add a new ball for the ship
            Ball_Add(shipSprite.x, shipSprite.y, 45);
            state = STATE_GAME_PLAY;
        }
        break;
    
    // when player has lost, show burnt chip for a second
    // in order to make the player think about what he's done
    case STATE_GAME_LOSS:
        frames += Speed_Multiplier();
        if (frames >= 60) {
            lives--;
            if (lives < 0) {
                frames = 0;
                //todo play "game over" music
                // sound_vgm_play();
                state = STATE_GAME_OVER;
                break;
            }
            Hud_ChipSet(STATE_CHIP_NONE);
            shipSprite.source.y = SHIP_SPRITESHEET_FIRST;
            shipSprite.y = SHIP_STARTY;
            shipState = SHIP_STATE_INIT;
            Ball_Add(shipSprite.x, shipSprite.y, 135);
            state = STATE_SHIP_SPAWN;
        }
        break;

    // move the ship to the center of the playfield in preparation for the
    // flying out animation
    case STATE_GAME_CENTERSHIP:
        if (shipSprite.x < SHIP_STARTX) {
            shipSprite.x += 3;
            if (shipSprite.x > SHIP_STARTX) {
                shipSprite.x -= 3;
                if (shipSprite.x < SHIP_STARTX) {
                    shipSprite.x = SHIP_STARTX;
                }
                shipSprite.x = SHIP_STARTX;
            }

            if (shipSprite.x == SHIP_STARTX) {
                state = STATE_GAME_FLYUP;
        }
        if (shipSprite.x > SHIP_STARTX) {
            shipSprite.x -= 3;
            if (shipSprite.x < SHIP_STARTX) {
                shipSprite.x = SHIP_STARTX;
            }
        }

            break;
        if (shipSprite.x == SHIP_STARTX) {
            state = STATE_GAME_FLYUP;
        }

        case STATE_GAME_FLYUP:
            if (shipSprite.y > SHIP_FLY1) {
                shipSprite.y--;
                // get the ship ready for animation
                if (shipSprite.y > SHIP_FLY2) {
                    shipSprite.source.y = SHIP_COLLAPSE_FIRST;
                }
            }
            else if (shipSprite.y > SHIP_FLY2) {
                shipSprite.y -= 0.5;
                Game_ShipCollapseAnim();
            }
            else {
                state = STATE_GAME_FLYDOWN;
            }
            break;
        break;

        case STATE_GAME_FLYDOWN:
            if (shipSprite.y < SHIP_FLY3) {
                shipSprite.y += 0.5;
            }
            else if (shipSprite.y < SHIP_FLY4) {
                shipSprite.y += 0.25;
                Game_FlameRun(FLAME_SMALL_START, FLAME_SMALL_END);
            }
            else {
                shipSpeed = 0;
                Game_FlameRun(FLAME_SMALL_START, FLAME_SMALL_END);
                state = STATE_GAME_FLYOUT;
    // ship moves up while transforming from a paddle to a ship
    case STATE_GAME_FLYUP:
        if (shipSprite.y > SHIP_FLY1) {
            shipSprite.y--;
            // get the ship ready for animation
            if (shipSprite.y > SHIP_FLY2) {
                shipSprite.source.y = SHIP_COLLAPSE_FIRST;
            }
        }
        else if (shipSprite.y > SHIP_FLY2) {
            shipSprite.y -= 0.5;
            Game_ShipCollapseAnim();
            break;
        }
        else {
            state = STATE_GAME_FLYDOWN;
        }
        break;

        case STATE_GAME_FLYOUT:
            shipSpeed += 0.2;
            shipSprite.y -= shipSpeed;
    // ship flies down with a small flame coming out the back
    case STATE_GAME_FLYDOWN:
        if (shipSprite.y < SHIP_FLY3) {
            shipSprite.y += 0.5;
        }
        else if (shipSprite.y < SHIP_FLY4) {
            shipSprite.y += 0.25;
            Game_FlameRun(FLAME_SMALL_START, FLAME_SMALL_END);
        }
        else {
            shipSpeed = 0;
            Game_FlameRun(FLAME_SMALL_START, FLAME_SMALL_END);
            state = STATE_GAME_FLYOUT;
        }
        Game_ShipCollapseAnim();
        break;

            if (shipSprite.y < -128) {
                return 1;
            }
            Game_FlameRun(FLAME_LARGE_START, FLAME_LARGE_END);
            break;
    // ship flies offscreen with a large flame coming out the back
    case STATE_GAME_FLYOUT:
        shipSpeed += 0.2;
        shipSprite.y -= shipSpeed;

        case STATE_GAME_OVER:
            frames += Speed_Multiplier();
            if (frames >= 360) {
                Sound_StopMusic();
                return 2;
            }
            break;
        if (shipSprite.y < -128) {
            return 1;
        }
        Game_FlameRun(FLAME_LARGE_START, FLAME_LARGE_END);
        break;

    case STATE_GAME_OVER:
        frames += Speed_Multiplier();
        if (frames >= 360) {
            Sound_StopMusic();
            return 2;
        }
        break;

    }

    //update powerups
    if (padDataE & PAD_POWERUP) {
        switch (powerupCursor) {
            case P_TURBO:
                if (turbo < MAX_TURBO) {
                    turbo++;
                    powerupCursor = P_NONE;
                    // sound_play(SOUND_POWERUP);
                }
                break;
            
            case P_BIT:
                if (bitShip == 0) {
                    // can't have bit and illusion on simultaneously
                    if (illusion) {
                        illusion = 0;
                        // sound_play(SOUND_REPLACE);
                    }
                    else {
                        // sound_play(SOUND_POWERUP);
                    }
        case P_TURBO:
            if (turbo < MAX_TURBO) {
                turbo++;
                powerupCursor = P_NONE;
                // sound_play(SOUND_POWERUP);
            }
            break;
        
        case P_BIT:
            if (bitShip == 0) {
                // can't have bit and illusion on simultaneously
                if (illusion) {
                    illusion = 0;
                    bitShip = 1;
                    powerupCursor = P_NONE;
                    // sound_play(SOUND_REPLACE);
                }
                break;

            case P_DISRUPTION:
                if (Ball_Disruption()) {
                    powerupCursor = P_NONE;
                else {
                    // sound_play(SOUND_POWERUP);
                }
                break;
                illusion = 0;
                bitShip = 1;
                powerupCursor = P_NONE;
            }
            break;

            case P_LASER:
                if (laserMax < MAX_LASER_MAX) {
                    laserMax += (MAX_LASER_MAX >> 1);
                    powerupCursor = P_NONE;
                    // sound_play(SOUND_POWERUP);
                }
                break;
        case P_DISRUPTION:
            if (Ball_Disruption()) {
                powerupCursor = P_NONE;
                // sound_play(SOUND_POWERUP);
            }
            break;

            case P_ILLUSION:
                if (illusion == 0) {
                    // can't have bit and illusion on simultaneously
                    if (bitShip) {
                        bitShip = 0;
                        // sound_play(SOUND_REPLACE);
                    }
                    else {
                        // sound_play(SOUND_POWERUP);
                    }
                    illusion = 1;
                    powerupCursor = P_NONE;
                }
                break;
        case P_LASER:
            if (laserMax < MAX_LASER_MAX) {
                laserMax += (MAX_LASER_MAX >> 1);
                powerupCursor = P_NONE;
                // sound_play(SOUND_POWERUP);
            }
            break;

            case P_GIGABALL:
                if (ballMode < POWER_GIGABALL2) {
                    ballMode++;
                    powerupCursor = P_NONE;
                    // sound_play(SOUND_POWERUP);
        case P_ILLUSION:
            if (illusion == 0) {
                // can't have bit and illusion on simultaneously
                if (bitShip) {
                    bitShip = 0;
                    // sound_play(SOUND_REPLACE);
                }
                break;

            case P_BARRIER:
                if (barrierLife == 0) {
                    barrierLife = BARRIER_MAXLIFE;
                    powerupCursor = P_NONE;
                else {
                    // sound_play(SOUND_POWERUP);
                }
                break;
                illusion = 1;
                powerupCursor = P_NONE;
            }
            break;

        case P_GIGABALL:
            if (ballMode < POWER_GIGABALL2) {
                ballMode++;
                powerupCursor = P_NONE;
                // sound_play(SOUND_POWERUP);
            }
            break;

        case P_BARRIER:
            if (barrierLife == 0) {
                barrierLife = BARRIER_MAXLIFE;
                powerupCursor = P_NONE;
                // sound_play(SOUND_POWERUP);
            }
            break;
        }
    }
    


@@ 716,10 736,15 @@ int Game_Run() {
    Barrier_Draw(); // barrier goes here so the edges get masked away
    Hud_DispBG();

    // TODO put drawing code in each state instead of this mess
    if (state < STATE_GAME_OVER) {
        gameLevel->disp(); // draw blocks
        Enemy_Run();
        Capsule_Draw();
        if (state < STATE_GAME_CENTERSHIP) {
            gameLevel->disp(); // draw blocks
        }
        if (state == STATE_GAME_PLAY) {
            Enemy_Run();
            Capsule_Draw();
        }
        Game_DrawShip();
        Ball_Draw(); // draw balls
        Laser_Draw();


@@ 727,9 752,8 @@ int Game_Run() {
        Capsule_FlushRemoveQueue();
        Enemy_FlushRemoveQueue();

        // this function will trigger a state change to STATE_GAME_LOSS
        // if there's no balls, so we only want it to run when the game
        // is playing
        // this will cause a state change to STATE_GAME_LOSS if there's no balls
        // so we only want it in STATE_GAME_PLAY
        if (state == STATE_GAME_PLAY) {
            Ball_FlushRemoveQueue();
        }

M level.cpp => level.cpp +0 -11
@@ 98,7 98,6 @@ Level::Level(int xPos, int yPos, int num, int mode) {
    Block_Stretch_RemoveAll();

    levelNum = num;
    alpha = 255; // level should start opaque

    this->mode = mode;
    if (mode == BLOCK_MODE_TUTORIAL) {


@@ 196,7 195,6 @@ void Level::animate() {
    else {
        for (Block &block : animRow) {
            block.y = rowY;
            block.setAlpha(alpha);
            block.draw();
        }
    }


@@ 224,17 222,9 @@ void Level::animate() {
    }
}

void Level::setAlpha(uint8_t alpha) {
    this->alpha = alpha;
}

void Level::disp() {
    SpriteInfo spr;

    if (alpha == 0) {
        return;
    }
    
    // scroll each row down, then move to the next row until we've put all rows onscreen
    if (rowNum >= 0) {
        animate();


@@ 257,7 247,6 @@ void Level::disp() {

    //draw all the blocks in the block arr
    for (Block &block : blocks) {
        block.setAlpha(alpha);
        block.draw();
        block.shine.move(block.x, block.y);
        block.shine.draw();

M level.h => level.h +1 -6
@@ 49,7 49,6 @@ private:
	// where the level is on the screen
	int xPos;
	int yPos;
	uint8_t alpha;
	// how fast the blocks move during animations
	float blockSpeed;
	// mover blocks


@@ 77,11 76,7 @@ public:
	// removes a block from the level
	// explode: 1 if we want to add an explosion, capsule, score, etc
	void removeBlock(Block *block, int explode);

	// sets the alpha transparency for the level (used for end-of-level fadeouts).
	// alpha should be between 0 and 255
	void setAlpha(uint8_t alpha);

	
	// shows level
	void disp();


M stage.cpp => stage.cpp +2 -1
@@ 191,7 191,8 @@ static int state;

void Stage_Init() {
    currentStage = 0;
    state = STATE_CUTSCENE_INIT;
    //state = STATE_CUTSCENE_INIT;
    state = STATE_GAME_INIT;
}

void Stage_Run() {