<commit_before><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="js/library/phaser.js"></script>
    <script src="js/library/HealthBar.standalone.js"></script>
    <title>Title</title>
</head>
<body>
    <div id="container"></div>

    <script type="text/javascript">
        var game = new Phaser.Game(512, 600, Phaser.AUTO, 'container', {
            preload: preload,
            create: create,
            update: update
            //render: render
        });

        function preload() {
            game.load.image('stage01BG', './assets/Background/stage01blue.png');
            game.load.image('stage01Boss', './assets/Background/stage01BossBG.png');
            game.load.image('sanaeHurtbox', './assets/Player/playerHurtbox.png');
            game.load.image('sanae', './assets/Player/playerStand.png');
            game.load.image('yuyuko', './assets/Boss/yuyuko.png');
            game.load.image('butterflyRed', './assets/Boss/bossBullets/butterflyRED.png');
            game.load.image('butterflyYellow', './assets/Boss/bossBullets/butterflyYELLOW.png');
            game.load.image('butterflyGreen', './assets/Boss/bossBullets/butterflyGREEN.png');
            game.load.image('butterflyCyan', './assets/Boss/bossBullets/butterflyCYAN.png');
            game.load.image('butterflyBlue', './assets/Boss/bossBullets/butterflyBLUE.png');
            game.load.image('butterflyPurple', './assets/Boss/bossBullets/butterflyPURPLE.png');
            game.load.image('butterflyBlack', './assets/Boss/bossBullets/butterflyBLACK.png');
            game.load.image('yuyukoBullet', './assets/Boss/bossBullets/yuyukoBullet.png');
            game.load.image('yuyukoOrb', './assets/Boss/bossBullets/yuyukoOrb.png');
            game.load.image('aimGruntShot', './assets/Enemy/enemyBullets/aimGruntShot.png');
            game.load.image('straightGruntShot', './assets/Enemy/enemyBullets/straightGruntShot.png');
            game.load.image('rotateGruntShot', './assets/Enemy/enemyBullets/rotateGruntShot.png');
            game.load.image('gruntRotate', './assets/Enemy/gruntRotate.png');
            game.load.image('gruntStraightRed', './assets/Enemy/gruntStraightRed.png');
            game.load.image('gruntStraightBlue', './assets/Enemy/gruntStraightBlue.png');
            game.load.image('gruntAimRed', './assets/Enemy/gruntAimRed.png');
            game.load.image('gruntAimBlue', './assets/Enemy/gruntAimBlue.png');
            game.load.image('singlePrimary', './assets/Player/playerShotA.png');
            game.load.image('doublePrimary', './assets/Player/playerShotB.png');
            game.load.image('spreadPrimary', './assets/Player/secondaryShotALT.png');
            game.load.image('smallP', './assets/Player/PowerSmall.png');
            game.load.image('largeP', './assets/Player/PowerLarge.png');
            game.load.spritesheet('gruntDeathExplode', './assets/Enemy/gruntDeathExplosion2.png', 64, 65);
            game.load.audio('enemyDeath', './assets/Audio/SFX/enemyDeath.wav');
            game.load.audio('playerDeath', './assets/Audio/SFX/playerExplosion.wav');
            game.load.audio('bossDeath', './assets/Audio/SFX/bossExplosion.wav');
            game.load.audio('bomb', './assets/Audio/SFX/SpecialSS.wav');
            game.load.audio('stage01BGM', './assets/Audio/BGM/EndOfSpring.mp3');
            game.load.audio('stage01BossBGM', './assets/Audio/BGM/BloomNobly.mp3');
        }

        var playerStats = {
            score: 0,
            graze: 0,
            bomb: 2,
            power: 0,
            weaponName: '<NAME>',
            bombTimer: 0,
            bombActive: false
        };
        const bossMaxHP = 60;
        var lifeText;
        var powerText;
        var weaponText;
        var gameOverText;
        var pocLineText;
        var pocLine;
        var fadeInPOCtext;
        var fadeInPOCline;
        var gameTimer = 0;
        const playerPhysicsStats = {
            normalVelocity: 275,
            focusVelocity: 150
        };
        const enemyStats = {
            aimGruntHP: 10,
            straightGruntHP: 16,
            rotateGruntHP: 24,
            gruntXvelocity: 50,
            gruntYvelocity: 50,
            gruntStraightVelocity: 100,
            movingGruntStraightXVelocity: 75,
            movingGruntRotateXVelocity: 150,
            movingGruntRotateYVelocity: 200,
            reverseGruntRotateXVelocity: 300,
            reverseGruntRotateYVelocity: 500
        };
        const enemyWeapon = {
            gruntBulletSpeed: 250,
            gruntBulletFireRate: 500,
            gruntBulletAngleOffset: 90,
            aimGruntBulletAngleOffset: 0,
            gruntStraightBulletSpeed: 150, //100
            gruntStraightBulletFireRate: 850, //16 is the lowest and quickest possible
            movingGruntStraightBulletSpeed: 150,
            movingGruntStraightBulletFireRate: 600,
            gruntRotateBulletSpeed: 150,
            gruntRotateBulletFireRate: 50,
            gruntExplosiveRotateBulletSpeed: 100,
            gruntExplosiveRotateFireRate: 16
        };
        const weaponStats = {
            singleShotBulletSpeed: 850,
            singleShotBulletFireRate: 90,
            singleShotBulletAngleOffSet: 90,
            singleShotDamage: 4,
            doubleShotDamage: 6,
            waveShotDamage: 1
        };
        var rotateGruntTimers = [];
        var counterClockwiseShootID = [];

        var bg;
        var bgm;
        var bossBGM;
        var enemyDeathSFX;
        var playerDeathSFX;
        var playerBombSFX;
        var smallP;
        var largeP;
        var singleShot;
        var doubleShot;
        var waveShotLT;
        var waveShotRT;
        var playerBombs;
        var playerHurtbox;
        var playerSprite;
        var cursors;
        var fireButton;
        var bombButton;
        var bombSignal;
        var focusButton;
        var aimGrunts;
        var straightGrunts;
        var rotateGrunts;
        var gruntDeaths;

        // Boss Variables
        var yuyukoBoss;
        var bossDeathSFX;
        var bossSpawned = false;
        var yuyukoFloatUp = false;
        var bossHPbar;
        var bossText;
        var bossTransition;
        /*var bossTrnznTwo;
        var bossTrnznThree;*/
        var trnznData = {
            trnznRandX: 0,
            trnznRandY: 0,
            trnznTimer: 0
        };

        // Enemy Weapons
        var aimGruntWeapons = [];
        var aimGruntWeaponDIS = []; // Stands for Death Index Signals
        var rotateGruntWeapons = [];
        var rotateGruntWeaponDIS = [];
        var straightGruntWeapons = [];
        var straightGruntWeaponDIS = [];

        // weapon.Bullets is a group
        function create() {
            // Scrolling Background
            /*bg = game.add.tileSprite(0, 0, 512, 600, 'stage01BG');

            // Music and SFX
            //bgm = game.add.audio('stage01BGM');
            //bgm.play();
            //bossBGM = game.add.audio('stage01BossBGM');*/

            enemyDeathSFX = game.add.audio('enemyDeath');
            enemyDeathSFX.volume = 0.7;
            playerDeathSFX = game.add.audio('playerDeath');
            playerDeathSFX.volume = 0.7;
            playerBombSFX = game.add.audio('bomb');
            playerBombSFX.volume = 0.7
            bossDeathSFX = game.add.audio('bossDeath');
            bossDeathSFX.volume = 1.1;


            // Items
            smallP = game.add.emitter(0, 0, 200);
            smallP.enableBody = true;
            smallP.physicsBodyType = Phaser.Physics.ARCADE;
            smallP.forEach(function(powPellet) {
                powPellet.outOfBoundsKill = true;
                powPellet.checkWorldBounds = true;
            });
            smallP.makeParticles('smallP');
            smallP.gravity = 200;
            smallP.setXSpeed(-10, 10);
            //smallP.setYSpeed(100);

            largeP = game.add.emitter(0, 0, 200);
            largeP.enableBody = true;
            largeP.physicsBodyType = Phaser.Physics.ARCADE;
            largeP.forEach(function(powPellet) {
                powPellet.outOfBoundsKill = true;
                powPellet.checkWorldBounds = true;
            });
            largeP.makeParticles('largeP');
            smallP.gravity = 175;
            smallP.setXSpeed(-5, 5);
            //smallP.setYSpeed(100);

            // ___WEAPONS___

            // Single Shot
            singleShot = game.add.weapon(30, 'singlePrimary');
            singleShot.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            singleShot.bulletAngleOffset = weaponStats.singleShotBulletAngleOffSet;
            singleShot.bulletSpeed = weaponStats.singleShotBulletSpeed;
            singleShot.fireRate = weaponStats.singleShotBulletFireRate;
            singleShot.bullets.forEach(function(bullet) {
                bullet.damageAmount = weaponStats.singleShotDamage;
            });

            // Double Shot
            doubleShot = game.add.weapon(30, 'doublePrimary');
            doubleShot.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            doubleShot.bulletAngleOffset = 90;
            doubleShot.bulletSpeed = 850;
            doubleShot.fireRate = 90;
            doubleShot.bullets.forEach(function(bullet) {
               bullet.damageAmount = 5;
            });

            // Wave Shot
            waveShotLT = game.add.weapon(30, 'spreadPrimary');
            waveShotLT.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            waveShotLT.bulletSpeed = 850;
            waveShotLT.fireRate = 180;
            waveShotLT.bullets.forEach(function(bullet) {
                bullet.damageAmount = weaponStats.waveShotDamage;
            });
            waveShotRT = game.add.weapon(30, 'spreadPrimary');
            waveShotRT.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            waveShotRT.bulletSpeed = 850;
            waveShotRT.fireRate = 180;
            waveShotRT.bullets.forEach(function(bullet) {
                bullet.damageAmount = weaponStats.waveShotDamage;
            });

            // Bomb
            playerBombs = game.add.group();
            playerBombs.enableBody = true;
            playerBombs.physicsBodyType = Phaser.Physics.ARCADE;

            // Enemies
            aimGrunts = game.add.group();
            aimGrunts.enableBody = true;
            aimGrunts.physicsBodyType = Phaser.Physics.ARCADE;

            straightGrunts = game.add.group();
            straightGrunts.enableBody = true;
            straightGrunts.physicsBodyType = Phaser.Physics.ARCADE;

            rotateGrunts = game.add.group();
            rotateGrunts.enableBody = true;
            rotateGrunts.physicsBodyType = Phaser.Physics.ARCADE;

            // Player
            playerHurtbox = this.add.sprite((game.world.width/2), game.world.height - 150, 'sanaeHurtbox');
            playerHurtbox.health = 3;
            playerHurtbox.anchor.setTo(0.5);
            playerSprite = this.add.sprite((game.world.width/2), game.world.height - 150, 'sanae');
            playerSprite.health = 3;
            playerSprite.anchor.setTo(0.5);


            game.physics.arcade.enable(playerHurtbox);
            game.physics.arcade.enable(playerSprite);
            playerHurtbox.body.collideWorldBounds = true;
            playerHurtbox.body.setCircle(6, 1);
            playerSprite.body.collideWorldBounds = true;
            console.log('hitbox x: ' + playerHurtbox.body.x + ', y: ' + playerHurtbox.body.y + ', ' + 'offset' + playerHurtbox.offsetX + ', ' + playerHurtbox.offsetY);
            console.log('sprite x: ' + playerSprite.body.x + ', y: ' + playerSprite.body.y + ', ' + 'offset' + playerSprite.offsetX + ', ' + playerSprite.offsetY);

            // Weapon Tracking
            // -- Weapon on player
            singleShot.trackSprite(playerSprite, 0, -(playerSprite.height/2 + 27));
            doubleShot.trackSprite(playerSprite, 0, -(playerSprite.height/2 + 27));
            waveShotLT.trackSprite(playerSprite, -50, -(playerSprite.height/2 + 27));
            waveShotRT.trackSprite(playerSprite, 50, -(playerSprite.height/2 + 27));

            // Setting Controls
            cursors = this.input.keyboard.createCursorKeys();
            fireButton = this.input.keyboard.addKey(Phaser.KeyCode.Z);
            bombButton = this.input.keyboard.addKey(Phaser.KeyCode.X);
            focusButton = this.input.keyboard.addKey(Phaser.KeyCode.SHIFT);

            // Boss Groups
            bossTransition = game.add.group();
            bossTransition.enableBody = true;
            bossTransition.physicsBodyType = Phaser.Physics.ARCADE;
            /*bossTrnznTwo = game.add.group();
            bossTrnznTwo.enableBody = true;
            bossTrnznTwo.physicsBodyType = Phaser.Physics.ARCADE;
            bossTrnznThree = game.add.group();
            bossTrnznThree.enableBody = true;
            bossTrnznThree.physicsBodyType = Phaser.Physics.ARCADE;*/

            // Game Text
                // Lives
            lifeText = game.add.text(10, game.world.height - 30, 'Lives: ' + playerSprite.health, { font: '20px Arial', fill: '#00FF00' });
            lifeText.render = function() {
                lifeText.text = 'Lives: ' + Math.max(playerSprite.health, 0);
            };
            powerText = game.add.text(10, game.world.height - 60, 'Power: ' + playerStats.power, { font: '20px Arial', fill: '#00FF00' });
            powerText.render = function() {
                powerText.text = 'Power: ' + Math.max(playerStats.power, 0);
            };

                // Game Over
            gameOverText = game.add.text(game.world.centerX, game.world.centerY, 'GAME OVER\nTo restart, refresh the browser', { font: '30px Arial', fill: '#fff'});
            gameOverText.anchor.setTo(0.5);
            gameOverText.visible = false;

                // Weapon
            weaponText = game.add.text(300, game.world.height - 40, playerStats.weaponName, { font: '30px Arial', fill: '#00FFFF' });
            weaponText.render = function() {
                weaponText.text = playerStats.weaponName;
            };

                // POC Line Text
            pocLineText = game.add.text(game.world.centerX, game.world.centerY/2 - 10, 'Point of Collection', {font: '25px Arial', fill: '#00FF00'});
            pocLineText.anchor.setTo(0.5);
            pocLineText.visible = false;
                // POC Line
            pocLine = game.add.text(0, game.world.centerY/2, '____________________________________________________________________________________________', { font: '20px Arial', fill: '#FF0000'});
            pocLine.anchor.setTo(0.5);
            pocLine.visible = false;

                // Point of Collection Line
            // implement here

            // Enemy Death
            gruntDeaths = game.add.group();
            gruntDeaths.enableBody = true;
            gruntDeaths.physicsBodyType = Phaser.Physics.ARCADE;
            gruntDeaths.createMultiple(30, 'gruntDeathExplode');
            gruntDeaths.setAll('anchor.x', 0.5);
            gruntDeaths.setAll('anchor.y', 0.5);
            gruntDeaths.forEach(function(explode) {
               explode.animations.add('gruntDeathExplode');
            });

            //spawnYuyuko();
        }

        function update() {
            playerSprite.sendToBack();
            playerHurtbox.sendToBack();
            //bg.sendToBack();
            smallP.callAll('bringToTop');
            largeP.callAll('bringToTop');
            aimGrunts.callAll('bringToTop');
            straightGrunts.callAll('bringToTop');
            rotateGrunts.callAll('bringToTop');
            playerHurtbox.body.velocity.x = 0;
            playerHurtbox.body.velocity.y = 0;
            playerSprite.body.velocity.x = 0;
            playerSprite.body.velocity.y = 0;

            // Collision Checking
                // aimGrunts
            if (!playerStats.bombActive) {
                game.physics.arcade.overlap(playerHurtbox, aimGrunts, playerCollide, null, this);
            }
            game.physics.arcade.overlap(singleShot.bullets, aimGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(doubleShot.bullets, aimGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotLT.bullets, aimGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotRT.bullets, aimGrunts, bulletCollide, null, this);

                // straightGrunts
            if (!playerStats.bombActive) {
                game.physics.arcade.overlap(playerHurtbox, straightGrunts, playerCollide, null, this);
            }
            game.physics.arcade.overlap(singleShot.bullets, straightGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(doubleShot.bullets, straightGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotLT.bullets, straightGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotRT.bullets, straightGrunts, bulletCollide, null, this);

                // rotateGrunts
            if (!playerStats.bombActive) {
                game.physics.arcade.overlap(playerHurtbox, rotateGrunts, playerCollide, null, this);
            }
            game.physics.arcade.overlap(singleShot.bullets, rotateGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(doubleShot.bullets, rotateGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotLT.bullets, rotateGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotRT.bullets, rotateGrunts, bulletCollide, null, this);

            // Check Enemy Bullet Collisions/Overlap
            if (!playerStats.bombActive) {
                checkGruntBulletOverlap(aimGruntWeapons);
                checkGruntBulletOverlap(straightGruntWeapons);
                checkGruntBulletOverlap(rotateGruntWeapons);
            }

            // Check Power Item Collisions
            game.physics.arcade.overlap(playerSprite, smallP, playerPowerUp, null, this);
            game.physics.arcade.overlap(playerSprite, largeP, playerPowerUp, null, this);

            checkControls();

            // Enemy Shooting
            gruntFireSprite(aimGrunts, aimGruntWeapons, aimGruntWeaponDIS);
            gruntStraightFire(straightGrunts, straightGruntWeapons, straightGruntWeaponDIS);
            gruntRotateFire(rotateGrunts, rotateGruntWeapons, rotateGruntWeaponDIS);

            // Scroll the bg
            //bg.tilePosition.y += 2;

            // Check game over
            if (!playerHurtbox.alive && gameOverText.visible === false) {
                gameOverText.visible = true;
                var fadeInGameOver = game.add.tween(gameOverText);
                fadeInGameOver.to({alpha: 0.2}, 1000, Phaser.Easing.Quintic.Out, false, 0, -1, true);
                fadeInGameOver.start();
            }

            // Display POC Line at the beginning and check for breaches
            /*displayPOCLine();
            checkPOClineBreach();*/

            /*startStageOne();
            if (bgm.volume <= 0) {
                bgm.stop();
                console.log('bgm stopped');
            }*/
            if (bossSpawned) {
                // boss movement
                yuyukoFloat();

                // boss collision
                game.physics.arcade.overlap(playerHurtbox, yuyukoBoss, playerCollide, null, this);
                game.physics.arcade.overlap(singleShot.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(doubleShot.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(waveShotLT.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(waveShotRT.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(playerHurtbox, bossTransition, playerCollide, null, this);
                /*game.physics.arcade.overlap(playerHurtbox, bossTrnznTwo, playerCollide, null, this);
                game.physics.arcade.overlap(playerHurtbox, bossTrnznThree, playerCollide, null, this);*/
                // check bomb collision with each butterfly transition
                // check bomb collision with yuyukoBoss

                // boss shoot (check hp, and change spell card accordingly)
                checkYuyukoHealthAndShoot();
                bossTransition.callAll('bringToTop');
                yuyukoBoss.moveDown();
            }
            gameTimer++;
            if (playerStats.bombActive) {
                playerStats.bombTimer++;
                // turn bombActive flag to false again at a certain time when bomb sound clip is over
            }

        }

        // DEBUGGING
        function render() {
            game.debug.body(playerHurtbox);
            game.debug.body(yuyukoBoss);
            aimGrunts.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.4)');
            straightGrunts.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.4)');
            rotateGrunts.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.4)');
            singleShot.bullets.forEachAlive(renderGroup, this, 'rgba(0, 0, 255, 0.4)');
            doubleShot.bullets.forEachAlive(renderGroup, this, 'rgba(0, 0, 255, 0.4)');
            bossTransition.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.8)');
        }

        function renderGroup(child, strColor) {
            game.debug.body(child, strColor);
        }
        // End DEBUGGING

        // Control Actions
        function checkControls() {
            if (focusButton.isDown) {
                playerHurtbox.bringToTop();
            }

            if (cursors.up.isDown && !focusButton.isDown) {
                if (playerSprite.body.y <= 0) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 16;
                }
                else {
                    playerHurtbox.body.velocity.y = -(playerPhysicsStats.normalVelocity);
                    playerSprite.body.velocity.y = -(playerPhysicsStats.normalVelocity);
                }
            }
            else if (cursors.up.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.y <= 0) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 16;

                }
                else {
                    playerHurtbox.body.velocity.y = -(playerPhysicsStats.focusVelocity);
                    playerSprite.body.velocity.y = -(playerPhysicsStats.focusVelocity);
                }
            }
            else if (cursors.down.isDown && !focusButton.isDown) {
                if (playerSprite.body.y >= 556) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 572;
                }
                else {
                    playerHurtbox.body.velocity.y = playerPhysicsStats.normalVelocity;
                    playerSprite.body.velocity.y = playerPhysicsStats.normalVelocity;
                }
            }
            else if (cursors.down.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.y >= 556) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 572;
                }
                else {
                    playerHurtbox.body.velocity.y = playerPhysicsStats.focusVelocity;
                    playerSprite.body.velocity.y = playerPhysicsStats.focusVelocity;
                }
            }

            if (cursors.left.isDown && !focusButton.isDown) {
                if (playerSprite.body.x <= 0) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 6;
                }
                else {
                    playerHurtbox.body.velocity.x = -(playerPhysicsStats.normalVelocity);
                    playerSprite.body.velocity.x = -(playerPhysicsStats.normalVelocity);
                }
            }
            else if (cursors.left.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.x <= 0) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 6;
                }
                else {
                    playerHurtbox.body.velocity.x = -(playerPhysicsStats.focusVelocity);
                    playerSprite.body.velocity.x = -(playerPhysicsStats.focusVelocity);
                }
            }
            else if (cursors.right.isDown && !focusButton.isDown) {
                if (playerSprite.body.x >= 486) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 492;
                }
                else {
                    playerHurtbox.body.velocity.x = playerPhysicsStats.normalVelocity;
                    playerSprite.body.velocity.x = playerPhysicsStats.normalVelocity;
                }
            }
            else if (cursors.right.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.x >= 486) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 492;
                }
                else {
                    playerHurtbox.body.velocity.x = playerPhysicsStats.focusVelocity;
                    playerSprite.body.velocity.x = playerPhysicsStats.focusVelocity;
                }
            }

            // Check amount of P and then fire appropriate weapon
            if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 0 && playerStats.power < 250) {
                singleShot.fire();
                // Update weapon text: 'SINGLE SHOT'
            }
            // focus fire single shot here
            else if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 250 && playerStats.power < 500) {
                doubleShot.fire();
                playerStats.weaponName = 'DOUBLE SHOT';
                weaponText.render();
                // Update weapon text: 'DOUBLE SHOT'
            }
            // focus fire double shot here
            else if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 500 && playerStats.power < 750) {
                singleShot.fire();
                doubleShot.fire();
                playerStats.weaponName = 'TRIPLE SHOT';
                weaponText.render();
                // Update weapon text: 'TRIPLE SHOT'
            }
            // focus fire triple shot here
            else if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 750) {
                // Update weapon text: 'MAX POWER'
                singleShot.fire();
                doubleShot.fire();
                waveShotLT.fire();
                waveShotRT.fire();
                playerStats.weaponName = 'WAVE SHOT';
                weaponText.render();
            }

            if (playerHurtbox.alive && bombButton.isDown && playerStats.bomb > 0 && !playerStats.bombActive) {
                // render bomb text here!
                playerStats.bombActive = true;
                playerBombSFX.play();
                playerBombSFX.onStop.add(function() {
                    playerStats.bomb--;
                    console.log(playerStats.bombTimer);
                    playerStats.bombActive = false;
                    playerStats.bombTimer = 0;

                }, this);
                /*var newBomb = playerBombs.create(playerHurtbox.body.x, playerHurtbox.body.y, 'bomb');
                newBomb.anchor.setTo(0.5);
                newBomb.outOfBoundsKill = true;
                newBomb.checkWorldBounds = true;
                newBomb.damageAmount = 24;
                newBomb.body.immovable = true;
                newBomb.body.velocity.x = 0;
                newBomb.body.velocity.y = 0;*/
            }

            // Check POC Line
        }

        function burstSmallPower(spriteX, spriteY, spriteYvel, amount) {
            smallP.x = spriteX;
            smallP.y = spriteY;
            smallP.setYSpeed(spriteYvel);
            smallP.setRotation(0, 0);
            smallP.start(true, 2500, null, amount);
        }

        function burstLargePower(spriteX, spriteY, spriteYvel, amount) {
            largeP.x = spriteX;
            largeP.y = spriteY;
            largeP.setYSpeed(spriteYvel);
            largeP.setRotation(0, 0);
            largeP.start(true, 0, null, amount);
        }

        // Display POC Line
        function displayPOCLine() {
            if (playerHurtbox.alive && pocLineText.visible === false && pocLine.visible === false && gameTimer <= 250) {
                pocLineText.visible = true;
                pocLine.visible = true;
                fadeInPOCtext = game.add.tween(pocLineText);
                fadeInPOCline = game.add.tween(pocLine);
                fadeInPOCtext.to({alpha: 0}, 500, Phaser.Easing.Quintic.Out, false, 0, 5, true);
                fadeInPOCline.to({alpha: 0.2}, 500, Phaser.Easing.Quintic.Out, false, 0, 5, true);
                fadeInPOCtext.start();
                fadeInPOCline.start();
            }
        }

        // check POC Line Breach
        function checkPOClineBreach() {
            if (playerHurtbox.alive && playerSprite.body.y <= game.world.centerY/2) {
                smallP.forEachAlive(function(smallPellet) {
                    game.physics.arcade.moveToObject(smallPellet, playerSprite, 400);
                });
                largeP.forEachAlive(function(largePellet) {
                    game.physics.arcade.moveToObject(largePellet, playerSprite, 400);
                });
            }
        }
        function playerPowerUp(player, p) {
            console.log('powered up');
            console.log(p.key);
            p.kill();
            if (p.key === 'smallP') {
                console.log('smallP collect');
                playerStats.power += 50;
                if (playerStats.power >= 250 && playerStats.power < 500 && playerStats.weaponName !== 'DOUBLE SHOT') {
                    playerStats.weaponName = 'DOUBLE SHOT';
                    weaponText.render();
                }
                else if (playerStats.power >= 500 && playerStats.power < 750 && playerStats.weaponName !== 'TRIPLE SHOT') {
                    playerStats.weaponName = 'TRIPLE SHOT';
                    weaponText.render();
                }
                else if (playerStats.power > 750 && playerStats.weaponName !== 'WAVE SHOT') {
                    playerStats.weaponName = 'WAVE SHOT';
                    weaponText.render();
                }
            }
            else if (p.key === 'largeP') {
                console.log('largeP collect');
                playerStats.power += 100;
            }
            powerText.render();
        }

        function playerPowerNerf() {
            playerStats.power -= 150;
            if (playerStats.power < 0) {
                playerStats.power = 0;
            }
        }

        function playerCollide(player, enemy) {
            console.log('enemy collide');
            player.damage(enemy.damageAmount);
            playerSprite.damage(enemy.damageAmount);
            lifeText.render();
            playerDeathSFX.play();
            player.body.x = 250;
            player.body.y = 443.5;
            playerSprite.body.x = 243;
            playerSprite.body.y = 428;
            console.log(player.health);
            console.log(playerSprite.health);
            clearGruntBullets();
            if (bossSpawned) {
                clearYuyukoBullets();
            }
        }

        // when sprite dies, its bullets linger and will still deal damage
        function bulletCollide(bullet, sprite) {
            if (bullet !== undefined) {
                bullet.kill();
                console.log(bullet.key);
                sprite.damage(bullet.damageAmount);
                if (sprite.health <= 0) {
                    var spriteX = sprite.body.x;
                    var spriteY = sprite.body.y;
                    var spriteYvel = sprite.body.velocity.y;
                    if (sprite.name === 'aimGrunt') {
                        burstSmallPower(spriteX, spriteY, spriteYvel, 5); // 250 Power
                        burstLargePower(spriteX, spriteY, spriteYvel, 2); // 200 Power
                        console.log('aim grunt release Power'); // Total Power Release: 450
                    }
                    else if (sprite.name === 'rotateGrunt') {
                        burstSmallPower(spriteX, spriteY, spriteYvel, 3); // 150 Power
                        burstLargePower(spriteX, spriteY, spriteYvel, 5); // 500 Power
                        console.log('rotateGrunt release Power'); // Total Power Release: 650
                    }
                    else if (sprite.name === 'straightGrunt') {
                        burstSmallPower(spriteX, spriteY, spriteYvel, 2); // 100 Power
                        burstLargePower(spriteX, spriteY, spriteYvel, 1); // 100 Power
                        console.log('straightGrunt release Power'); // Total Power Release: 200
                    }
                    var spriteDeathAnim = gruntDeaths.getFirstExists(false);
                    spriteDeathAnim.reset(sprite.body.x + sprite.body.halfWidth, sprite.body.y + sprite.body.halfHeight);
                    spriteDeathAnim.body.velocity.y = sprite.body.velocity.y;
                    spriteDeathAnim.alpha = 1;
                    spriteDeathAnim.play('gruntDeathExplode', 30, false, true);
                    /*if (sprite.key === 'yuyuko') {
                        // add some big score for boss kill
                        // play big explosion sound
                        bossDeathSFX.play();
                        return;
                    }*/
                    enemyDeathSFX.play();
                }
            }
        }

        function checkGruntBulletOverlap(gruntWeaponArray) {
            // if there is exists a grunt weapon in the aimGruntWeapons array (means that an enemy has spawned as well), then check collision for each weapon
            if (gruntWeaponArray.length > 0) {
                for (var i = 0; i < gruntWeaponArray.length; i++) {
                    //since its a group vs sprite, then first argument to gruntShotCollide is the sprite
                    if (gruntWeaponArray[i] != null) {
                        game.physics.arcade.overlap(gruntWeaponArray[i].bullets, playerHurtbox, gruntShotCollide, null, this);
                    }
                }
            }
        }

        function gruntShotCollide(player, bullet) {
            console.log('grunt bullet collide');
            player.damage(bullet.damageAmount);
            playerSprite.damage(bullet.damageAmount);<commit_msg>Bomb now vacuums every enemy bullet and absorbs them all while giving the player invulnerability until animation ends, but does not update bomb text ui yet, or disperse anything<commit_after><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="js/library/phaser.js"></script>
    <script src="js/library/HealthBar.standalone.js"></script>
    <title>Title</title>
</head>
<body>
    <div id="container"></div>

    <script type="text/javascript">
        var game = new Phaser.Game(512, 600, Phaser.AUTO, 'container', {
            preload: preload,
            create: create,
            update: update,
            render: render
        });

        function preload() {
            game.load.image('stage01BG', './assets/Background/stage01blue.png');
            game.load.image('stage01Boss', './assets/Background/stage01BossBG.png');
            game.load.image('sanaeHurtbox', './assets/Player/playerHurtbox.png');
            game.load.image('sanae', './assets/Player/playerStand.png');
            game.load.image('yuyuko', './assets/Boss/yuyuko.png');
            game.load.image('butterflyRed', './assets/Boss/bossBullets/butterflyRED.png');
            game.load.image('butterflyYellow', './assets/Boss/bossBullets/butterflyYELLOW.png');
            game.load.image('butterflyGreen', './assets/Boss/bossBullets/butterflyGREEN.png');
            game.load.image('butterflyCyan', './assets/Boss/bossBullets/butterflyCYAN.png');
            game.load.image('butterflyBlue', './assets/Boss/bossBullets/butterflyBLUE.png');
            game.load.image('butterflyPurple', './assets/Boss/bossBullets/butterflyPURPLE.png');
            game.load.image('butterflyBlack', './assets/Boss/bossBullets/butterflyBLACK.png');
            game.load.image('yuyukoBullet', './assets/Boss/bossBullets/yuyukoBullet.png');
            game.load.image('yuyukoOrb', './assets/Boss/bossBullets/yuyukoOrb.png');
            game.load.image('aimGruntShot', './assets/Enemy/enemyBullets/aimGruntShot.png');
            game.load.image('straightGruntShot', './assets/Enemy/enemyBullets/straightGruntShot.png');
            game.load.image('rotateGruntShot', './assets/Enemy/enemyBullets/rotateGruntShot.png');
            game.load.image('gruntRotate', './assets/Enemy/gruntRotate.png');
            game.load.image('gruntStraightRed', './assets/Enemy/gruntStraightRed.png');
            game.load.image('gruntStraightBlue', './assets/Enemy/gruntStraightBlue.png');
            game.load.image('gruntAimRed', './assets/Enemy/gruntAimRed.png');
            game.load.image('gruntAimBlue', './assets/Enemy/gruntAimBlue.png');
            game.load.image('singlePrimary', './assets/Player/playerShotA.png');
            game.load.image('doublePrimary', './assets/Player/playerShotB.png');
            game.load.image('spreadPrimary', './assets/Player/secondaryShotALT.png');
            game.load.image('playerBomb', './assets/Player/bomb.png');
            game.load.image('smallP', './assets/Player/PowerSmall.png');
            game.load.image('largeP', './assets/Player/PowerLarge.png');
            game.load.spritesheet('gruntDeathExplode', './assets/Enemy/gruntDeathExplosion2.png', 64, 65);
            game.load.audio('enemyDeath', './assets/Audio/SFX/enemyDeath.wav');
            game.load.audio('playerDeath', './assets/Audio/SFX/playerExplosion.wav');
            game.load.audio('bossDeath', './assets/Audio/SFX/bossExplosion.wav');
            game.load.audio('bomb', './assets/Audio/SFX/SpecialSS.wav');
            game.load.audio('stage01BGM', './assets/Audio/BGM/EndOfSpring.mp3');
            game.load.audio('stage01BossBGM', './assets/Audio/BGM/BloomNobly.mp3');
        }

        var playerStats = {
            score: 0,
            graze: 0,
            bomb: 2,
            power: 0,
            weaponName: 'SINGLE SHOT',
            bombTimer: 0,
            bombActive: false
        };
        const bossMaxHP = 60;
        var lifeText;
        var powerText;
        var weaponText;
        var bombText;
        var gameOverText;
        var pocLineText;
        var pocLine;
        var fadeInPOCtext;
        var fadeInPOCline;
        var gameTimer = 0;
        const playerPhysicsStats = {
            normalVelocity: 275,
            focusVelocity: 150
        };
        const enemyStats = {
            aimGruntHP: 10,
            straightGruntHP: 16,
            rotateGruntHP: 24,
            gruntXvelocity: 50,
            gruntYvelocity: 50,
            gruntStraightVelocity: 100,
            movingGruntStraightXVelocity: 75,
            movingGruntRotateXVelocity: 150,
            movingGruntRotateYVelocity: 200,
            reverseGruntRotateXVelocity: 300,
            reverseGruntRotateYVelocity: 500
        };
        const enemyWeapon = {
            gruntBulletSpeed: 250,
            gruntBulletFireRate: 500,
            gruntBulletAngleOffset: 90,
            aimGruntBulletAngleOffset: 0,
            gruntStraightBulletSpeed: 150, //100
            gruntStraightBulletFireRate: 850, //16 is the lowest and quickest possible
            movingGruntStraightBulletSpeed: 150,
            movingGruntStraightBulletFireRate: 600,
            gruntRotateBulletSpeed: 150,
            gruntRotateBulletFireRate: 50,
            gruntExplosiveRotateBulletSpeed: 100,
            gruntExplosiveRotateFireRate: 16
        };
        const weaponStats = {
            singleShotBulletSpeed: 850,
            singleShotBulletFireRate: 90,
            singleShotBulletAngleOffSet: 90,
            singleShotDamage: 4,
            doubleShotDamage: 6,
            waveShotDamage: 1
        };
        var rotateGruntTimers = [];
        var counterClockwiseShootID = [];

        var bg;
        var bgm;
        var bossBGM;
        var enemyDeathSFX;
        var playerDeathSFX;
        var playerBombSFX;
        var smallP;
        var largeP;
        var singleShot;
        var doubleShot;
        var waveShotLT;
        var waveShotRT;
        var playerBombs; // Divine Wind: Forgotten Cyclone
        var playerHurtbox;
        var playerSprite;
        var cursors;
        var fireButton;
        var bombButton;
        var bombSignal;
        var focusButton;
        var aimGrunts;
        var straightGrunts;
        var rotateGrunts;
        var gruntDeaths;

        // Boss Variables
        var yuyukoBoss;
        var bossDeathSFX;
        var bossSpawned = false;
        var yuyukoFloatUp = false;
        var bossHPbar;
        var bossText;
        var bossTransition;
        /*var bossTrnznTwo;
        var bossTrnznThree;*/
        var trnznData = {
            trnznRandX: 0,
            trnznRandY: 0,
            trnznTimer: 0
        };

        // Enemy Weapons
        var aimGruntWeapons = [];
        var aimGruntWeaponDIS = []; // Stands for Death Index Signals
        var rotateGruntWeapons = [];
        var rotateGruntWeaponDIS = [];
        var straightGruntWeapons = [];
        var straightGruntWeaponDIS = [];

        // weapon.Bullets is a group
        function create() {
            // Scrolling Background
            /*bg = game.add.tileSprite(0, 0, 512, 600, 'stage01BG');

            // Music and SFX
            //bgm = game.add.audio('stage01BGM');
            //bgm.play();
            //bossBGM = game.add.audio('stage01BossBGM');*/

            enemyDeathSFX = game.add.audio('enemyDeath');
            enemyDeathSFX.volume = 0.7;
            playerDeathSFX = game.add.audio('playerDeath');
            playerDeathSFX.volume = 0.7;
            playerBombSFX = game.add.audio('bomb');
            playerBombSFX.volume = 0.7
            bossDeathSFX = game.add.audio('bossDeath');
            bossDeathSFX.volume = 1.1;


            // Items
            smallP = game.add.emitter(0, 0, 200);
            smallP.enableBody = true;
            smallP.physicsBodyType = Phaser.Physics.ARCADE;
            smallP.forEach(function(powPellet) {
                powPellet.outOfBoundsKill = true;
                powPellet.checkWorldBounds = true;
            });
            smallP.makeParticles('smallP');
            smallP.gravity = 200;
            smallP.setXSpeed(-10, 10);
            //smallP.setYSpeed(100);

            largeP = game.add.emitter(0, 0, 200);
            largeP.enableBody = true;
            largeP.physicsBodyType = Phaser.Physics.ARCADE;
            largeP.forEach(function(powPellet) {
                powPellet.outOfBoundsKill = true;
                powPellet.checkWorldBounds = true;
            });
            largeP.makeParticles('largeP');
            smallP.gravity = 175;
            smallP.setXSpeed(-5, 5);
            //smallP.setYSpeed(100);

            // ___WEAPONS___

            // Single Shot
            singleShot = game.add.weapon(30, 'singlePrimary');
            singleShot.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            singleShot.bulletAngleOffset = weaponStats.singleShotBulletAngleOffSet;
            singleShot.bulletSpeed = weaponStats.singleShotBulletSpeed;
            singleShot.fireRate = weaponStats.singleShotBulletFireRate;
            singleShot.bullets.forEach(function(bullet) {
                bullet.damageAmount = weaponStats.singleShotDamage;
            });

            // Double Shot
            doubleShot = game.add.weapon(30, 'doublePrimary');
            doubleShot.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            doubleShot.bulletAngleOffset = 90;
            doubleShot.bulletSpeed = 850;
            doubleShot.fireRate = 90;
            doubleShot.bullets.forEach(function(bullet) {
               bullet.damageAmount = 5;
            });

            // Wave Shot
            waveShotLT = game.add.weapon(30, 'spreadPrimary');
            waveShotLT.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            waveShotLT.bulletSpeed = 850;
            waveShotLT.fireRate = 180;
            waveShotLT.bullets.forEach(function(bullet) {
                bullet.damageAmount = weaponStats.waveShotDamage;
            });
            waveShotRT = game.add.weapon(30, 'spreadPrimary');
            waveShotRT.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
            waveShotRT.bulletSpeed = 850;
            waveShotRT.fireRate = 180;
            waveShotRT.bullets.forEach(function(bullet) {
                bullet.damageAmount = weaponStats.waveShotDamage;
            });

            // Bomb
            playerBombs = game.add.group();
            playerBombs.enableBody = true;
            playerBombs.physicsBodyType = Phaser.Physics.ARCADE;

            // Enemies
            aimGrunts = game.add.group();
            aimGrunts.enableBody = true;
            aimGrunts.physicsBodyType = Phaser.Physics.ARCADE;

            straightGrunts = game.add.group();
            straightGrunts.enableBody = true;
            straightGrunts.physicsBodyType = Phaser.Physics.ARCADE;

            rotateGrunts = game.add.group();
            rotateGrunts.enableBody = true;
            rotateGrunts.physicsBodyType = Phaser.Physics.ARCADE;

            // Player
            playerHurtbox = this.add.sprite((game.world.width/2), game.world.height - 150, 'sanaeHurtbox');
            playerHurtbox.health = 3;
            playerHurtbox.anchor.setTo(0.5);
            playerSprite = this.add.sprite((game.world.width/2), game.world.height - 150, 'sanae');
            playerSprite.health = 3;
            playerSprite.anchor.setTo(0.5);


            game.physics.arcade.enable(playerHurtbox);
            game.physics.arcade.enable(playerSprite);
            playerHurtbox.body.collideWorldBounds = true;
            playerHurtbox.body.setCircle(6, 1);
            playerSprite.body.collideWorldBounds = true;
            console.log('hitbox x: ' + playerHurtbox.body.x + ', y: ' + playerHurtbox.body.y + ', ' + 'offset' + playerHurtbox.offsetX + ', ' + playerHurtbox.offsetY);
            console.log('sprite x: ' + playerSprite.body.x + ', y: ' + playerSprite.body.y + ', ' + 'offset' + playerSprite.offsetX + ', ' + playerSprite.offsetY);

            // Weapon Tracking
            // -- Weapon on player
            singleShot.trackSprite(playerSprite, 0, -(playerSprite.height/2 + 27));
            doubleShot.trackSprite(playerSprite, 0, -(playerSprite.height/2 + 27));
            waveShotLT.trackSprite(playerSprite, -50, -(playerSprite.height/2 + 27));
            waveShotRT.trackSprite(playerSprite, 50, -(playerSprite.height/2 + 27));

            // Setting Controls
            cursors = this.input.keyboard.createCursorKeys();
            fireButton = this.input.keyboard.addKey(Phaser.KeyCode.Z);
            bombButton = this.input.keyboard.addKey(Phaser.KeyCode.X);
            focusButton = this.input.keyboard.addKey(Phaser.KeyCode.SHIFT);

            // Boss Groups
            bossTransition = game.add.group();
            bossTransition.enableBody = true;
            bossTransition.physicsBodyType = Phaser.Physics.ARCADE;
            /*bossTrnznTwo = game.add.group();
            bossTrnznTwo.enableBody = true;
            bossTrnznTwo.physicsBodyType = Phaser.Physics.ARCADE;
            bossTrnznThree = game.add.group();
            bossTrnznThree.enableBody = true;
            bossTrnznThree.physicsBodyType = Phaser.Physics.ARCADE;*/

            // Game Text
                // Power
            powerText = game.add.text(10, game.world.height - 90, 'Power: ' + playerStats.power, {font: '20px Arial', fill: '#00FF00'});
            powerText.render = function() {
                powerText.text = 'Power: ' + Math.max(playerStats.power, 0);
            };
                // Bombs
            bombText = game.add.text(10, game.world.height - 60, 'Bombs: ' + playerStats.bomb, {font: '20px Arial', fill: '#00FF00'});
                // Lives
            lifeText = game.add.text(10, game.world.height - 30, 'Lives: ' + playerSprite.health, {font: '20px Arial', fill: '#00FF00'});
            lifeText.render = function() {
                lifeText.text = 'Lives: ' + Math.max(playerSprite.health, 0);
            };

                // Game Over
            gameOverText = game.add.text(game.world.centerX, game.world.centerY, 'GAME OVER\nTo restart, refresh the browser', {font: '30px Arial', fill: '#fff'});
            gameOverText.anchor.setTo(0.5);
            gameOverText.visible = false;

                // Weapon
            weaponText = game.add.text(300, game.world.height - 40, playerStats.weaponName, {font: '30px Arial', fill: '#00FFFF'});
            weaponText.render = function() {
                weaponText.text = playerStats.weaponName;
            };

                // Point of Collection Line
                    // POC Line Text
            pocLineText = game.add.text(game.world.centerX, game.world.centerY/2 - 10, 'Point of Collection', {font: '25px Arial', fill: '#00FF00'});
            pocLineText.anchor.setTo(0.5);
            pocLineText.visible = false;
                    // POC Line
            pocLine = game.add.text(0, game.world.centerY/2, '____________________________________________________________________________________________', {font: '20px Arial', fill: '#FF0000'});
            pocLine.anchor.setTo(0.5);
            pocLine.visible = false;

            // Enemy Death
            gruntDeaths = game.add.group();
            gruntDeaths.enableBody = true;
            gruntDeaths.physicsBodyType = Phaser.Physics.ARCADE;
            gruntDeaths.createMultiple(30, 'gruntDeathExplode');
            gruntDeaths.setAll('anchor.x', 0.5);
            gruntDeaths.setAll('anchor.y', 0.5);
            gruntDeaths.forEach(function(explode) {
               explode.animations.add('gruntDeathExplode');
            });

            spawnStraightGrunt(350, 200, 0, 0, 'gruntStraightRed', 'straightGruntShot');
            //spawnYuyuko();
        }

        function update() {
            playerSprite.sendToBack();
            playerHurtbox.sendToBack();
            //bg.sendToBack();
            smallP.callAll('bringToTop');
            largeP.callAll('bringToTop');
            aimGrunts.callAll('bringToTop');
            straightGrunts.callAll('bringToTop');
            rotateGrunts.callAll('bringToTop');
            playerHurtbox.body.velocity.x = 0;
            playerHurtbox.body.velocity.y = 0;
            playerSprite.body.velocity.x = 0;
            playerSprite.body.velocity.y = 0;

            // Collision Checking
                // aimGrunts
            if (!playerStats.bombActive) {
                game.physics.arcade.overlap(playerHurtbox, aimGrunts, playerCollide, null, this);
            }
            game.physics.arcade.overlap(singleShot.bullets, aimGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(doubleShot.bullets, aimGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotLT.bullets, aimGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotRT.bullets, aimGrunts, bulletCollide, null, this);

                // straightGrunts
            if (!playerStats.bombActive) {
                game.physics.arcade.overlap(playerHurtbox, straightGrunts, playerCollide, null, this);
            }
            game.physics.arcade.overlap(singleShot.bullets, straightGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(doubleShot.bullets, straightGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotLT.bullets, straightGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotRT.bullets, straightGrunts, bulletCollide, null, this);

                // rotateGrunts
            if (!playerStats.bombActive) {
                game.physics.arcade.overlap(playerHurtbox, rotateGrunts, playerCollide, null, this);
            }
            game.physics.arcade.overlap(singleShot.bullets, rotateGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(doubleShot.bullets, rotateGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotLT.bullets, rotateGrunts, bulletCollide, null, this);
            game.physics.arcade.overlap(waveShotRT.bullets, rotateGrunts, bulletCollide, null, this);

            // Check Enemy Bullet Collisions/Overlap with player and bomb if active
            checkGruntBulletOverlap(aimGruntWeapons);
            checkGruntBulletOverlap(straightGruntWeapons);
            checkGruntBulletOverlap(rotateGruntWeapons);

            // Vacuum Grunt Bullets when bomb is active
            bombVacuum();

            // Check bomb's cyclone collision with bullets
            /*if (playerStats.bombActive) {
                game.physics.arcade.overlap(playerBombs.getChildAt(playerBombs.length - 1).body, aimGrunts, bombCycloneCollide, null, this);
                game.physics.arcade.overlap(playerBombs.getChildAt(playerBombs.length - 1).body, straightGrunts, bombCycloneCollide, null, this);
                game.physics.arcade.overlap(playerBombs.getChildAt(playerBombs.length - 1).body, rotateGrunts, bombCycloneCollide, null, this);
            }*/

            // Check Power Item Collisions
            game.physics.arcade.overlap(playerSprite, smallP, playerPowerUp, null, this);
            game.physics.arcade.overlap(playerSprite, largeP, playerPowerUp, null, this);

            checkControls();

            // Enemy Shooting
            gruntFireSprite(aimGrunts, aimGruntWeapons, aimGruntWeaponDIS);
            gruntStraightFire(straightGrunts, straightGruntWeapons, straightGruntWeaponDIS);
            gruntRotateFire(rotateGrunts, rotateGruntWeapons, rotateGruntWeaponDIS);

            // Scroll the bg
            //bg.tilePosition.y += 2;

            // Check game over
            if (!playerHurtbox.alive && gameOverText.visible === false) {
                gameOverText.visible = true;
                var fadeInGameOver = game.add.tween(gameOverText);
                fadeInGameOver.to({alpha: 0.2}, 1000, Phaser.Easing.Quintic.Out, false, 0, -1, true);
                fadeInGameOver.start();
            }

            // Display POC Line at the beginning and check for breaches
            /*displayPOCLine();
            checkPOClineBreach();*/

            /*startStageOne();
            if (bgm.volume <= 0) {
                bgm.stop();
                console.log('bgm stopped');
            }*/
            if (bossSpawned) {
                // boss movement
                yuyukoFloat();

                // boss collision
                game.physics.arcade.overlap(playerHurtbox, yuyukoBoss, playerCollide, null, this);
                game.physics.arcade.overlap(singleShot.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(doubleShot.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(waveShotLT.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(waveShotRT.bullets, yuyukoBoss, yuyukoShotCollide, null, this);
                game.physics.arcade.overlap(playerHurtbox, bossTransition, playerCollide, null, this);
                /*game.physics.arcade.overlap(playerHurtbox, bossTrnznTwo, playerCollide, null, this);
                game.physics.arcade.overlap(playerHurtbox, bossTrnznThree, playerCollide, null, this);*/
                // check bomb collision with each butterfly transition
                // check bomb collision with yuyukoBoss

                // boss shoot (check hp, and change spell card accordingly)
                checkYuyukoHealthAndShoot();
                bossTransition.callAll('bringToTop');
                yuyukoBoss.moveDown();
            }
            gameTimer++;
            if (playerStats.bombActive) {
                playerStats.bombTimer++;
                playerBombs.callAll('bringToTop');
                // turn bombActive flag to false again at a certain time when bomb sound clip is over
            }

        }

        // DEBUGGING
        function render() {
            game.debug.body(playerHurtbox);
            //game.debug.body(yuyukoBoss);
            aimGrunts.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.4)');
            straightGrunts.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.4)');
            rotateGrunts.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.4)');
            singleShot.bullets.forEachAlive(renderGroup, this, 'rgba(0, 0, 255, 0.4)');
            doubleShot.bullets.forEachAlive(renderGroup, this, 'rgba(0, 0, 255, 0.4)');
            bossTransition.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.8)');
            playerBombs.forEachAlive(renderGroup, this, 'rgba(255, 0, 0, 0.8)');
        }

        function renderGroup(child, strColor) {
            game.debug.body(child, strColor);
        }
        // End DEBUGGING

        // Control Actions
        function checkControls() {
            if (focusButton.isDown) {
                playerHurtbox.bringToTop();
            }

            if (cursors.up.isDown && !focusButton.isDown) {
                if (playerSprite.body.y <= 0) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 16;
                }
                else {
                    playerHurtbox.body.velocity.y = -(playerPhysicsStats.normalVelocity);
                    playerSprite.body.velocity.y = -(playerPhysicsStats.normalVelocity);
                }
            }
            else if (cursors.up.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.y <= 0) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 16;

                }
                else {
                    playerHurtbox.body.velocity.y = -(playerPhysicsStats.focusVelocity);
                    playerSprite.body.velocity.y = -(playerPhysicsStats.focusVelocity);
                }
            }
            else if (cursors.down.isDown && !focusButton.isDown) {
                if (playerSprite.body.y >= 556) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 572;
                }
                else {
                    playerHurtbox.body.velocity.y = playerPhysicsStats.normalVelocity;
                    playerSprite.body.velocity.y = playerPhysicsStats.normalVelocity;
                }
            }
            else if (cursors.down.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.y >= 556) {
                    playerHurtbox.body.velocity.y = 0;
                    playerHurtbox.body.y = 572;
                }
                else {
                    playerHurtbox.body.velocity.y = playerPhysicsStats.focusVelocity;
                    playerSprite.body.velocity.y = playerPhysicsStats.focusVelocity;
                }
            }

            if (cursors.left.isDown && !focusButton.isDown) {
                if (playerSprite.body.x <= 0) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 6;
                }
                else {
                    playerHurtbox.body.velocity.x = -(playerPhysicsStats.normalVelocity);
                    playerSprite.body.velocity.x = -(playerPhysicsStats.normalVelocity);
                }
            }
            else if (cursors.left.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.x <= 0) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 6;
                }
                else {
                    playerHurtbox.body.velocity.x = -(playerPhysicsStats.focusVelocity);
                    playerSprite.body.velocity.x = -(playerPhysicsStats.focusVelocity);
                }
            }
            else if (cursors.right.isDown && !focusButton.isDown) {
                if (playerSprite.body.x >= 486) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 492;
                }
                else {
                    playerHurtbox.body.velocity.x = playerPhysicsStats.normalVelocity;
                    playerSprite.body.velocity.x = playerPhysicsStats.normalVelocity;
                }
            }
            else if (cursors.right.isDown && focusButton.isDown) {
                playerHurtbox.bringToTop();
                if (playerSprite.body.x >= 486) {
                    playerHurtbox.body.velocity.x = 0;
                    playerHurtbox.body.x = 492;
                }
                else {
                    playerHurtbox.body.velocity.x = playerPhysicsStats.focusVelocity;
                    playerSprite.body.velocity.x = playerPhysicsStats.focusVelocity;
                }
            }

            // Check amount of P and then fire appropriate weapon
            if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 0 && playerStats.power < 250) {
                singleShot.fire();
                // Update weapon text: 'SINGLE SHOT'
            }
            // focus fire single shot here
            else if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 250 && playerStats.power < 500) {
                doubleShot.fire();
                playerStats.weaponName = 'DOUBLE SHOT';
                weaponText.render();
                // Update weapon text: 'DOUBLE SHOT'
            }
            // focus fire double shot here
            else if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 500 && playerStats.power < 750) {
                singleShot.fire();
                doubleShot.fire();
                playerStats.weaponName = 'TRIPLE SHOT';
                weaponText.render();
                // Update weapon text: 'TRIPLE SHOT'
            }
            // focus fire triple shot here
            else if (playerHurtbox.alive && fireButton.isDown && playerStats.power >= 750) {
                // Update weapon text: 'MAX POWER'
                singleShot.fire();
                doubleShot.fire();
                waveShotLT.fire();
                waveShotRT.fire();
                playerStats.weaponName = 'WAVE SHOT';
                weaponText.render();
            }

            if (playerHurtbox.alive && bombButton.isDown && playerStats.bomb > 0 && !playerStats.bombActive) {
                // render bomb text here!
                playerStats.bombActive = true;
                playerBombSFX.play();
                // Do sanaeCard tween
                var newBomb = playerBombs.create(playerHurtbox.body.x, playerHurtbox.body.y, 'playerBomb');
                newBomb.anchor.setTo(0.5);
                newBomb.outOfBoundsKill = true;
                newBomb.checkWorldBounds = true;
                newBomb.damageAmount = 24;
                newBomb.body.immovable = true;
                newBomb.body.velocity.x = 0;
                newBomb.body.velocity.y = 0;
                newBomb.body.setCircle(9, -1, -2);
                game.physics.arcade.moveToXY(newBomb, game.world.centerX, game.world.centerY);
                playerBombSFX.onStop.add(function() {
                    playerStats.bomb--;
                    console.log(playerStats.bombTimer);
                    playerStats.bombActive = false;
                    playerStats.bombTimer = 0;
                    newBomb.kill();
                }, this);
            }
        }

        function bombVacuum() {
            if (playerStats.bombActive) {
                //var tempBombSprite = playerBombs.getChildAt(playerBombs.length - 1);
                var tempBombSprite = playerBombs.getFirstExists(true);
                if (aimGruntWeapons.length > 0) {
                    for (var i = 0; i < aimGruntWeapons.length; i++) {
                            aimGruntWeapons[i].bullets.forEachAlive(function (aimGruntBullet) {
                                game.physics.arcade.moveToObject(aimGruntBullet, tempBombSprite.body, 400);
                            }, this);
                    }
                }
                if (straightGruntWeapons.length > 0) {
                    for (var j = 0; j < straightGruntWeapons.length; j++) {
                            straightGruntWeapons[j].bullets.forEachAlive(function (straightGruntBullet) {
                                game.physics.arcade.moveToObject(straightGruntBullet, tempBombSprite.body, 400);
                            }, this);
                    }
                }
                if (rotateGruntWeapons.length > 0) {
                    for (var k = 0; k < rotateGruntWeapons.length; k++) {
                            rotateGruntWeapons[k].bullets.forEachAlive(function (rotateGruntBullet) {
                                game.physics.arcade.moveToObject(rotateGruntBullet, tempBombSprite.body, 400);
                            }, this);
                    }
                }
                bossTransition.forEachAlive(function(butterfly) {
                    game.physics.arcade.moveToObject(butterfly, tempBombSprite.body, 600);
                }, this);
            }
        }

        function bombCycloneCollide(bullet, bomb) {
            console.log('bullet absorbed');
            bullet.kill();
            // add to score here and render
            // maybe some sound?
        }
        function burstSmallPower(spriteX, spriteY, spriteYvel, amount) {
            smallP.x = spriteX;
            smallP.y = spriteY;
            smallP.setYSpeed(spriteYvel);
            smallP.setRotation(0, 0);
            smallP.start(true, 2500, null, amount);
        }

        function burstLargePower(spriteX, spriteY, spriteYvel, amount) {
            largeP.x = spriteX;
            largeP.y = spriteY;
            largeP.setYSpeed(spriteYvel);
            largeP.setRotation(0, 0);
            largeP.start(true, 0, null, amount);
        }

        // Display POC Line
        function displayPOCLine() {
            if (playerHurtbox.alive && pocLineText.visible === false && pocLine.visible === false && gameTimer <= 250) {
                pocLineText.visible = true;
                pocLine.visible = true;
                fadeInPOCtext = game.add.tween(pocLineText);
                fadeInPOCline = game.add.tween(pocLine);
                fadeInPOCtext.to({alpha: 0}, 500, Phaser.Easing.Quintic.Out, false, 0, 5, true);
                fadeInPOCline.to({alpha: 0.2}, 500, Phaser.Easing.Quintic.Out, false, 0, 5, true);
                fadeInPOCtext.start();
                fadeInPOCline.start();
            }
        }

        // check POC Line Breach
        function checkPOClineBreach() {
            if (playerHurtbox.alive && playerSprite.body.y <= game.world.centerY/2) {
                smallP.forEachAlive(function(smallPellet) {
                    game.physics.arcade.moveToObject(smallPellet, playerSprite, 400);
                });
                largeP.forEachAlive(function(largePellet) {
                    game.physics.arcade.moveToObject(largePellet, playerSprite, 400);
                });
            }
        }
        function playerPowerUp(player, p) {
            console.log('powered up');
            console.log(p.key);
            p.kill();
            if (p.key === 'smallP') {
                console.log('smallP collect');
                playerStats.power += 50;
                if (playerStats.power >= 250 && playerStats.power < 500 && playerStats.weaponName !== 'DOUBLE SHOT') {
                    playerStats.weaponName = 'DOUBLE SHOT';
                    weaponText.render();
                }
                else if (playerStats.power >= 500 && playerStats.power < 750 && playerStats.weaponName !== 'TRIPLE SHOT') {
                    playerStats.weaponName = 'TRIPLE SHOT';
                    weaponText.render();
                }
                else if (playerStats.power > 750 && playerStats.weaponName !== 'WAVE SHOT') {
                    playerStats.weaponName = 'WAVE SHOT';
                    weaponText.render();
                }
            }
            else if (p.key === 'largeP') {
                console.log('largeP collect');
                playerStats.power += 100;
            }
            powerText.render();
        }

        function playerPowerNerf() {
            playerStats.power -= 150;
            if (playerStats.power < 0) {
                playerStats.power = 0;
            }
        }

        function playerCollide(player, enemy) {
            console.log('enemy collide');
            player.damage(enemy.damageAmount);
            playerSprite.damage(enemy.damageAmount);
            lifeText.render();
            playerDeathSFX.play();
            player.body.x = 250;
            player.body.y = 443.5;
            playerSprite.body.x = 243;
            playerSprite.body.y = 428;
            console.log(player.health);
            console.log(playerSprite.health);
            clearGruntBullets();
            if (bossSpawned) {
                clearYuyukoBullets();
            }
        }

        // when sprite dies, its bullets linger and will still deal damage
        function bulletCollide(bullet, sprite) {
            if (bullet !== undefined) {
                bullet.kill();
                console.log(bullet.key);
                sprite.damage(bullet.damageAmount);
                if (sprite.health <= 0) {
                    var spriteX = sprite.body.x;
                    var spriteY = sprite.body.y;
                    var spriteYvel = sprite.body.velocity.y;
                    if (sprite.name === 'aimGrunt') {
                        burstSmallPower(spriteX, spriteY, spriteYvel, 5); // 250 Power
                        burstLargePower(spriteX, spriteY, spriteYvel, 2); // 200 Power
                        console.log('aim grunt release Power'); // Total Power Release: 450
                    }
                    else if (sprite.name === 'rotateGrunt') {
                        burstSmallPower(spriteX, spriteY, spriteYvel, 3); // 150 Power
                        burstLargePower(spriteX, spriteY, spriteYvel, 5); // 500 Power
                        console.log('rotateGrunt release Power'); // Total Power Release: 650
                    }
                    else if (sprite.name === 'straightGrunt') {
                        burstSmallPower(spriteX, spriteY, spriteYvel, 2); // 100 Power
                        burstLargePower(spriteX, spriteY, spriteYvel, 1); // 100 Power
                        console.log('straightGrunt release Power'); // Total Power Release: 200
                    }
                    var spriteDeathAnim = gruntDeaths.getFirstExists(false);
                    spriteDeathAnim.reset(sprite.body.x + sprite.body.halfWidth, sprite.body.y + sprite.body.halfHeight);
                    spriteDeathAnim.body.velocity.y = sprite.body.velocity.y;
                    spriteDeathAnim.alpha = 1;
                    spriteDeathAnim.play('gruntDeathExplode', 30, false, true);
                    /*if (sprite.key === 'yuyuko') {
                        // add some big score for boss kill
                        // play big explosion sound
                        bossDeathSFX.play();
                        return;
                    }*/
                    enemyDeathSFX.play();
                }
            }
        }

        function checkGruntBulletOverlap(gruntWeaponArray) {
            // if there is exists a grunt weapon in the aimGruntWeapons array (means that an enemy has spawned as well), then check collision for each weapon
            if (gruntWeaponArray.length > 0) {
                for (var i = 0; i < gruntWeaponArray.length; i++) {
                    //since its a group vs sprite, then first argument to gruntShotCollide is the sprite
                    if (gruntWeaponArray[i] != null && !playerStats.bombActive) {
                        game.physics.arcade.overlap(gruntWeaponArray[i].bullets, playerHurtbox, gruntShotCollide, null, this);
                    }
                    else if (gruntWeaponArray[i] != null && playerStats.bombActive) {
                        console.log('checking');
                        //for (var j = 0; j < gruntWeaponArray[i].bullets.length; j++) {
                            gruntWeaponArray[i].bullets.forEachAlive(function(specificBullet) {
                                console.log('inside');
                                game.physics.arcade.overlap(specificBullet, playerBombs, bombCycloneCollide, null, this);
                            }, this);
                        //}
                    }
                }
            }
        }

        function gruntShotCollide(player, bullet) {
            console.log('grunt bullet collide');
            player.damage(bullet.damageAmount);
            playerSprite.damage(bullet.damageAmount);
{'fraction_non_alphanumeric': 0.10883334008561898, 'fraction_numerical': 0.014841523855825196, 'mean_word_length': 1.7074954296160878, 'pattern_counts': {'":': 0, '<': 68, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3766620', 'n_tokens_mistral': 22914, 'n_tokens_neox': 21025, 'n_words': 3560}