public class DreamsGame extends BaseGame {

    public static boolean DEBUG = false;
    public static FPSLogger log;

    @Override
    public void create() {
        Gdx.input.setCatchBackKey(true);
        resourcesManager =new ResourcesManager();
        preferencesManager = PreferencesManager.instance;
        profileManager= new ProfileManager();
        levelManager=new LevelManager(this);
        audioManager =new AudioManager(this);

        log = new FPSLogger();
        setGameState(GameState.GAME_SHOW_SPLASH);
    }

    @Override
    public void dispose() {
        super.dispose();
    }

    @Override
    public void render() {
        super.render();
        log.log();
    }

    @Override
    public void resize(int width, int height) {
        super.resize(width, height);
    }

    @Override
    public void pause() {
        super.pause();
    }

    @Override
    public void resume() {
        super.resume();
    }

} public class Constants {

    public static final float WORLD_HEIGHT = 16.875f; // 1080 / 64 =16.875 px
    public static final float WORLD_WIDTH = 30f;     //  1920 / 64 = 30f px

    public static final float VIRTUAL_HEIGHT = 1080f; // 16.875 x 64 =1080 px
    public static final float VIRTUAL_WIDTH = 1920f;     //  30 x 64 = 1920 px
    // Box2D config
    public static final float RUNNING_FRAME_DURATION = 0.02f;
    public static final int VELOCITY_ITERATIONS = 10;
    public static final int POSITION_ITERATIONS = 8;
    // Game attributes
    public static final String VERSION = "0.3 Alpha";
    public static final String LOG = "Hero Dreams";
    // Preferences
    public static final String PREFS_NAME = "DreamsGame";
    public static final String PREF_VOLUME_SOUND = "volume.music";
    public static final String PREF_VOLUME_MUSIC = "volume.sound";
    public static final String PREF_MUSIC_ENABLED = "music.enabled";
    public static final String PREF_SOUND_ENABLED = "sound.enabled";
    public static final String PREF_TOUCHPAD_ENABLED = "touchpad.enabled";
    // Profile
    public static final String PROFILE_DATA_FILE = "data/profile.game";
    public static final String INIT_PROFILE_DATA_FILE = "data/initProfile.game";

    //Name elements GUI STATS
    public static final String LABEL_SCORE= "Puntuacion";
    public static final String SCORE= "Score";
    public static final String IMAGE_LIVES= "ImageLives";
    public static final String LIVES= "Lives";

    // Name World Events
    public static final int COLLET_COIN = 1;
} public enum GameState {
    GAME_RUNNING,
    GAME_PAUSED,
    GAME_UPDATE,
    GAME_OVER,
    GAME_WIN,
    GAME_LEVELWIN,
    GAME_IDLE,
    GAME_SLOWMOTION,
    GAME_BACK,
    SCREEN_TRANSITION,
    GAME_EXIT ,
    GAME_SHOW_MENU,
    GAME_SHOW_SCORE,
    GAME_SHOW_LEVEL_MENU,
    GAME_SHOW_SPLASH,
    GAME_SHOW_OPTIONS, GAME_SHOW_HIGHSCORES, GAME_SHOW_GAME;
} public class WorldController implements ContactListener, ContactFilter ,Disposable{

    private World world;
    private HeroManager heroManager;
    private PlatformManager platformManager;
    private WaterManager waterManager;
    private EnemyManager enemyManager;
    private ItemsManager itemsManager;
    private CheckPointManager checkPointManager;
    private List<Box2DPhysicsObject> destroy=new ArrayList<Box2DPhysicsObject>();

    public static java.util.Map<WorldController.Keys, Boolean> keys = new java.util.HashMap<WorldController.Keys, Boolean>();

    static {
        keys.put(WorldController.Keys.LEFT, false);
        keys.put(WorldController.Keys.RIGHT, false);
        keys.put(WorldController.Keys.JUMP, false);
        keys.put(WorldController.Keys.FIRE, false);
    }

    public static enum Keys {
        LEFT, RIGHT, JUMP, FIRE
    }


    public WorldController(DreamsGame game, World world) {
        this.world=world;
        world.getPhysics().setContactListener(this);
        heroManager = new HeroManager();
        platformManager = new PlatformManager();
        waterManager = new WaterManager();
        enemyManager = new EnemyManager();
        itemsManager= new ItemsManager();
        checkPointManager = new CheckPointManager();

        itemsManager.addObserver(game.getProfileManager());
        itemsManager.addObserver(game.getAudioManager());
        heroManager.addObserver(game.getProfileManager());
        heroManager.addObserver(game.getAudioManager());

    }

    public void leftPressed() {
        keys.get(keys.put(WorldController.Keys.LEFT, true));
    }

    public void rightPressed() {
        keys.get(keys.put(WorldController.Keys.RIGHT, true));
    }

    public void jumpPressed() {
        keys.get(keys.put(WorldController.Keys.JUMP, true));
    }

    public void firePressed() {
        keys.get(keys.put(WorldController.Keys.FIRE, true));
    }

    public void leftReleased() {
        keys.get(keys.put(WorldController.Keys.LEFT, false));
    }

    public void rightReleased() {
        keys.get(keys.put(WorldController.Keys.RIGHT, false));
    }

    public void jumpReleased() {
        keys.get(keys.put(WorldController.Keys.JUMP, false));
        //jumpingPressed = false;
    }

    public void fireReleased() {
        keys.get(keys.put(WorldController.Keys.FIRE, false));
    }

    /**
     * The main update method *
     */
    public void update(float delta) {
        for(Box2DPhysicsObject e: world.getEntities()) {
            if (e.getState().equals(Box2DPhysicsObject.BaseState.DESTROY)){
                destroy.add(e);
            } else {
                AbstractWorldManager manager =getManager(e.getGrupo());
                if(manager!=null) manager.update(delta,e);
            }
        }
        for(Box2DPhysicsObject d:destroy){
            Gdx.app.log(Constants.LOG,"Destroy entity :" + d.getGrupo());
            world.destroyEntity(d);
        }
        destroy.clear();

        world.getPhysics().step(delta, Constants.VELOCITY_ITERATIONS, Constants.POSITION_ITERATIONS);
    }

    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {
        contact.resetFriction();
        AbstractWorldManager managerA=getManager(((Box2DPhysicsObject) contact.getFixtureA().getUserData()).getGrupo());
        AbstractWorldManager managerB=getManager(((Box2DPhysicsObject) contact.getFixtureB().getUserData()).getGrupo());

        if(managerA!=null) managerA.handlePreSolve(contact, oldManifold);
        if(managerB!=null) managerB.handlePreSolve(contact, oldManifold);
    }

    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {
        AbstractWorldManager managerA=getManager(((Box2DPhysicsObject) contact.getFixtureA().getUserData()).getGrupo());
        AbstractWorldManager managerB=getManager(((Box2DPhysicsObject) contact.getFixtureB().getUserData()).getGrupo());

        if(managerA!=null) managerA.handlePostSolve(contact, impulse);
        if(managerB!=null) managerB.handlePostSolve(contact, impulse);

    }

    public AbstractWorldManager getManager(GRUPO grupo){
        switch (grupo){
            case ENEMY:
                return enemyManager;

            case ITEMS:
                return itemsManager;
            case FLUID:
                return waterManager;
            case HERO:
                return heroManager;
            case PLATFORM:
                break;
            case MOVING_PLATFORM:
                return platformManager;
            case CHECKPOINT:
                return checkPointManager;
            case SENSOR:
                break;
            case STATIC:
                break;

            default:
                break;
        }
        return null;
    }

    @Override
    public void beginContact(Contact contact) {
        AbstractWorldManager managerA=getManager(((Box2DPhysicsObject) contact.getFixtureA().getUserData()).getGrupo());
        AbstractWorldManager managerB=getManager(((Box2DPhysicsObject) contact.getFixtureB().getUserData()).getGrupo());

        if(managerA!=null) managerA.handleBeginContact(contact);
        if(managerB!=null) managerB.handleBeginContact(contact);

    }

    @Override
    public void endContact(Contact contact) {
        if (contact.getFixtureA() == null || contact.getFixtureB()==null ) return;

        AbstractWorldManager managerA=getManager(((Box2DPhysicsObject) contact.getFixtureA().getUserData()).getGrupo());
        AbstractWorldManager managerB=getManager(((Box2DPhysicsObject) contact.getFixtureB().getUserData()).getGrupo());

        if(managerA!=null) managerA.handleEndContact(contact);
        if(managerB!=null) managerB.handleEndContact(contact);

    }

    @Override
    public boolean shouldCollide(Fixture fixtureA, Fixture fixtureB) {
        return true;
    }


    @Override
    public void dispose() {
        heroManager=null;
        platformManager=null;
        enemyManager=null;
        waterManager=null;
        checkPointManager=null;
    }
} public class GameInputs implements InputProcessor {


    private WorldController controller;
    private WorldRenderer renderer;

    public GameInputs( WorldController controller, WorldRenderer renderer) {

        this.controller=controller;
        this.renderer=renderer;
    }

    // * InputProcessor methods ***************************//

    @Override
    public boolean keyDown(int keycode) {
        if (keycode == Keys.LEFT)
            controller.leftPressed();
        if (keycode == Keys.RIGHT)
            controller.rightPressed();
        if (keycode == Keys.Z)
            controller.jumpPressed();
        if (keycode == Keys.X)
            controller.firePressed();
        return true;
    }

    @Override
    public boolean keyUp(int keycode) {
        if (keycode == Keys.LEFT)
            controller.leftReleased();
        if (keycode == Keys.RIGHT)
            controller.rightReleased();
        if (keycode == Keys.Z)
            controller.jumpReleased();
        if (keycode == Keys.X)
            controller.fireReleased();
        if (keycode == Keys.D)
            DreamsGame.DEBUG=!DreamsGame.DEBUG;
        return true;
    }

    @Override
    public boolean keyTyped(char character) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        return false;
    }


    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;  //To change bodyA of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
       /* renderer.getCam().position.x -= Gdx.input.getDeltaX();
        renderer.getCam().position.y += Gdx.input.getDeltaY();*/
        return true;
    }

    @Override
    public boolean scrolled(int amount) {
        renderer.getCam().zoom += amount / 25f;
        System.out.println(amount);
        return true;
    }
} public class Hero extends Box2DPhysicsObject implements Disposable {


     public enum StateHero implements State {
        IDLE, WALKING, JUMPING, DYING, FALL, SWIMMING, PROPULSION,WIN ;

         protected float stateTimeMin;

         StateHero(){
             this.stateTimeMin = 0.1f;
         }

         StateHero(float stateTimeMin){
             this.stateTimeMin = stateTimeMin;
         }

         StateHero(BaseState state){
             this.stateTimeMin =state.getStateTimeMin();
         }

         @Override
         public float getStateTimeMin(){
             return this.stateTimeMin;
         }
    }

    public enum StatePos {ONGROUND, INWATER, ONAIR}


    // States
    private StatePos statePos = StatePos.ONGROUND;
    boolean facingLeft = true;

    public final static float MAX_VELOCITY = 4f;
    public final static float JUMP_FORCE = 14.5f;
    private HashSet<Fixture> grounContacts;
    private Fixture heroPhysicsFixture;
    private Fixture heroSensorFixture;
    private ParticleEffect particleEffectDust;
    private ParticleEffect particleEffectContact;

    public Hero(String name, Body body) {
        super(name, GRUPO.HERO,body);
        setGrounContacts(new HashSet<Fixture>());
        setState(StateHero.IDLE);
    }

    public void velocityLimit() {
        Vector2 vel = this.getBodyA().getLinearVelocity();

        if (Math.abs(vel.x) > this.MAX_VELOCITY) {
            vel.x = Math.signum(vel.x) * this.MAX_VELOCITY;
            this.setVelocity(new Vector2(vel.x, vel.y));
        } else if (Math.abs(vel.y) > this.MAX_VELOCITY * 2) {
            vel.y = Math.signum(vel.y) * this.MAX_VELOCITY * 2;
            this.setVelocity(new Vector2(vel.x, vel.y));
        }
    }

    public boolean isFacingLeft() {
        return facingLeft;
    }

    public void setFacingLeft(boolean facingLeft) {
        this.facingLeft = facingLeft;
    }

    public Vector2 getVelocity() {
        return super.getBodyA().getLinearVelocity();
    }

    public void setVelocity(Vector2 velocity) {
        super.getBodyA().setLinearVelocity(velocity);
    }

    public Fixture getHeroPhysicsFixture() {
        return heroPhysicsFixture;
    }

    public Fixture getHeroSensorFixture() {
        return heroSensorFixture;
    }

    public void setHeroPhysicsFixture(Fixture heroPhysicsFixture) {
        this.heroPhysicsFixture = heroPhysicsFixture;
    }

    public void setHeroSensorFixture(Fixture heroSensorFixture) {
        this.heroSensorFixture = heroSensorFixture;
    }


    public HashSet<Fixture> getGrounContacts() {
        return grounContacts;
    }

    public void setGrounContacts(HashSet<Fixture> grounContacts) {
        this.grounContacts = grounContacts;
    }



    public StatePos getStatePos() {
        return statePos;
    }

    public void setStatePos(StatePos statePos) {
        this.statePos = statePos;
    }

    public ParticleEffect getParticleEffectDust() {
        return particleEffectDust;
    }

    public void setParticleEffectDust(ParticleEffect particleEffectDust) {
        this.particleEffectDust = particleEffectDust;
    }

    public ParticleEffect getParticleEffectContact() {
        return particleEffectContact;
    }

    public void setParticleEffectContact(ParticleEffect particleEffectContact) {
        this.particleEffectContact = particleEffectContact;
    }

    @Override
    public String toString() {
        return
                "StatePos=" + statePos +
                        "\nstate=" + getState() +
                        "\nfacingLeft=" + facingLeft +
                        "\nGravityScale=" + getBodyA().getGravityScale() +
                        "\nInertia=" + getBodyA().getInertia() +
                        "\nMasa=" + getBodyA().getMass() +
                        "\nPeso=" + getBodyA().getMass() * 9.8f +
                        "\nisFixedRotation=" + getBodyA().isFixedRotation() +
                        "\nLinearDamping=" + getBodyA().getLinearDamping() +
                        "\nLinearVelocity=" + getBodyA().getLinearVelocity().toString() +
                        "\nPosition=" + getBodyA().getPosition().toString() +
                        "\nSizeGroundContact=" + grounContacts.size() +
                        "\nWidth=" + getWidthBodyA() +
                        "\nHeight=" + getHeightBodyA() +
                        "\nTimeState=" + getStateTime();
    }

    @Override
    public void dispose() {
        super.dispose();
        grounContacts = null;
        heroPhysicsFixture = null;
        heroSensorFixture = null;
    }

} public class Profile implements Serializable {

    private int lives;
    private int kills;
    private int coinsAquired;
    private int starAquired;
    private List<Level> levels;

    public Profile() {
        lives = 2;
        kills=0;
        coinsAquired=0;
        starAquired=0;
    }

    public Profile(List<Level> levels) {
        lives = 2;
        kills=0;
        coinsAquired=0;
        starAquired=0;
        this.levels = levels;
    }

    public int getHighScore(int levelId) {
        return levels.get(levelId).getHighScore();
    }

    public boolean notifyScore(int levelId, int score) {
        if (score > getHighScore(levelId)) {
            levels.get(levelId).setHighScore(score);
            return true;
        }
        return false;
    }

    public int getLives() {
        return lives;
    }

    public void addLives(int lives){
        Gdx.app.log(Constants.LOG,"Añadido una Vida....");
        this.lives+=lives;
    }

    public boolean removeLive() {
        Gdx.app.log(Constants.LOG,"Pierdes una Vida....");
        --lives;
        if(lives<0) lives=0;
        return lives == 0;
    }

    @Override
    public void read(Json json, JsonValue jsonData) {
        levels = json.readValue("levels", List.class, jsonData);
        lives = json.readValue("lives", Integer.class, jsonData);
    }

    @Override
    public void write(Json json) {
        json.writeValue("levels", levels);
        json.writeValue("lives", lives);
    }

    public void resetValues(){
        if(lives<=0) lives=1;
        coinsAquired=0;
        kills=0;
        starAquired=0;
    }

    public CharSequence getLivesAsText() {
        return String.valueOf(lives);
    }

    public List<Level> getLevels() {
        return levels;
    }

    public int getKills() {
        return kills;
    }

    public void setKills(int kills) {
        this.kills = kills;
    }

    public int getCoinsAquired() {
        return coinsAquired;
    }

    public void setCoinsAquired(int coinsAquired) {
        this.coinsAquired = coinsAquired;
    }

    public void addCoinsAquired(int goldAquired) {
        this.coinsAquired += goldAquired;
    }

    public int getStarAquired() {
        return starAquired;
    }

    public void setStarAquired(int starAquired) {
        this.starAquired = starAquired;
    }

    public void addStarAquired(int starAquired) {
        this.starAquired += starAquired;
    }
} public class World implements Disposable {

    private TiledMap map;
    private com.badlogic.gdx.physics.box2d.World physics;
    private Box2DMapObjectParser parser;
    private ArrayList<Box2DPhysicsObject> entities ;
    private Hero hero;
    private Array<Body> bodiesFlaggedDestroy = new Array<Body>();
    private Texture background_03;
    private Texture background_02;
    private Texture background_01;
    protected Box2dObjectFactory box2dObjectFactory;

    public World(DreamsGame game) {
        entities=new ArrayList<Box2DPhysicsObject>();
        Collections.sort(entities,new Comparator<Box2DPhysicsObject>(){
            public int compare(Box2DPhysicsObject one, Box2DPhysicsObject two){
                return one.getGrupo().compareTo(two.getGrupo());
            }
        });
        createDreamsWorld(game.getLevelManager().getCurrentLevel(), game.getResourcesManager());
    }


    private void createDreamsWorld(Level level, ResourcesManager resourcesManager) {
        physics = new com.badlogic.gdx.physics.box2d.World(new Vector2(0, -9.81f), true);
        box2dObjectFactory = new Box2dObjectFactory(physics, this, resourcesManager);
        map = resourcesManager.get(level.getMap());
        parser = new Box2DMapObjectParser(this, box2dObjectFactory);
        // System.out.println(getParser().getHierarchy(map));
        parser.load(getPhysics(), map);

        background_01 = resourcesManager.get(level.getBackground_01());
        background_02 = resourcesManager.get(level.getBackground_02());
        background_03 = resourcesManager.get(level.getBackground_03());

    }

    public void destroyEntity(Box2DPhysicsObject data) {

        if (data != null) {
            data.getBodyA().setUserData(null);
            physics.destroyBody(data.getBodyA());
            entities.remove(data);
            data.setBodyA(null);
            data = null;
        }

    }

    @Override
    public void dispose() {
        map.dispose();
        physics.dispose();
        physics = null;
        background_01 = null;
        bodiesFlaggedDestroy = null;
        for (Box2DPhysicsObject e : entities) {
            e.dispose();
            e = null;
        }
    }

    public TiledMap getMap() {
        return map;
    }

    public com.badlogic.gdx.physics.box2d.World getPhysics() {
        return physics;
    }


    public Box2DMapObjectParser getParser() {
        return parser;
    }

    public void removeParser() {
        parser = null;
    }

    public Texture getBackground_01() {
        return background_01;
    }

    public void addBodiesFlaggedDestroy(Body body) {
        bodiesFlaggedDestroy.add(body);
    }

    public Array<Body> getBodiesFlaggedDestroy() {
        return bodiesFlaggedDestroy;
    }

    public Texture getBackground_03() {
        return background_03;
    }

    public Texture getBackground_02() {
        return background_02;
    }

    public ArrayList<Box2DPhysicsObject> getEntities() {
        return entities;
    }

    public void setHero(Hero hero) {
        this.hero = hero;
    }

    public Hero getHero() {
        return hero;
    }
} public interface ScreenTransition {
    public float getDuration();

    public void render(SpriteBatch batch, Texture currScreen, Texture nextScreen, float alpha);

} public class ScreenTransitionSlice implements ScreenTransition {
    public static final int UP = 1;
    public static final int DOWN = 2;
    public static final int UP_DOWN = 3;
    private static final ScreenTransitionSlice instance =
            new ScreenTransitionSlice();
    private float duration;
    private int direction;
    private Interpolation easing;
    private Array<Integer> sliceIndex = new Array<Integer>();

    public static ScreenTransitionSlice init(float duration,
                                             int direction, int numSlices, Interpolation easing) {
        instance.duration = duration;
        instance.direction = direction;
        instance.easing = easing;
        instance.sliceIndex.clear();
        for (int i = 0; i < numSlices; i++)
            instance.sliceIndex.add(i);
        instance.sliceIndex.shuffle();
        return instance;
    }

    @Override
    public float getDuration() {
        return duration;
    }

    @Override
    public void render(SpriteBatch batch, Texture currScreen,
                       Texture nextScreen, float alpha) {
        float w = currScreen.getWidth();
        float h = currScreen.getHeight();
        float x = 0;
        float y = 0;
        int sliceWidth = (int) (w / sliceIndex.size);
        Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.draw(currScreen, 0, 0, 0, 0, w, h, 1, 1, 0, 0, 0,
                currScreen.getWidth(), currScreen.getHeight(),
                false, true);
        if (easing != null) alpha = easing.apply(alpha);
        for (int i = 0; i < sliceIndex.size; i++) {

            x = i * sliceWidth;

            float offsetY = h * (1 + sliceIndex.get(i)
                    / (float) sliceIndex.size);
            switch (direction) {
                case UP:
                    y = -offsetY + offsetY * alpha;
                    break;
                case DOWN:
                    y = offsetY - offsetY * alpha;
                    break;
                case UP_DOWN:
                    if (i % 2 == 0) {
                        y = -offsetY + offsetY * alpha;
                    } else {
                        y = offsetY - offsetY * alpha;
                    }
                    break;
            }
            batch.draw(nextScreen, x, y, 0, 0, sliceWidth, h, 1, 1, 0,
                    i * sliceWidth, 0, sliceWidth, nextScreen.getHeight(),
                    false, true);
        }
        batch.end();
    }
} public class GuiBuilder {

    public static final Table buildPadButtons(float width,float height, Styles styles, final WorldController controller) {

        Table tableControlPad = new Table();


        tableControlPad.row().height(height);
        ImageButton btnLeft = new ImageButton( styles.skin, "buttonLeft");
        tableControlPad.add(btnLeft).width(width).expandY().fill();

        btnLeft.addListener(new ClickListener() {

            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                System.out.println("Event " + event.getType());
                super.touchDown(event, x, y, pointer, button);
                controller.leftPressed();
                controller.rightReleased();
                return true;
            }

            @Override
            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                System.out.println("Event " + event.getType());
                super.touchUp(event, x, y, pointer, button);
                controller.leftReleased();
            }

            @Override
            public void touchDragged(InputEvent event, float x, float y, int pointer) {
                System.out.println("Event- " + event.getType());
                super.touchDragged(event, x, y, pointer);
                if (isOver(event.getListenerActor(), x, y)) {
                    controller.rightReleased();
                    controller.leftPressed();
                } else {
                    controller.leftReleased();
                }
            }
        });


        ImageButton btnRight = new ImageButton(styles.skin, "buttonRight");
        tableControlPad.add(btnRight).width(width).expandY().fill().padRight((width)*2);
        btnRight.addListener(new ClickListener() {

            @Override
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
                System.out.println("Event "+event.getType());
                super.touchDown(event,x,y,pointer,button);
                controller.leftReleased();
                controller.rightPressed();
                return true;
            }

            @Override
            public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
                System.out.println("Event "+event.getType());
                super.touchUp(event,x,y,pointer,button);
                controller.rightReleased();
            }

            @Override
            public void touchDragged (InputEvent event, float x, float y, int pointer) {
                System.out.println("Event- "+event.getType());
                super.touchDragged(event, x, y, pointer);
                if(isOver(event.getListenerActor(), x, y)){
                    controller.rightPressed();
                    controller.leftReleased();
                }else {
                    controller.rightReleased();
                }
            }
        });

        ImageButton btnUP = new ImageButton(styles.skin, "buttonUp");
        tableControlPad.add(btnUP).width(width).expandY().fill();
        btnUP.addListener(new ClickListener() {

            @Override
            public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
                System.out.println("Event "+event.getType());
                super.touchDown(event,x,y,pointer,button);
                controller.jumpPressed();
                return true;
            }

            @Override
            public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
                System.out.println("Event "+event.getType());
                super.touchUp(event,x,y,pointer,button);
                controller.jumpReleased();
            }
            @Override
            public void touchDragged (InputEvent event, float x, float y, int pointer) {
                System.out.println("Event- "+event.getType());
                super.touchDragged(event, x, y, pointer);
                if(isOver(event.getListenerActor(), x, y)){
                    controller.jumpPressed();
                }else {
                    controller.jumpReleased();
                }
            }
        });

        tableControlPad.setBounds(0,0, Gdx.graphics.getWidth(),height+10);
        return tableControlPad;

    }


    public static final Touchpad buildTouchPad(float width,float height, Styles styles, final WorldController controller) {
        Touchpad touchpad = new Touchpad(10* ScaleUtil.getSizeRatio(), styles.skin);
        touchpad.setPosition(25 * ScaleUtil.getSizeRatio(), 15);
        touchpad.setWidth(width);
        touchpad.setHeight(height);

        touchpad.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                System.out.println("PercentX "+((Touchpad) actor).getKnobPercentX()+"PercentY "+((Touchpad) actor).getKnobPercentY());
                if (((Touchpad) actor).getKnobPercentX() == 0 || ((Touchpad) actor).getKnobPercentX() < 0.5
                        && ((Touchpad) actor).getKnobPercentX() > -0.5) {
                    controller.rightReleased();
                    controller.leftReleased();
                }
                if (((Touchpad) actor).getKnobPercentX() > 0.5) {
                    controller.rightPressed();
                    controller.leftReleased();
                }
                if (((Touchpad) actor).getKnobPercentX() < -0.5){
                    controller.leftPressed();
                    controller.rightReleased();
                }
                if (((Touchpad) actor).getKnobPercentY() > 0.5) {
                    controller.jumpPressed();
                } else {
                    controller.jumpReleased();
                }

            }
        });

        return touchpad;
    }

    public static final Table buildStats(float width,float height, Styles styles,ResourcesManager resourcesManager) {

        Table tableProfile = new Table();
        tableProfile.setBounds(0, 0, width , height );


        Image imageLives = new Image(((TextureAtlas) resourcesManager.get(resourcesManager.GUI_ATLAS)).findRegion("vidas"));
        imageLives.setName(Constants.IMAGE_LIVES);

        Label lives = new Label("0", styles.skin, "default", Color.ORANGE);
        lives.setName(Constants.LIVES);

        Label labelScore = new Label("Tijeras: ", styles.skin, "default", Color.ORANGE);
        labelScore.setName(Constants.LABEL_SCORE);

        Label score = new Label("0000", styles.skin, "default", Color.ORANGE);
        score.setName(Constants.SCORE);
        tableProfile.defaults().height(height);
        tableProfile.defaults().width(width/4.5f);


        tableProfile.add(imageLives).left().padRight(15).width(imageLives.getPrefWidth()*ScaleUtil.getSizeRatio());
        tableProfile.add(lives).expandY().fill();
        tableProfile.add();

        tableProfile.add(labelScore).right().expandY().fill();
        tableProfile.add(score).right().expandY().fill();
        tableProfile.debug();
        return tableProfile;
    }



} public class ScaleUtil {

    public static float getRatioX(){
        return Gdx.graphics.getWidth() / Constants.VIRTUAL_WIDTH;
    }

    public static float getRatioY(){
        return Gdx.graphics.getHeight() / Constants.VIRTUAL_HEIGHT;
    }

    public static float getWorldRatioX(){
        return Gdx.graphics.getWidth() / Constants.WORLD_WIDTH;
    }

    public static float getWorldRatioY(){
        return Gdx.graphics.getHeight() / Constants.WORLD_HEIGHT;
    }

    public static float getSizeRatio(){
        if(getRatioX() < getRatioY())
            return getRatioX();
        else
            return getRatioY();
    }

    public static float getWorldSizeRatio() {
        if(getWorldRatioX() < getWorldRatioY())
            return getWorldRatioX();
        else
            return getWorldRatioY();
    }
} public class WorldRenderer implements Disposable {

    /**
     * for debug rendering *
     */
    Box2DDebugRenderer debugRenderer;
    private final DreamsGame game;

    private World world;
    private OrthographicCamera cam;
    private OrthogonalTiledMapRenderer renderer;

    private SpriteBatch spriteBatch;
    private float width;
    private float height;

    private ModelsAndViews modelsAndViews;
    private ParallaxBackground background;



    public WorldRenderer(DreamsGame game,World world) {
        this.game= game;
        this.world = world;

        modelsAndViews=new ModelsAndViews(game.getResourcesManager(),world);

        debugRenderer = new Box2DDebugRenderer();
        renderer = new OrthogonalTiledMapRenderer(world.getMap(), world.getParser().getUnitScale());
        world.removeParser();
        spriteBatch = (SpriteBatch) renderer.getSpriteBatch();
        cam = new OrthographicCamera();
    }

    public void resize(int w, int h) {
        this.width=w;
        this.height=h;
        cam.viewportHeight = Constants.WORLD_HEIGHT;
        cam.viewportWidth = (Constants.WORLD_HEIGHT / height) * width;
        Gdx.app.log(Constants.LOG,"World ViewPortWidth: "+cam.viewportWidth+ " World ViewPortHeight: "+cam.viewportHeight);

        background=new ParallaxBackground(Constants.WORLD_WIDTH, cam.viewportHeight);
        background.addLayer(new ParallaxLayer(world.getBackground_01(),0.4f,0,100,100));
        background.addLayer(new ParallaxLayer(world.getBackground_03(),0.6f,0,100,100));
        background.addLayer(new ParallaxLayer(world.getBackground_02(), 0.8f, 0.02f, 100, 100));

    }

    public void render() {
        background.render(cam.position,spriteBatch);
        cam.position.set(world.getHero().getBodyA().getPosition().x, cam.viewportHeight / 2 - cam.viewportHeight / 12, 0);
        cam.update();

        renderer.setView(cam);
        renderer.render();

        spriteBatch.begin();
        modelsAndViews.render(spriteBatch);

        if (DreamsGame.DEBUG) {
            DebugWindow.getInstance(game.getResourcesManager()).setPosition(cam.position.x - 13f, cam.position.y - 5);
            DebugWindow.myLabel.setText("Modo Debug:\n\n" + world.getHero().toString());
            DebugWindow.getInstance(game.getResourcesManager()).pack();
            DebugWindow.getInstance(game.getResourcesManager()).draw(spriteBatch, 1f);

        }

        spriteBatch.end();

        if (DreamsGame.DEBUG) {
            debugRenderer.render(world.getPhysics(), cam.combined);

        }
    }

    @Override
    public void dispose() {
        renderer.dispose();
        renderer=null;
        modelsAndViews=null;
        debugRenderer.dispose();
        debugRenderer=null;
        cam=null;
        spriteBatch=null;
        background=null;
    }

    public OrthographicCamera getCam() {
        return cam;
    }

    public float getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public float getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }


}
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Touchpad;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.rubentxu.juegos.core.DreamsGame;
import com.rubentxu.juegos.core.constantes.Constants;
import com.rubentxu.juegos.core.constantes.GameState;
import com.rubentxu.juegos.core.controladores.WorldController;
import com.rubentxu.juegos.core.inputs.GameInputs;
import com.rubentxu.juegos.core.modelo.Hero;
import com.rubentxu.juegos.core.modelo.Profile;
import com.rubentxu.juegos.core.modelo.World;
import com.rubentxu.juegos.core.pantallas.transiciones.ScreenTransition;
import com.rubentxu.juegos.core.pantallas.transiciones.ScreenTransitionSlice;
import com.rubentxu.juegos.core.utils.builders.GuiBuilder;
import com.rubentxu.juegos.core.utils.gui.ScaleUtil;
import com.rubentxu.juegos.core.vista.WorldRenderer;
package com.rubentxu.juegos.core.pantallas;



public class GameScreen extends BaseScreen {

    private World world;
    private WorldRenderer renderer;
    private WorldController controller;
    private Profile profile;
    private Table stats;


    public GameScreen(DreamsGame dreamsGame) {
        super(dreamsGame, new Stage(0, 0, true));
        CURRENT_SCREEN = SCREEN.GAME;
        profile=game.getProfileManager().getProfile();
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        //updates
        if (!DreamsGame.getGameState().equals(GameState.GAME_PAUSED) &&
                !DreamsGame.getGameState().equals(GameState.GAME_LEVELWIN) &&
                !DreamsGame.getGameState().equals(GameState.GAME_OVER)) {
            controller.update(delta);
            updateStats();
        }

        stage.act(delta);
        //render
        renderer.render();
        stage.draw();
    }

    private void updateStats() {
        Hero hero = world.getHero();
        ((Label) stats.findActor(Constants.SCORE)).setText( String.valueOf(profile.getCoinsAquired()));
        ((Label) stats.findActor(Constants.LIVES)).setText(profile.getLivesAsText());
    }

    @Override
    public void showDialog() {
        if (dialog == null) {
            dialog = new Window("Que desea hacer ?", game.getResourcesManager().getStyles().skin);

            TextButton btnSalir = new TextButton("Salir", game.getResourcesManager().getStyles().skin);
            TextButton btnContinuar = new TextButton("Continuar", game.getResourcesManager().getStyles().skin);
            btnSalir.addListener(new ClickListener() {
                public void clicked(InputEvent event, float x, float y) {
                    System.out.println("Click Salir...");
                    DreamsGame.setGameState(GameState.GAME_SHOW_MENU);
                }
            });
            btnContinuar.addListener(new ClickListener() {
                public void clicked(InputEvent event, float x, float y) {
                    System.out.println("Click Continuar...");
                    DreamsGame.setGameState(GameState.GAME_RUNNING);
                    dialog.remove();
                    dialog = null;
                }
            });

            dialog.defaults().spaceBottom(10);
            dialog.row().fill().expandX();
            dialog.add(btnContinuar);
            dialog.add(btnSalir);
            dialog.pack();
            dialog.setPosition(width / 2 - dialog.getWidth() / 2, height / 2 - dialog.getHeight() / 2);
            stage.addActor(dialog);
        }
    }

    @Override
    public void resize(int width, int height) {
        super.resize(width, height);
        world = new World(game);
        controller = new WorldController(game, world);
        renderer = new WorldRenderer(game, world);
        renderer.resize(width, height);

        stats = GuiBuilder.buildStats(stage.getWidth(), 100 * ScaleUtil.getSizeRatio(), game.getResourcesManager().getStyles(), game.getResourcesManager());