public class GdxArtemisGame extends Game {

	private static GdxArtemisGame instance;

	@Override
	public void create() {
		instance = this;
		restart();
	}

	public void restart() {
		setScreen(new GameScreen());
	}

	public static GdxArtemisGame getInstance()
	{
		return instance;
	}
} public class G {

    public static final int LOGO_WIDTH = 280;
    public static final int LOGO_HEIGHT = 221;
    public static final int LAYER_CURSOR = 2000;

    public static final boolean PRODUCTION = false;

    public static final boolean INTERLACING_SIMULATION = true;

    public static final boolean DEBUG_SKIP_INTRO = (!PRODUCTION && false);
    public static final boolean DEBUG_ACHIEVEMENTS = (!PRODUCTION && false);
    public static final boolean DEBUG_DRAWING = (!PRODUCTION && true);
    public static final boolean DEBUG_NO_MUSIC =(!PRODUCTION && false);
    public static final boolean DEBUG_NO_ENTITY_RENDERING =(!PRODUCTION && false);
    public static final boolean DEBUG_NO_SECOND_PASS  =(!PRODUCTION && false);
    public static final boolean DEBUG_NO_ACHIEVEMENTS  = (!PRODUCTION && true);
    public static boolean DEBUG_NO_FLOW = (!PRODUCTION && false);
    public static boolean DEBUG_AIR_PLANET = (!PRODUCTION && false);
    public static boolean DEBUG_NAIVE_GRAVITY = (!PRODUCTION && false);
    public static boolean DEBUG_NO_CARDS = (!PRODUCTION && true);

    public static final float CARD_X = 5;
    public static final float CARD_Y = 5;


    public static final int SIMULATION_WIDTH = 220 + 50;
    public static final int SIMULATION_HEIGHT = 220 + 50;
    public static final int MARGIN_BETWEEN_CARDS = 5;

    public static final int LAYER_STAR = -50;
    public static final int LAYER_STRUCTURES_BACKGROUND = -2;
    public static final int LAYER_PLANET = 0;
    public static final int LAYER_DUDES = 99;
    public static final int LAYER_GHOST = 100;
    public static final int LAYER_CARDS = 1000;
    public static final int LAYER_CARDS_HOVER = 1001;
    public static final int LAYER_CARDS_FLYING = 1002;
    public static final int LAYER_ACHIEVEMENTS = 900;
    public static final int LAYER_STRUCTURES = -1;
    public static final int LAYER_STRUCTURES_FOREGROUND = 101;

    public static int CAMERA_ZOOM = 2;
    public static final int SCREEN_WIDTH = SIMULATION_WIDTH * 2 * CAMERA_ZOOM;
    private static int CARD_HEIGHT = 90;
    private static int MARGIN_BETWEEN_CARD_AND_SIM = 10;

    public static int PLANET_X = (SIMULATION_WIDTH) - (SIMULATION_WIDTH / 2);
    public static int PLANET_Y = MARGIN_BETWEEN_CARD_AND_SIM + CARD_HEIGHT;
    private static final int MARGIN_BETWEEN_SIM_AND_ROOF = 20;
    public static final int SCREEN_HEIGHT = (SIMULATION_HEIGHT + CARD_HEIGHT + MARGIN_BETWEEN_CARD_AND_SIM + MARGIN_BETWEEN_SIM_AND_ROOF) * CAMERA_ZOOM;

    public static final int PLANET_CENTER_X = PLANET_X + (SIMULATION_WIDTH / 2);
    public static final int PLANET_CENTER_Y = PLANET_Y + (SIMULATION_HEIGHT / 2);

    public static final int GRADIENT_SCALE = 5;
    public static float TOOL_HEIGHT = 50;
} public class CardScriptSystem extends FluidIteratingSystem {


    private GameScreenAssetSystem gameScreenAssetSystem;

    public CardScriptSystem() {
        super(Aspect.all(CardScript.class));
    }

    PlanetStencilSystem planetStencilSystem;
    PlanetCreationSystem planetCreationSystem;
    GameScreenAssetSystem assetSystem;
    AchievementSystem achievementSystem;
    CardSystem cardSystem;

    int statusIndex = 0;

    @Override
    protected void initialize() {
        super.initialize();
        reset();
    }

    public void reset() {
        IntBag cards = world.getAspectSubscriptionManager().get(Aspect.all(StatusEffect.class)).getEntities();
        int[] ids = cards.getData();
        for (int i = 0, s = cards.size(); s > i; i++) {
            E.E(ids[i]).deleteFromWorld();
        }
        spawnSkyscrapers();
    }

    @Override
    protected void process(E e) {
        CardData cardData = e.getPlayableCard().card;
        String sfx = cardData.sfx;
        if (sfx != null) {
            assetSystem.playSfx(sfx);
        }

        if (cardData.statuseffect) {
            String cardGfx = "card" + cardData.id;
            addStatusEffect(cardGfx);
        }

        run(e.cardScriptScript());
        e.deleteFromWorld();

        timeoutEffects();
    }

    private void timeoutEffects() {
        IntBag cards = world.getAspectSubscriptionManager().get(Aspect.all(StatusEffect.class)).getEntities();
        int[] ids = cards.getData();
        for (int i = 0, s = cards.size(); s > i; i++) {
            E e = E.E(ids[i]);
            StatusEffect statusEffect = e.getStatusEffect();
            statusEffect.duration--;
            if (statusEffect.duration < 0) {
                e.deleteFromWorld();
            }
            break;
        }
    }

    private void addStatusEffect(String cardGfx) {
        E.E().anim(cardGfx)
                .clickable()
                .statusEffect()
                .angleRotation(10f)
                .pos(
                        33 + ((statusIndex % 2) * 40),
                        G.SCREEN_HEIGHT / G.CAMERA_ZOOM - 90 - (statusIndex * 40))
                .tint(1f, 1f, 1f, 0.8f)
                .scale(0.8f)
                .renderLayer(G.LAYER_CARDS + statusIndex);
        statusIndex++;
    }

    private void run(ScriptCommand[] commands) {
        System.out.println(Arrays.toString(commands));
        for (ScriptCommand c : commands) {
            runScriptStep(c);
        }
    }

    private void runScriptStep(ScriptCommand c) {
        System.out.println(c.toString());
        switch (c) {
            case LAVA_TENDRIL:
                planetStencilSystem.stencilRotateCenter(MathUtils.randomBoolean() ? "AIRPOCKET" : "AIRPOCKET2");
                break;
            case HOLLOWEARTH:
                planetStencilSystem.stencil("HOLLOWEARTH");
                for (int i = 0; i < 5; i++) {
                    spawnHollowEarther();
                }
                break;
            case WATERWORLD:
                planetStencilSystem.stencil("WATERWORLD");
                break;
            case KILL_DUDES:
                killDudes();
            case ADD_DUDES:
                spawnDudes();
                break;
            case LAVA_PRESSURE_UP:
                getPlanet().lavaPressure += 1000;
                break;
            case WATER_PRESSURE_UP:
                getPlanet().waterPressure += 3000;
                break;
            case ANGRY_RANDOMIZE:
                randomizeAnger();
                break;
            case ANGRY_ALL:
                allAnger();
                break;
            case ANGRY_NONE:
                killAnger();
                break;
            case DOLPHINIZE:
                randomizeDolphin();
                break;
            case RESTART:
                restartGame();
                break;
            case CURE_FOR_DEATH:
                innoculateEveryoneForDeath();
                break;
            case SPAWN_ICBMS:
                spawnIcbms();
                break;
            case UNSPAWN_ICBMS:
                unspawnIcbms();
                break;
            case SPAWN_GALAXYBUCKS:
                spawnStarbucks();
                break;
            case SPAWN_ACCELERATOR:
                spawnAccelerators();
                break;
            case SPAWN_STRUCTURES:
                spawnSkyscrapers();
                break;
            case TRIGGER_EXPLOSIVES:
                triggerExplosives();
                break;
        }
    }

    private void spawnHollowEarther() {
        Vector2 location = planetCreationSystem.getSpawnLocationHollowEarth();
        planetCreationSystem.spawnDude(location.x, location.y).massInverse(true).alien();
    }

    private void unspawnIcbms() {
        for (E e : allEntitiesWith(Explosive.class)) {
            e.deleteFromWorld();
        }
    }

    public void triggerExplosives() {
        boolean found = false;
        for (E e : allEntitiesMatching(Aspect.all(Explosive.class))) {
            e.explosivePrimed(true);
            found = true;
        }
        if (found) {
            gameScreenAssetSystem.playSfx("LD_lowfi_explosion");
        }
    }

    public void spawnIcbms() {
        for (int i = 0; i < MathUtils.random(2, 4); i++) {
            spawnStructure("icbm", G.LAYER_STRUCTURES_FOREGROUND)
                    .explosiveYield(MathUtils.random(20, 50));
        }
    }

    public void spawnSkyscrapers() {
        for (int i = 0; i < MathUtils.random(10, 20); i++) {
            spawnStructure("skyscraper" + MathUtils.random(7), G.LAYER_STRUCTURES_BACKGROUND);
        }

    }

    public void spawnAccelerators() {
        spawnStructure("spaceship", G.LAYER_STRUCTURES_FOREGROUND);
        spawnStructure("alien", G.LAYER_STRUCTURES_FOREGROUND);
    }

    private void spawnStarbucks() {
        for (int i = 0; i < MathUtils.random(2, 5); i++) {
            spawnStructure("galaxybucks", G.LAYER_STRUCTURES)
                    .food();
        }
    }

    private void spawnStructure(int min, int max, String id, int layer) {
        for (int i = 0; i < MathUtils.random(min, max); i++) {
            spawnStructure(id, layer)
                    .wealth();
        }
    }

    public E spawnStructure(String id, int layer) {
        Vector2 location = planetCreationSystem.getSpawnLocation();
        E e = E.E()
                .pos(location.x, location.y)
                .anim(id)
                .originX(0.5f)
                .originY(0.1f)
                .renderLayer(layer)
                .angle()
                .physics()
                .planetbound()
                .flammable()
                .tint(Tint.TRANSPARENT)
                .script(sequence(delay(MathUtils.random(0.1f, 0.4f)), add(new Mass(1.1f)), tween(Tint.TRANSPARENT, Tint.WHITE, 0.2f)))
                .orientToGravityIgnoreFloor(true);

        if (G.DEBUG_NO_ENTITY_RENDERING) {
            e.invisible();
        }

        return e;
    }

    private void innoculateEveryoneForDeath() {
        for (E e : allEntitiesWith(Wander.class)) {
            e.reviveAfterDeath();
        }
    }

    public void restartGame() {
        planetCreationSystem.restart();
        reset();
        achievementSystem.gameEnded = false;
        gameScreenAssetSystem.playMusicInGame();
    }

    private void killDudes() {
        for (E e : allEntitiesWith(Wander.class)) {
            e.removeDolphinized();
            if (MathUtils.randomBoolean()) {
                e.died();
            }
        }
    }

    public void spawnDudes() {
        for (int i = 0; i < 5; i++) {
            planetCreationSystem.spawnDude(MathUtils.random(0, 360));
        }
    }

    Vector2 v = new Vector2();

    public void randomizeDolphin() {
        for (E e : allEntitiesWith(Wander.class)) {
            Vector2 gravityVector = v.set(e.planetboundGravity()).rotate(180f);
            e
                    .dolphinized()
                    .physicsVr(1000f)
                    .physicsVx(gravityVector.x * 100f)
                    .physicsVy(gravityVector.y * 100f);
        }
    }

    private void randomizeAnger() {
        for (E e : allEntitiesWith(Wander.class)) {
            e.removeDolphinized();
            if (MathUtils.randomBoolean()) {
                e.removeAngry();
            } else {
                e.angry();
            }
        }
    }

    private void allAnger() {
        for (E e : allEntitiesWith(Wander.class)) {
            e.angry();
        }
    }

    private void killAnger() {
        for (E e : allEntitiesWith(Wander.class)) {
            e.removeAngry();
        }
    }

    private Planet getPlanet() {
        return planetCreationSystem.planetEntity.getPlanet();
    }
} public class CardSortSystem extends FluidIteratingSystem {

    public boolean shouldResort;

    public CardSortSystem() {
        super(Aspect.all(Pos.class, PlayableCard.class));
    }

    @Override
    protected void initialize() {
        super.initialize();
    }

    @Override
    protected void begin() {
        super.begin();
        if (shouldResort) { // && onlyClickableCardsRemain()) {
            shouldResort = false;
            resortCards();
        }
    }

    private boolean onlyClickableCardsRemain() {
        IntBag entities = getEntityIds();
        int[] ids = entities.getData();
        for (int i = 0, s = entities.size(); s > i; i++) {
            if (!E.E(ids[i]).hasClickable()) return false;
        }
        return true;
    }


    @Override
    protected void process(E e) {
    }

    public void resortCards() {
        IntBag entities = getEntityIds();
        int[] ids = entities.getData();
        int count=0;
        for (int i = 0, s = entities.size(); s > i; i++) {
            E e = E.E(ids[i]);
            if (e.hasClickable())
                count++;
        }
        float x = G.PLANET_CENTER_X - (count*33) - (MathUtils.clamp(count-1,0,99)*G.MARGIN_BETWEEN_CARDS);

        for (int i = 0, s = entities.size(); s > i; i++) {
            E e = E.E(ids[i]);
            if (!e.hasClickable())
                continue;
            if (e.posX() != x) {
                e.script(moveBetween(e.posX(), e.posY(), x, e.posY(), 1f, Interpolation.fade));
            }
            x += e.playableCardCard().width + G.MARGIN_BETWEEN_CARDS;
        }
    }
} public class CardSystem extends FluidIteratingSystem {

    private static TransitionSystem transitionSystem;
    private CardLibrary cardLibrary;
    private GameScreenAssetSystem gameScreenAssetSystem;
    private RenderBatchingSystem renderBatchingSystem;
    CardSortSystem cardSortSystem;
    private AchievementSystem achievementSystem;

    public CardSystem() {
        super(Aspect.all(Pos.class, PlayableCard.class, Clickable.class));
    }

    @Override
    protected void initialize() {
        super.initialize();
        loadCards();
        //spawnCard("HOLLOWEARTH");
    }


    private void loadCards() {
        final Json json = new Json();
        cardLibrary = json.fromJson(CardLibrary.class, Gdx.files.internal("cards.json"));
        dealRandomCards(3);
    }

    private void dealRandomCards(int count) {
        for (int i = 0; i < count; i++) {
            CardData card = cardLibrary.random();
            spawnCard(card);
        }
    }

    public void dealResetCard() {
        clearDeck();
        spawnCard(cardLibrary.getById("RESTART"));
    }

    private void clearDeck() {
        IntBag cards = getEntityIds();
        int[] ids = cards.getData();
        for (int i = 0, s = cards.size(); s > i; i++) {
            E e = E.E(ids[i]);
            e.removeClickable().script(sequence(moveBetween(e.posX(), e.posY(), e.posX(), e.posY() - 100, 1f, Interpolation.smooth), deleteFromWorld()));
        }
    }

    @Override
    protected void begin() {
        super.begin();

        if (Gdx.input.isKeyJustPressed(Input.Keys.NUM_0)) {
            //dealRandomCards(1);
            dealResetCard();
        }

        int cards = getEntityIds().size();
        if (cards <= 1 && !achievementSystem.gameEnded) {
            dealRandomCards(3-cards);
        }
    }

    @Override
    protected void process(E e) {

        e.scale(e.clickableState() == Clickable.ClickState.HOVER ? 1.2f : 1.0f);
        int layer = e.clickableState() == Clickable.ClickState.HOVER ? G.LAYER_CARDS_HOVER : G.LAYER_CARDS;
        if (e.renderLayer() != layer) {
            e.renderLayer(layer);
            renderBatchingSystem.sortedDirty = true;
        }
        if (e.clickableState() == Clickable.ClickState.CLICKED) {
            gameScreenAssetSystem.playSfx("LD1_event1");
            e.removeClickable();
            float MOVE_DURATION = 1.5f;
            float FINAL_CARD_SCALE = 0.4f;
            e.physicsVr(500f).physicsFriction(0).angle().tint(Tint.WHITE).renderLayer(G.LAYER_CARDS_FLYING);
            e.script(
                    sequence(
                            parallel(
                                    moveBetween(e.posX(), e.posY(), G.PLANET_CENTER_X - e.boundsCx() * FINAL_CARD_SCALE, G.PLANET_CENTER_Y - e.boundsCy() * FINAL_CARD_SCALE, MOVE_DURATION, Interpolation.smooth),
                                    scaleBetween(1f, FINAL_CARD_SCALE, MOVE_DURATION, Interpolation.smooth),
                                    sequence(
                                            delay(MOVE_DURATION - 0.2f),
                                            tween(Tint.WHITE, Tint.TRANSPARENT, 0.2f)
                                    )),
                            add(new CardScript(e.playableCardCard().script))
                    ));
            cardSortSystem.shouldResort = true;
        }
    }

    private void spawnCard(CardData card) {
        if ( G.DEBUG_NO_CARDS ) return;

        String cardGfx = "card" + card.id;
        gameScreenAssetSystem.add(cardGfx, card.x, card.y, card.width, card.height, 1);
        E()
                .anim(cardGfx)
                .clickable()
                .playableCardCard(card)
                .bounds(0, 0, card.width, card.height)
                .pos(-300, G.CARD_Y)
                .physics()
                .scale(1.0f)
                .renderLayer(G.LAYER_CARDS);
        cardSortSystem.shouldResort = true;
    }

    private static void restartGame() {
        transitionSystem.transition(GameScreen.class, 0f);
    }

    public void spawnCard(String id) {
        spawnCard(cardLibrary.getById(id));
    }
} @Wire
public class TransitionSystem extends EntityProcessingSystem {

    private Game game;

    public TransitionSystem(Game game) {
        super(Aspect.all(Transition.class));
        this.game = game;
    }

    /**
     * Transition to screen after delay in seconds.
     */
    public void transition(Class<? extends Screen> screen, float delay) {
        E()
                .script(
                        sequence(
                                delay(seconds(delay)),
                                add(new Transition(screen))
                        )
                );
    }

    @Override
    protected void process(Entity e) {
        try {
            game.setScreen(ClassReflection.newInstance(E(e).transitionScreen()));
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
} public class PlanetStencilSystem extends PassiveSystem {

    GameScreenAssetSystem gameScreenAssetSystem;
    PlanetCreationSystem planetCreationSystem;

    StencilLibrary stencilLibrary = new StencilLibrary();
    private Color c = new Color();

    @Override
    protected void initialize() {
        super.initialize();
        loadPlanets();
    }

    private void loadPlanets() {
        final Json json = new Json();
        stencilLibrary = json.fromJson(StencilLibrary.class, Gdx.files.internal("stencils.json"));
    }

    public void stencilRotateCenter(String id) {
        final StencilData stencilData = stencilLibrary.getById(id);
        if (stencilData != null) {
            stencil(planetCreationSystem.planetEntity.getPlanet(),
                    new Texture(stencilData.texture),
                    stencilData.replaceTypes,
                    FauxRng.random(360),
                    G.SIMULATION_WIDTH / 2, G.SIMULATION_HEIGHT / 2);
        }
    }

    public void stencil(String id) {
        final StencilData stencilData = stencilLibrary.getById(id);
        if (stencilData != null) {
            Texture texture = new Texture(stencilData.texture);
            stencil(planetCreationSystem.planetEntity.getPlanet(), texture,
                    stencilData.replaceTypes, 0,
                    (G.SIMULATION_WIDTH / 2) - texture.getWidth() / 2, (G.SIMULATION_HEIGHT / 2) - texture.getHeight() / 2);
        }
    }

    Vector2 tv = new Vector2();

    private void stencil(Planet planet, Texture texture, PlanetCell.CellType[] replaceTypes, int degrees, int x1, int y1) {
        final TextureData textureData = texture.getTextureData();
        textureData.prepare();

        final Pixmap pixmap = textureData.consumePixmap();
        for (int y = 0; y < texture.getHeight(); y++) {
            for (int x = 0; x < texture.getWidth(); x++) {

                tv.set(x, y).rotate(degrees).add(x1, y1);

                int color = pixmap.getPixel(x, texture.getHeight() - y);
                final PlanetCell.CellType type = getSourceCellType(planet, color);
                if (type != null) {
                    replaceCell(planet, Math.round(tv.x), Math.round(tv.y), replaceTypes, type, color);
                }

            }
        }
        pixmap.dispose();
    }

    private void replaceCell(Planet planet, int tx, int ty, PlanetCell.CellType[] replaceTypes, PlanetCell.CellType type, int color) {
        final PlanetCell cell = planet.get(tx, ty);
        if (cell != null) {
            if (isType(replaceTypes, cell.type)) {
                cell.nextType = type;
                cell.nextColor = color;
            }
        }
    }

    private boolean isType(PlanetCell.CellType[] replaceTypes, PlanetCell.CellType type) {
        for (PlanetCell.CellType replaceType : replaceTypes) {
            if (replaceType == type) return true;
        }
        return false;
    }

    private PlanetCell.CellType getSourceCellType(Planet planet, int pixel) {
        for (PlanetData.CellType type : planet.data.types) {
            if (FauxPixMap.sameIsh(pixel, type.intColor)) {
                return type.type;
            }
        }
        Color.rgba8888ToColor(c, pixel);
        if (c.a != 0) {
            return PlanetCell.CellType.STATIC;
        }

        return null;
    }


} @Wire
public class MouseClickSystem extends FluidIteratingSystem {

    CollisionSystem system;
    TagManager tagManager;

    private boolean leftMousePressed;

    public MouseClickSystem() {
        super(Aspect.all(Clickable.class, Bounds.class));
    }

    @Override
    protected void begin() {
        super.begin();

        leftMousePressed = Gdx.input.isButtonPressed(Input.Buttons.LEFT);
    }

    @Override
    protected void process(E e) {
        final Entity cursor = tagManager.getEntity("cursor");
        if ( cursor != null )
        {
            // update state based on cursor.
            final Clickable clickable = e.getClickable();
            final boolean overlapping = system.overlaps(cursor, e.entity());
            if ( overlapping )
            {
               clickable.state = leftMousePressed ? Clickable.ClickState.CLICKED : Clickable.ClickState.HOVER;
            } else {
                clickable.state = Clickable.ClickState.NONE;
            }
        }
    }
} @Wire
public class GameScreenAssetSystem extends AbstractAssetSystem {

    private SpriteLibrary spriteLibrary;
    private Music music;

    public GameScreenAssetSystem() {
        super("cards.png");
        loadSprites();

        // recycle!
        int offsetY = 140;
        add("star-0-0", 32, 136 + offsetY, 4, 4, 1);
        add("star-0-1", 32 - 4, 136 + offsetY, 4, 4, 1);
        add("star-0-2", 32 - 8, 136 + offsetY, 4, 4, 1);
        add("star-0-3", 40, 136 + offsetY, 7, 4, 1);
        add("star-0-4", 48, 136 + offsetY, 26, 4, 1);
        add("star-0-5", 80, 136 + offsetY, 36, 4, 1);

        add("star-1-0", 32, 144 + offsetY, 2, 2, 1);
        add("star-1-1", 32 - 4, 144 + offsetY, 2, 2, 1);
        add("star-1-2", 32 - 8, 144 + offsetY, 2, 2, 1);
        add("star-1-3", 40, 144 + offsetY, 6, 2, 1);
        add("star-1-4", 48, 144 + offsetY, 12, 2, 1);
        add("star-1-5", 80, 144 + offsetY, 21, 2, 1);

        add("star-2-0", 32, 152 + offsetY, 1, 1, 1);
        add("star-2-1", 32 - 4, 152 + offsetY, 1, 1, 1);
        add("star-2-2", 32 - 8, 152 + offsetY, 1, 1, 1);
        add("star-2-3", 40, 152 + offsetY, 4, 1, 1);
        add("star-2-4", 48, 152 + offsetY, 7, 1, 1);
        add("star-2-5", 80, 152 + offsetY, 15, 1, 1);

        loadSounds(
                new String[]{
                        "LD1_badthing",
                        "LD1_event1",
                        "LD1_event2",
                        "LD1_event3",
                        "LD1_volcano",
                        "LD1_volcano2",
                        "LD_genuine earth men_jingle",
//                        "LD_titleloop",
                        "LD_troop_amazing",
                        "LD_troop_hello",
                        "LD_troop_no",
                        "LD_troop_prologue",
                        "LD_troop_yeah",
                        "LD_troop_yeah_higher",
                        "LD_lowfi_explosion",
                        "nutrition-coffee",
                        "Politic-Dolphins",
                        "Politic-New Leader",
                        "tech-missiles",
                        "Tech-particle accel",

                        "LD_ghostflipper",
                        "LD_ghostflipper2",
                        "LD_rebornflipper",
                }
        );

        loadLogo();

        playMusicTitle();
        //playMusicInGame();
    }

    private void loadLogo() {
        TextureRegion[] regions = new TextureRegion[16];
        for (int i = 0; i < 16; i++) {
            regions[i] = new TextureRegion(new Texture("index" + (i + 1) + ".png"), G.LOGO_WIDTH, G.LOGO_HEIGHT);
        }

        Animation animation = new Animation<>(0.05f, regions);
        animation.setPlayMode(Animation.PlayMode.NORMAL);
        sprites.put("logo", animation);
    }

    private void playMusicTitle() {
        if (DEBUG_NO_MUSIC) return;
        if (music != null) music.stop();
        music = Gdx.audio.newMusic(Gdx.files.internal("sfx/LD_titleloop.mp3"));
        music.setLooping(true);
        music.play();
        music.setPan(0, 0.1f);

        if (!G.DEBUG_SKIP_INTRO) {
            playSfx("LD_troop_prologue");
        }
    }

    int musicIndex = 0;
    String[] musicFiles = new String[]
            {
                    "sfx/LD1_fortune_teller_loop.mp3",
                    "sfx/LD1_amb_main.mp3",
                    "sfx/LD_titleloop.mp3"
            };

    public void playMusicInGame() {
        if (DEBUG_NO_MUSIC) return;
        if (music != null) music.stop();
        music = Gdx.audio.newMusic(Gdx.files.internal(musicFiles[musicIndex]));
        music.setLooping(true);
        music.play();
        music.setPan(0, 0.1f);

        musicIndex = (++musicIndex % 3);
    }

    @Override
    protected void initialize() {
        super.initialize();
    }

    private void loadSprites() {
        final Json json = new Json();
        spriteLibrary = json.fromJson(SpriteLibrary.class, Gdx.files.internal("sprites.json"));
        for (SpriteData sprite : spriteLibrary.sprites) {
            add(sprite.id, sprite.x, sprite.y, sprite.width, sprite.height, sprite.countX, sprite.countY);
        }
    }

} @Wire
public class GameScreenSetupSystem extends PassiveSystem {

    GameScreenAssetSystem assetSystem;

    @Override
    protected void initialize() {
        createMousecursor();
    }

    private Entity createMousecursor() {
        return E()
                .pos()
                .mouseCursor()
                .bounds()
                .tag("cursor").entity();

    }


}
import com.artemis.SuperMapper;
import com.artemis.World;
import com.artemis.WorldConfigurationBuilder;
import com.artemis.link.EntityLinkManager;
import com.artemis.managers.GroupManager;
import com.artemis.managers.TagManager;
import net.mostlyoriginal.api.screen.core.WorldScreen;
import net.mostlyoriginal.api.system.graphics.RenderBatchingSystem;
import net.mostlyoriginal.api.system.mouse.MouseCursorSystem;
import net.mostlyoriginal.api.system.physics.CollisionSystem;
import net.mostlyoriginal.api.system.physics.PhysicsSystem;
import net.mostlyoriginal.api.system.render.AnimRenderSystem;
import net.mostlyoriginal.game.GdxArtemisGame;
import net.mostlyoriginal.game.component.G;
import net.mostlyoriginal.game.system.*;
import net.mostlyoriginal.game.system.dilemma.CardScriptSystem;
import net.mostlyoriginal.game.system.dilemma.CardSortSystem;
import net.mostlyoriginal.game.system.dilemma.CardSystem;
import net.mostlyoriginal.game.system.logic.TransitionSystem;
import net.mostlyoriginal.game.system.planet.*;
import net.mostlyoriginal.game.system.planet.physics.*;
import net.mostlyoriginal.game.system.stencil.PlanetStencilSystem;
import net.mostlyoriginal.game.system.ui.MouseClickSystem;
import net.mostlyoriginal.game.system.view.GameScreenAssetSystem;
import net.mostlyoriginal.game.system.view.GameScreenSetupSystem;
import net.mostlyoriginal.plugin.OperationsPlugin;
import net.mostlyoriginal.plugin.ProfilerPlugin;
package net.mostlyoriginal.game.screen;


/**
 * Example main game screen.
 *
 * @author Daan van Yperen
 */
public class GameScreen extends WorldScreen {

    public static final String BACKGROUND_COLOR_HEX = "0000FF";

    @Override
    protected World createWorld() {
        RenderBatchingSystem renderBatchingSystem;
        return new World(new WorldConfigurationBuilder()
                .dependsOn(EntityLinkManager.class, ProfilerPlugin.class, OperationsPlugin.class)
                .with(
                        new SuperMapper(),
                        new TagManager(),

                        new GroupManager(),
                        new CardSystem(),
                        new CardSortSystem(),
                        new CardScriptSystem(),