summaryrefslogtreecommitdiff
path: root/core/src/kz/ilotterytea/maxon/ui
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2024-06-01 00:51:20 +0500
committerilotterytea <iltsu@alright.party>2024-06-01 00:51:20 +0500
commite49f8b310d6032c99406baf04b5ec3eba0fd111f (patch)
tree5120a1fbbf923da5ee8bc8561ed1545855aa5547 /core/src/kz/ilotterytea/maxon/ui
parent10e9df6190ddc3f9c8dd7c86482449bec4651e0c (diff)
upd: moved the whole project under kz.ilotterytea.maxon name
Diffstat (limited to 'core/src/kz/ilotterytea/maxon/ui')
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/AnimatedImage.java60
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/AnimatedImageButton.java24
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/DebugInfo.kt56
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/InventoryAnimatedItem.java26
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/LeafParticle.java30
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/MovingChessBackground.java150
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/NinepatchButton.java28
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/OptionsTable.java180
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/PurchaseItem.java85
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/SavegameWidget.java202
-rw-r--r--core/src/kz/ilotterytea/maxon/ui/SupaIconButton.java24
11 files changed, 865 insertions, 0 deletions
diff --git a/core/src/kz/ilotterytea/maxon/ui/AnimatedImage.java b/core/src/kz/ilotterytea/maxon/ui/AnimatedImage.java
new file mode 100644
index 0000000..097fb2b
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/AnimatedImage.java
@@ -0,0 +1,60 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
+import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
+import com.badlogic.gdx.utils.Disposable;
+
+public class AnimatedImage extends Image implements Disposable {
+ private final TextureRegion[] regions;
+ private int index = 0;
+
+ private boolean stopAnim = false;
+
+ public AnimatedImage(TextureRegion[] regions) {
+ super(regions[0]);
+ this.regions = regions;
+ }
+
+ @Override public void act(float delta) {
+ if (!stopAnim) {
+ if (index > regions.length - 1) {
+ index = 0;
+ }
+ if (regions[index + 1] == null) {
+ index = 0;
+ }
+ super.setDrawable(new TextureRegionDrawable(regions[index]));
+ index++;
+ }
+ super.act(delta);
+ }
+
+ public TextureRegion getFrame(int index) { return regions[index]; }
+ public int getIndex() { return index; }
+ public Drawable getDrawable() { return super.getDrawable(); }
+
+ public void nextFrame() {
+ index++;
+
+ if (index > regions.length - 1 || regions[index] == null) {
+ index = 0;
+ }
+
+ super.setDrawable(new TextureRegionDrawable(regions[index]));
+ }
+
+ public void disableAnim() { stopAnim = true; }
+ public void enableAnim() { stopAnim = false; }
+
+ public boolean isAnimationStopped() { return stopAnim; }
+
+ @Override public void dispose() {
+ for (TextureRegion reg : regions) {
+ if (reg != null) {
+ reg.getTexture().dispose();
+ }
+ }
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/AnimatedImageButton.java b/core/src/kz/ilotterytea/maxon/ui/AnimatedImageButton.java
new file mode 100644
index 0000000..4972afd
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/AnimatedImageButton.java
@@ -0,0 +1,24 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
+import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
+
+public class AnimatedImageButton extends ImageButton {
+ public AnimatedImageButton(AnimatedImage image) {
+ super(image.getDrawable());
+ ImageButtonStyle style = new ImageButtonStyle();
+
+ style.up = image.getDrawable();
+ super.setStyle(style);
+ }
+
+ public void setDrawable(Drawable drawable) {
+ ImageButtonStyle style = new ImageButtonStyle();
+
+ style.up = drawable;
+ super.setStyle(style);
+ }
+
+ @Override public void act(float delta) {
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/DebugInfo.kt b/core/src/kz/ilotterytea/maxon/ui/DebugInfo.kt
new file mode 100644
index 0000000..7329725
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/DebugInfo.kt
@@ -0,0 +1,56 @@
+package kz.ilotterytea.maxon.ui
+
+import com.badlogic.gdx.Gdx
+import com.badlogic.gdx.Version
+import com.badlogic.gdx.scenes.scene2d.ui.Label
+import com.badlogic.gdx.scenes.scene2d.ui.Skin
+import com.badlogic.gdx.scenes.scene2d.ui.Table
+import com.badlogic.gdx.utils.Align
+import kz.ilotterytea.maxon.MaxonConstants
+import kz.ilotterytea.maxon.utils.I18N
+
+/**
+ * Debug information.
+ * @since a_1.0
+ * @author ilotterytea
+ */
+class DebugInfo(skin: Skin, locale: I18N) : Table() {
+ private val i18n = locale
+ private var c_fps: Label
+ private var c_mem: Label
+
+ init {
+ val rt = Runtime.getRuntime()
+ val usedmem = ((rt.totalMemory() - rt.freeMemory()) / 1024) / 1024
+ val totalmem = (rt.totalMemory() / 1024) / 1024
+
+ // Version info:
+ val ver = Label(i18n.FormattedText("debug.version", MaxonConstants.GAME_VERSION, Version.VERSION, System.getProperty("java.version")), skin, "debug")
+ ver.setAlignment(Align.left)
+ this.add(ver).fillX().row()
+
+ // Frames per second:
+ c_fps = Label(i18n.FormattedText("debug.c_fps", Gdx.graphics.framesPerSecond.toString()), skin, "debug")
+ c_fps.setAlignment(Align.left)
+ this.add(c_fps).fillX().row()
+
+ // Memory usage:
+ c_mem = Label(i18n.FormattedText("debug.c_mem", usedmem.toString(), totalmem.toString()), skin, "debug")
+ c_mem.setAlignment(Align.left)
+ this.add(c_mem).fillX().row()
+
+ this.align(Align.left)
+ this.skin = skin
+ this.background("tile_03")
+ }
+
+ override fun act(delta: Float) {
+ val rt = Runtime.getRuntime()
+ val usedmem = ((rt.totalMemory() - rt.freeMemory()) / 1024) / 1024
+ val totalmem = (rt.totalMemory() / 1024) / 1024
+
+ super.act(delta)
+ c_fps.setText(i18n.FormattedText("debug.c_fps", Gdx.graphics.framesPerSecond.toString()))
+ c_mem.setText(i18n.FormattedText("debug.c_mem", usedmem.toString(), totalmem.toString()))
+ }
+} \ No newline at end of file
diff --git a/core/src/kz/ilotterytea/maxon/ui/InventoryAnimatedItem.java b/core/src/kz/ilotterytea/maxon/ui/InventoryAnimatedItem.java
new file mode 100644
index 0000000..af6c6da
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/InventoryAnimatedItem.java
@@ -0,0 +1,26 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.scenes.scene2d.ui.*;
+import kz.ilotterytea.maxon.player.MaxonItem;
+
+public class InventoryAnimatedItem extends Stack {
+ public InventoryAnimatedItem(
+ MaxonItem item,
+ Skin skin,
+ Integer amount
+ ) {
+ super(new Image(item.icon.getDrawable()));
+
+ Table table = new Table();
+ table.setSize(super.getWidth(), super.getHeight());
+ table.add(new Label(String.format("x%s", amount), skin, "default")).bottom().right();
+
+ TextTooltip.TextTooltipStyle style = new TextTooltip.TextTooltipStyle();
+ style.label = new Label.LabelStyle();
+ style.label.font = skin.getFont("small");
+ style.label.fontColor = skin.getColor("white");
+
+ super.add(table);
+ super.addListener(new TextTooltip(String.format("%s (%s)", item.name, item.multiplier), style));
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/LeafParticle.java b/core/src/kz/ilotterytea/maxon/ui/LeafParticle.java
new file mode 100644
index 0000000..82879cf
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/LeafParticle.java
@@ -0,0 +1,30 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.Sprite;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+
+public class LeafParticle extends Sprite {
+ private float angle, x, y, vertAngle, rotation, time;
+
+ public LeafParticle(TextureRegion region, float x, float y, float angle, float vertAngle, float rotation) {
+ super(region);
+ this.angle = angle;
+ this.vertAngle = vertAngle;
+ this.rotation = rotation;
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public void draw(Batch batch) {
+ this.time = Gdx.graphics.getDeltaTime();
+ this.x -= (float) Math.sin(time) * this.angle;
+ this.y -= (float) Math.sin(time) * this.vertAngle;
+
+ super.setPosition(x, y);
+ super.setRotation(super.getRotation() + this.rotation);
+ super.draw(batch);
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/MovingChessBackground.java b/core/src/kz/ilotterytea/maxon/ui/MovingChessBackground.java
new file mode 100644
index 0000000..a585d0b
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/MovingChessBackground.java
@@ -0,0 +1,150 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MovingChessBackground {
+ private final Logger log = LoggerFactory.getLogger(MovingChessBackground.class.getSimpleName());
+
+ private final float velocityX;
+ private final float velocityY;
+ private float screenWidth, screenHeight;
+ private final List<Drawable> drawables;
+
+ private final ArrayList<ArrayList<Image>> tiles;
+
+ /**
+ * Background that looking like chess and moves.
+ * @param velocityX X Velocity
+ * @param velocityY Y Velocity
+ * @param screenWidth Width of the screen
+ * @param screenHeight Height of the screen
+ * @param drawables Drawables to draw
+ */
+ public MovingChessBackground(
+ float velocityX,
+ float velocityY,
+ float screenWidth,
+ float screenHeight,
+ Drawable... drawables
+ ) {
+ this.tiles = new ArrayList<>();
+ this.drawables = Arrays.asList(drawables);
+
+ this.velocityX = velocityX;
+ this.velocityY = velocityY;
+ this.screenWidth = screenWidth;
+ this.screenHeight = screenHeight;
+
+ update(screenWidth, screenHeight);
+ }
+
+ /**
+ * Clean up the background tiles and create new ones.
+ * @param width Width of the screen.
+ * @param height Height of the screen.
+ */
+ public void update(float width, float height) {
+ screenWidth = width;
+ screenHeight = height;
+
+ log.info("Starting to update the \"Moving chess\" background...");
+ tiles.clear();
+ log.info("List of tiles is cleared!");
+
+ float totalDWidth = 0, totalDHeight = 0;
+
+ for (Drawable drawable : drawables) {
+ totalDWidth += 64;
+ totalDHeight += 64;
+ }
+
+ totalDWidth = totalDWidth / drawables.size();
+ totalDHeight = totalDHeight / drawables.size();
+
+ log.info(String.format("Total size of %s drawables: %sx%s", drawables.size(), totalDWidth, totalDHeight));
+
+ int DIndex = 0;
+
+ log.info("Starting to generating tiles...");
+
+ for (int h = 0; h < height / totalDHeight + 3; h++) {
+ tiles.add(h, new ArrayList<Image>());
+
+ for (int w = -1; w < width / totalDWidth; w++) {
+ if (DIndex + 1 > drawables.size()) DIndex = 0;
+ Image tile = new Image(drawables.get(DIndex++));
+ tile.setSize(64f, 64f);
+
+ tile.setPosition(tile.getWidth() * w, tile.getHeight() * h);
+
+ tiles.get(h).add(tile);
+ }
+ }
+
+ log.info("\"Moving chess\" background is successfully updated!");
+ }
+
+ /**
+ * Draw the background tiles.
+ * @param batch Sprite batch.
+ */
+ public void draw(
+ SpriteBatch batch
+ ) {
+ ArrayList<ArrayList<Image>> outYSprites = new ArrayList<>();
+
+ // For horizontal:
+ for (ArrayList<Image> array : tiles) {
+ for (Image tile : array) {
+ tile.setPosition(tile.getX() + velocityX, tile.getY() + velocityY);
+ tile.draw(batch, 1f);
+
+ if (tile.getX() > screenWidth) {
+ Image fTile = array.get(0);
+
+ tile.setPosition(fTile.getX() - tile.getWidth(), fTile.getY());
+
+ if (array.size() > 1 && tile.getDrawable() == fTile.getDrawable()) {
+ tile.setDrawable(array.get(1).getDrawable());
+ }
+
+ array.remove(tile);
+ array.add(0, tile);
+ }
+
+ if (!outYSprites.contains(array) && tile.getY() > screenHeight) {
+ outYSprites.add(array);
+ }
+ }
+ }
+
+ // For vertical:
+ for (ArrayList<Image> array : outYSprites) {
+ int index = 0;
+
+ for (Image tile : array) {
+ if (index + 1 > tiles.get(0).size()) index = 0;
+ Image fTile = tiles.get(0).get(index++);
+ tile.setPosition(tile.getX(), fTile.getY() - tile.getHeight());
+
+ if (fTile.getDrawable() == tile.getDrawable()) {
+ if (index + 1 > tiles.get(0).size()) index = 0;
+ tile.setDrawable(tiles.get(0).get(index).getDrawable());
+ }
+ }
+
+ tiles.remove(array);
+ tiles.add(0, array);
+ }
+
+ outYSprites.clear();
+ }
+} \ No newline at end of file
diff --git a/core/src/kz/ilotterytea/maxon/ui/NinepatchButton.java b/core/src/kz/ilotterytea/maxon/ui/NinepatchButton.java
new file mode 100644
index 0000000..ab96c63
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/NinepatchButton.java
@@ -0,0 +1,28 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.graphics.g2d.NinePatch;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable;
+
+public class NinepatchButton extends TextButton {
+ public NinepatchButton(
+ NinePatch up,
+ NinePatch down,
+ NinePatch over,
+ String text,
+ Skin skin,
+ String styleName
+ ) {
+ super(text, skin, styleName);
+ TextButtonStyle style = new TextButtonStyle();
+
+ style.up = new NinePatchDrawable(up);
+ style.down = new NinePatchDrawable(down);
+ style.over = new NinePatchDrawable(over);
+ style.fontColor = skin.getColor("white");
+ style.font = skin.getFont("default");
+
+ super.setStyle(style);
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/OptionsTable.java b/core/src/kz/ilotterytea/maxon/ui/OptionsTable.java
new file mode 100644
index 0000000..2b0a185
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/OptionsTable.java
@@ -0,0 +1,180 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.audio.Music;
+import com.badlogic.gdx.files.FileHandle;
+import com.badlogic.gdx.math.Interpolation;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.actions.Actions;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Align;
+import kz.ilotterytea.maxon.MaxonConstants;
+import kz.ilotterytea.maxon.MaxonGame;
+import kz.ilotterytea.maxon.screens.SplashScreen;
+import kz.ilotterytea.maxon.utils.I18N;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class OptionsTable extends Table {
+ public OptionsTable(
+ final MaxonGame game,
+ Skin skin,
+ Skin widgetSkin,
+ final Music music,
+ final Table menuTable,
+ final Image bgImage,
+ final Image brandLogo
+ ) {
+ super();
+
+ Label optionsLabel = new Label(game.locale.TranslatableText("options.title"), skin);
+ optionsLabel.setAlignment(Align.center);
+ super.add(optionsLabel).fillX().pad(81f).row();
+
+ Table lidlOptionsTable = new Table();
+
+ // Music button:
+ final TextButton musicButton = new TextButton(game.locale.FormattedText("options.music", (game.prefs.getBoolean("music", true)) ? "ON" : "OFF"), widgetSkin, "default");
+
+ musicButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ game.prefs.putBoolean("music", !game.prefs.getBoolean("music", true));
+ game.prefs.flush();
+
+ if (game.prefs.getBoolean("music", true)) {
+ music.setVolume(1f);
+ music.setLooping(true);
+ music.play();
+ } else {
+ music.stop();
+ }
+
+ musicButton.setText(game.locale.FormattedText("options.music", (game.prefs.getBoolean("music", true)) ? "ON" : "OFF"));
+ }
+ });
+
+ lidlOptionsTable.add(musicButton).size(512f, 81f).pad(10f).left();
+
+ final TextButton soundButton = new TextButton(game.locale.FormattedText("options.sound", (game.prefs.getBoolean("sound", true)) ? "ON" : "OFF"), widgetSkin, "default");
+
+ soundButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ game.prefs.putBoolean("sound", !game.prefs.getBoolean("sound", true));
+ game.prefs.flush();
+
+ soundButton.setText(game.locale.FormattedText("options.sound", (game.prefs.getBoolean("sound", true)) ? "ON" : "OFF"));
+ }
+ });
+
+ lidlOptionsTable.add(soundButton).size(512f, 81f).pad(10f).right().row();
+
+ final TextButton vsyncButton = new TextButton(game.locale.FormattedText("options.vsync", (game.prefs.getBoolean("vsync", true)) ? "ON" : "OFF"), widgetSkin, "default");
+
+ vsyncButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ game.prefs.putBoolean("vsync", !game.prefs.getBoolean("vsync", true));
+ game.prefs.flush();
+
+ if (game.prefs.getBoolean("vsync", true)) {
+ Gdx.graphics.setVSync(true);
+ } else {
+ Gdx.graphics.setVSync(false);
+ }
+
+ vsyncButton.setText(game.locale.FormattedText("options.vsync", (game.prefs.getBoolean("vsync", true)) ? "ON" : "OFF"));
+ }
+ });
+
+ lidlOptionsTable.add(vsyncButton).size(512f, 81f).pad(10f).left();
+
+ final TextButton fullscreenButton = new TextButton(game.locale.FormattedText("options.fullscreen", (game.prefs.getBoolean("fullscreen", false)) ? "ON" : "OFF"), widgetSkin, "default");
+
+ fullscreenButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ game.prefs.putBoolean("fullscreen", !game.prefs.getBoolean("fullscreen", false));
+ game.prefs.flush();
+
+ if (game.prefs.getBoolean("fullscreen", false)) {
+ Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
+ } else {
+ Gdx.graphics.setWindowedMode(game.prefs.getInteger("width", Gdx.graphics.getWidth()), game.prefs.getInteger("height", Gdx.graphics.getHeight()));
+ }
+
+ fullscreenButton.setText(game.locale.FormattedText("options.fullscreen", (game.prefs.getBoolean("fullscreen", false)) ? "ON" : "OFF"));
+ }
+ });
+
+ lidlOptionsTable.add(fullscreenButton).size(512f, 81f).pad(10f).right().row();
+
+ super.add(lidlOptionsTable).center().row();
+
+ String[] fh4Locale = game.locale.getFileHandle().nameWithoutExtension().split("_");
+ Locale locale = new Locale(fh4Locale[0], fh4Locale[1]);
+
+ final TextButton switchLangButton = new TextButton(game.locale.FormattedText("options.language", locale.getDisplayLanguage(), locale.getDisplayCountry()), widgetSkin, "default");
+
+ switchLangButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ int index = 0;
+ ArrayList<FileHandle> fhArray = new ArrayList<>();
+ fhArray.add(MaxonConstants.FILE_RU_RU);
+ fhArray.add(MaxonConstants.FILE_EN_US);
+
+ if (fhArray.indexOf(game.locale.getFileHandle()) + 1 < fhArray.size()) {
+ index = fhArray.indexOf(game.locale.getFileHandle()) + 1;
+ }
+
+ FileHandle fhNext = fhArray.get(index);
+
+ game.locale = new I18N(fhNext);
+ game.prefs.putString("lang", fhNext.nameWithoutExtension());
+ game.prefs.flush();
+
+ String[] fh4Locale = fhNext.nameWithoutExtension().split("_");
+ Locale locale = new Locale(fh4Locale[0], fh4Locale[1]);
+
+ switchLangButton.setText(game.locale.FormattedText("options.language", locale.getDisplayLanguage(), locale.getDisplayCountry()));
+ game.setScreen(new SplashScreen(game));
+ music.stop();
+ }
+ });
+
+ super.add(switchLangButton).size(1024f, 81f).padTop(91f).center().row();
+
+ final TextButton optionsCloseButton = new TextButton(game.locale.TranslatableText("options.close"), widgetSkin, "default");
+
+ optionsCloseButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ close(menuTable, bgImage, brandLogo);
+ }
+ });
+
+ super.add(optionsCloseButton).size(1024f, 81f).pad(91f).center().row();
+
+ super.setPosition(0, 0);
+ super.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+ }
+
+ private void close(Table menu, Image bg, Image logo) {
+ super.clearActions();
+ super.addAction(Actions.moveTo(Gdx.graphics.getWidth(), super.getY(), 0.75f, Interpolation.sine));
+
+ menu.clearActions();
+ menu.addAction(Actions.moveTo(0, menu.getY(), 0.75f, Interpolation.sine));
+
+ bg.clearActions();
+ bg.addAction(Actions.alpha(0.25f));
+
+ logo.addAction(
+ Actions.moveTo(logo.getX(), logo.getY() - 512f, 0.5f, Interpolation.sine)
+ );
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/PurchaseItem.java b/core/src/kz/ilotterytea/maxon/ui/PurchaseItem.java
new file mode 100644
index 0000000..5ef7ab6
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/PurchaseItem.java
@@ -0,0 +1,85 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Align;
+import kz.ilotterytea.maxon.MaxonConstants;
+import kz.ilotterytea.maxon.player.MaxonItem;
+
+public class PurchaseItem extends Table {
+ private double price;
+ private final Label priceLabel;
+ private final MaxonItem item;
+
+ private boolean isDisabled = false;
+
+ public PurchaseItem(
+ Skin skin,
+ MaxonItem item
+ ) {
+ super(skin);
+ super.setBackground("shop_item");
+ super.align(Align.left | Align.center);
+
+ super.add(item.icon).size(64f).pad(6f);
+
+ this.price = item.price;
+ this.item = item;
+
+ Table summary = new Table();
+ summary.align(Align.topLeft);
+
+ Label name = new Label(item.name, skin, "item_title");
+ name.setAlignment(Align.left);
+
+ this.priceLabel = new Label(String.format("%s SQP (%s/click)", MaxonConstants.DECIMAL_FORMAT.format(price), MaxonConstants.DECIMAL_FORMAT.format(item.multiplier)), skin, "item_price");
+ this.priceLabel.setAlignment(Align.left);
+
+ summary.add(name).align(Align.left).row();
+ summary.add(this.priceLabel).grow();
+
+ super.add(summary).grow();
+
+ super.addListener(new ClickListener() {
+ @Override
+ public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
+ super.enter(event, x, y, pointer, fromActor);
+ if (!isDisabled) {
+ PurchaseItem.super.setBackground("shop_item_hover");
+ }
+ }
+ @Override
+ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
+ super.exit(event, x, y, pointer, toActor);
+ if (!isDisabled) {
+ PurchaseItem.super.setBackground("shop_item");
+ }
+ }
+ });
+ }
+
+ public void setPrice(double price) {
+ this.price = price;
+ this.priceLabel.setText(String.format("%s SQP (%s/click)", MaxonConstants.DECIMAL_FORMAT.format(price), MaxonConstants.DECIMAL_FORMAT.format(item.multiplier)));
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public boolean isDisabled() {
+ return isDisabled;
+ }
+
+ public void setDisabled(boolean disabled) {
+ isDisabled = disabled;
+
+ super.setBackground(isDisabled ? "bg" : "shop_item");
+ }
+
+ public MaxonItem getItem() {
+ return item;
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/SavegameWidget.java b/core/src/kz/ilotterytea/maxon/ui/SavegameWidget.java
new file mode 100644
index 0000000..7069911
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/SavegameWidget.java
@@ -0,0 +1,202 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;
+import com.badlogic.gdx.scenes.scene2d.Action;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.actions.Actions;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Align;
+import com.badlogic.gdx.utils.Disposable;
+import kz.ilotterytea.maxon.MaxonGame;
+import kz.ilotterytea.maxon.player.MaxonSavegame;
+import kz.ilotterytea.maxon.screens.GameScreen;
+import kz.ilotterytea.maxon.utils.formatters.NumberFormatter;
+
+import java.io.IOException;
+
+public class SavegameWidget extends Table implements Disposable {
+ private final Skin skin;
+ private MaxonSavegame savegame;
+ private final Table dataTable, controlTable;
+ private final TextureAtlas atlas;
+ private final MaxonGame game;
+ private final Stage stage;
+
+ public SavegameWidget(final MaxonGame game, Skin skin, final Stage stage, final MaxonSavegame savegame) {
+ super();
+ this.game = game;
+ this.stage = stage;
+ this.atlas = game.assetManager.get("MainSpritesheet.atlas", TextureAtlas.class);
+
+ this.skin = skin;
+ this.savegame = savegame;
+
+ this.dataTable = new Table(this.skin);
+ this.dataTable.pad(16f);
+ this.dataTable.setBackground("bg");
+
+ super.add(this.dataTable).grow().padBottom(16f).row();
+
+ this.controlTable = new Table();
+ this.controlTable.align(Align.left);
+ super.add(this.controlTable).growX();
+
+ if (savegame == null) {
+ createEmpty();
+ } else {
+ createWithSavegame();
+ }
+ }
+
+ private void createEmpty() {
+ final boolean[] gameCreation = {false};
+
+ // Body
+ Table body = new Table();
+
+ Label name = new Label("New Game", skin);
+ name.setAlignment(Align.center);
+ body.add(name).grow().row();
+
+ this.dataTable.add(body).grow().row();
+
+ // - - - C O N T R O L - - -
+ TextButton playButton = new TextButton("play", skin);
+ TextField field = new TextField(System.getProperty("user.name", "Maxon"), skin);
+
+ body.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+
+ if (!gameCreation[0]) {
+ name.setText("What is your name?");
+
+ body.add(field).growX();
+
+ controlTable.add(playButton).growX();
+ gameCreation[0] = true;
+ }
+ }
+ });
+
+ playButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+
+ if (savegame == null) {
+ savegame = new MaxonSavegame();
+ savegame.name = field.getText();
+ }
+
+ moveToNextScreen();
+ }
+ });
+ }
+
+ private void createWithSavegame() {
+ // - - - S A V E G A M E D A T A - - -
+ // Header
+ Table header = new Table();
+
+ Label name = new Label(savegame.name, skin);
+ header.add(name).grow();
+
+ long minutes = savegame.elapsedTime / 1000 / 60;
+ long seconds = savegame.elapsedTime / 1000 % 60;
+
+ Label time = new Label(String.format("%s:%s", NumberFormatter.pad(minutes), NumberFormatter.pad(seconds)), skin);
+ time.setAlignment(Align.right);
+ header.add(time).grow().row();
+
+ this.dataTable.add(header).grow().row();
+
+ // Data
+ Table data = new Table();
+ data.align(Align.left);
+
+ // Points
+ Image pointsIcon = new Image(atlas.findRegion("points"));
+ data.add(pointsIcon).size(32f, 32f).padRight(8f);
+
+ Label points = new Label(NumberFormatter.format(savegame.points), skin);
+ data.add(points).padRight(32f);
+
+ // Unit
+ long amount = savegame.inv.size();
+
+ Image unitIcon = new Image(atlas.findRegion("points"));
+ data.add(unitIcon).size(32f, 32f).padRight(8f);
+
+ Label unit = new Label(NumberFormatter.format(amount), skin);
+ data.add(unit).padRight(32f);
+
+ // Multiplier
+ Image multiplierIcon = new Image(atlas.findRegion("multiplier"));
+ data.add(multiplierIcon).size(32f, 32f).padRight(8f);
+
+ Label multiplier = new Label(NumberFormatter.format(savegame.multiplier), skin);
+ data.add(multiplier);
+
+ this.dataTable.add(data).grow();
+
+ // - - - C O N T R O L - - -
+ TextButton playButton = new TextButton(game.locale.TranslatableText("menu.continue"), skin);
+ controlTable.add(playButton).padRight(16f).growX();
+
+ playButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+ moveToNextScreen();
+ }
+ });
+
+ TextButton resetButton = new TextButton(game.locale.TranslatableText("menu.reset"), skin);
+ controlTable.add(resetButton);
+
+ resetButton.addListener(new ClickListener() {
+ @Override
+ public void clicked(InputEvent event, float x, float y) {
+ super.clicked(event, x, y);
+
+ controlTable.clear();
+ dataTable.clear();
+ createEmpty();
+ }
+ });
+ }
+
+ private void moveToNextScreen() {
+ Image bg = new Image(skin, "white_tile");
+ bg.setFillParent(true);
+
+ bg.addAction(
+ Actions.sequence(
+ Actions.alpha(0.0f),
+ Actions.alpha(1.0f, 1.5f),
+ Actions.delay(0.5f),
+ new Action() {
+ @Override
+ public boolean act(float delta) {
+ try {
+ game.setScreen(new GameScreen(game, savegame, 0));
+ } catch (IOException | ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ }
+ }
+ )
+ );
+ stage.addActor(bg);
+ }
+
+ @Override
+ public void dispose() {
+ atlas.dispose();
+ }
+}
diff --git a/core/src/kz/ilotterytea/maxon/ui/SupaIconButton.java b/core/src/kz/ilotterytea/maxon/ui/SupaIconButton.java
new file mode 100644
index 0000000..2ebdbc0
--- /dev/null
+++ b/core/src/kz/ilotterytea/maxon/ui/SupaIconButton.java
@@ -0,0 +1,24 @@
+package kz.ilotterytea.maxon.ui;
+
+import com.badlogic.gdx.graphics.g2d.NinePatch;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
+import com.badlogic.gdx.utils.Align;
+
+public class SupaIconButton extends Stack {
+
+ public SupaIconButton(
+ NinePatch ninepatch,
+ CharSequence text,
+ Skin skin
+ ) {
+ super(new Image(ninepatch));
+
+ Label label = new Label(text, skin);
+ Table table = new Table();
+
+ label.setAlignment(Align.center);
+
+ table.add(label).expand().fillX().center().left();
+ super.add(table);
+ }
+}