diff --git a/android/assets/share.png b/android/assets/share.png new file mode 100644 index 0000000..7342cc9 Binary files /dev/null and b/android/assets/share.png differ diff --git a/android/assets/themes/bandw.theme b/android/assets/themes/bandw.theme new file mode 100644 index 0000000..87d7119 --- /dev/null +++ b/android/assets/themes/bandw.theme @@ -0,0 +1,26 @@ +{ + "name": "Black et White", + "price": 20, + "colors": { + "background": "0a0a0aff", + "foreground": "202020ff", + "buttons": [ + "f0f0f0ff", + "f0f0f0ff", + "f0f0f0ff", + "f0f0f0ff" + ], + "empty_cell": "000000ff", + "cells": [ + "f2f2f2ff", "f2f2f2ff", "f2f2f2ff", + "f2f2f2ff", "f2f2f2ff", "f2f2f2ff", "f2f2f2ff", + "f2f2f2ff", "f2f2f2ff" + ], + "current_score": "b3b3b3ff", + "high_score": "f9f9f9ff", + "bonus": "f9f9f9ff", + "band": "f0f0f0ff", + "text": "0a0a0aff" + }, + "cell_texture": "basic.png" +} diff --git a/android/assets/themes/dark.theme b/android/assets/themes/dark.theme index 654e204..df7b253 100644 --- a/android/assets/themes/dark.theme +++ b/android/assets/themes/dark.theme @@ -3,6 +3,7 @@ "price": 0, "colors": { "background": "333333ff", + "foreground": "ddddddff", "buttons": [ "03c13dff", "007da4ff", @@ -18,7 +19,8 @@ "current_score": "c83737ff", "high_score": "d400aaff", "bonus": "e3e3e3ff", - "band": "2b5ccfff" + "band": "2b5ccfff", + "text": "ffffffff" }, "cell_texture": "basic.png" } diff --git a/android/assets/themes/default.theme b/android/assets/themes/default.theme index 595d0e6..ee6b2c6 100644 --- a/android/assets/themes/default.theme +++ b/android/assets/themes/default.theme @@ -3,6 +3,7 @@ "price": 0, "colors": { "background": "ffffffff", + "foreground": "ffffffff", "buttons": [ "00ff33ff", "ffd700ff", @@ -18,7 +19,8 @@ "current_score": "ffcc00ff", "high_score": "65d681ff", "bonus": "4d4d4dff", - "band": "87ceebff" + "band": "87ceebff", + "text": "111111ff" }, "cell_texture": "basic.png" } diff --git a/android/assets/themes/solarized-dark.theme b/android/assets/themes/solarized-dark.theme new file mode 100644 index 0000000..6f27107 --- /dev/null +++ b/android/assets/themes/solarized-dark.theme @@ -0,0 +1,26 @@ +{ + "name": "Underwater", + "price": 50, + "colors": { + "background": "0044aaff", + "foreground": "d7f4e3ff", + "buttons": [ + "37c871ff", + "2a7fffff", + "00ccffff", + "5f5fd3ff" + ], + "empty_cell": "0066ffff", + "cells": [ + "37c871ff", "2ad4ffff", "0000d4ff", + "00ffccff", "5599ffff", "87cddeff", "80b3ffff", + "00ff66ff", "00d4aaff" + ], + "current_score": "aaccffff", + "high_score": "2aff80ff", + "bonus": "aaeeffff", + "band": "3771c8ff", + "text": "002255ff" + }, + "cell_texture": "bubble.png" +} diff --git a/android/assets/themes/theme.list b/android/assets/themes/theme.list index 8443421..8ffea23 100644 --- a/android/assets/themes/theme.list +++ b/android/assets/themes/theme.list @@ -1,2 +1,4 @@ default dark +bandw +underwater diff --git a/android/assets/themes/underwater.theme b/android/assets/themes/underwater.theme new file mode 100644 index 0000000..6f27107 --- /dev/null +++ b/android/assets/themes/underwater.theme @@ -0,0 +1,26 @@ +{ + "name": "Underwater", + "price": 50, + "colors": { + "background": "0044aaff", + "foreground": "d7f4e3ff", + "buttons": [ + "37c871ff", + "2a7fffff", + "00ccffff", + "5f5fd3ff" + ], + "empty_cell": "0066ffff", + "cells": [ + "37c871ff", "2ad4ffff", "0000d4ff", + "00ffccff", "5599ffff", "87cddeff", "80b3ffff", + "00ff66ff", "00d4aaff" + ], + "current_score": "aaccffff", + "high_score": "2aff80ff", + "bonus": "aaeeffff", + "band": "3771c8ff", + "text": "002255ff" + }, + "cell_texture": "bubble.png" +} diff --git a/android/assets/ui/cells/basic.png b/android/assets/ui/cells/basic.png index e8f30bc..f242f18 100644 Binary files a/android/assets/ui/cells/basic.png and b/android/assets/ui/cells/basic.png differ diff --git a/android/assets/ui/cells/bubble.png b/android/assets/ui/cells/bubble.png new file mode 100644 index 0000000..54eb12d Binary files /dev/null and b/android/assets/ui/cells/bubble.png differ diff --git a/android/assets/ui/cells/circle.png b/android/assets/ui/cells/circle.png new file mode 100644 index 0000000..875ba9e Binary files /dev/null and b/android/assets/ui/cells/circle.png differ diff --git a/android/assets/ui/x0.75/cells/basic.png b/android/assets/ui/x0.75/cells/basic.png new file mode 100644 index 0000000..f242f18 Binary files /dev/null and b/android/assets/ui/x0.75/cells/basic.png differ diff --git a/android/assets/ui/x0.75/cells/bubble.png b/android/assets/ui/x0.75/cells/bubble.png new file mode 100644 index 0000000..54eb12d Binary files /dev/null and b/android/assets/ui/x0.75/cells/bubble.png differ diff --git a/android/assets/ui/x0.75/cells/circle.png b/android/assets/ui/x0.75/cells/circle.png new file mode 100644 index 0000000..875ba9e Binary files /dev/null and b/android/assets/ui/x0.75/cells/circle.png differ diff --git a/android/assets/ui/x0.75/palette.png b/android/assets/ui/x0.75/palette.png index 0c421f6..5d26360 100644 Binary files a/android/assets/ui/x0.75/palette.png and b/android/assets/ui/x0.75/palette.png differ diff --git a/android/assets/ui/x1.0/cells/basic.png b/android/assets/ui/x1.0/cells/basic.png new file mode 100644 index 0000000..da45655 Binary files /dev/null and b/android/assets/ui/x1.0/cells/basic.png differ diff --git a/android/assets/ui/x1.0/cells/bubble.png b/android/assets/ui/x1.0/cells/bubble.png new file mode 100644 index 0000000..49996f3 Binary files /dev/null and b/android/assets/ui/x1.0/cells/bubble.png differ diff --git a/android/assets/ui/x1.0/cells/circle.png b/android/assets/ui/x1.0/cells/circle.png new file mode 100644 index 0000000..0cae43c Binary files /dev/null and b/android/assets/ui/x1.0/cells/circle.png differ diff --git a/android/assets/ui/x1.0/cells/round.png b/android/assets/ui/x1.0/cells/round.png new file mode 100644 index 0000000..8555cfd Binary files /dev/null and b/android/assets/ui/x1.0/cells/round.png differ diff --git a/android/assets/ui/x1.0/palette.png b/android/assets/ui/x1.0/palette.png index ec20a93..489844b 100644 Binary files a/android/assets/ui/x1.0/palette.png and b/android/assets/ui/x1.0/palette.png differ diff --git a/android/assets/ui/x1.25/cells/basic.png b/android/assets/ui/x1.25/cells/basic.png new file mode 100644 index 0000000..7f6141f Binary files /dev/null and b/android/assets/ui/x1.25/cells/basic.png differ diff --git a/android/assets/ui/x1.25/cells/bubble.png b/android/assets/ui/x1.25/cells/bubble.png new file mode 100644 index 0000000..8bece5e Binary files /dev/null and b/android/assets/ui/x1.25/cells/bubble.png differ diff --git a/android/assets/ui/x1.25/cells/circle.png b/android/assets/ui/x1.25/cells/circle.png new file mode 100644 index 0000000..5668eef Binary files /dev/null and b/android/assets/ui/x1.25/cells/circle.png differ diff --git a/android/assets/ui/x1.25/cells/round.png b/android/assets/ui/x1.25/cells/round.png new file mode 100644 index 0000000..bd5b071 Binary files /dev/null and b/android/assets/ui/x1.25/cells/round.png differ diff --git a/android/assets/ui/x1.25/palette.png b/android/assets/ui/x1.25/palette.png index 59b6489..a4d3b9a 100644 Binary files a/android/assets/ui/x1.25/palette.png and b/android/assets/ui/x1.25/palette.png differ diff --git a/android/assets/ui/x1.5/cells/basic.png b/android/assets/ui/x1.5/cells/basic.png new file mode 100644 index 0000000..f5fe488 Binary files /dev/null and b/android/assets/ui/x1.5/cells/basic.png differ diff --git a/android/assets/ui/x1.5/cells/bubble.png b/android/assets/ui/x1.5/cells/bubble.png new file mode 100644 index 0000000..d5556ac Binary files /dev/null and b/android/assets/ui/x1.5/cells/bubble.png differ diff --git a/android/assets/ui/x1.5/cells/circle.png b/android/assets/ui/x1.5/cells/circle.png new file mode 100644 index 0000000..0cc02e4 Binary files /dev/null and b/android/assets/ui/x1.5/cells/circle.png differ diff --git a/android/assets/ui/x1.5/cells/round.png b/android/assets/ui/x1.5/cells/round.png new file mode 100644 index 0000000..ae0481b Binary files /dev/null and b/android/assets/ui/x1.5/cells/round.png differ diff --git a/android/assets/ui/x1.5/palette.png b/android/assets/ui/x1.5/palette.png index 04160d9..c1ebaaf 100644 Binary files a/android/assets/ui/x1.5/palette.png and b/android/assets/ui/x1.5/palette.png differ diff --git a/android/assets/ui/x2.0/cells/basic.png b/android/assets/ui/x2.0/cells/basic.png new file mode 100644 index 0000000..2058054 Binary files /dev/null and b/android/assets/ui/x2.0/cells/basic.png differ diff --git a/android/assets/ui/x2.0/cells/bubble.png b/android/assets/ui/x2.0/cells/bubble.png new file mode 100644 index 0000000..4f29be6 Binary files /dev/null and b/android/assets/ui/x2.0/cells/bubble.png differ diff --git a/android/assets/ui/x2.0/cells/circle.png b/android/assets/ui/x2.0/cells/circle.png new file mode 100644 index 0000000..e6cfb7a Binary files /dev/null and b/android/assets/ui/x2.0/cells/circle.png differ diff --git a/android/assets/ui/x2.0/cells/round.png b/android/assets/ui/x2.0/cells/round.png new file mode 100644 index 0000000..8574550 Binary files /dev/null and b/android/assets/ui/x2.0/cells/round.png differ diff --git a/android/assets/ui/x2.0/palette.png b/android/assets/ui/x2.0/palette.png index 5828295..34b525d 100644 Binary files a/android/assets/ui/x2.0/palette.png and b/android/assets/ui/x2.0/palette.png differ diff --git a/android/assets/ui/x4.0/cells/basic.png b/android/assets/ui/x4.0/cells/basic.png new file mode 100644 index 0000000..83c16f9 Binary files /dev/null and b/android/assets/ui/x4.0/cells/basic.png differ diff --git a/android/assets/ui/x4.0/cells/bubble.png b/android/assets/ui/x4.0/cells/bubble.png new file mode 100644 index 0000000..3521739 Binary files /dev/null and b/android/assets/ui/x4.0/cells/bubble.png differ diff --git a/android/assets/ui/x4.0/cells/circle.png b/android/assets/ui/x4.0/cells/circle.png new file mode 100644 index 0000000..1660443 Binary files /dev/null and b/android/assets/ui/x4.0/cells/circle.png differ diff --git a/android/assets/ui/x4.0/cells/round.png b/android/assets/ui/x4.0/cells/round.png new file mode 100644 index 0000000..595f57d Binary files /dev/null and b/android/assets/ui/x4.0/cells/round.png differ diff --git a/android/assets/ui/x4.0/palette.png b/android/assets/ui/x4.0/palette.png index ec5e56e..9dff51e 100644 Binary files a/android/assets/ui/x4.0/palette.png and b/android/assets/ui/x4.0/palette.png differ diff --git a/android/build.gradle b/android/build.gradle index c3070d7..53e2aa2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -22,8 +22,8 @@ android { minSdkVersion 8 targetSdkVersion 25 - versionCode 400 - versionName "0.4" + versionCode 500 + versionName "0.5" } } diff --git a/android/src/io/github/lonamiwebs/klooni/AndroidLauncher.java b/android/src/io/github/lonamiwebs/klooni/AndroidLauncher.java index 97611d5..7ebc7b9 100644 --- a/android/src/io/github/lonamiwebs/klooni/AndroidLauncher.java +++ b/android/src/io/github/lonamiwebs/klooni/AndroidLauncher.java @@ -6,10 +6,11 @@ import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; public class AndroidLauncher extends AndroidApplication { - @Override - protected void onCreate (Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); - initialize(new Klooni(), config); - } + @Override + protected void onCreate (Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); + final AndroidShareChallenge shareChallenge = new AndroidShareChallenge(this); + initialize(new Klooni(shareChallenge), config); + } } diff --git a/android/src/io/github/lonamiwebs/klooni/AndroidShareChallenge.java b/android/src/io/github/lonamiwebs/klooni/AndroidShareChallenge.java new file mode 100644 index 0000000..cdc14ac --- /dev/null +++ b/android/src/io/github/lonamiwebs/klooni/AndroidShareChallenge.java @@ -0,0 +1,51 @@ +package io.github.lonamiwebs.klooni; + + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.widget.Toast; + +import java.io.File; + +class AndroidShareChallenge extends ShareChallenge { + + private final Handler handler; + private final Context context; + + AndroidShareChallenge(final Context context) { + handler = new Handler(); + this.context = context; + } + + @Override + File getShareImageFilePath() { + return new File(context.getExternalCacheDir(), "share_challenge.png"); + } + + @Override + public void shareScreenshot(final boolean ok) { + handler.post(new Runnable() { + @Override + public void run() { + if (!ok) { + Toast.makeText(context, "Failed to create the file", Toast.LENGTH_SHORT).show(); + return; + } + + final String text = "Check out my score at 1010 Klooni!"; + final Uri pictureUri = Uri.fromFile(getShareImageFilePath()); + final Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.setType("image/png"); + + shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, ""); + shareIntent.putExtra(Intent.EXTRA_TEXT, text); + shareIntent.putExtra(Intent.EXTRA_STREAM, pictureUri); + + context.startActivity(Intent.createChooser(shareIntent, "Challenge your friends...")); + } + }); + } +} diff --git a/build.gradle b/build.gradle index 7ce013a..cf9b08f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ allprojects { apply plugin: "eclipse" apply plugin: "idea" - version = '0.4' + version = '0.5' ext { appName = "1010! Klooni" gdxVersion = '1.9.5' diff --git a/core/src/io/github/lonamiwebs/klooni/Klooni.java b/core/src/io/github/lonamiwebs/klooni/Klooni.java index 986dd6b..62563cd 100644 --- a/core/src/io/github/lonamiwebs/klooni/Klooni.java +++ b/core/src/io/github/lonamiwebs/klooni/Klooni.java @@ -21,6 +21,8 @@ public class Klooni extends Game { public static Theme theme; public Skin skin; + public ShareChallenge shareChallenge; + public static boolean onDesktop; private final static float SCORE_TO_MONEY = 1f / 100f; @@ -32,6 +34,12 @@ public class Klooni extends Game { //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); diff --git a/core/src/io/github/lonamiwebs/klooni/ShareChallenge.java b/core/src/io/github/lonamiwebs/klooni/ShareChallenge.java new file mode 100644 index 0000000..b3bc28a --- /dev/null +++ b/core/src/io/github/lonamiwebs/klooni/ShareChallenge.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.graphics.GL20; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.PixmapIO; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.glutils.FrameBuffer; +import com.badlogic.gdx.math.Matrix4; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.utils.BufferUtils; +import com.badlogic.gdx.utils.ScreenUtils; + +import java.io.File; + +public abstract class ShareChallenge { + + // Meant to return the file path to which the image will be saved + // On some platforms it might be as simple as Gdx.files.local().file() + abstract File getShareImageFilePath(); + + // Meant to share the saved screenshot at getShareImageFilePath() + public abstract void shareScreenshot(final boolean saveResult); + + // Saves the "Challenge me" shareable image to getShareImageFilePath() + public boolean saveChallengeImage(final int score) { + final File saveAt = getShareImageFilePath(); + if (!saveAt.getParentFile().isDirectory()) + if (!saveAt.mkdirs()) + return false; + + final FileHandle output = new FileHandle(saveAt); + + final Texture shareBase = new Texture(Gdx.files.internal("share.png")); + final int width = shareBase.getWidth(); + final int height = shareBase.getHeight(); + + final FrameBuffer frameBuffer = new FrameBuffer(Pixmap.Format.RGB888, width, height, false); + frameBuffer.begin(); + + // Render the base share texture + final SpriteBatch batch = new SpriteBatch(); + final Matrix4 matrix = new Matrix4(); + matrix.setToOrtho2D(0, 0, width, height); + batch.setProjectionMatrix(matrix); + + Gdx.gl.glClearColor(Color.GOLD.r, Color.GOLD.g, Color.GOLD.b, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + batch.begin(); + batch.draw(shareBase, 0, 0); + + // Render the achieved score + final Label.LabelStyle style = new Label.LabelStyle(); + style.font = new BitmapFont(Gdx.files.internal("font/x1.0/geosans-light64.fnt")); + Label label = new Label("just scored " + score + " on", style); + label.setColor(Color.BLACK); + label.setPosition(40, 500); + label.draw(batch, 1); + + label.setText("try to beat me if you can"); + label.setPosition(40, 40); + label.draw(batch, 1); + + batch.end(); + + // Get the framebuffer pixels and write them to a local file + final byte[] pixels = ScreenUtils.getFrameBufferPixels(0, 0, width, height, true); + + final Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888); + + BufferUtils.copy(pixels, 0, pixmap.getPixels(), pixels.length); + PixmapIO.writePNG(output, pixmap); + + // Dispose everything + pixmap.dispose(); + shareBase.dispose(); + batch.dispose(); + frameBuffer.end(); + + return true; + } +} diff --git a/core/src/io/github/lonamiwebs/klooni/SkinLoader.java b/core/src/io/github/lonamiwebs/klooni/SkinLoader.java index 2e84905..485c1dd 100644 --- a/core/src/io/github/lonamiwebs/klooni/SkinLoader.java +++ b/core/src/io/github/lonamiwebs/klooni/SkinLoader.java @@ -59,7 +59,7 @@ public class SkinLoader { } public static Texture loadPng(String name) { - final String filename = "ui/x" + bestMultiplier + "/" + name + ".png"; + final String filename = "ui/x" + bestMultiplier + "/" + name; return new Texture(Gdx.files.internal(filename)); } } diff --git a/core/src/io/github/lonamiwebs/klooni/Theme.java b/core/src/io/github/lonamiwebs/klooni/Theme.java index 12ff1d6..d366851 100644 --- a/core/src/io/github/lonamiwebs/klooni/Theme.java +++ b/core/src/io/github/lonamiwebs/klooni/Theme.java @@ -24,19 +24,21 @@ public class Theme { private int price; public Color background; + public Color foreground; public Color emptyCell; public Color currentScore; public Color highScore; public Color bonus; public Color bandColor; + public Color textColor; private Color[] cells; private Color[] buttons; public static Skin skin; - public NinePatch cellPatch; + public Texture cellTexture; // Save the button styles so the changes here get reflected private ImageButton.ImageButtonStyle[] buttonStyles; @@ -84,6 +86,20 @@ public class Theme { return new Theme().update(handle); } + // Used to determine the best foreground color (black or white) given a background color + // Formula took from http://alienryderflex.com/hsp.html + // Not used yet, but may be useful + private final static double BRIGHTNESS_CUTOFF = 0.5; + + public static boolean shouldUseWhite(Color color) { + double brightness = Math.sqrt( + color.r * color.r * .299 + + color.g * color.g * .587 + + color.b * color.b * .114); + + return brightness < BRIGHTNESS_CUTOFF; + } + //endregion //region Theme updating @@ -105,8 +121,9 @@ public class Theme { 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)); + // Java won't allow unsigned integers, we need to use Long + background = new Color((int)Long.parseLong(colors.getString("background"), 16)); + foreground = new Color((int)Long.parseLong(colors.getString("foreground"), 16)); JsonValue buttonColors = colors.get("buttons"); buttons = new Color[buttonColors.size]; @@ -125,6 +142,7 @@ public class Theme { highScore = new Color((int)Long.parseLong(colors.getString("high_score"), 16)); bonus = new Color((int)Long.parseLong(colors.getString("bonus"), 16)); bandColor = new Color((int)Long.parseLong(colors.getString("band"), 16)); + textColor = new Color((int)Long.parseLong(colors.getString("text"), 16)); emptyCell = new Color((int)Long.parseLong(colors.getString("empty_cell"), 16)); @@ -135,8 +153,7 @@ public class Theme { } String cellTextureFile = json.getString("cell_texture"); - cellPatch = new NinePatch(new Texture( - Gdx.files.internal("ui/cells/"+cellTextureFile)), 4, 4, 4, 4); + cellTexture = SkinLoader.loadPng("cells/"+cellTextureFile); return this; } diff --git a/core/src/io/github/lonamiwebs/klooni/actors/Band.java b/core/src/io/github/lonamiwebs/klooni/actors/Band.java index db3e3e8..e789ac9 100644 --- a/core/src/io/github/lonamiwebs/klooni/actors/Band.java +++ b/core/src/io/github/lonamiwebs/klooni/actors/Band.java @@ -65,9 +65,11 @@ public class Band extends Actor { scoreLabel.setBounds(x + scoreBounds.x, y + scoreBounds.y, scoreBounds.width, scoreBounds.height); scoreLabel.setText(Integer.toString(scorer.getCurrentScore())); + scoreLabel.setColor(Klooni.theme.textColor); scoreLabel.draw(batch, parentAlpha); infoLabel.setBounds(x + infoBounds.x, y + infoBounds.y, infoBounds.width, infoBounds.height); + infoLabel.setColor(Klooni.theme.textColor); infoLabel.draw(batch, parentAlpha); } diff --git a/core/src/io/github/lonamiwebs/klooni/actors/MoneyBuyBand.java b/core/src/io/github/lonamiwebs/klooni/actors/MoneyBuyBand.java index d4f5088..59ecfd4 100644 --- a/core/src/io/github/lonamiwebs/klooni/actors/MoneyBuyBand.java +++ b/core/src/io/github/lonamiwebs/klooni/actors/MoneyBuyBand.java @@ -182,6 +182,7 @@ public class MoneyBuyBand extends Table { } } setColor(Klooni.theme.bandColor); + infoLabel.setColor(Klooni.theme.textColor); super.draw(batch, parentAlpha); } diff --git a/core/src/io/github/lonamiwebs/klooni/actors/SoftButton.java b/core/src/io/github/lonamiwebs/klooni/actors/SoftButton.java index f61ec83..d79c7ff 100644 --- a/core/src/io/github/lonamiwebs/klooni/actors/SoftButton.java +++ b/core/src/io/github/lonamiwebs/klooni/actors/SoftButton.java @@ -1,5 +1,6 @@ package io.github.lonamiwebs.klooni.actors; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; @@ -19,17 +20,21 @@ public class SoftButton extends ImageButton { //region Constructor - public SoftButton(int styleIndex, String imageName) { + public SoftButton(final int styleIndex, final String imageName) { super(Klooni.theme.getStyle(styleIndex)); this.styleIndex = styleIndex; - image = Theme.skin.getDrawable(imageName); + updateImage(imageName); } //endregion //region Public methods + public void updateImage(final String imageName) { + image = Theme.skin.getDrawable(imageName); + } + @Override public void draw(Batch batch, float parentAlpha) { // Always update the style to make sure we're using the right image. @@ -40,6 +45,7 @@ public class SoftButton extends ImageButton { Klooni.theme.updateStyle(style, styleIndex); style.imageUp = image; + getImage().setColor(Klooni.theme.foreground); super.draw(batch, parentAlpha); } diff --git a/core/src/io/github/lonamiwebs/klooni/actors/ThemeCard.java b/core/src/io/github/lonamiwebs/klooni/actors/ThemeCard.java index 425202c..a4b34f7 100644 --- a/core/src/io/github/lonamiwebs/klooni/actors/ThemeCard.java +++ b/core/src/io/github/lonamiwebs/klooni/actors/ThemeCard.java @@ -1,5 +1,6 @@ package io.github.lonamiwebs.klooni.actors; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; @@ -28,11 +29,11 @@ public class ThemeCard extends Actor { public float cellSize; - //endregion - - //region Static members - - private final static double BRIGHTNESS_CUTOFF = 0.5; + private final static int colorsUsed[][] = { + {0, 7, 7}, + {8, 7, 3}, + {8, 8, 3} + }; //endregion @@ -48,7 +49,7 @@ public class ThemeCard extends Actor { priceLabel = new Label("", labelStyle); nameLabel = new Label(theme.getDisplay(), labelStyle); - Color labelColor = shouldUseWhite(theme.background) ? Color.WHITE : Color.BLACK; + Color labelColor = Theme.shouldUseWhite(theme.background) ? Color.WHITE : Color.BLACK; priceLabel.setColor(labelColor); nameLabel.setColor(labelColor); @@ -69,21 +70,14 @@ public class ThemeCard extends Actor { batch.setColor(theme.background); batch.draw(background, x, y, getWidth(), getHeight()); - // Do not draw on the borders (0,0 offset to add some padding), colors used: - // 0 7 7 - // 8 7 3 - // 8 8 3 - Cell.draw(theme.getCellColor(0), batch, x + cellSize, y + cellSize, cellSize); - Cell.draw(theme.getCellColor(7), batch, x + cellSize * 2, y + cellSize, cellSize); - Cell.draw(theme.getCellColor(7), batch, x + cellSize * 3, y + cellSize, cellSize); - Cell.draw(theme.getCellColor(8), batch, x + cellSize, y + cellSize * 2, cellSize); - Cell.draw(theme.getCellColor(7), batch, x + cellSize * 2, y + cellSize * 2, cellSize); - Cell.draw(theme.getCellColor(8), batch, x + cellSize * 3, y + cellSize * 2, cellSize); - - Cell.draw(theme.getCellColor(8), batch, x + cellSize, y + cellSize * 3, cellSize); - Cell.draw(theme.getCellColor(8), batch, x + cellSize * 2, y + cellSize * 3, cellSize); - Cell.draw(theme.getCellColor(3), batch, x + cellSize * 3, y + cellSize * 3, cellSize); + // Avoid drawing on the borders by adding +1 cell padding + for (int i = 0; i < colorsUsed.length; ++i) { + for (int j = 0; j < colorsUsed[i].length; ++j) { + Cell.draw(theme.cellTexture, theme.getCellColor(colorsUsed[i][j]), batch, + x + cellSize * (j + 1), y + cellSize * (i + 1), cellSize); + } + } nameLabel.setBounds(x + nameBounds.x, y + nameBounds.y, nameBounds.width, nameBounds.height); nameLabel.draw(batch, parentAlpha); @@ -112,19 +106,4 @@ public class ThemeCard extends Actor { } //endregion - - //region Private methods - - // Used to determine the best foreground color (black or white) given a background color - // Formula took from http://alienryderflex.com/hsp.html - private static boolean shouldUseWhite(Color color) { - double brightness = Math.sqrt( - color.r * color.r * .299 + - color.g * color.g * .587 + - color.b * color.b * .114); - - return brightness < BRIGHTNESS_CUTOFF; - } - - //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java b/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java index e8d9900..c5017a6 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java +++ b/core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java @@ -37,7 +37,7 @@ public abstract class BaseScorer implements BinSerializable { // The board size is required when calculating the score BaseScorer(final Klooni game, GameLayout layout, int highScore) { - cupTexture = SkinLoader.loadPng("cup"); + cupTexture = SkinLoader.loadPng("cup.png"); cupColor = Klooni.theme.currentScore.cpy(); cupArea = new Rectangle(); diff --git a/core/src/io/github/lonamiwebs/klooni/game/Cell.java b/core/src/io/github/lonamiwebs/klooni/game/Cell.java index 861332e..f4a827d 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Cell.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Cell.java @@ -2,6 +2,7 @@ package io.github.lonamiwebs.klooni.game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Interpolation; @@ -105,11 +106,18 @@ public class Cell implements BinSerializable { //region Static methods - // TODO Use skin atlas - public static void draw(Color color, Batch batch, - float x, float y, float size) { + // Default texture (don't call overloaded version to avoid overhead) + public static void draw(final Color color, final Batch batch, + final float x, final float y, final float size) { batch.setColor(color); - Klooni.theme.cellPatch.draw(batch, x, y, size, size); + batch.draw(Klooni.theme.cellTexture, x, y, size, size); + } + + // Custom texture + public static void draw(final Texture texture, final Color color, final Batch batch, + final float x, final float y, final float size) { + batch.setColor(color); + batch.draw(texture, x, y, size, size); } //endregion diff --git a/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java b/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java index f27ba70..624ab34 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java @@ -125,6 +125,7 @@ class GameScreen implements Screen, InputProcessor, BinSerializable { if (!gameOverDone) { gameOverDone = true; + saveMoney(); holder.enabled = false; pauseMenu.showGameOver(gameOverReason); if (Klooni.soundsEnabled()) @@ -150,13 +151,7 @@ class GameScreen implements Screen, InputProcessor, BinSerializable { // Save the state, the user might leave the game in any of the following 2 methods private void showPauseMenu() { - // Calculate new money since the previous saving - int nowScore = scorer.getCurrentScore(); - int newMoneyScore = nowScore - savedMoneyScore; - savedMoneyScore = nowScore; - Klooni.addMoneyFromScore(newMoneyScore); - - // Show the pause menu + saveMoney(); pauseMenu.show(); save(); } @@ -275,6 +270,14 @@ class GameScreen implements Screen, InputProcessor, BinSerializable { //region Saving and loading + private void saveMoney() { + // Calculate new money since the previous saving + int nowScore = scorer.getCurrentScore(); + int newMoneyScore = nowScore - savedMoneyScore; + savedMoneyScore = nowScore; + Klooni.addMoneyFromScore(newMoneyScore); + } + private void save() { // Only save if the game is not over and the game mode is not the time mode. It // makes no sense to save the time game mode since it's supposed to be something quick. diff --git a/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java b/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java index 10c4cea..6b37de1 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/PauseMenuStage.java @@ -1,8 +1,11 @@ package io.github.lonamiwebs.klooni.screens; +import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; +import com.badlogic.gdx.files.FileHandle; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Interpolation; @@ -13,7 +16,10 @@ import com.badlogic.gdx.scenes.scene2d.actions.RunnableAction; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; +import java.io.File; + import io.github.lonamiwebs.klooni.Klooni; +import io.github.lonamiwebs.klooni.ShareChallenge; import io.github.lonamiwebs.klooni.actors.Band; import io.github.lonamiwebs.klooni.actors.SoftButton; import io.github.lonamiwebs.klooni.game.BaseScorer; @@ -31,8 +37,10 @@ class PauseMenuStage extends Stage { private final ShapeRenderer shapeRenderer; + private final Klooni game; private final Band band; private final BaseScorer scorer; + private final SoftButton playButton; //endregion @@ -40,6 +48,7 @@ class PauseMenuStage extends Stage { // We need the score to save the maximum score if a new record was beaten PauseMenuStage(final GameLayout layout, final Klooni game, final BaseScorer scorer, final int gameMode) { + this.game = game; this.scorer = scorer; shapeRenderer = new ShapeRenderer(20); // 20 vertex seems to be enough for a rectangle @@ -90,8 +99,7 @@ class PauseMenuStage extends Stage { }); // Continue playing OR share (if game over) button - // TODO Enable both actions for this button? Or leave play? - final SoftButton playButton = new SoftButton(2, "play_texture"); + playButton = new SoftButton(2, "play_texture"); table.add(playButton).space(16); playButton.addListener(new ChangeListener() { @@ -143,6 +151,16 @@ class PauseMenuStage extends Stage { } void showGameOver(final String gameOverReason) { + if (game.shareChallenge != null) { + playButton.updateImage("share_texture"); + playButton.addListener(new ChangeListener() { + public void changed(ChangeEvent event, Actor actor) { + game.shareChallenge.shareScreenshot( + game.shareChallenge.saveChallengeImage(scorer.getCurrentScore())); + } + }); + } + band.setMessage(gameOverReason); show(); } @@ -166,7 +184,9 @@ class PauseMenuStage extends Stage { // This is the only place where ShapeRenderer is OK because the batch hasn't started Gdx.gl.glEnable(GL20.GL_BLEND); shapeRenderer.begin(ShapeRenderer.ShapeType.Filled); - shapeRenderer.setColor(1f, 1f, 1f, 0.3f); + Color color = new Color(Klooni.theme.bandColor); + color.a = 0.1f; + shapeRenderer.setColor(color); shapeRenderer.rect(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); shapeRenderer.end(); } diff --git a/desktop/src/io/github/lonamiwebs/klooni/desktop/DesktopLauncher.java b/desktop/src/io/github/lonamiwebs/klooni/desktop/DesktopLauncher.java index dbd83d5..f9f2e3b 100644 --- a/desktop/src/io/github/lonamiwebs/klooni/desktop/DesktopLauncher.java +++ b/desktop/src/io/github/lonamiwebs/klooni/desktop/DesktopLauncher.java @@ -14,6 +14,6 @@ public class DesktopLauncher { config.addIcon("ic_launcher/icon128.png", Files.FileType.Internal); config.addIcon("ic_launcher/icon32.png", Files.FileType.Internal); config.addIcon("ic_launcher/icon16.png", Files.FileType.Internal); - new LwjglApplication(new Klooni(), config); + new LwjglApplication(new Klooni(null), config); } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dd70a4a..c69932f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Sat Apr 08 12:05:23 CEST 2017 +#Thu May 04 19:58:22 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/html/src/io/github/lonamiwebs/klooni/client/HtmlLauncher.java b/html/src/io/github/lonamiwebs/klooni/client/HtmlLauncher.java index 2229472..cdb4719 100644 --- a/html/src/io/github/lonamiwebs/klooni/client/HtmlLauncher.java +++ b/html/src/io/github/lonamiwebs/klooni/client/HtmlLauncher.java @@ -14,6 +14,6 @@ public class HtmlLauncher extends GwtApplication { @Override public ApplicationListener createApplicationListener () { - return new Klooni(); + return new Klooni(null); } } diff --git a/ios/src/io/github/lonamiwebs/klooni/IOSLauncher.java b/ios/src/io/github/lonamiwebs/klooni/IOSLauncher.java index fc18d90..0a78b49 100644 --- a/ios/src/io/github/lonamiwebs/klooni/IOSLauncher.java +++ b/ios/src/io/github/lonamiwebs/klooni/IOSLauncher.java @@ -11,7 +11,7 @@ public class IOSLauncher extends IOSApplication.Delegate { @Override protected IOSApplication createApplication() { IOSApplicationConfiguration config = new IOSApplicationConfiguration(); - return new IOSApplication(new Klooni(), config); + return new IOSApplication(new Klooni(null), config); } public static void main(String[] argv) { diff --git a/original-resources/buttons.svg b/original-resources/buttons.svg index 87900c0..15360c7 100644 --- a/original-resources/buttons.svg +++ b/original-resources/buttons.svg @@ -10,15 +10,27 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="500" - height="500" + width="533.33331" + height="533.33331" viewBox="0 0 500.00001 500.00001" id="svg2" version="1.1" - inkscape:version="0.91 r13725" + inkscape:version="0.92.1 r15371" sodipodi:docname="buttons.svg"> + + + + @@ -94,6 +106,17 @@ y1="1012.8427" x2="-441.97687" y2="1072.3632" /> + + id="grid4248" + originx="0" + originy="0" + spacingx="1" + spacingy="1" /> @@ -159,7 +186,7 @@ inkscape:export-xdpi="90" inkscape:export-filename="/home/lonami/button_up" style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - d="m 4.5449252,998.2813 c -2.8585,3.9506 -4.5449200236115,8.8096 -4.5449200236115,14.08 l 0,16 c 0,13.296 10.7039998236115,24 23.9999998236115,24 l 16,0 c 4.9535,0 9.54683,-1.4871 13.36133,-4.039 l -27.91016,0 c -11.58215,0 -20.9062498,-9.3241 -20.9062498,-20.9063 l 0,-29.1347 z" + d="m 4.5449252,998.2813 c -2.8585,3.9506 -4.5449200236115,8.8096 -4.5449200236115,14.08 v 16 c 0,13.296 10.7039998236115,24 23.9999998236115,24 h 16 c 4.9535,0 9.54683,-1.4871 13.36133,-4.039 h -27.91016 c -11.58215,0 -20.9062498,-9.3241 -20.9062498,-20.9063 z" id="path4252" inkscape:connector-curvature="0" /> @@ -209,7 +236,7 @@ rx="24" /> @@ -272,48 +299,17 @@ width="64" id="rect4218" style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> - - - - - - - + + transform="matrix(3.0000588,0,0,3.0000588,0,-2123.8991)"> buttons + y="836.78644" + style="font-size:15.69341087px;line-height:1.25">buttons cells - - - - - - - + x="7.3185968" + y="769.04504" + style="font-size:15.69341087px;line-height:1.25">cells @@ -634,24 +593,24 @@ style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> @@ -729,7 +688,7 @@ @@ -757,21 +716,21 @@ transform="translate(-357.12497,7.2166511)"> + transform="translate(-340)"> + transform="translate(-350)"> measures - 2px radius - 4px patch - - - - - - - - + y="587.79303" + style="font-size:40px;line-height:1.25">measures 24px radius + y="600.63055" + style="font-size:10.25197601px;line-height:1.25">24px radius 28px patch + sodipodi:role="line" + style="font-size:10.25197601px;line-height:1.25">28px patch @@ -1099,7 +976,7 @@ + transform="rotate(-45)" /> @@ -1220,5 +1097,23 @@ d="m 320.52609,778.38092 c -0.57668,0.0508 -1.14636,0.20524 -1.67578,0.47266 l -1.69336,0.85547 c -2.11769,1.06969 -2.76965,3.52564 -1.46289,5.50586 l 5.56836,8.43945 -7.875,6.89063 c -1.84803,1.61683 -1.84803,4.21909 0,5.83593 l 0.95312,0.83399 c 1.84803,1.61684 4.82189,1.61684 6.66992,0 l 5.83399,-5.10352 4.125,6.25196 c 1.30675,1.98021 4.06395,2.71227 6.18164,1.64257 l 1.69336,-0.85547 c 2.11769,-1.06969 2.76965,-3.52564 1.46289,-5.50586 l -5.56836,-8.43945 7.875,-6.89062 c 1.84803,-1.61684 1.84803,-4.2191 0,-5.83594 l -0.95312,-0.83399 c -1.84804,-1.61683 -4.82385,-1.61683 -6.67188,0 l -5.83203,5.10352 -4.125,-6.25195 c -0.98007,-1.48516 -2.77584,-2.26753 -4.50586,-2.11524 z" style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:30;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + + + + diff --git a/original-resources/gen-ui-png.py b/original-resources/gen-ui-png.py index 6335a7e..dc1a3b8 100755 --- a/original-resources/gen-ui-png.py +++ b/original-resources/gen-ui-png.py @@ -36,6 +36,11 @@ ids = [ 'web' ] +cells = [ + 'basic', + 'bubble' +] + inkscape_default_dpi = 90 svg = 'buttons.svg' root = '../android/assets/ui' @@ -55,4 +60,10 @@ for multiplier in multipliers: # -d to specify the DPI run(f'inkscape -z -i{objectid} -j -e{filename} -d{dpi} {svg}', shell=True, stdout=DEVNULL) - + + folder = os.path.join(folder, 'cells') + os.makedirs(folder, exist_ok=True) + for cellid in cells: + filename = os.path.join(folder, cellid + '.png') + run(f'inkscape -z -i{cellid} -j -e{filename} -d{dpi} {svg}', + shell=True, stdout=DEVNULL) diff --git a/original-resources/share.svg b/original-resources/share.svg new file mode 100644 index 0000000..fbcbf6f --- /dev/null +++ b/original-resources/share.svg @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/generate_theme.py b/themes/generate_theme.py index 233513a..6f3925d 100755 --- a/themes/generate_theme.py +++ b/themes/generate_theme.py @@ -5,14 +5,18 @@ import re import os import subprocess -color_re = \ - re.compile('') + +fill_re = \ + re.compile('fill:#([0-9a-f]+)') template = '''{{ "name": "{name}", "price": {price}, "colors": {{ "background": "{background}", + "foreground": "{foreground}", "buttons": [ "{button_0}", "{button_1}", @@ -28,7 +32,8 @@ template = '''{{ "current_score": "{current_score}", "high_score": "{high_score}", "bonus": "{bonus}", - "band": "{band}" + "band": "{band}", + "text": "{text}" }}, "cell_texture": "{cell_tex}" }} @@ -90,9 +95,14 @@ def work(filename): xml = f.read().replace('\n', '') replacements = {} - for m in color_re.finditer(xml): + for m in group_id_re.finditer(xml): + f = fill_re.search(m.group(0)) + if not f: + raise ValueError( + 'Error: The object %s missing the fill attribute' % m.group(1)) + # Append 'ff' because the themes require the alpha to be set - replacements[m.group(1)] = m.group(2)+'ff' + replacements[m.group(1)] = f.group(1) + 'ff' replacements['name'] = input('Enter theme name for "{}": '.format(name)) replacements['price'] = input('Enter theme price: ') diff --git a/themes/template.svg b/themes/template.svg index 30f717a..30891d4 100644 --- a/themes/template.svg +++ b/themes/template.svg @@ -1,42 +1,17 @@ - - + id="svg2" + viewBox="0 0 800.00001 700.00001" + height="746.66669" + width="853.33331"> - @@ -50,228 +25,234 @@ + transform="translate(0,-352.36216)" + id="layer1"> + transform="translate(0,-199.99998)"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + d="M 26.857031,798.76837 H 378.28562 V 907.33982 H 26.857031 Z" + style="opacity:1;fill:#00f230;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + transform="translate(0,-199.99998)"> - - - + style="fill:#2182ef;fill-opacity:1" + id="export_button_2" + transform="translate(0,-199.99998)"> + id="rect4153" + style="opacity:1;fill:#2182ef;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> - - - - - - + style="fill:#ce4444;fill-opacity:1" + id="export_button_3" + transform="translate(0,-199.99998)"> + style="opacity:1;fill:#ce4444;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect4155" + width="105.7143" + height="108.57145" + x="266.85712" + y="921.62555" /> + style="fill:#ffcc00;fill-opacity:1" + id="export_current_score" + transform="translate(0,-199.99998)"> + style="opacity:1;fill:#ffcc00;fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="m 106.16769,680.7189 a 20.572971,33.748715 52.281084 0 0 -0.3613,0.23047 h -3.5703 a 31.071428,74.892753 0 0 0 0.207,2.32227 20.572971,33.748715 52.281084 0 0 -17.67971,31.1875 20.572971,33.748715 52.281084 0 0 27.33211,9.97851 31.071428,74.892753 0 0 0 16.5234,18.62501 19.482912,22.977165 0 0 0 -14.6016,18.60157 h 38.4278 a 19.482912,22.977165 0 0 0 -15.1055,-18.75 31.071428,74.892753 0 0 0 16.3164,-18.47853 33.748715,20.572971 37.718916 0 0 27.3379,-9.97656 33.748715,20.572971 37.718916 0 0 -17.6738,-31.1836 31.071428,74.892753 0 0 0 0.2011,-2.32617 h -3.5703 a 33.748715,20.572971 37.718916 0 0 -0.3613,-0.23047 l -0.033,0.23047 h -53.3555 l -0.033,-0.23047 z m -3.2187,8.00977 a 31.071428,74.892753 0 0 0 7.5312,32.01562 16.78108,29.001088 59.891063 0 1 -22.259706,-8.39257 16.78108,29.001088 59.891063 0 1 14.728506,-23.62305 z m 59.8652,0.004 a 29.001088,16.78108 30.108937 0 1 14.7227,23.61915 29.001088,16.78108 30.108937 0 1 -22.2637,8.39062 31.071428,74.892753 0 0 0 7.541,-32.00977 z m -29.9355,4.67774 4.1054,8.31836 9.1797,1.33398 -6.6426,6.47461 1.5684,9.14453 -8.2109,-4.3164 -8.211,4.3164 1.5684,-9.14453 -6.6445,-6.47461 9.1816,-1.33398 z" + id="path4181" /> + + + + + + + + + + + + + + +