diff --git a/android/assets/themes/default.theme b/android/assets/themes/default.theme new file mode 100644 index 0000000..77c9c34 --- /dev/null +++ b/android/assets/themes/default.theme @@ -0,0 +1,19 @@ +{ + "name": "Default", + "price": 0, + "colors": { + "background": "e6e6e6ff", + "buttons": [ + "00ff33ff", + "ffd700ff", + "2389fcff", + "d94848ff" + ], + "cells": [ + "7988bfff", "98dc53ff", "4cd4aeff", + "fec63dff", "ec9548ff", "e66a82ff", "da6554ff", + "57cb84ff", "5abee2ff" + ] + }, + "cell_texture": "basic.png" +} diff --git a/core/src/io/github/lonamiwebs/klooni/Klooni.java b/core/src/io/github/lonamiwebs/klooni/Klooni.java index 5e46390..4195783 100644 --- a/core/src/io/github/lonamiwebs/klooni/Klooni.java +++ b/core/src/io/github/lonamiwebs/klooni/Klooni.java @@ -11,12 +11,17 @@ import io.github.lonamiwebs.klooni.screens.MainMenuScreen; public class Klooni extends Game { + // TODO Not sure whether the theme should be static or not since it might load textures + public static Theme theme; public Skin skin; @Override public void create() { prefs = Gdx.app.getPreferences("io.github.lonamiwebs.klooni.game"); + // Use only one instance for the theme, so anyone using it uses the most up-to-date + theme = Theme.getTheme(prefs.getString("themeName", "default")); + // TODO Better way to have this skin somewhere // Gotta create that darn .jsonā€¦! skin = new Skin(Gdx.files.internal("skin/uiskin.json")); @@ -54,6 +59,7 @@ public class Klooni extends Game { public void dispose() { super.dispose(); skin.dispose(); + theme.dispose(); } //region Settings diff --git a/core/src/io/github/lonamiwebs/klooni/Theme.java b/core/src/io/github/lonamiwebs/klooni/Theme.java new file mode 100644 index 0000000..a44a486 --- /dev/null +++ b/core/src/io/github/lonamiwebs/klooni/Theme.java @@ -0,0 +1,87 @@ +package io.github.lonamiwebs.klooni; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; +import com.badlogic.gdx.scenes.scene2d.ui.Skin; +import com.badlogic.gdx.utils.JsonReader; +import com.badlogic.gdx.utils.JsonValue; + +public class Theme { + + private String displayName; + private String name; + private int price; + private Color background; + private Color[] cells; + private Color[] buttons; + + private Theme() { } + + public static Theme[] getThemes() { + FileHandle[] handles = Gdx.files.internal("themes").list(); + + Theme[] result = new Theme[handles.length]; + for (int i = 0; i < handles.length; i++) { + result[i] = Theme.fromFile(handles[i]); + } + + return result; + } + + static Theme getTheme(final String name) { + return new Theme().update(name); + } + + private static Theme fromFile(FileHandle handle) { + return new Theme().update(handle); + } + + public Theme update(final String name) { + return update(Gdx.files.internal("themes/"+name+".theme")); + } + + private Theme update(final FileHandle handle) { + final JsonValue json = new JsonReader().parse(handle.readString()); + + name = handle.nameWithoutExtension(); + displayName = json.getString("name"); + price = json.getInt("price"); + + JsonValue colors = json.get("colors"); + background = new Color( // Java won't allow unsigned integers, we need to use Long + (int)Long.parseLong(colors.getString("background"), 16)); + + JsonValue buttonColors = colors.get("buttons"); + buttons = new Color[buttonColors.size]; + for (int i = 0; i < buttons.length; i++) { + buttons[i] = new Color((int)Long.parseLong(buttonColors.getString(i), 16)); + } + + JsonValue cellColors = colors.get("cells"); + cells = new Color[cellColors.size]; + for (int i = 0; i < cells.length; i++) { + cells[i] = new Color((int)Long.parseLong(cellColors.getString(i), 16)); + } + + String cellTextureFile = json.getString("cell_texture"); + return this; + } + + // TODO Avoid creating game.skin.newDrawable all the time without disposingā€¦ + public ImageButton.ImageButtonStyle getStyle(final Skin skin, int button, final String imageName) { + return new ImageButton.ImageButtonStyle( + skin.newDrawable("button_up", buttons[button]), + skin.newDrawable("button_down", buttons[button]), + null, skin.getDrawable(imageName), null, null); + } + + public Color getCellColor(int colorIndex) { + return cells[colorIndex]; + } + + void dispose() { + + } +} diff --git a/core/src/io/github/lonamiwebs/klooni/game/Piece.java b/core/src/io/github/lonamiwebs/klooni/game/Piece.java index d20871c..5c146c1 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Piece.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Piece.java @@ -7,16 +7,12 @@ import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; +import io.github.lonamiwebs.klooni.Klooni; + // Pieces can be L shaped and be rotated 0 to 3 times to make it random // Maximum cellSize = 4 public class Piece { - private final static int[] colors = { - 0x7988bfff, 0x98dc53ff, 0x4cd4aeff, // Squares - 0xfec63dff, 0xec9548ff, 0xe66a82ff, 0xda6554ff, // Lines - 0x57cb84ff, 0x5abee2ff // L's - }; - final Vector2 pos; float cellSize = 10f; // Default @@ -26,7 +22,7 @@ public class Piece { final Color color; private Piece(int cols, int rows, boolean swapSize, int colorIndex) { - color = new Color(colors[colorIndex]); + color = Klooni.theme.getCellColor(colorIndex); pos = new Vector2(); cellCols = swapSize ? rows : cols; @@ -40,7 +36,7 @@ public class Piece { } private Piece(int lSize, int rotateCount, int colorIndex) { - color = new Color(colors[colorIndex]); + color = Klooni.theme.getCellColor(colorIndex); pos = new Vector2(); cellCols = cellRows = lSize; diff --git a/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java b/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java index 7f91c34..2bf3665 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java @@ -4,7 +4,6 @@ package io.github.lonamiwebs.klooni.screens; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.Screen; -import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Stage; @@ -14,7 +13,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; -import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import io.github.lonamiwebs.klooni.Klooni; @@ -35,13 +33,7 @@ public class CustomizeScreen implements Screen { optionsGroup.space(12); // Back to the previous screen - ImageButton.ImageButtonStyle backStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.GOLD), - game.skin.newDrawable("button_down", Color.GOLD), - null, game.skin.getDrawable("back_texture"), null, null); - - final ImageButton backButton = new ImageButton(backStyle); - optionsGroup.addActor(backButton); + final ImageButton backButton = new ImageButton(Klooni.theme.getStyle(game.skin, 1, "back_texture")); backButton.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { @@ -49,18 +41,12 @@ public class CustomizeScreen implements Screen { dispose(); } }); + optionsGroup.addActor(backButton); // Turn sound on/off - Drawable soundDrawable = game.skin.getDrawable( - Klooni.soundsEnabled() ? "sound_on_texture" : "sound_off_texture"); + final ImageButton soundButton = new ImageButton(Klooni.theme.getStyle( + game.skin, 0, Klooni.soundsEnabled() ? "sound_on_texture" : "sound_off_texture")); - ImageButton.ImageButtonStyle soundStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.LIME), - game.skin.newDrawable("button_down", Color.LIME), - null, soundDrawable, null, null); - - final ImageButton soundButton = new ImageButton(soundStyle); - optionsGroup.addActor(soundButton); soundButton.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { @@ -69,36 +55,27 @@ public class CustomizeScreen implements Screen { Klooni.soundsEnabled() ? "sound_on_texture" : "sound_off_texture"); } }); + optionsGroup.addActor(soundButton); // Issues - ImageButton.ImageButtonStyle issuesStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.FIREBRICK), - game.skin.newDrawable("button_down", Color.FIREBRICK), - null, game.skin.getDrawable("issues_texture"), null, null); - - final ImageButton issuesButton = new ImageButton(issuesStyle); - optionsGroup.addActor(issuesButton); + final ImageButton issuesButton = new ImageButton(Klooni.theme.getStyle(game.skin, 3, "issues_texture")); issuesButton.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { Gdx.net.openURI("https://github.com/LonamiWeb/Klooni1010/issues"); } }); + optionsGroup.addActor(issuesButton); // Website - ImageButton.ImageButtonStyle webStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", new Color(0x6E99FFFF)), - game.skin.newDrawable("button_down", new Color(0x6E99FFFF)), - null, game.skin.getDrawable("web_texture"), null, null); - - final ImageButton webButton = new ImageButton(webStyle); - optionsGroup.addActor(webButton); + final ImageButton webButton = new ImageButton(Klooni.theme.getStyle(game.skin, 2, "web_texture")); webButton.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { Gdx.net.openURI("https://lonamiwebs.github.io"); } }); + optionsGroup.addActor(webButton); table.add(new ScrollPane(optionsGroup)).pad(20, 4, 12, 4); table.row(); diff --git a/core/src/io/github/lonamiwebs/klooni/screens/MainMenuScreen.java b/core/src/io/github/lonamiwebs/klooni/screens/MainMenuScreen.java index 877b515..bd30933 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/MainMenuScreen.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/MainMenuScreen.java @@ -3,7 +3,6 @@ package io.github.lonamiwebs.klooni.screens; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.Screen; -import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.Actor; @@ -32,56 +31,34 @@ public class MainMenuScreen extends InputListener implements Screen { stage.addActor(table); // Play button - ImageButton.ImageButtonStyle playStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.GREEN), - game.skin.newDrawable("button_down", Color.GREEN), - null, game.skin.getDrawable("play_texture"), null, null); - - final ImageButton playButton = new ImageButton(playStyle); - table.add(playButton).colspan(3).fill().space(16); - + final ImageButton playButton = new ImageButton(Klooni.theme.getStyle(game.skin, 0, "play_texture")); playButton.addListener(new ChangeListener() { public void changed (ChangeEvent event, Actor actor) { game.setScreen(new GameScreen(game)); dispose(); } }); + table.add(playButton).colspan(3).fill().space(16); table.row(); // Star button (on GitHub) - ImageButton.ImageButtonStyle starStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.YELLOW), - game.skin.newDrawable("button_down", Color.YELLOW), - null, game.skin.getDrawable("star_texture"), null, null); - - final ImageButton starButton = new ImageButton(starStyle); + final ImageButton starButton = new ImageButton(Klooni.theme.getStyle(game.skin, 1, "star_texture")); table.add(starButton).space(16); // Stats button (high scores) - ImageButton.ImageButtonStyle statsStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.BLUE), - game.skin.newDrawable("button_down", Color.BLUE), - null, game.skin.getDrawable("stats_texture"), null, null); - - final ImageButton statsButton = new ImageButton(statsStyle); + final ImageButton statsButton = new ImageButton(Klooni.theme.getStyle(game.skin, 2, "stats_texture")); table.add(statsButton).space(16); // Palette button (buy colors) - ImageButton.ImageButtonStyle paletteStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.FIREBRICK), - game.skin.newDrawable("button_down", Color.FIREBRICK), - null, game.skin.getDrawable("palette_texture"), null, null); - - final ImageButton paletteButton = new ImageButton(paletteStyle); - table.add(paletteButton).space(16); - + final ImageButton paletteButton = new ImageButton(Klooni.theme.getStyle(game.skin, 3, "palette_texture")); paletteButton.addListener(new ChangeListener() { public void changed (ChangeEvent event, Actor actor) { game.setScreen(new CustomizeScreen(game, game.getScreen())); // Don't dispose because then it needs to take us to the previous screen } }); + table.add(paletteButton).space(16); } @Override diff --git a/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java b/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java index 4a23f97..5121001 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java @@ -42,12 +42,7 @@ public class PauseMenuStage extends Stage { addActor(band); // Home screen button - ImageButton.ImageButtonStyle homeStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.FIREBRICK), - game.skin.newDrawable("button_down", Color.FIREBRICK), - null, game.skin.getDrawable("home_texture"), null, null); - - final ImageButton homeButton = new ImageButton(homeStyle); + final ImageButton homeButton = new ImageButton(Klooni.theme.getStyle(game.skin, 3, "home_texture")); table.add(homeButton).space(16); homeButton.addListener(new ChangeListener() { @@ -58,12 +53,7 @@ public class PauseMenuStage extends Stage { }); // Replay button - ImageButton.ImageButtonStyle replayStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.GREEN), - game.skin.newDrawable("button_down", Color.GREEN), - null, game.skin.getDrawable("replay_texture"), null, null); - - final ImageButton replayButton = new ImageButton(replayStyle); + final ImageButton replayButton = new ImageButton(Klooni.theme.getStyle(game.skin, 0, "replay_texture")); table.add(replayButton).space(16); replayButton.addListener(new ChangeListener() { @@ -77,12 +67,7 @@ public class PauseMenuStage extends Stage { table.row(); // Palette button (buy colors) - ImageButton.ImageButtonStyle paletteStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.YELLOW), - game.skin.newDrawable("button_down", Color.YELLOW), - null, game.skin.getDrawable("palette_texture"), null, null); - - final ImageButton paletteButton = new ImageButton(paletteStyle); + final ImageButton paletteButton = new ImageButton(Klooni.theme.getStyle(game.skin, 1, "palette_texture")); table.add(paletteButton).space(16); paletteButton.addListener(new ChangeListener() { @@ -95,12 +80,7 @@ public class PauseMenuStage extends Stage { // Continue playing OR share (if game over) button // TODO Enable both actions for this button - ImageButton.ImageButtonStyle playStyle = new ImageButton.ImageButtonStyle( - game.skin.newDrawable("button_up", Color.BLUE), - game.skin.newDrawable("button_down", Color.BLUE), - null, game.skin.getDrawable("play_texture"), null, null); - - final ImageButton playButton = new ImageButton(playStyle); + final ImageButton playButton = new ImageButton(Klooni.theme.getStyle(game.skin, 2, "play_texture")); table.add(playButton).space(16); playButton.addListener(new ChangeListener() {