# HG changeset patch # User dermetfan # Date 1422321258 -3600 # Tue Jan 27 02:14:18 2015 +0100 # Node ID 11c541d96f861581c5f16087855316333108ee29 # Parent e1e8c0df5f9d05d5697073bd9d59f34cc63fc30b various minor architecture changes diff --git a/core/src/net/dermetfan/jigsawPuzzle/puzzle/JigsawPuzzle.java b/core/src/net/dermetfan/jigsawPuzzle/puzzle/JigsawPuzzle.java --- a/core/src/net/dermetfan/jigsawPuzzle/puzzle/JigsawPuzzle.java +++ b/core/src/net/dermetfan/jigsawPuzzle/puzzle/JigsawPuzzle.java @@ -30,100 +30,59 @@ import com.badlogic.gdx.utils.Pools; import net.dermetfan.jigsawPuzzle.Constants; import net.dermetfan.jigsawPuzzle.utils.PolygonRegionDrawable; -import net.dermetfan.utils.libgdx.math.GeometryUtils; import net.dermetfan.utils.libgdx.scene2d.Scene2DUtils; /** represents a puzzle and manages {@link Piece Pieces} * @author dermetfan */ public class JigsawPuzzle { - private final Array placedPieces, remainingPieces; + private final Array pieces; public JigsawPuzzle() { - remainingPieces = new Array<>(Piece.class); - placedPieces = new Array<>(Piece.class); + pieces = new Array<>(Piece.class); } /** @param pieces the amount of pieces that will probably be in this puzzle */ public JigsawPuzzle(int pieces) { - remainingPieces = new Array<>(pieces); - placedPieces = new Array<>(pieces); - } - - /** @param pieces the {@link #remainingPieces remaining pieces} */ - public JigsawPuzzle(Piece... pieces) { - remainingPieces = new Array<>(pieces); - placedPieces = new Array<>(pieces.length); + this.pieces = new Array<>(pieces); } - /** Solves the puzzle by {@link #place(Piece) placing} all {@link #remainingPieces remaining pieces}. - * @param relativeTo the piece relative to which the puzzle should be solved */ - public void solve(Piece relativeTo) { - if(placedPieces.contains(relativeTo, true) || remainingPieces.contains(relativeTo, true)) - for(Piece piece : remainingPieces) { - if(piece == relativeTo) - continue; - place(piece); - } - else - throw new IllegalArgumentException("the reference piece is not part of the puzzle"); - } - - /** moves all {@link #placedPieces} to {@link #remainingPieces} */ - public void unsolve() { - remainingPieces.addAll(placedPieces); - placedPieces.clear(); - placedPieces.ensureCapacity(remainingPieces.size); // just for performance + /** @param pieces the {@link #pieces} */ + public JigsawPuzzle(Piece... pieces) { + this.pieces = new Array<>(pieces); } - /** Places the given piece in its spot on the puzzle. If no piece was {@link #placedPieces placed} yet, it's position is assumed to be correct (hence it will simply be moved to {@link #placedPieces}) - * @param piece the piece to automatically place in its spot on the puzzle */ - public void place(Piece piece) { - if(!remainingPieces.removeValue(piece, true)) - throw new IllegalArgumentException("the given piece is not remaining and hence cannot be automatically placed"); - Piece ref = placedPieces.size > 0 ? placedPieces.first() : piece; - piece.snap(ref); - placedPieces.add(piece); - } - - /** @param piece the piece to add to {@link #remainingPieces} */ - public void addRemaining(Piece piece) { - placedPieces.removeValue(piece, true); - remainingPieces.add(piece); + /** solves the puzzle by letting all {@link #pieces} {@link Piece#place(Piece) snap} into their spot + * @param relativeTo the piece relative to which the puzzle should be solved */ + public void solve(Piece relativeTo) { + if(!pieces.contains(relativeTo, true)) + throw new IllegalArgumentException("the reference piece is not part of the puzzle"); + for(Piece piece : pieces) { + if(piece == relativeTo) + continue; + piece.place(relativeTo); + } } - /** @return if the puzzle is solved */ - public boolean isSolved() { - return remainingPieces.size == 0; + /** @param piece the piece to add to {@link #pieces} */ + public void add(Piece piece) { + if(!pieces.contains(piece, true)) + pieces.add(piece); } - /** Checks if the given piece is correctly positioned. Always returns true if no piece was placed yet. - * @param piece the piece which position to check - * @param tolerance the distance by which the piece is allowed to be off - * @return if the given piece is correctly placed in relation to {@link #placedPieces} */ - public boolean isCorrectlyPlaced(Piece piece, float tolerance) { - return placedPieces.size <= 0 || piece.inRelationTo(placedPieces.first(), tolerance); - } - - /** usually not necessary, {@link #isSolved()} should return the right result - * @param tolerance the distance by which each piece is allowed to be off - * @return if the {@link #placedPieces} are really correctly placed */ - public boolean checkPlaced(float tolerance) { - Piece reference = placedPieces.first(); - for(Piece piece : placedPieces) - if(!piece.inRelationTo(reference, tolerance)) + /** @param tolerance the distance by which each piece is allowed to be off + * @return if the puzzle is solved */ + public boolean isSolved(float tolerance) { + Piece reference = pieces.first(); + for(Piece piece : pieces) + if(!piece.isPlacedCorrectly(reference, tolerance)) return false; return true; } - /** @return the {@link #placedPieces} */ - public Array getPlacedPieces() { - return placedPieces; - } - - /** @return the {@link #remainingPieces} */ - public Array getRemainingPieces() { - return remainingPieces; + /** @return the {@link #pieces} */ + public Array getPieces() { + return pieces; } public Source createSource(final Group board, final DragAndDrop dnd) { @@ -181,11 +140,10 @@ Actor dragged = payload.getDragActor(); Scene2DUtils.addAtStageCoordinates(dragged, board); if(dragged instanceof Piece) { - Piece piece = (Piece) dragged; - if(isCorrectlyPlaced(piece, Constants.tolerance)) { - if(remainingPieces.contains(piece, true)) // TODO remove this condition (not the body!) when Puzzle doesn't know the difference between remaining and placed Pieces anymore - place(piece); // snap it into its perfect position in relation to some already placed piece - if(isSolved() && solvedCallback != null) + Piece piece = (Piece) dragged, ref = pieces.first(); + if(piece.isPlacedCorrectly(ref, Constants.tolerance)) { + piece.place(ref); // snap it into its perfect position in relation to some already placed piece + if(isSolved(Constants.tolerance) && solvedCallback != null) solvedCallback.run(); } } @@ -197,7 +155,7 @@ * @author dermetfan */ public static class Piece extends Image { - /** the position of the piece on the puzzle (the minX and minY of its vertices) */ + /** the position of the piece on the puzzle (the {@link PolygonRegionDrawable#getPolygonX() minX} and {@link PolygonRegionDrawable#getPolygonY() minY} of its vertices) */ private float slotX, slotY; public Piece(PolygonRegionDrawable drawable) { @@ -224,27 +182,27 @@ if(hit == this && drawable != null) { tmpPolygon.setVertices(drawable.getRegion().getVertices()); tmpPolygon.setPosition(-slotX, -slotY); - if(!tmpPolygon.contains(x / getWidth() * GeometryUtils.width(tmpPolygon.getVertices()), y / getHeight() * GeometryUtils.height(tmpPolygon.getVertices()))) + if(!tmpPolygon.contains(x / getWidth() * drawable.getPolygonWidth(), y / getHeight() * drawable.getPolygonHeight())) return null; } return hit; } - /** @param ref the piece in relation to which to snap into this piece's spot */ - public void snap(Piece ref) { - Vector2 refPuzzlePoint = Pools.obtain(Vector2.class).set(ref.getX(), ref.getY()).sub(ref.slotX, ref.slotY); + /** @param reference the piece in relation to which to this piece should snap in its spot */ + public void place(Piece reference) { + Vector2 refPuzzlePoint = Pools.obtain(Vector2.class).set(reference.getX(), reference.getY()).sub(reference.slotX, reference.slotY); setPosition(refPuzzlePoint.x + slotX, refPuzzlePoint.y + slotY); Pools.free(refPuzzlePoint); } - /** @param ref the piece in which relation this piece should be - * @param tolerance the tolerance in the x and y axis - * @return if this piece is in relation to the given piece with the given tolerance */ - public boolean inRelationTo(Piece ref, float tolerance) { + /** @param reference the piece in relation to which this piece's position should be checked + * @param tolerance the distance by which each piece is allowed to be off + * @return if this piece is placed correctly in relation to the given reference piece with the given tolerance */ + public boolean isPlacedCorrectly(Piece reference, float tolerance) { // get puzzle points (bottom left corner of the puzzle) - Vector2 puzzlePoint = Pools.obtain(Vector2.class).set(-slotX, -slotY), refPuzzlePoint = Pools.obtain(Vector2.class).set(-ref.slotX, -ref.slotY); + Vector2 puzzlePoint = Pools.obtain(Vector2.class).set(-slotX, -slotY), refPuzzlePoint = Pools.obtain(Vector2.class).set(-reference.slotX, -reference.slotY); localToStageCoordinates(puzzlePoint); - ref.localToStageCoordinates(refPuzzlePoint); + reference.localToStageCoordinates(refPuzzlePoint); // see if they're the same boolean rel = puzzlePoint.epsilonEquals(refPuzzlePoint, tolerance); diff --git a/core/src/net/dermetfan/jigsawPuzzle/screens/PlayScreen.java b/core/src/net/dermetfan/jigsawPuzzle/screens/PlayScreen.java --- a/core/src/net/dermetfan/jigsawPuzzle/screens/PlayScreen.java +++ b/core/src/net/dermetfan/jigsawPuzzle/screens/PlayScreen.java @@ -83,7 +83,7 @@ float nextX = 0, tallest = 0; for(FileHandle psh : Assets.puzzlePSHs(level)) { // set up the pieces on the bank Piece piece = new Piece(new PolygonRegionDrawable(Assets.manager.get(psh.path(), PolygonRegion.class))); - puzzle.addRemaining(piece); + puzzle.add(piece); board.addActor(piece); piece.setX(nextX); nextX += piece.getWidth(); diff --git a/core/src/net/dermetfan/jigsawPuzzle/utils/PolygonRegionDrawable.java b/core/src/net/dermetfan/jigsawPuzzle/utils/PolygonRegionDrawable.java --- a/core/src/net/dermetfan/jigsawPuzzle/utils/PolygonRegionDrawable.java +++ b/core/src/net/dermetfan/jigsawPuzzle/utils/PolygonRegionDrawable.java @@ -99,4 +99,14 @@ return polygonY; } + /** @return the {@link #polygonWidth} */ + public float getPolygonWidth() { + return polygonWidth; + } + + /** @return the {@link #polygonHeight} */ + public float getPolygonHeight() { + return polygonHeight; + } + }