diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java b/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java index 3b42f55d6246b0ab264d7c763ef14614fe163f10..6e67f5ab84f86e0a21b7c9a33e6c8103e36dd573 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java @@ -130,7 +130,9 @@ public class PursuitGame extends AbstractTablexiaGame<int[][]> { dragAndRotateActorListener = new DragAndRotateActorListener(new DragAndRotateActorListener.IOnRotationFinished() { @Override - public void onRotationFinished() { + public void onDragAndRotationFinished() { + Log.info(getClass(),"DRAG AND ROTATION FINISHED"); + dragAndRotateActorListener.setPieceAnimationDone(true); setGameScore(SCORE_KEY_MOVE_COUNT, movesCounter++); } }) { diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/action/Interruptable.java b/core/src/cz/nic/tablexia/game/games/pursuit/action/Interruptable.java new file mode 100644 index 0000000000000000000000000000000000000000..3c087a9b47555f22f7a07d7d6b6291d90999e8c9 --- /dev/null +++ b/core/src/cz/nic/tablexia/game/games/pursuit/action/Interruptable.java @@ -0,0 +1,8 @@ +package cz.nic.tablexia.game.games.pursuit.action; + +/** + * Created by Václav TarantĂk on 26.10.15. + */ +public interface Interruptable { + void interrupt(); +} diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/action/MovePieceToPosition.java b/core/src/cz/nic/tablexia/game/games/pursuit/action/MovePieceToPosition.java index 23ec4b91ff61e7252776d98348409bb9d6d9e770..6bfdcf736daa81cfe9ff7d3b7f79883bbdb8ee6c 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/action/MovePieceToPosition.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/action/MovePieceToPosition.java @@ -11,7 +11,7 @@ import cz.nic.tablexia.util.listener.DragAndRotateActorListener; /** * Created by Václav TarantĂk on 3.8.15. */ -public class MovePieceToPosition extends SequenceAction { +public class MovePieceToPosition extends SequenceAction implements Interruptable { /* *Moves specified piece in position using built-in actions @@ -19,11 +19,20 @@ public class MovePieceToPosition extends SequenceAction { public MovePieceToPosition(final PuzzlePiece draggedPiece, Point dest){ setActor(draggedPiece); setTarget(draggedPiece); - addAction(Actions.moveTo(dest.x, dest.y, DragAndRotateActorListener.MOVETO_ANIMATION_DURATION)); + addAction(new MyMoveToAction(dest.x, dest.y, DragAndRotateActorListener.MOVETO_ANIMATION_DURATION)); } public MovePieceToPosition(final PuzzlePiece draggedPiece, Point dest,Action finalAction){ this(draggedPiece,dest); addAction(finalAction); } + + @Override + public void interrupt() { + for(Action action: getActions()){ + if(action instanceof Interruptable){ + ((Interruptable)action).interrupt(); + } + } + } } diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/action/MyMoveToAction.java b/core/src/cz/nic/tablexia/game/games/pursuit/action/MyMoveToAction.java new file mode 100644 index 0000000000000000000000000000000000000000..3735fcc67a7dc9e9f117bf8551c3cd7053f3c284 --- /dev/null +++ b/core/src/cz/nic/tablexia/game/games/pursuit/action/MyMoveToAction.java @@ -0,0 +1,33 @@ +package cz.nic.tablexia.game.games.pursuit.action; + +import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction; + +import cz.nic.tablexia.util.Log; + +/** + * Created by Václav TarantĂk on 26.10.15. + */ +public class MyMoveToAction extends MoveToAction implements Interruptable { + private boolean interrupted; + + public MyMoveToAction(float x, float y, float duration){ + setPosition(x, y); + setDuration(duration); + } + @Override + protected void update(float percent) { + if(!interrupted){ + super.update(percent); + } + } + + private void setInterrupted(boolean interrupted) { + this.interrupted = interrupted; + } + + @Override + public void interrupt() { + Log.info(getClass(),"Interrupting action"); + setInterrupted(true); + } +} diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/action/RotateAndMovePieceInPosition.java b/core/src/cz/nic/tablexia/game/games/pursuit/action/RotateAndMovePieceInPosition.java index 9be82be065bb143d2259bbe3b13c2e990e76e075..a3beb56458a00aedbe5d8078f784534c46cdec75 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/action/RotateAndMovePieceInPosition.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/action/RotateAndMovePieceInPosition.java @@ -1,9 +1,12 @@ package cz.nic.tablexia.game.games.pursuit.action; import com.badlogic.gdx.scenes.scene2d.Action; +import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction; +import com.badlogic.gdx.scenes.scene2d.actions.TemporalAction; +import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Point; import cz.nic.tablexia.game.games.pursuit.model.PuzzlePiece; import cz.nic.tablexia.util.listener.DragAndRotateActorListener; @@ -11,19 +14,27 @@ import cz.nic.tablexia.util.listener.DragAndRotateActorListener; /** * Created by Václav TarantĂk on 3.8.15. */ -public class RotateAndMovePieceInPosition extends SequenceAction { - public RotateAndMovePieceInPosition(PuzzlePiece draggedPiece,Point position, final DragAndRotateActorListener.IOnRotationFinished iOnRotationFinished){ +public class RotateAndMovePieceInPosition extends SequenceAction implements Interruptable{ + public RotateAndMovePieceInPosition(PuzzlePiece draggedPiece,float originalRotation, Point position, final DragAndRotateActorListener.IOnRotationFinished iOnRotationFinished){ setActor(draggedPiece); setTarget(draggedPiece); Action rotationFinishedAction = new Action() { @Override public boolean act(float delta) { - iOnRotationFinished.onRotationFinished(); + iOnRotationFinished.onDragAndRotationFinished(); return true; } }; - addAction(Actions.parallel(new RotatePieceToClosestAngle(draggedPiece),new MovePieceToPosition(draggedPiece,position))); + addAction(Actions.parallel(new RotatePieceToClosestAngle(draggedPiece,originalRotation),new MovePieceToPosition(draggedPiece,position))); addAction(rotationFinishedAction); } + + public void interrupt(){ + for(Action a: getActions()){ + if(a instanceof Interruptable){ + ((Interruptable)a).interrupt(); + } + } + } } diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/action/RotatePieceToClosestAngle.java b/core/src/cz/nic/tablexia/game/games/pursuit/action/RotatePieceToClosestAngle.java index 211e24950d1bc379528ebac29db92d232364b98b..28bea3a78de3ae5726241404aa146af82ccc3e0a 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/action/RotatePieceToClosestAngle.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/action/RotatePieceToClosestAngle.java @@ -17,13 +17,18 @@ public class RotatePieceToClosestAngle extends SequenceAction { setActor(draggedPiece); addAction(Actions.rotateTo(ArithmeticsHelper.getClosestRightAngle(draggedPiece.getRotation()), DragAndRotateActorListener.ROTATION_ANIMATION_DURATION)); } + public RotatePieceToClosestAngle(PuzzlePiece draggedPiece,float originalRotation){ + setTarget(draggedPiece); + setActor(draggedPiece); + addAction(Actions.rotateTo(ArithmeticsHelper.getAngleInRotationDirection(originalRotation,draggedPiece.getRotation()), DragAndRotateActorListener.ROTATION_ANIMATION_DURATION)); + } - public RotatePieceToClosestAngle(PuzzlePiece draggedPiece, final DragAndRotateActorListener.IOnRotationFinished iOnRotationFinished){ - this(draggedPiece); + public RotatePieceToClosestAngle(PuzzlePiece draggedPiece, float originalRotation,final DragAndRotateActorListener.IOnRotationFinished iOnRotationFinished){ + this(draggedPiece,originalRotation); Action afterAction = new Action() { @Override public boolean act(float delta) { - iOnRotationFinished.onRotationFinished(); + iOnRotationFinished.onDragAndRotationFinished(); return true; } }; diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/helper/ArithmeticsHelper.java b/core/src/cz/nic/tablexia/game/games/pursuit/helper/ArithmeticsHelper.java index b3459b3b27f31be277a75c9ebde401dd7c26fe73..8ebc001e45fbae5fc7b02e8345672fd42d9b4c29 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/helper/ArithmeticsHelper.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/helper/ArithmeticsHelper.java @@ -2,12 +2,14 @@ package cz.nic.tablexia.game.games.pursuit.helper; import java.util.Random; +import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Point; /** * Created by Václav TarantĂk on 2.7.15. */ public class ArithmeticsHelper { + private static final float SUFFICIENT_ROTATION_AMOUNT_DEGREES = 15; public static final int CARDINAL_POINTS_COUNT = 4; public static double getAngleBetweenTwoPoints(Point firstPoint, Point secondPoint) { @@ -18,17 +20,30 @@ public class ArithmeticsHelper { return recalcAngle; } + /* + calculates the angle according to rotation direction, if rotation of piece exceeds the + SUFFICIENT_ROTATION_AMOUNT_DEGREES, piece will be rotated to closest right angle after drop + */ + public static float getAngleInRotationDirection(float originalRotation, float currentAngle) { + float rotationAmount = currentAngle - originalRotation; + int numOfNinetyDegreesPassed = (int) (rotationAmount / 90); + //original angle added with number of ninety degrees which we rotated piece over + float baseAngle = originalRotation + (numOfNinetyDegreesPassed * 90); + if ((Math.abs(rotationAmount) % 90) > SUFFICIENT_ROTATION_AMOUNT_DEGREES) { + baseAngle+= (getRotationDirection(originalRotation, currentAngle) * 90); + } + return baseAngle; + } + public static float getClosestRightAngle(float currentAngle) { + int numOfNinetyDegreesInAngle = (int)(currentAngle/90); float angleModule = currentAngle % 90; - float nearestRightAngle = 0; - float roundedAngle = currentAngle - (angleModule); - //rotating actor clockwise - if (currentAngle < 0) { - nearestRightAngle = angleModule < -45 ? roundedAngle - 90 : roundedAngle; - } else { - nearestRightAngle = angleModule > 45 ? roundedAngle + 90 : roundedAngle; + float highestLowerRightAngle = numOfNinetyDegreesInAngle*90; + if(currentAngle<0){ + return angleModule<-45?highestLowerRightAngle-90:highestLowerRightAngle; + }else{ + return angleModule>45?highestLowerRightAngle+90:highestLowerRightAngle; } - return nearestRightAngle; } //returns right angle inside 360 degrees @@ -61,4 +76,8 @@ public class ArithmeticsHelper { return new Point(x, y); } + public static int getRotationDirection(float originalRotation, float currentRotation){ + return (currentRotation<originalRotation)?-1:1; + } + } diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/model/Grid.java b/core/src/cz/nic/tablexia/game/games/pursuit/model/Grid.java index 5b4ed740497fd45d9a17646e47928ef8822b4ae6..9a3e91e414eaf49c8015f3acbd1f4b2c7e8d2493 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/model/Grid.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/model/Grid.java @@ -134,6 +134,7 @@ public class Grid extends Group { public void switchPieces(PuzzlePiece draggedPiece, PuzzlePiece overlappedPiece,Action moveAction) { if (draggedPiece != null) { + Log.info(getClass(),"SWITCH PIECES"); int draggedPieceActualPosition = draggedPiece.getActualPosition(); cz.nic.tablexia.util.Point draggedPiecePositionInPixels = getPieceGridPositionInPixels(draggedPieceActualPosition); @@ -150,7 +151,7 @@ public class Grid extends Group { } //returns the position of piece inside grid according to piece's actual position - private cz.nic.tablexia.util.Point getPieceGridPositionInPixels(int actualPositionInGrid){ + public cz.nic.tablexia.util.Point getPieceGridPositionInPixels(int actualPositionInGrid){ float pieceSize = getWidth() / (float) numberOfColumns; cz.nic.tablexia.util.Point pieceOrderNumbers = getPieceOrderNumbers(actualPositionInGrid); diff --git a/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java b/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java index 366f8e82a7521f93f0aab49caa50a70963fbfd51..d215c4c40b5950589888099f7b01f8e816653c78 100644 --- a/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java +++ b/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java @@ -1,15 +1,20 @@ package cz.nic.tablexia.util.listener; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; +import com.badlogic.gdx.scenes.scene2d.actions.Actions; +import com.badlogic.gdx.utils.TimeUtils; import java.util.LinkedHashMap; import cz.nic.tablexia.game.games.pursuit.action.RotateAndMovePieceInPosition; import cz.nic.tablexia.game.games.pursuit.action.RotatePieceToClosestAngle; import cz.nic.tablexia.game.games.pursuit.helper.ArithmeticsHelper; +import cz.nic.tablexia.game.games.pursuit.model.Grid; +import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Point; import cz.nic.tablexia.game.games.pursuit.model.PuzzlePiece; @@ -25,7 +30,10 @@ public class DragAndRotateActorListener extends InputListener { private Actor draggedActor; private Actor parentActor; private IOnRotationFinished iOnRotationFinished; + private float actorOriginalRotation; private boolean performingAction; + private boolean pieceAnimationDone; + private RotateAndMovePieceInPosition pieceTranslationAction; private LinkedHashMap<Integer, Point> activePointers; @@ -45,7 +53,7 @@ public class DragAndRotateActorListener extends InputListener { @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { - if(button!=1){ + if (button != 1) { activePointers.put(pointer, new Point(x, y)); } if (activePointers.size() == 1) { @@ -66,6 +74,8 @@ public class DragAndRotateActorListener extends InputListener { } else if (activePointers.size() == 2) { initialFingersAngle = (float) ArithmeticsHelper.getAngleBetweenTwoPoints(activePointers.get(activePointers.keySet().toArray()[0]), activePointers.get(activePointers.keySet().toArray()[1])); + actorOriginalRotation = draggedActor.getRotation(); + Log.info(getClass(), "Actors initial angle: " + actorOriginalRotation); } } return true; @@ -86,9 +96,7 @@ public class DragAndRotateActorListener extends InputListener { moved(bx, by, draggedActor); } else if (activePointers.size() > 1) { //not updating the first finger coordinates when rotating so the piece does not move - if (pointer != activePointers.keySet().toArray()[0]) { - activePointers.put(pointer, new Point(x, y)); - } + activePointers.put(pointer, new Point(x, y)); Point firstFingerCoordinates = activePointers.get(activePointers.keySet().toArray()[0]); Point secondFingerCoordinates = activePointers.get(activePointers.keySet().toArray()[1]); double angle = ArithmeticsHelper.getAngleBetweenTwoPoints(firstFingerCoordinates, secondFingerCoordinates); @@ -99,29 +107,45 @@ public class DragAndRotateActorListener extends InputListener { } @Override - public void touchUp(InputEvent event, float x, float y, int pointer, int button) { - if(button != 1){ + public void touchUp(InputEvent event, final float x, final float y, int pointer, int button) { + if (button != 1) { if (draggedActor != null && !performingAction) { + //storing original fingers positions and deciding which finger was released boolean draggingFingerLifted = ((Integer) (activePointers.keySet().toArray()[0]) == pointer); boolean rotatingFingerLifted = false; if (activePointers.size() > 1) { rotatingFingerLifted = (Integer) activePointers.keySet().toArray()[1] == pointer; } + //removing lifted finger pointer after storing its position activePointers.remove(pointer); if (activePointers.size() == 0) { - dropped(x, y, draggedActor); + //if user removed all fingers before animation finished, piece is stopped and animated back to its original position + if (!isPieceAnimationDone()) { + pieceTranslationAction.interrupt(); + Point pieceOriginalPosition = ((Grid) parentActor).getPieceGridPositionInPixels(((PuzzlePiece) draggedActor).getActualPosition()); + parentActor.addAction(new RotateAndMovePieceInPosition((PuzzlePiece) draggedActor, actorOriginalRotation, pieceOriginalPosition, iOnRotationFinished)); + } + parentActor.addAction(Actions.after(new Action() { + @Override + public boolean act(float delta) { + dropped(x, y, draggedActor); + return true; + } + })); + } else if (activePointers.size() > 0) { //if user raised the dragging finger, animate piece under second finger Point currentFirstPointer = activePointers.get(activePointers.keySet().toArray()[0]); if (draggingFingerLifted) { + setPieceAnimationDone(false); Vector2 recalculatedCoords = new Vector2(currentFirstPointer.x, currentFirstPointer.y); draggedActor.stageToLocalCoordinates(recalculatedCoords); float bx = draggedActor.getX() + (recalculatedCoords.x - (draggedActor.getWidth() / 2)); float by = draggedActor.getY() + (recalculatedCoords.y - (draggedActor.getHeight() / 2)); - - parentActor.addAction(new RotateAndMovePieceInPosition((PuzzlePiece) draggedActor, new Point(bx, by), iOnRotationFinished)); + pieceTranslationAction = new RotateAndMovePieceInPosition((PuzzlePiece) draggedActor, actorOriginalRotation, new Point(bx, by), iOnRotationFinished); + parentActor.addAction(pieceTranslationAction); } else if (rotatingFingerLifted) { - parentActor.addAction(new RotatePieceToClosestAngle((PuzzlePiece) draggedActor, iOnRotationFinished)); + parentActor.addAction(new RotatePieceToClosestAngle((PuzzlePiece) draggedActor, actorOriginalRotation, iOnRotationFinished)); } } } else { @@ -132,7 +156,7 @@ public class DragAndRotateActorListener extends InputListener { } public interface IOnRotationFinished { - void onRotationFinished(); + void onDragAndRotationFinished(); } public void setDraggedActor(Actor actor) { @@ -150,4 +174,12 @@ public class DragAndRotateActorListener extends InputListener { public void setParentActor(Actor parentActor) { this.parentActor = parentActor; } + + public void setPieceAnimationDone(boolean pieceAnimationDone) { + this.pieceAnimationDone = pieceAnimationDone; + } + + public boolean isPieceAnimationDone() { + return pieceAnimationDone; + } }