Package LixoGame

Source Code of LixoGame.GameManager$ProblemCollisionGroup

package LixoGame;

/**
* The purpose of this class is to provide a manager for the "game". It manages
* state changes, such as from Puzzle mode to Platform mode, and performs the
* loading and unloading operations for each state change. The Game itself doesn't
* need to know which state the "game" is in, only wether it is running or not.
* The outside world calls LoadGame and UnloadGame.
*
* @author Bruno
*/

import com.golden.gamedev.engine.BaseAudio;
import java.awt.*;
import java.awt.event.*;
import com.golden.gamedev.engine.BaseAudioRenderer;
import com.golden.gamedev.object.*;
import com.golden.gamedev.object.background.*;
import com.golden.gamedev.object.collision.BasicCollisionGroup;
import com.golden.gamedev.object.collision.CollisionGroup;
import com.golden.gamedev.util.ImageUtil;
import java.awt.image.BufferedImage;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URISyntaxException;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter;
import java.util.LinkedList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;


public class GameManager {

    private LixoGame GameRef;

    private InGameState OldState;
    private InGameState GameState;
    private ArrayList<Recyclables> Baskets; //Baskets states
    private RecyclableFeature[] TrashInBaskets; //What will be loaded on PlatformState

    private Player Hero;
    private BufferedImage[] HeroSpriteSheet;
    private Sprite[] Lives;
    private Sprite[] HealthBar;
    private Sprite Pause;
    private Sprite Clock;
    private Sprite Ammo;
    private Sprite MatchColors;
    private ImageBackground GameBackground;
    private Block[] Blocks;

    private int Stage;
    private int ActiveBlock; //Which block is active
    private LinkedList<Column> ColumnOrder; //Order of block appearance
    private boolean[] blocksOk; //Which baskets are ok
    private double dropVelocity;

    private SpriteGroup PlayerGroup;
    private SpriteGroup PlayerShotsGroup;
    private SpriteGroup EnemyShotsGroup;
    private SpriteGroup SceneObjects;
    private SpriteGroup EnemyGroup;
    private SpriteGroup BlocksGroup;
    private SpriteGroup RecyclableBinGroup;
    private SpriteGroup UIElementsGroup;
    private SpriteGroup BlockableGroup;
    private SpriteGroup DoorExitGroup;
    private SpriteGroup ResultGroup;

    private PlayField GameField;

    private TerrainCollision terrainCollisionHandler;
    private AssetCollision assetCollisionHandler;
    private DoorCollision exitCollisionHandler;
    private ProblemCollisionGroup problemCollisionGroup;
    private ProblemCollisionGroup blockableCollisionGroup;
    private ProblemCollisionGroup enemyBlockableCollisionGroup;
    private PlayerShotCollision playerShotCollisionGroup;
    private PlayerShotCollision playerShotBlockableCollisionGroup;
    private EnemyShotCollision enemyShotCollisionGroup;

    private Timer gameOverTimer;
    private Timer gameTimer;
    private Timer cutsceneTimer;
    private Timer endgameTimer;
    private BananaTimer bananaGameTimer;
    private String time;
    private LinkedList<BufferedImage> cutsceneScreens;
    private int cutsceneIndex;
    private Sprite Invincible;
    private Sprite Perfect;

    /**
     * @param Ref Reference to the Game object that called the GameManager. Needed
     * to get info about window size and other stuff
     */
    public GameManager(LixoGame Ref)
    {
        OldState = null;
        GameState = InGameState.PuzzleState;
        GameRef = Ref;
        cutsceneIndex = GameRef.getRandom(0, GameConstants.Cutscenes-1);
        GameBackground = new ImageBackground(GameRef.getImage(GameConstants.BackgroundImageGame),
                    GameRef.getWidth(), GameRef.getHeight());

        Stage = 1;
        time = "";
        dropVelocity = GameConstants.InitialBlockVelocity;

        //gameTimer = new Timer(GameConstants.ClockTimer);
        //gameTimer.setActive(false);
        bananaGameTimer = new BananaTimer(GameConstants.ClockTimer);
        gameOverTimer = new Timer (GameConstants.GameOverTimer);
        gameOverTimer.setActive(false);
        cutsceneTimer = new Timer (GameConstants.CutsceneTimer);
        cutsceneTimer.setActive(false);
        endgameTimer = new Timer (GameConstants.EndGameTimer);
        endgameTimer.setActive(false);

        MatchColors = new Sprite(GameRef.getImage(GameConstants.Match));
        Invincible = new Sprite (GameRef.getImage(GameConstants.InvincibeImage,true));
        Invincible.move(GameConstants.InvincibleX, GameConstants.InvincibleY);
        Perfect = new Sprite(GameRef.getImage(GameConstants.PerfectBonus));
        Perfect.move(GameConstants.InvincibleX, GameConstants.InvincibleY + 170);
        HeroSpriteSheet = LoadPlayerSpriteSheet();
        LoadHero();

        cutsceneScreens = new LinkedList<BufferedImage>();

        for (int i = 0; i < GameConstants.Cutscenes; i++)
        {
            cutsceneScreens.add(ImageUtil.getImage(GameRef.bsIO.getURL(GameConstants.CutsceneFile + (i+1) + ".png")));
        }

        Collections.shuffle(cutsceneScreens);
    }

    public boolean update (long elapsedTime) throws IOException, ClassNotFoundException
    {
        int keyPressed = GameRef.bsInput.getKeyPressed();

        switch (GameState)
        {
            case PuzzleState:

                //System.out.println("DEBUG: Puzzle block state. If everything true, must go to Platform state");
                //System.out.println("blocksOk[0] = " + blocksOk[0] + "\tblocksOk[1] = " + blocksOk[1] +
                //         "\tblocksOk[2] = " + blocksOk[2] + "\tblocksOk[3] = " + blocksOk[3] + "\n");

                boolean allcorrect = true;
               
                if (blocksOk[0] == true && blocksOk[1] == true &&
                        blocksOk[2] == true && blocksOk[3] == true)
                {
                    for (int i = 0; i < TrashInBaskets.length; i++)
                    {
                        if(TrashInBaskets[i] == RecyclableFeature.MetalProblem ||
                                TrashInBaskets[i] == RecyclableFeature.OrganicProblem ||
                                TrashInBaskets[i] == RecyclableFeature.GlassProblem ||
                                TrashInBaskets[i] == RecyclableFeature.PlasticProblem)
                        {
                            allcorrect = false;
                            break;
                        }
                    }

                    if (allcorrect)
                    {
                        Perfect.render(GameRef.bsGraphics.getBackBuffer()); //render PERFECT in backbuffer
                        GameRef.bsGraphics.flip()//draw back buffer to screen
                        //Updates player score
                        Hero.setScore(Hero.getScore() + GameConstants.Perfect);

                        if(GameRef.GetSoundState())
                        {
                            try{
                                BaseAudioRenderer dummy = GameRef.bsSound.getAudioRenderer(
                                    GameRef.bsSound.play(SoundStrings.AllBlocksCorrect, BaseAudio.SINGLE));

                                /** @TODO: Linux problem */
                                //Wait for sound to play
                                //while (dummy.getStatus() != BaseAudioRenderer.END_OF_SOUND){ /* Empty */ }
                                Thread.sleep(1000L);

                            }
                            catch(ArrayIndexOutOfBoundsException e)
                            {
                                System.out.println("ERROR MESSAGE: Sound in your system may not be supported.");
                                System.out.println("ERROR MESSAGE: This was set by GameManager::update#puzzlestate");
                                System.out.println(e.getMessage());
                            }
                            catch (InterruptedException e)
                            {
                                System.out.println(e.getMessage());
                            }
                           
                        }//if
                       
                        AdvanceStage(allcorrect);
                        break;

                    }//if
                    else
                    {
                        UnloadPuzzleState();
                        LoadPlatformState();
                        GameState = InGameState.PlatformState;
                    }
                }
                else
                {
                    if (keyPressed == KeyEvent.VK_S)
                    {
                        GameRef.ChangeSoundState();
                    }
                    else
                    {
                        if(keyPressed == KeyEvent.VK_M)
                        {
                            GameRef.ChangeMusicState();
                        }//if
                    }//if

                    if (keyPressed == KeyEvent.VK_ESCAPE)
                    {
                        return false;
                    }
                    else if ( keyPressed == KeyEvent.VK_RIGHT)
                    {
                        Blocks[ActiveBlock].RotateClockWise();
                    }
                    else if ( keyPressed == KeyEvent.VK_LEFT)
                    {
                        Blocks[ActiveBlock].RotateCounterClockWise();
                    }
                    else if ( keyPressed == KeyEvent.VK_DOWN )
                    {
                        Blocks[ActiveBlock].setY(GameConstants.AssetY - Blocks[ActiveBlock].getHeight());
                    }
                    else
                    {
                        //GameField.update(elapsedTime);
                    }//if

                    if ( dropVelocity > GameConstants.MaxVelocity)
                    {
                        Blocks[ActiveBlock].moveY(GameConstants.MaxVelocity);
                    }
                    else
                    {
                        Blocks[ActiveBlock].moveY( dropVelocity );
                    }

                    GameField.update(elapsedTime);
                }
               
                break;

            case PlatformState:

                bananaGameTimer.update();

                int leftTime = (int) ((GameConstants.ClockTimer - bananaGameTimer.getTimePast())/1000);
               
                if (bananaGameTimer.checkTimer())
                {
                    Hero.setHealth(0);
                }//if

                if (Hero.getLives() > 0)
                {
                    if (Hero.getHealth() <= 0)
                    {
                        ResetPlayerOnDeath();
                        GameState = InGameState.PuzzleState;
                       
                        UnloadPlatformState();
                        LoadPuzzleState();

                        if (GameRef.GetMusicState())
                            GameRef.bsMusic.play(GameConstants.GameInsideMusicPath, BaseAudio.MULTIPLE);

                        break;
                    }

                    //Updates how many Health Dots should be drawn
                    for (int i = 0; i < HealthBar.length; i++)
                    {
                        if (i < Hero.getHealth())
                        {
                            HealthBar[i].setActive(true);
                        }
                        else
                        {
                            HealthBar[i].setActive(false);
                        }
                    }

                    //Updates how many Life Dots should be drawn
                    for (int i = 0; i < Lives.length; i++)
                    {
                        if (i < Hero.getLives())
                        {
                            Lives[i].setActive(true);
                        }
                        else
                        {
                            Lives[i].setActive(false);
                        }
                    }

                    if (keyPressed == KeyEvent.VK_ESCAPE)
                    {
                        return false;
                    }//if

                    if (keyPressed == KeyEvent.VK_P || keyPressed == KeyEvent.VK_PAUSE )
                    {
                        GameState = InGameState.PausedState;
                        bananaGameTimer.pauseTimer();
                        //timeStop = gameTimer.getCurrentTick();
                        //System.out.println("TimeStop = " + timeStop);
                        if(Hero.isInvincible())
                        {
                            /**@TODO:Create Player::GetInvincibilityTimer()*/
                        }
                       
                        GameRef.bsMusic.setVolume((float)0.0);
                    }
                    else
                    {

                        GameField.update(elapsedTime);

                        if (keyPressed == KeyEvent.VK_CONTROL && Hero.hasGun())
                        {
                            AddBulletToScene ( (Hero.getCurrentState() == PlayerConstants.DirectionRight? Hero.getX() + Hero.getWidth() :
                                Hero.getX()), Hero.getY() + 60,
                                    (Hero.getCurrentState() == PlayerConstants.DirectionRight? GameConstants.BulletSpeed : -GameConstants.BulletSpeed),
                                    elapsedTime, Hero);
                        }//if
                        else
                        {
                            if (keyPressed == KeyEvent.VK_S)
                            {
                                GameRef.ChangeSoundState();
                            }
                            else
                            {
                                if(keyPressed == KeyEvent.VK_M)
                                {
                                    GameRef.ChangeMusicState();
                                }//if
                            }//if
                        }
                    }//if
                }
                else
                {
                    GameState = InGameState.GameOverState;
                    LoadGameOverState();
                }

                if(leftTime <= GameConstants.BeepThreshold)
                {
                    if(GameRef.GetSoundState() && GameState == InGameState.PlatformState)
                    {
                        GameRef.bsSound.play(SoundStrings.Beep, BaseAudio.SINGLE);
                    }
                }

                break;

            case PausedState:

                //keyPressed = GameRef.bsInput.getKeyPressed();
                //gameTimer.setCurrentTick(timeStop);

                if (keyPressed == KeyEvent.VK_P || keyPressed == KeyEvent.VK_PAUSE )
                {
                    //gameTimer.notify();
                    GameState = InGameState.PlatformState;
                    GameRef.bsMusic.setVolume((float)1.0);
                    bananaGameTimer.unpauseTimer();
                    GameField.update(elapsedTime);
                }//if
                else
                {
                    if (keyPressed == KeyEvent.VK_S)
                    {
                        GameRef.ChangeSoundState();
                    }
                    else
                    {
                        if(keyPressed == KeyEvent.VK_M)
                        {
                            GameRef.ChangeMusicState();
                        }//if
                    }//if
                }
                break;

            case GameOverState:
                if (gameOverTimer.action(elapsedTime))
                {
                    GameState = InGameState.PuzzleState;
                    UnloadGameOverState();
                    GameRef.bsMusic.stopAll();
                    RegisterScore();
                    return false;
                }//if

                break;

            case Cutscene:
                if (cutsceneTimer.action(elapsedTime))
                {
                    GameState = InGameState.PuzzleState;
                    LoadPuzzleState();
                    if (GameRef.GetMusicState())
                            GameRef.bsMusic.play(GameConstants.GameInsideMusicPath, BaseAudio.MULTIPLE);
                }//if
                break;

            case EndScene:
                if (endgameTimer.action(elapsedTime))
                {
                    GameRef.bsMusic.stopAll();
                    RegisterScore();
                    return false;
                }
                break;
        }//switch

        return true;
    }

    @SuppressWarnings("empty-statement")
    public void render (Graphics2D g)
    {
        switch (GameState)
        {
            case PausedState:
                GameField.render(g);
                InterfaceRender(g);
                Pause.render(g);
                break;

            case PlatformState:
                GameField.render(g);
                InterfaceRender(g);
                break;

            case PuzzleState:
                GameField.render(g);
                MatchColors.render(g,(int) (0.5*GameRef.getWidth() -
                        0.5*MatchColors.getWidth()), GameConstants.MatchY);
                GameRef.BigFont.drawText(g, "Stage: " + Stage, GameFont.CENTER,
                200, -40, 400, 0, 0);
                ResultGroup.render(g);
                break;

            case GameOverState:
                GameField.render(g);
                break;

            case Cutscene:
                GameField.render(g);
                break;

            case EndScene:
                GameField.render(g);
                break;
        }//switch
    }

    /**
     * Register score prompts user for Name input and updates hiscore file
     * @throws ClassNotFoundException
     * @throws IOException
     */
    private void RegisterScore() throws ClassNotFoundException, IOException
    {
        ObjectOutputStream output = null;
        String playerName = JOptionPane.showInputDialog("Register your name in the Hall of Fame!");
        JOptionPane.showMessageDialog(null, String.format("%s, your score was %s and your stage was %s", playerName, Hero.getScore(), this.Stage));

        ScoreTracker current = new ScoreTracker(playerName, (int) Hero.getScore(),
                this.Stage, (this.GameState == InGameState.EndScene? true: false));
        List<ScoreTracker> scores = new ArrayList<ScoreTracker>();

        try {

            String parentPath = null;

            try {
                //Gets the parent directory of the running class (ex: jar directory)
                parentPath = (new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI())).getParent();
            } catch (URISyntaxException ex) {
                Logger.getLogger(GameManager.class.getName()).log(Level.SEVERE, null, ex);
            }

            ObjectInputStream input = null;

            try{
                input = new ObjectInputStream(new FileInputStream(parentPath + File.separator + GameConstants.HiscoreFileString));

                while (true)
                {
                    scores.add((ScoreTracker)input.readObject());
                }
            }
            catch(EOFException e)
            {
                if(input != null)
                    input.close();
            }
            catch (FileNotFoundException e)
            {
                //Creates an empty hiscore.dat
                Formatter formatter = new Formatter(parentPath + File.separator + GameConstants.HiscoreFileString);
                formatter.close();
            }
            finally
            {
                scores.add(current);
                Collections.sort(scores);
            }

            output = new ObjectOutputStream(new FileOutputStream(parentPath + File.separator + "hiscore.dat"));
            //ObjectOutputStream output = new ObjectOutputStream(getClass().getResource("hiscore.dat").openStream());

            /**
             * @TODO: Write this in a better way for keeping just the top 10 scores
             */
            for (ScoreTracker score : scores)
            {
                //System.out.printf("%s\t%s\t%s\n",score._name,score._score,score._stage);
                output.writeObject(score);
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(GameManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch(IOException e)
        {
            System.out.println(e.getMessage());
        }
        finally
        {
            if (output != null)
                output.close();
        }
    }

    /**
     * This method handles the collision for the Player and the Terrain.
     * @param sprite Sprite that collided with the collision group
     */
//    private void handleCollision (Sprite terrain, Sprite character) {
//        Player spr = (Player) character;
//
//        //spr.forceY(spr.getY() - 2);
//        spr.setY(terrain.getY() - spr.getHeight());
//        spr.setOnGround ();
//    }

    /**
     * This method handles the effects of RecyclableBlock collision with the ground,
     * setting the next active block and checking if all blocks have been set. Must check
     * the block state and set which blocks are incorret.
     * @param sprite
     */
    private void blockCollision (Sprite block){

        //System.out.println("DEBUG: Entered blockCollision");

        Block blk = (Block) block;

        //Calculates penetration from block into terrain
        //double dif = blk.getHeight() + blk.getY() - terrain.getY();

        int basketNumber = blk.GetColumn().ordinal();

        //Moves the block up
        //blk.setY(terrain.getY() - blk.getHeight());
        blk.setY(GameConstants.AssetY - blk.getHeight());

        //Sets basket state to full
        blocksOk[basketNumber] = true;

        //Sets basket feature for Platform level
        if(blk.GetState() == Baskets.get(basketNumber) )
        {
            //In case the trash was thrown in the right basket
            if(GameRef.GetSoundState())
                GameRef.bsSound.play(SoundStrings.BlockMatch, BaseAudio.MULTIPLE);

            /**@TODO:Fix these magic numbers*/
            ResultGroup.add(new Sprite(GameRef.getImage(GameConstants.GoodResult, true),
                    blk.getX() + 33, blk.getY() - 25));

            switch(blk.GetState())
            {
                case Metal:
                    TrashInBaskets[basketNumber] = RecyclableFeature.MetalBonus;
                    break;
                case Glass:
                    TrashInBaskets[basketNumber] = RecyclableFeature.GlassBonus;
                    break;
                case Organic:
                    TrashInBaskets[basketNumber] = RecyclableFeature.OrganicBonus;
                    break;
                case Plastic:
                    TrashInBaskets[basketNumber] = RecyclableFeature.PlasticBonus;
                    break;
            }//switch
        }
        else
        {
            if(GameRef.GetSoundState())
                GameRef.bsSound.play(SoundStrings.BlockMiss, BaseAudio.MULTIPLE);

            ResultGroup.add(new Sprite(GameRef.getImage(GameConstants.BadResult, true),
                    blk.getX() + 41, blk.getY() - 25));

            switch(blk.GetState())
            {
                case Metal:
                    TrashInBaskets[basketNumber] = RecyclableFeature.MetalProblem;
                    break;
                case Glass:
                    TrashInBaskets[basketNumber] = RecyclableFeature.GlassProblem;
                    break;
                case Organic:
                    TrashInBaskets[basketNumber] = RecyclableFeature.OrganicProblem;
                    break;
                case Plastic:
                    TrashInBaskets[basketNumber] = RecyclableFeature.PlasticProblem;
                    break;
            }//switch
        }//if

        //System.out.println("DEBUG: " + Blocks[ActiveBlock].toString());
        //System.out.println("DEBUG: ActiveBlock = " + ActiveBlock + " Number of Blocks = " + GameConstants.NumberofBlocks);

        //Maybe this is what was giving us erros (was less than 3)
        if (ActiveBlock < GameConstants.NumberofBlocks - 1)
        {
            LinkedList<Column> col = new LinkedList<Column>();

            //Setting a list of free columns
            for (int i = 0; i < blocksOk.length; i++)
            {
                if (!blocksOk[i])
                {
                    try
                    {
                        col.add(ConvertIndexToColumn(i));
                    }
                    catch (Exception e)
                    {
                        System.out.println(e.getMessage());
                    }//try
                }//if
            }//for

            Collections.shuffle(col);

            ++ActiveBlock; //Goes to the next block

            if (ActiveBlock >= GameConstants.NumberofBlocks)
            {
                assert(blocksOk[0] == true && blocksOk[1] == true &&
                        blocksOk[2] == true && blocksOk[3] == true);
                return;
            }

            Blocks[ActiveBlock].setActive(true);
            Blocks[ActiveBlock].SetColumn(col.poll());
            Blocks[ActiveBlock].move(ConvertColumnToCoordinate(Blocks[ActiveBlock].GetColumn()) , 0);
        }//if

    }

    /**
     * This method is called from player class to add gun bullets into the scene
     * @param x X position of the bullet
     * @param y Y position of the bullet
     * @param speed X speed of the bullet
     * @param elapsedtime Time elapsed since the start of the simulation
     * @param creator AnimatedSprite that created the bullet. The current implementation
     * takes that creator can be Robot or Player. Should check for a Shooter Interface
     */
    public void AddBulletToScene (double x, double y, double speed, long elapsedtime, AnimatedSprite creator)
    {
        Bullet newBullet;

        if (creator instanceof Player)
        {
            if (((Player)creator).checkBulletTimer(elapsedtime))
            {
                newBullet = new Bullet(ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.BulletImage),
                        1, 1, Color.WHITE), x, y, GameConstants.BulletDamage, speed, creator, GameRef);
                ((Player)creator).setBulletTimer();
                PlayerShotsGroup.add(newBullet);
                ((Player)creator).modifyAmmo(-1);

                if(GameRef.GetSoundState())
                    GameRef.bsSound.play(SoundStrings.GunShot, BaseAudio.MULTIPLE);
            }//if
        }
        else
        {
            if (creator instanceof Robot)
            {
                if (((Robot)creator).checkBulletTimer(elapsedtime))
                {
                    newBullet = new Bullet(ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.BulletImage),
                            1, 1), x, y, GameConstants.BulletDamage, speed, creator, this.GameRef);
                    newBullet.setActive(true);
                    ((Robot)creator).setBulletTimer();
                    EnemyShotsGroup.add(newBullet);
                }//if
            }//if
        }//if
    }

    /**
     * Loads the game resources and makes necessairy changes
     */
    public void LoadGame()
    {
        if (GameRef.GetMusicState() && OldState == null)
        {
            GameRef.bsMusic.stopAll();
            GameRef.bsMusic.play(GameConstants.GameInsideMusicPath, BaseAudio.SINGLE_REPLAY);
        }

        switch(GameState)
        {
            case PuzzleState:
                LoadPuzzleState();
                break;
            case PlatformState:
                LoadPlatformState();
                break;
        }//switch
    }

    /**
     * Unloads game resources, depending on which state it is in
     */
    public void UnloadGame()
    {
        switch(GameState)
        {
            case PuzzleState:
                UnloadPuzzleState();
                break;
            case PausedState: //fallthrough desired
            case PlatformState:
                UnloadPlatformState();
                break;
            case GameOverState:
                UnloadGameOverState();
                break;
        }//switch

        FreeResources();
    }

    /**
     * Loads the resources needed to run the platform part of the game
     */
    private void LoadPlatformState()
    {
        GameField = new PlayField();
        //HeroSpriteSheet = LoadPlayerSpriteSheet();

        Lives = new Sprite[PlayerConstants.MaxLife];
        HealthBar = new Sprite[PlayerConstants.MaxHealth];

        Clock = new Sprite(GameRef.bsLoader.getImage(GameConstants.ClockString));
        Ammo = new Sprite(GameRef.bsLoader.getImage(GameConstants.BulletImage));

        Pause = new Sprite(ImageUtil.getImage(GameRef.bsIO.getURL(GameConstants.PauseImage),Color.WHITE));
        Pause.move(GameRef.getWidth()/2 - Pause.getWidth()/2 , GameRef.getHeight()/2 - Pause.getHeight());

        //Creating collision groups
        terrainCollisionHandler = new TerrainCollision();
        assetCollisionHandler = new AssetCollision();
        exitCollisionHandler = new DoorCollision();
        problemCollisionGroup = new ProblemCollisionGroup();
        playerShotCollisionGroup = new PlayerShotCollision();
        enemyShotCollisionGroup = new EnemyShotCollision();
        blockableCollisionGroup = new ProblemCollisionGroup();
        enemyBlockableCollisionGroup = new ProblemCollisionGroup();
        playerShotBlockableCollisionGroup = new PlayerShotCollision();

        if (Hero == null)
        {
            LoadHero();
        }
        else
        {
            Hero.resetMudTimer();//Forgot this =/
            if(PlayerGroup != null)
                PlayerGroup.remove(Hero);
        }

        Hero.setLocation(PlayerConstants.PlayerStartX, GameConstants.AssetY - Hero.getHeight());
       
        Hero.forceX(PlayerConstants.PlayerStartX);
        Hero.forceY(GameConstants.AssetY - Hero.getHeight());

        //Creating groups
        PlayerGroup = new SpriteGroup("Player Group");
        PlayerShotsGroup = new SpriteGroup("Player Shots Group");
        EnemyShotsGroup = new SpriteGroup("Enemy Shots Group");
        SceneObjects = new SpriteGroup("Scene Objects");
        EnemyGroup = new SpriteGroup("Enemy Group");
        UIElementsGroup = new SpriteGroup("UI Elements");
        DoorExitGroup = new SpriteGroup("Exit Door");
        BlockableGroup = new SpriteGroup("Blockable Group");

        Sprite ExitDoor = new Sprite(GameRef.getImage(GameConstants.GameDoor));
        ExitDoor.setLocation(649 + 0.5*GameConstants.AssetBlockSize, GameConstants.AssetY - ExitDoor.getHeight());

        DoorExitGroup.add(ExitDoor);

        PlayerGroup.setBackground(GameBackground);
        PlayerShotsGroup.setBackground(GameBackground);
        EnemyShotsGroup.setBackground(GameBackground);
        SceneObjects.setBackground(GameBackground);
        EnemyGroup.setBackground(GameBackground);
        DoorExitGroup.setBackground(GameBackground);
        UIElementsGroup.setBackground(GameBackground);
        BlockableGroup.setBackground(GameBackground);

        //Adding HeroSprites to player group
        PlayerGroup.add(Hero);
        UIElementsGroup.add(Ammo);
        UIElementsGroup.add(Clock);
        Clock.move(GameConstants.ClockPositionX - Clock.getWidth(), GameConstants.ClockPositionY);
        Ammo.move(GameConstants.UIElementsStartX + GameRef.LittleFont.getWidth(GameConstants.AmmoString),
                GameConstants.UIElementsStartY + 75);

        double XPos = GameRef.LittleFont.getWidth(GameConstants.LivesString) + GameConstants.UIElementsStartX;

        //Populating life bar
        for (int i = 0; i < Lives.length; i++)
        {
            Lives[i] = new Sprite(GameRef.getImage(GameConstants.LifeSprite));
            Lives[i].setImmutable(true);
            Lives[i].move( XPos, GameConstants.UIElementsStartY - 10);
            XPos += Lives[i].getWidth();
            UIElementsGroup.add(Lives[i]);
        }

        XPos = GameRef.LittleFont.getWidth(GameConstants.HealthString) + GameConstants.UIElementsStartX;

        //Populating health bar
        for (int i = 0; i < HealthBar.length; i++)
        {
            HealthBar[i] = new Sprite(GameRef.getImage(GameConstants.HealthSprite));
            HealthBar[i].setImmutable(true);
            HealthBar[i].move(XPos, GameConstants.UIElementsStartY + 33);
            XPos += HealthBar[i].getWidth() + 2;
            UIElementsGroup.add(HealthBar[i]);
        }

        //Adding SceneObjects to SceneObjectsGroup
        for (int i = 0; i < TrashInBaskets.length; i++)
        {
            switch (TrashInBaskets[i])
            {
                case GlassBonus:
                    Potion newPotion = new Potion(
                            ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetGlassBonus),
                            1, 1, Color.WHITE), 0, 0, Hero, this.GameRef);
                    newPotion.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - newPotion.getWidth(),
                            GameConstants.AssetY - newPotion.getHeight());
                    newPotion.setFrame(0);
                    newPotion.setActive(true);
                    SceneObjects.add(newPotion);
                    break;

                case GlassProblem:
                    GlassWall newGlassWall = new GlassWall(
                            ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetGlassProblem),
                            2, 1, Color.WHITE), 0, 0, Hero, ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetGlassBroken),
                            2, 1, Color.WHITE), this.GameRef);
                    newGlassWall.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - 0.5*newGlassWall.getWidth(),
                            GameConstants.AssetY - newGlassWall.getHeight());
                    newGlassWall.setFrame(0);
                    newGlassWall.setActive(true);
                    //EnemyGroup.add(newGlassWall);
                    BlockableGroup.add(newGlassWall);
                    break;

                case MetalBonus:
                    Coin newCoin = new Coin(
                            ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetMetalBonus),
                            1, 1, Color.WHITE), 0, 0, Hero, GameRef);
                    newCoin.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - 0.5*newCoin.getWidth(),
                            GameConstants.AssetY - newCoin.getHeight());
                    newCoin.setFrame(0);
                    newCoin.setActive(true);
                    SceneObjects.add(newCoin);
                    break;

                case MetalProblem:
                    Spikes newSpike = new Spikes(ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetMetalProblem),
                            1, 1, Color.WHITE),0, 0, Hero);
                    newSpike.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - 0.5*newSpike.getWidth(),
                            GameConstants.AssetY - newSpike.getHeight());
                    newSpike.setFrame(0);
                    newSpike.setActive(true);
                    //EnemyGroup.add(newSpike);
                    BlockableGroup.add(newSpike);
                    break;

                case OrganicBonus:
                    Apple newApple = new Apple(ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetOrganicBonus),
                            1, 1, Color.WHITE),0, 0, Hero, GameRef);
                    newApple.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - 0.5*newApple.getWidth(),
                            GameConstants.AssetY - newApple.getHeight());
                    newApple.setFrame(0);
                    newApple.setActive(true);
                    SceneObjects.add(newApple);
                    break;

                case OrganicProblem:
                    Mud newMud = new Mud(
                            ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetOrganicProblem),
                            1, 1, Color.WHITE), 0, 0, Hero);
                    newMud.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - 0.5*newMud.getWidth(),
                            GameConstants.AssetY - newMud.getHeight());
                    newMud.setFrame(0);
                    newMud.setActive(true);
                    EnemyGroup.add(newMud);
                    break;

                case PlasticBonus:
                    Gun newGun = new Gun (
                            ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetPlasticBonus),
                            1, 1, Color.WHITE), 0, 0, Hero, this.GameRef);
                    newGun.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - newGun.getWidth(),
                            GameConstants.AssetY - newGun.getHeight());
                    newGun.setFrame(0);
                    newGun.setActive(true);
                    SceneObjects.add(newGun);
                    break;

                case PlasticProblem:
                    Robot newRobot = new Robot(
                            ImageUtil.getImages(GameRef.bsIO.getURL(GameConstants.GameAssetPlasticProblem),
                            2, 1, Color.WHITE), 0, 0, Hero, GameConstants.RobotHealth, this.GameRef);
                    newRobot.setLocation(
                            GameConstants.AssetOneX + (i)*GameConstants.AssetBlockSize + 0.5*GameConstants.AssetBlockSize - newRobot.getWidth(),
                            GameConstants.AssetY - newRobot.getHeight());
                    newRobot.setActive(true);
                    EnemyGroup.add(newRobot);
                    break;

                default:
                    break;
            }//switch
        }//for

        GameField.addCollisionGroup(RecyclableBinGroup, PlayerGroup, terrainCollisionHandler);
        GameField.addCollisionGroup(EnemyGroup, PlayerGroup, problemCollisionGroup);
        GameField.addCollisionGroup(BlockableGroup, PlayerGroup, blockableCollisionGroup);
        GameField.addCollisionGroup(PlayerShotsGroup, EnemyGroup, playerShotCollisionGroup);
        GameField.addCollisionGroup(EnemyShotsGroup, PlayerGroup, enemyShotCollisionGroup);
        GameField.addCollisionGroup(BlockableGroup, EnemyGroup, enemyBlockableCollisionGroup);
        GameField.addCollisionGroup(PlayerShotsGroup, BlockableGroup, playerShotBlockableCollisionGroup);
        GameField.addCollisionGroup(SceneObjects, PlayerGroup, assetCollisionHandler);
        GameField.addCollisionGroup(DoorExitGroup, PlayerGroup, exitCollisionHandler);
       
        GameField.setBackground(GameBackground);

        //This order influences the element drawing order
        GameField.addGroup(PlayerGroup);
        GameField.addGroup(PlayerShotsGroup);
        GameField.addGroup(EnemyShotsGroup);
        GameField.addGroup(BlockableGroup);
        GameField.addGroup(SceneObjects);
        GameField.addGroup(RecyclableBinGroup);
        GameField.addGroup(DoorExitGroup);
        GameField.addGroup(EnemyGroup); //So, enemies are drawn in front of the door
        GameField.addGroup(UIElementsGroup);

        //gameTimer.setActive(true);
        //gameTimer.refresh();
        bananaGameTimer.startTimer();
    }

    /**
     * Releases the resources needed to run the platform part of the game
     */
    private void UnloadPlatformState()
    {
        Pause = null;
        //gameTimer.setActive(false);
        bananaGameTimer.resetTimer();
        OldState = InGameState.PlatformState;

        //As images remain stored until removed, the flip remains as well
        //This is needed to avoid having a flipped image being used after
        //the game was canceled. Using a spritesheet with flipped images and
        //properly using AdvanceSprite should solve this properly.
        //GameRef.bsLoader.removeImages(HeroSpriteSheet);

        Hero.turnOffInvincibility();
        GameField.clearPlayField();
    }
   
    /**
     * Loads the resources needed to run the puzzle part of the game
     */
    private void LoadPuzzleState()
    {
        try
        {
            //Initializes GameField
            GameField = new PlayField(GameBackground);
           
            //Generating random column order
            ColumnOrder = new LinkedList<Column>();
            ColumnOrder.add(Column.First);
            ColumnOrder.add(Column.Second);
            ColumnOrder.add(Column.Third);
            ColumnOrder.add(Column.Fourth);
            Collections.shuffle(ColumnOrder);

            Baskets = GenerateRandomPositions();
            TrashInBaskets = new RecyclableFeature[GameConstants.NumberofBlocks];
            RecyclableBinGroup = new SpriteGroup("RecyclableBins");
            ResultGroup = new SpriteGroup("Results");
            //ResultGroup.setBackground(GameBackground);
            terrainCollisionHandler = new TerrainCollision();

            ActiveBlock = 0;

            //Adding the platforms firstly, for the blocks will appear in front of them
            RecyclableBinGroup.add(new Sprite(GameRef.getImage(GameConstants.GameAssetStart),
                GameConstants.AssetStartX,GameConstants.AssetY));
            RecyclableBinGroup.add(new Sprite(GameRef.getImage(GameConstants.GameAssetStart),
                650,GameConstants.AssetY));

            for (int i = 0; i < Baskets.size(); i++)
            {
                switch (Baskets.get(i))
                {
                    case Glass:
                        RecyclableBinGroup.add(new Sprite(GameRef.getImage(GameConstants.GameAssetGlass),
                            GameConstants.AssetOneX+(i)*GameConstants.AssetBlockSize,GameConstants.AssetY));
                        break;
                    case Metal:
                        RecyclableBinGroup.add(new Sprite(GameRef.getImage(GameConstants.GameAssetMetal),
                            GameConstants.AssetOneX+(i)*GameConstants.AssetBlockSize,GameConstants.AssetY));
                        break;
                    case Organic:
                        RecyclableBinGroup.add(new Sprite(GameRef.getImage(GameConstants.GameAssetOrganic),
                            GameConstants.AssetOneX+(i)*GameConstants.AssetBlockSize,GameConstants.AssetY));
                        break;
                    case Plastic:
                        RecyclableBinGroup.add(new Sprite(GameRef.getImage(GameConstants.GameAssetPlastic),
                            GameConstants.AssetOneX+(i)*GameConstants.AssetBlockSize,GameConstants.AssetY));
                        break;
                }//switch

            }//for

            RecyclableBinGroup.setBackground(GameBackground);
            ResultGroup.setBackground(GameBackground);
            GameField.addGroup(RecyclableBinGroup);
            //GameField.addGroup(ResultGroup);

            //Initializes blocksOk
            blocksOk = new boolean[GameConstants.NumberofBlocks];
            blocksOk[0] = false;
            blocksOk[1] = false;
            blocksOk[2] = false;
            blocksOk[3] = false;

            //Old code is kept here if rotate seems to be inefficient
            //
            //BufferedImage Block1 = new BufferedImage(BlockImage.getWidth(), BlockImage.getHeight(),
            //        BufferedImage.TYPE_4BYTE_ABGR_PRE);
            ////This writes BlockImage to Block1 buffer
            //Block1.createGraphics().drawImage(BlockImage, 0, 0, null);

            BufferedImage Block = GameRef.bsLoader.getImage(GameConstants.Block);

            Blocks = new Block[GameConstants.NumberofBlocks];
            Blocks[0] = new Block(Block);
            Blocks[1] = new Block(Block);
            Blocks[2] = new Block(Block);
            Blocks[3] = new Block(Block);

            Random rand = new Random(); //Initialized with seed = currentTime (as of Java2 SE 1.4.2)
            int rots;

            //Randomizing blocks starting position
            for (int i = 0; i < GameConstants.NumberofBlocks; i++)
            {
                rots = rand.nextInt()%GameConstants.NumberofBlocks;

                //rotates the block rots times
                for(int j = 0; j < rots; j++)
                {
                  Blocks[i].RotateCounterClockWise();
                }
            }

            BlocksGroup = new SpriteGroup("Blocks");
            BlocksGroup.add(Blocks[0]);
            BlocksGroup.add(Blocks[1]);
            BlocksGroup.add(Blocks[2]);
            BlocksGroup.add(Blocks[3]);

            BlocksGroup.setBackground(GameBackground);
            BlocksGroup.setActive(true);

            //Must be set to Immutable, or when setActive to false, will be disposed
            //When Immutable == true, can only be disposed by SpriteGroup
            Blocks[0].setImmutable(true);
            Blocks[1].setImmutable(true);
            Blocks[2].setImmutable(true);
            Blocks[3].setImmutable(true);

            Blocks[0].setActive(false);
            Blocks[1].setActive(false);
            Blocks[2].setActive(false);
            Blocks[3].setActive(false);

            Blocks[ActiveBlock].setActive(true);
            Blocks[ActiveBlock].SetColumn(ColumnOrder.poll());
            Blocks[ActiveBlock].move(ConvertColumnToCoordinate(Blocks[ActiveBlock].GetColumn()), 0);

            GameField.addCollisionGroup(RecyclableBinGroup, BlocksGroup, terrainCollisionHandler);
            GameField.addGroup(BlocksGroup);
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
   
    /**
     * Releases the resources needed to run the puzzle part of the game
     */
    private void UnloadPuzzleState() {
        //Removes so this isn't cleared by clear playfield
        OldState = InGameState.PuzzleState;
        GameField.removeGroup(RecyclableBinGroup);
        GameField.removeGroup(ResultGroup);
        ResultGroup.clear();
        GameField.clearPlayField();
    }

    /**
     * Generates a list of unique Recyclables in random order
     * @return ArrayList containing the numbers in random order
     */
    private ArrayList<Recyclables> GenerateRandomPositions ()
    {
        ArrayList<Recyclables> baskets = new ArrayList<Recyclables>();

        baskets.add(Recyclables.Glass);
        baskets.add(Recyclables.Metal);
        baskets.add(Recyclables.Organic);
        baskets.add(Recyclables.Plastic);

        Collections.shuffle(baskets);
        return baskets;
    }

   
    /**
     * Convert column enumerate to world coordinates
     * @param col
     * @return
     */
    private double ConvertColumnToCoordinate ( Column col )
    {
        switch(col)
        {
            case First:
                return GameConstants.AssetOneX + 1;

            case Second:
                return GameConstants.AssetOneX + 1 + GameConstants.AssetBlockSize;
               
            case Third:
                return GameConstants.AssetOneX + 1 + 2*GameConstants.AssetBlockSize;
           
            case Fourth:
                return GameConstants.AssetOneX + 1 + 3*GameConstants.AssetBlockSize;
               
            default:
                return GameConstants.AssetOneX;
        }//switch
    }
   
    /**
     * Convert passed index to Column equivalent
     * @param i
     * @return
     * @throws Exception
     */
    private Column ConvertIndexToColumn(int i) throws Exception
    {
        switch (i)
        {
            case 0:
                return Column.First;
            case 1:
                return Column.Second;
            case 2:
                return Column.Third;
            case 3:
                return Column.Fourth;
            default:
                throw new Exception("Invalid index to column convertion");
        }
    }

    private BufferedImage[] LoadPlayerSpriteSheet() {
        BufferedImage[] spritesheet = new BufferedImage[PlayerConstants.SpriteSheetImages];

        for (int i = 0; i < PlayerConstants.SpriteSheetImages; i++)
        {
            spritesheet[i] = GameRef.getImage("resources/images/character/banana" + (i+1) + ".png", true);
        }

        return spritesheet;
    }

    private void ResetPlayerOnDeath()
    {
        Hero.setHealth(PlayerConstants.StartingHealth);
        Hero.removeGun();
    }

    private void LoadGameOverState() {
        try
        {
            GameField = new PlayField(new ImageBackground(
                    GameRef.getImage(GameConstants.GameOverScreen)));

            GameRef.bsMusic.stopAll();

            if(GameRef.GetSoundState())
                GameRef.bsSound.play(SoundStrings.GameOver);

            gameOverTimer.setActive(true);
            gameOverTimer.refresh();
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }

    private void UnloadGameOverState()
    {
        GameField.clearPlayField();
        gameOverTimer.setActive(false);
    }

    private void InterfaceRender(Graphics2D g) {
        int NextLine = GameRef.LittleFont.drawText(g, GameConstants.LivesString, GameFont.LEFT,
                        GameConstants.UIElementsStartX, GameConstants.UIElementsStartY , GameRef.LittleFont.getWidth(GameConstants.LivesString), 0, 0);
        NextLine = GameRef.LittleFont.drawText(g, GameConstants.HealthString, GameFont.LEFT,
                GameConstants.UIElementsStartX, NextLine, GameRef.LittleFont.getWidth(GameConstants.HealthString), 0, 0);
        GameRef.LittleFont.drawText(g, GameConstants.AmmoString, GameFont.LEFT,
                GameConstants.UIElementsStartX, NextLine, 400, 0, 0);
        GameRef.LittleFont.drawText(g, " x " + Hero.getAmmo(), GameFont.LEFT,
                GameConstants.UIElementsStartX + Ammo.getWidth() +
                GameRef.LittleFont.getWidth(GameConstants.AmmoString), NextLine, 400, 0, 0);

        NextLine = GameRef.LittleFont.drawText(g, "Stage: " + Stage, GameFont.LEFT,
                GameRef.getWidth() - GameRef.LittleFont.getWidth("Stage: " + Stage) - 20, GameConstants.UIElementsStartY, 400, 0, 0);
        NextLine = GameRef.LittleFont.drawText(g, "Score: " + Hero.getScore(), GameFont.LEFT,
                GameRef.getWidth() - GameRef.LittleFont.getWidth("Score: " + Hero.getScore()) - 20, NextLine, 400, 0 ,0);

        time = "" + (int)(((long)GameConstants.ClockTimer - bananaGameTimer.getTimePast())/1000);

        //As time may not be set already when game starts, this could throw an NumberFormatException
        try
        {
            if (Integer.parseInt(time) < 10)
            {
                time = "0" + time;
            }
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }

        if (GameState != InGameState.PausedState)
            GameRef.BigFont.drawText(g, "0:" + time, GameFont.CENTER,
                (int)Clock.getX(), (int) (Clock.getY() - 60), 200, 0, 0);

        //Prints INVINCIBLE on screen
        if(Hero.getInvincibleDueToPotion())
        {
            Invincible.render(g);
            //GameRef.BigFont.drawText(g, GameConstants.Invincible, GameFont.LEFT,
            //    GameConstants.InvincibleX, GameConstants.InvincibleY, 400, 0, 0);
            //System.out.println(NextLine+30);
        }
    }

    /**
     * This method is necessary to free resources from JVM. As of 2010/08/23, we're getting
     * numerous memory leaks due to references not being freed
     */
    private void FreeResources() {

        //Before GC
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();

        System.out.println("free memory: " + freeMemory / 1024);
        System.out.println("allocated memory: " + allocatedMemory / 1024);
        System.out.println("max memory: " + maxMemory /1024);
        System.out.println("total free memory: " + (freeMemory + (maxMemory - allocatedMemory)) / 1024);

        OldState = null;
        GameState = null;

        if (GameField != null)
        {
            GameField.clearCache();
            GameField.clearPlayField();
            GameField = null;
        }

        if (PlayerGroup != null)
        {
            PlayerGroup.clear();
            PlayerGroup = null;
        }

        if (PlayerShotsGroup != null)
        {
            PlayerShotsGroup.clear();
            PlayerShotsGroup = null;
        }

        if (EnemyShotsGroup != null)
        {
            EnemyShotsGroup.clear();
            EnemyShotsGroup = null;
        }

        if (SceneObjects != null)
        {
            SceneObjects.clear();
            SceneObjects = null;
        }

        if (EnemyGroup != null)
        {
            EnemyGroup.clear();
            EnemyGroup = null;
        }

        if (BlocksGroup != null)
        {
            BlocksGroup.clear();
            BlocksGroup = null;
        }

        if (RecyclableBinGroup != null)
        {
            RecyclableBinGroup.clear();
            RecyclableBinGroup = null;
        }

        if (UIElementsGroup != null)
        {
            UIElementsGroup.clear();
            UIElementsGroup = null;
        }

        if (BlockableGroup != null)
        {
            BlockableGroup.clear();
            BlockableGroup = null;
        }

        if (DoorExitGroup != null)
        {
            DoorExitGroup.clear();
            DoorExitGroup = null;
        }

        if (ResultGroup != null)
        {
            ResultGroup.clear();
            ResultGroup = null;
        }


        if (Baskets != null)
        {
            Baskets.clear();
            Baskets = null;
        }

        if (TrashInBaskets != null)
        {
            for(int i = 0; i < TrashInBaskets.length; i++)
                TrashInBaskets[i] = null;
            TrashInBaskets = null;
        }

        Hero = null;

        if (Lives != null)
        {
            for(int i = 0; i < Lives.length; i++)
                Lives[i] = null;
            Lives = null;
        }

        if (HealthBar != null)
        {
            for(int i = 0; i < HealthBar.length; i++)
                HealthBar[i] = null;
            HealthBar = null;
        }

        if (Blocks != null)
        {
            for(int i = 0; i < Blocks.length; i++)
                Blocks[i] = null;
            Blocks = null;
        }

        Pause = null;
        Clock = null;
        Ammo = null;
        MatchColors = null;
        GameBackground = null;

        if(ColumnOrder != null)
        {
            ColumnOrder.clear();
            ColumnOrder = null;
        }

        terrainCollisionHandler = null;
        assetCollisionHandler = null;
        exitCollisionHandler = null;
        problemCollisionGroup = null;
        blockableCollisionGroup = null;
        enemyBlockableCollisionGroup = null;
        playerShotCollisionGroup = null;
        playerShotBlockableCollisionGroup = null;
        enemyShotCollisionGroup = null;

        gameOverTimer = null;
        gameTimer = null;
        cutsceneTimer = null;
        endgameTimer = null;
        bananaGameTimer = null;
        time = null;

        if (cutsceneScreens != null)
        {
            cutsceneScreens.clear();
            cutsceneScreens = null;
        }

        Invincible = null;
        Perfect = null;
    }

    /**
     * Advances one stage, updating GameState and loading assets relative to
     * the next stage. Must unload previous state before calling.
     * @param advancePuzzle True if must advance to a puzzle stage
     */
    private void AdvanceStage(boolean advancePuzzle) {
        ++Stage;
        dropVelocity += GameConstants.BlockAcceleration*Stage*0.15;
        if (Stage > GameConstants.EndStage )
        {
            LoadEndGameState();
            GameState = InGameState.EndScene;
        }
        //Cutscene check, every stage divisible by 5
        else if(Stage % GameConstants.CutsceneStageModulo == 0)
        {
            GameState = InGameState.Cutscene;
            LoadCutsceneState();  
        }
        else if (advancePuzzle)
        {
            GameState = InGameState.PuzzleState;
            LoadPuzzleState();
        }
        else{
            GameState = InGameState.PlatformState;
            LoadPlatformState();
        }
    }

    /**
     * This class provides methods that handle collision between the terrain and something else,
     * for example the character
     */
    private class TerrainCollision extends CollisionGroup {

        public TerrainCollision () {
            // Check on pixels.
            pixelPerfectCollision = true;
        }

        @Override
        public void collided (Sprite one, Sprite two) {
            if (two instanceof Player)
            {
                //handleCollision(one, two);
                if (collisionSide == TOP_BOTTOM_COLLISION)
                {
                    two.moveY(two.getOldY() - two.getY());
                    ((Player)two).setOnGround ();
                }
            }
            else
            {
                if (two instanceof Block)
                {
                    blockCollision(two);
                }//if
            }//if
        }
    }

    private void LoadEndGameState()
    {
        GameField.clearPlayField();
        Stage--; //Just to not write something weird at the score
        GameField.setBackground(new ImageBackground(GameRef.getImage(GameConstants.EndGameImage)));
        GameRef.bsMusic.stopAll();
        if(GameRef.GetMusicState())
            GameRef.bsMusic.play(GameConstants.GameEndMusic);
        endgameTimer.setActive(true);
        endgameTimer.refresh();
    }

    private void LoadCutsceneState() {
        cutsceneTimer.setActive(true);
        cutsceneTimer.refresh();
        cutsceneIndex = ++cutsceneIndex%(GameConstants.Cutscenes-1);
        GameField = new PlayField(new ImageBackground(cutsceneScreens.get(cutsceneIndex)));
    }

    /**
     * Provides methods to handle collison between player and Items
     */
    private class AssetCollision extends BasicCollisionGroup
    {
        public AssetCollision () {
            // Check on pixels.
            pixelPerfectCollision = true;
        }

        @Override
        public void collided(Sprite s1, Sprite s2) {
            if (s2 instanceof Player && s1 instanceof SceneObject)
            {
                //System.out.println("Player collided with SceneObject");
                SceneObject item = (SceneObject)s1;
                item.OnCollision();
                //System.out.println(Hero.getScore());
            }//if
        }

    }

    private class PlayerShotCollision extends BasicCollisionGroup
    {
        public PlayerShotCollision () {
            // Check on pixels.
            pixelPerfectCollision = true;
        }

        @Override
        public void collided(Sprite s1, Sprite s2) {
            if(s1 instanceof Bullet)
            {
                //System.out.println("Bullet collided");
                ((Bullet)s1).OnCollision(s2);
            }
        }
    }

    private class EnemyShotCollision extends BasicCollisionGroup
    {
        public EnemyShotCollision () {
            // Check on pixels.
            pixelPerfectCollision = true;
        }

        @Override
        public void collided(Sprite s1, Sprite s2) {
            if(s1 instanceof Bullet)
            {
                //System.out.println("Bullet collided");
                ((Bullet)s1).OnCollision(s2);
            }
        }
    }

    private class DoorCollision extends BasicCollisionGroup
    {

        public DoorCollision () {
            // Check on pixels.
            pixelPerfectCollision = true;
        }

        @Override
        public void collided(Sprite s1, Sprite s2) {
            if (s2 instanceof Player)
            {
                try
                {
                    int slot;
                    BaseAudioRenderer test = null;
                    if(GameRef.GetSoundState())
                    {
                        slot = GameRef.bsSound.play(SoundStrings.DoorExit, BaseAudio.SINGLE);
                        test = GameRef.bsSound.getAudioRenderer(slot);

                        /**
                         * @TODO: This doesn't work in Linux. Why???
                         * I think it depends on JVM implementation and if System
                         * is 64 or 32 bit
                         */
//                        while (test.getStatus() != BaseAudioRenderer.END_OF_SOUND)
//                        {
//                            //Waits for audio file to finish before loading
//                        }//while
                       
                        // wait for 1 second
                        Thread.sleep(1000L);
                    }//if
                }
                catch (Exception e)
                {
                    System.out.println(e.getMessage());
                }

                GameField.removeGroup(PlayerGroup);
                UnloadPlatformState();

                AdvanceStage(true);
            }//if
        }
    }

    /**
     * Group collision that deals with Recyclables Problems collision
     */
    private class ProblemCollisionGroup extends CollisionGroup
    {

        public ProblemCollisionGroup() {
            pixelPerfectCollision = true;
        }


        @Override
        public void collided(Sprite s1, Sprite s2) {
            if(s2 instanceof Player || s2 instanceof Robot)
            {
                //System.out.println("Player collided");
                if (!(s1 instanceof Mud))
                {
                    switch (collisionSide)
                    {
                        case BOTTOM_TOP_COLLISION:
                            //Not tested
                            //System.out.println("BOTTOM TOP COLLISION");
                            //s2.moveY((collisionY1 + s1.getHeight() - collisionY2));
                            s2.moveY(s2.getOldY() + s2.getY());
                            break;
                           
                        case TOP_BOTTOM_COLLISION:
                            //PORTAL!!! s2.moveY(-(collisionY2 + s2.getHeight() + collisionY1));
                            //s2.moveY(-(collisionY2 + s2.getHeight() - collisionY1));
                            s2.moveY(s2.getOldY() - s2.getY());

                            if(s2 instanceof Player)
                            {
                                ((Player)s2).setOnGround();
                               
                                if (s1 instanceof GlassWall)
                                {
                                    //System.out.println(collisionSide);
                                    ((GlassWall)s1).OnCollision();
                                }
                                else if (s1 instanceof Robot)
                                {
                                    ((Robot)s1).OnCollision();
                                }
                                else if (s1 instanceof Spikes)
                                {
                                    ((Spikes)s1).OnCollision();
                                }
                            }

                            break;

                        case LEFT_RIGHT_COLLISION:
                            //s2.moveX((collisionX1 - (collisionX2 + s2.getWidth())));

                            if (s1 instanceof Spikes && s2 instanceof Player)
                                s2.setX(s2.getOldX());
                            else
                                s2.moveX((collisionX1 - (collisionX2 + s2.getWidth())));
                           
                            //Treats collision with left border
                            if (s2.getX() < 0)
                            {
                                s2.moveX(-s2.getX()); //I think this is unaccurate
                            }//if

                            if(s2 instanceof Player)
                            {
                                if (s1 instanceof Robot)
                                {
                                    ((Robot)s1).OnCollision();
                                }
                            }

                            break;

                        case RIGHT_LEFT_COLLISION:
                            //OK
                            //System.out.println("RIGHT LEFT COLLISION");
                            //s2.moveX(-(collisionX2 - s1.getWidth() - collisionX1));
                            if (s1 instanceof Spikes && s2 instanceof Player)
                                s2.setX(s2.getOldX());
                            else
                                s2.moveX(-(collisionX2 - s1.getWidth() - collisionX1));

                            //treats collision with screen right border
                            if (s2.getX() + s2.getWidth() > GameRef.getWidth())
                            {
                                s2.moveX(GameRef.getWidth() - (s2.getX() + s2.getWidth()));
                            }//if

                            if(s2 instanceof Player)
                            {
                                if (s1 instanceof Robot)
                                {
                                    ((Robot)s1).OnCollision();
                                }
                            }

                            break;
                    }//switch
                }
                else
                {
                    if (s2 instanceof Player)
                    {
                        //System.out.println("Bananixo collided with Mud");
                        ((Mud)s1).OnCollision();
                    }
                }//if
            }//if
        }
    }

    private void LoadHero()
    {
        Hero = new Player(HeroSpriteSheet,PlayerConstants.PlayerStartX, PlayerConstants.PlayerStartY,
                    PlayerConstants.StartingLives, PlayerConstants.StartingHealth, PlayerConstants.StartingAmmo, PlayerConstants.StartWithGun,
                    GameRef);
        Hero.setImmutable(true);
        Hero.setAnimationFrame(PlayerConstants.WalkAnimation);
        Hero.getAnimationTimer().setDelay(300); //In milliseconds
        Hero.setAnimate(true);
        Hero.setLoopAnim(true);
    }

    public void RemoveRobotFromCollision(Robot myself)
    {
        EnemyGroup.remove(myself);
        UIElementsGroup.add(myself);//Well, this is ugly, but may work
    }
}
TOP

Related Classes of LixoGame.GameManager$ProblemCollisionGroup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.