/* 1010! Klooni, a free customizable puzzle game for Android and Desktop Copyright (C) 2017 Lonami Exo | LonamiWebs This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package dev.lonami.klooni; import com.badlogic.gdx.Application; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Preferences; import com.badlogic.gdx.Screen; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import java.util.HashMap; import java.util.Map; import dev.lonami.klooni.effects.EvaporateEffectFactory; import dev.lonami.klooni.effects.ExplodeEffectFactory; import dev.lonami.klooni.effects.SpinEffectFactory; import dev.lonami.klooni.effects.VanishEffectFatory; import dev.lonami.klooni.effects.WaterdropEffectFactory; import dev.lonami.klooni.interfaces.IEffectFactory; import dev.lonami.klooni.screens.MainMenuScreen; import dev.lonami.klooni.screens.TransitionScreen; public class Klooni extends Game { //region Members // FIXME theme should NOT be static as it might load textures which will expose it to the race condition iff GDX got initialized before or not public static Theme theme; public IEffectFactory effect; // ordered list of effects. index 0 will get default if VanishEffectFactory is removed from list public final static IEffectFactory[] EFFECTS = { new VanishEffectFatory(), new WaterdropEffectFactory(), new EvaporateEffectFactory(), new SpinEffectFactory(), new ExplodeEffectFactory(), }; private Map effectSounds; public Skin skin; public final ShareChallenge shareChallenge; public static boolean onDesktop; private final static float SCORE_TO_MONEY = 1f / 100f; public static final int GAME_HEIGHT = 680; public static final int GAME_WIDTH = 408; //endregion //region Creation // TODO Possibly implement a 'ShareChallenge' // for other platforms instead passing null public Klooni(final ShareChallenge shareChallenge) { this.shareChallenge = shareChallenge; } @Override public void create() { onDesktop = Gdx.app.getType().equals(Application.ApplicationType.Desktop); prefs = Gdx.app.getPreferences("dev.lonami.klooni.game"); // Load the best match for the skin (depending on the device screen dimensions) skin = SkinLoader.loadSkin(); // Use only one instance for the theme, so anyone using it uses the most up-to-date Theme.skin = skin; // Not the best idea final String themeName = prefs.getString("themeName", "default"); if (Theme.exists(themeName)) theme = Theme.getTheme(themeName); else theme = Theme.getTheme("default"); Gdx.input.setCatchBackKey(true); // To show the pause menu setScreen(new MainMenuScreen(this)); String effectName = prefs.getString("effectName", "vanish"); effectSounds = new HashMap(EFFECTS.length); effect = EFFECTS[0]; for (IEffectFactory e : EFFECTS) { loadEffectSound(e.getName()); if (e.getName().equals(effectName)) { effect = e; } } } //endregion //region Screen // TransitionScreen will also dispose by default the previous screen public void transitionTo(Screen screen) { transitionTo(screen, true); } public void transitionTo(Screen screen, boolean disposeAfter) { setScreen(new TransitionScreen(this, getScreen(), screen, disposeAfter)); } //endregion //region Disposing @Override public void dispose() { super.dispose(); skin.dispose(); theme.dispose(); if (effectSounds != null) { for (Sound s : effectSounds.values()) { s.dispose(); } effectSounds = null; } } //endregion // region Effects private void loadEffectSound(final String effectName) { FileHandle soundFile = Gdx.files.internal("sound/effect_" + effectName + ".mp3"); if (!soundFile.exists()) soundFile = Gdx.files.internal("sound/effect_vanish.mp3"); effectSounds.put(effectName, Gdx.audio.newSound(soundFile)); } public void playEffectSound() { effectSounds.get(effect.getName()) .play(MathUtils.random(0.7f, 1f), MathUtils.random(0.8f, 1.2f), 0); } // endregion //region Settings private static Preferences prefs; // Score related public static int getMaxScore() { return prefs.getInteger("maxScore", 0); } public static int getMaxTimeScore() { return prefs.getInteger("maxTimeScore", 0); } public static void setMaxScore(int score) { prefs.putInteger("maxScore", score).flush(); } public static void setMaxTimeScore(int maxTimeScore) { prefs.putInteger("maxTimeScore", maxTimeScore).flush(); } // Settings related public static boolean soundsEnabled() { return !prefs.getBoolean("muteSound", false); } public static boolean toggleSound() { final boolean result = soundsEnabled(); prefs.putBoolean("muteSound", result).flush(); return !result; } public static boolean shouldSnapToGrid() { return prefs.getBoolean("snapToGrid", false); } public static boolean toggleSnapToGrid() { final boolean result = !shouldSnapToGrid(); prefs.putBoolean("snapToGrid", result).flush(); return result; } // Themes related public static boolean isThemeBought(Theme theme) { if (theme.getPrice() == 0) return true; String[] themes = prefs.getString("boughtThemes", "").split(":"); for (String t : themes) if (t.equals(theme.getName())) return true; return false; } public static boolean buyTheme(Theme theme) { final float money = getRealMoney(); if (theme.getPrice() > money) return false; setMoney(money - theme.getPrice()); String bought = prefs.getString("boughtThemes", ""); if (bought.equals("")) bought = theme.getName(); else bought += ":" + theme.getName(); prefs.putString("boughtThemes", bought); return true; } public static void updateTheme(Theme newTheme) { prefs.putString("themeName", newTheme.getName()).flush(); theme.update(newTheme.getName()); } // Effects related public static boolean isEffectBought(IEffectFactory effect) { if (effect.getPrice() == 0) return true; String[] effects = prefs.getString("boughtEffects", "").split(":"); for (String e : effects) if (e.equals(effect.getName())) return true; return false; } public static boolean buyEffect(IEffectFactory effect) { final float money = getRealMoney(); if (effect.getPrice() > money) return false; setMoney(money - effect.getPrice()); String bought = prefs.getString("boughtEffects", ""); if (bought.equals("")) bought = effect.getName(); else bought += ":" + effect.getName(); prefs.putString("boughtEffects", bought); return true; } public void updateEffect(IEffectFactory newEffect) { prefs.putString("effectName", newEffect.getName()).flush(); // Create a new effect, since the one passed through the parameter may dispose later effect = newEffect; } // Money related public static void addMoneyFromScore(int score) { setMoney(getRealMoney() + score * SCORE_TO_MONEY); } private static void setMoney(float money) { prefs.putFloat("money", money).flush(); } public static int getMoney() { return (int) getRealMoney(); } private static float getRealMoney() { return prefs.getFloat("money"); } //endregion }