diff --git a/android/assets/ui/snap_off.png b/android/assets/ui/snap_off.png new file mode 100644 index 0000000..993ab25 Binary files /dev/null and b/android/assets/ui/snap_off.png differ diff --git a/android/assets/ui/snap_on.png b/android/assets/ui/snap_on.png new file mode 100644 index 0000000..2dafd33 Binary files /dev/null and b/android/assets/ui/snap_on.png differ diff --git a/core/src/io/github/lonamiwebs/klooni/Klooni.java b/core/src/io/github/lonamiwebs/klooni/Klooni.java index 9a3df41..8c39939 100644 --- a/core/src/io/github/lonamiwebs/klooni/Klooni.java +++ b/core/src/io/github/lonamiwebs/klooni/Klooni.java @@ -50,6 +50,8 @@ public class Klooni extends Game { skin.add("share_texture", new Texture(Gdx.files.internal("ui/share.png"))); skin.add("sound_on_texture", new Texture(Gdx.files.internal("ui/sound_on.png"))); skin.add("sound_off_texture", new Texture(Gdx.files.internal("ui/sound_off.png"))); + skin.add("snap_on_texture", new Texture(Gdx.files.internal("ui/snap_on.png"))); + skin.add("snap_off_texture", new Texture(Gdx.files.internal("ui/snap_off.png"))); skin.add("issues_texture", new Texture(Gdx.files.internal("ui/issues.png"))); skin.add("credits_texture", new Texture(Gdx.files.internal("ui/credits.png"))); skin.add("web_texture", new Texture(Gdx.files.internal("ui/web.png"))); @@ -121,6 +123,14 @@ public class Klooni extends Game { prefs.putBoolean("muteSound", soundsEnabled()).flush(); } + public static boolean shouldSnapToGrid() { + return prefs.getBoolean("snapToGrid", false); + } + + public static void toggleSnapToGrid() { + prefs.putBoolean("snapToGrid", !shouldSnapToGrid()).flush(); + } + public static boolean isThemeBought(Theme theme) { if (theme.getPrice() == 0) return true; diff --git a/core/src/io/github/lonamiwebs/klooni/game/Board.java b/core/src/io/github/lonamiwebs/klooni/game/Board.java index d091237..01b45ad 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Board.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Board.java @@ -121,6 +121,21 @@ public class Board implements BinSerializable { return putPiece(piece, x, y); } + Vector2 snapToGrid(final Piece piece, final Vector2 position) { + // Snaps the given position (e.g. mouse) to the grid, + // assuming piece wants to be put at the specified position. + // If the piece was not on the grid, the original position is returned + // + // Logic to determine the x and y is a copy-paste from putScreenPiece + final Vector2 local = position.cpy().sub(pos); + int x = MathUtils.round(local.x / piece.cellSize); + int y = MathUtils.round(local.y / piece.cellSize); + if (canPutPiece(piece, x, y)) + return new Vector2(pos.x + x * piece.cellSize, pos.y + y * piece.cellSize); + else + return position; + } + // This will clear both complete rows and columns, all at once. // The reason why we can't check first rows and then columns // (or vice versa) is because the following case (* filled, _ empty): diff --git a/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java b/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java index 7a57844..f70eb04 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java +++ b/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java @@ -209,7 +209,8 @@ public class PieceHolder implements BinSerializable { } // Updates the state of the piece holder (and the held piece) - public void update() { + // TODO Passing the board seems expensive… Should it rather be an attribute? + public void update(Board board) { Piece piece; if (heldPiece > -1) { piece = pieces[heldPiece]; @@ -227,6 +228,8 @@ public class PieceHolder implements BinSerializable { // avoiding to cover it with the finger (issue on Android devices) mouse.sub(piece.getRectangle().width * 0.5f, -pickedCellSize); } + if (Klooni.shouldSnapToGrid()) + mouse.set(board.snapToGrid(piece, mouse)); piece.pos.lerp(mouse, DRAG_SPEED); piece.cellSize = Interpolation.linear.apply(piece.cellSize, pickedCellSize, DRAG_SPEED); diff --git a/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java b/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java index 99ad816..cccbee0 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/CustomizeScreen.java @@ -80,6 +80,20 @@ class CustomizeScreen implements Screen { }); optionsGroup.addActor(soundButton); + // Snap to grid on/off + final SoftButton snapButton = new SoftButton( + 2, Klooni.shouldSnapToGrid() ? "snap_on_texture" : "snap_off_texture"); + + snapButton.addListener(new ChangeListener() { + @Override + public void changed(ChangeEvent event, Actor actor) { + Klooni.toggleSnapToGrid(); + snapButton.image = CustomizeScreen.this.game.skin.getDrawable( + Klooni.shouldSnapToGrid() ? "snap_on_texture" : "snap_off_texture"); + } + }); + optionsGroup.addActor(snapButton); + // Issues final SoftButton issuesButton = new SoftButton(3, "issues_texture"); issuesButton.addListener(new ChangeListener() { diff --git a/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java b/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java index b7aa2b2..05cf406 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java @@ -166,7 +166,7 @@ class GameScreen implements Screen, InputProcessor, BinSerializable { scorer.draw(batch); board.draw(batch); - holder.update(); + holder.update(board); holder.draw(batch); bonusParticleHandler.run(batch); diff --git a/original-resources/buttons.svg b/original-resources/buttons.svg index 3ac7792..b902870 100644 --- a/original-resources/buttons.svg +++ b/original-resources/buttons.svg @@ -102,9 +102,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="4.0000001" - inkscape:cx="16.355684" - inkscape:cy="190.15864" + inkscape:zoom="1.4142136" + inkscape:cx="95.169026" + inkscape:cy="193.1638" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -141,7 +141,7 @@ style="opacity:1;fill:#e3e3e3;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0" id="rect4301" width="120" - height="100" + height="90" x="0" y="752.36218" ry="0" /> @@ -358,14 +358,14 @@ buttons + x="128.69154" + y="836.78644">buttons + + + + + + + diff --git a/original-resources/window_size.svg b/original-resources/window_size.svg index 29d9ea2..25ac142 100644 --- a/original-resources/window_size.svg +++ b/original-resources/window_size.svg @@ -17,7 +17,36 @@ inkscape:version="0.91 r13725" sodipodi:docname="window_size.svg"> + id="defs4"> + + + + + + + image/svg+xml - + @@ -283,7 +312,7 @@ style="opacity:1;fill:#0000ff;fill-opacity:0.25;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect4312" width="715.76221" - height="750.81952" + height="622.24811" x="799.99988" y="243.2572" /> @@ -307,11 +336,6 @@ height="151.81004" x="1474.7661" y="289.58844" /> - default colors - hodor hodor bought - pieces: 300px (25%) + + 42h | confirm purchase? + + + + +