From 9ecf36ba57c336aa68b1ddbda4d8be7bcfc011f0 Mon Sep 17 00:00:00 2001
From: "v.tarantik" <v.tarantik@gmail.com>
Date: Fri, 24 Jul 2015 13:15:39 +0200
Subject: [PATCH] #32 Pieces animation fix, pieces position calculation change

---
 .../game/games/pursuit/PursuitGame.java       |  54 +++---
 .../game/games/pursuit/environment/Grid.java  | 168 ++++++++++++------
 .../pursuit/environment/PuzzlePiece.java      |  26 +--
 .../pursuit/helper/ArithmeticsHelper.java     |   8 +
 .../listener/DragAndRotateActorListener.java  |  67 +++----
 ios/robovm.xml                                |   6 +-
 6 files changed, 175 insertions(+), 154 deletions(-)

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 0e816afe5..3c136c6b4 100644
--- a/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java
+++ b/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java
@@ -1,23 +1,20 @@
 package cz.nic.tablexia.game.games.pursuit;
 
 import com.badlogic.gdx.graphics.g2d.TextureRegion;
-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.Group;
-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.scenes.scene2d.ui.Image;
 
 import net.dermetfan.utils.Pair;
 
+import java.util.Map;
+
 import cz.nic.tablexia.TablexiaSettings;
 import cz.nic.tablexia.game.AbstractTablexiaGame;
 import cz.nic.tablexia.game.games.pursuit.environment.Grid;
 import cz.nic.tablexia.game.games.pursuit.environment.PuzzlePiece;
 import cz.nic.tablexia.game.games.pursuit.helper.TextureHelper;
-import cz.nic.tablexia.util.Log;
 import cz.nic.tablexia.util.listener.DragAndRotateActorListener;
 
 /**
@@ -34,9 +31,10 @@ public class PursuitGame extends AbstractTablexiaGame<Void> {
     private Grid grid;
     private Image backgroundImage;
     private DragAndRotateActorListener dragAndRotateActorListener;
+    private int movesCounter;
 
     @Override
-    protected void gameLoaded() {
+    protected void gameLoaded(Map<String, String> gameState) {
         contentGroup = new Group();
         contentGroup.setSize(SCREEN_WIDTH, SCREEN_MIN_HEIGHT);
         getStage().addActor(contentGroup);
@@ -54,7 +52,7 @@ public class PursuitGame extends AbstractTablexiaGame<Void> {
 
             @Override
             public void moved(float x, float y, Actor draggedPiece) {
-                PuzzlePiece puzzlePiece = (PuzzlePiece)draggedPiece;
+                PuzzlePiece puzzlePiece = (PuzzlePiece) draggedPiece;
                 PuzzlePiece overlappedPiece = grid.pieceIntersectingWithDragged(puzzlePiece.getId());
                 if (overlappedPiece != null) {
                     overlappedPiece.setZIndex(OVERLAPPED_PIECE_ZINDEX);
@@ -67,19 +65,22 @@ public class PursuitGame extends AbstractTablexiaGame<Void> {
 
             @Override
             public void dropped(float x, float y, Actor draggedPiece) {
-                PuzzlePiece puzzlePiece = (PuzzlePiece)draggedPiece;
-                PuzzlePiece overlappedPiece = grid.pieceIntersectingWithDragged(puzzlePiece.getId());
-                Pair<Float, Float> startingPosition = dragAndRotateActorListener.getStartingPosition();
-
-                if (overlappedPiece == null) {
-                    Log.info(getClass(), "PIECE RELEASED ABOVE EMPTY AREA");
-                    addAction(animatePieceInPosition(puzzlePiece, startingPosition.getKey(), startingPosition.getValue()));
-                } else {
-                    Log.info(getClass(), "PIECE RELEASED ABOVE PIECE: " + overlappedPiece.toString());
-                    addAction(Actions.parallel(animatePieceInPosition(puzzlePiece, overlappedPiece.getX(), overlappedPiece.getY()), animatePieceInPosition(overlappedPiece, startingPosition.getKey(), startingPosition.getValue())));
+                if (draggedPiece != null) {
+                    PuzzlePiece puzzlePiece = (PuzzlePiece) draggedPiece;
+                    PuzzlePiece overlappedPiece = grid.pieceIntersectingWithDragged(puzzlePiece.getId());
+                    Action onPiecesSwitchFinishedAction = new Action() {
+                        @Override
+                        public boolean act(float delta) {
+                            movesCounter++;
+                            dragAndRotateActorListener.setActor(null);
+                            if (grid.allPiecesInCorrectPositions()) {
+                                gameComplete(movesCounter);
+                            }
+                            return true;
+                        }
+                    };
+                    grid.switchPieces(puzzlePiece, overlappedPiece,onPiecesSwitchFinishedAction);
                 }
-
-                dragAndRotateActorListener.setActor(null);
             }
         };
         backgroundImage.addListener(dragAndRotateActorListener);
@@ -96,21 +97,8 @@ public class PursuitGame extends AbstractTablexiaGame<Void> {
         TextureRegion mapTextureRegion = getScreenTextureRegion(TextureHelper.getMapFullName(1));
 
         grid = new Grid(SCREEN_WIDTH / 2 - SCREEN_MIN_HEIGHT / 2, GRID_PADDING, SCREEN_MIN_HEIGHT - 2 * GRID_PADDING, GRID_COLUMNS, mapTextureRegion);
+        grid.shufflePieces(getRandom());
         contentGroup.addActor(grid);
     }
 
-
-    private Action animatePieceInPosition(final PuzzlePiece piece, final float x, final float y) {
-        Action action = new Action() {
-            @Override
-            public boolean act(float delta) {
-                piece.setZIndex(1);
-                piece.setScale(1);
-                piece.addAction(Actions.moveTo(x, y));
-                return true;
-            }
-        };
-        return action;
-    }
-
 }
diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/environment/Grid.java b/core/src/cz/nic/tablexia/game/games/pursuit/environment/Grid.java
index e6354f442..de899e990 100644
--- a/core/src/cz/nic/tablexia/game/games/pursuit/environment/Grid.java
+++ b/core/src/cz/nic/tablexia/game/games/pursuit/environment/Grid.java
@@ -4,16 +4,22 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
 import com.badlogic.gdx.math.Intersector;
 import com.badlogic.gdx.math.Rectangle;
 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.Group;
 import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.actions.Actions;
+
+import net.dermetfan.utils.Pair;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Random;
 
 import cz.nic.tablexia.TablexiaSettings;
 import cz.nic.tablexia.util.Log;
+import cz.nic.tablexia.util.listener.DragAndRotateActorListener;
 
 /**
  * Created by Václav Tarantík on 17.6.15.
@@ -21,13 +27,8 @@ import cz.nic.tablexia.util.Log;
 public class Grid extends Group {
     private float size;
     private int numberOfColumns;//number of rows respectively columns
-    private Map<Integer,PuzzlePiece> piecesMap;
+    private Map<Integer, PuzzlePiece> piecesMap;
     private TextureRegion textureRegion;
-    private PuzzlePiece draggedPiece;
-
-    private PuzzlePiece.PieceSelectedListener pieceSelectedListener;
-    private PuzzlePiece.PieceMovedListener pieceMovedListener;
-    private PuzzlePiece.PieceDroppedListener pieceDroppedListener;
 
     public Grid(float x, float y, float size, int numberOfColumns, TextureRegion textureRegion) {
         super();
@@ -38,33 +39,30 @@ public class Grid extends Group {
 
         this.textureRegion = textureRegion;
         this.numberOfColumns = numberOfColumns;
-        this.pieceSelectedListener = pieceSelectedListener;
-        this.pieceMovedListener = pieceMovedListener;
-        this.pieceDroppedListener = pieceDroppedListener;
 
         setTouchable(Touchable.disabled);
 
-        piecesMap = new HashMap<Integer,PuzzlePiece>();
+        piecesMap = new HashMap<Integer, PuzzlePiece>();
         placePieces();
 
     }
 
-    private void placePieces(){
-        for(int i = 0; i < Math.pow(numberOfColumns,2);i++){
+    //creates pieces texture regions and places them in the grid
+    private void placePieces() {
+        for (int i = 0; i < Math.pow(numberOfColumns, 2); i++) {
             float pieceSize = getWidth() / (float) numberOfColumns;
-            int xOrderCoord = (i % numberOfColumns);
-            int yOrderCoord = (i / numberOfColumns);
-
-            float relativeXPosition = (float)xOrderCoord/(float)numberOfColumns;
-            float relativeYPosition = (float)yOrderCoord/(float)numberOfColumns;
-            float relativePieceSize = pieceSize/getWidth();
+            Pair<Float,Float> pieceRelativePosition = getPieceRelativePosition(i);
+            float relativePieceSize = pieceSize / getWidth();
 
             //TextureRegion divided in parts for each piece
-            Log.info(getClass(),"Texture: "+textureRegion.getTexture()+" RPX: "+relativeXPosition+" RPSX: "+(relativeXPosition+relativePieceSize)+", RPY: "+relativeYPosition+", RPSY: "+(relativeYPosition+relativePieceSize)+", SIZE: "+relativePieceSize*getWidth());
-            TextureRegion pieceRegion = new TextureRegion(textureRegion.getTexture(),relativeXPosition,relativeYPosition,relativeXPosition+relativePieceSize,relativeYPosition+relativePieceSize);
+            Log.info(getClass(), "Texture: " + textureRegion.getTexture() + " RPX: " + pieceRelativePosition.getKey() + " RPSX: " + (pieceRelativePosition.getKey() + relativePieceSize) + ", RPY: " + pieceRelativePosition.getValue() + ", RPSY: " + (pieceRelativePosition.getValue() + relativePieceSize) + ", SIZE: " + relativePieceSize * getWidth());
+            TextureRegion pieceRegion = new TextureRegion(textureRegion.getTexture(), pieceRelativePosition.getKey(), pieceRelativePosition.getValue(), pieceRelativePosition.getKey() + relativePieceSize, pieceRelativePosition.getValue() + relativePieceSize);
+            Pair<Float,Float> piecePosition = getPieceGridPositionInPixels(i);
 
-            PuzzlePiece puzzlePiece = new PuzzlePiece(i,pieceRegion);
-            puzzlePiece.setPosition(xOrderCoord * pieceSize, getHeight() - ((1 + yOrderCoord) * pieceSize));
+            PuzzlePiece puzzlePiece = new PuzzlePiece(i, pieceRegion);
+            puzzlePiece.setCorrectPosition(i);
+            puzzlePiece.setActualPosition(i);
+            puzzlePiece.setPosition(piecePosition.getKey(),piecePosition.getValue());
             puzzlePiece.setSize(pieceSize, pieceSize);
             puzzlePiece.setOrigin(pieceSize / 2, pieceSize / 2);
             puzzlePiece.setZIndex(1);
@@ -79,41 +77,21 @@ public class Grid extends Group {
     }
 
     //method shuffles pieces inside grid and sets its rotation randomly
-    public void shufflePieces() {
-        //TODO
-    }
-
-    public void setDraggedPiece(PuzzlePiece draggedPiece) {
-            this.draggedPiece = draggedPiece;
-    }
-
-    public PuzzlePiece getDraggedPiece() {
+    public void shufflePieces(Random random) {
+        //random rotation
         for (PuzzlePiece piece : piecesMap.values()) {
-            if (piece.isDragged()) {
-                return piece;
-            }
+            piece.setRotation(90 * (random.nextInt(4)));
         }
-        Log.info(getClass(), "NO PIECE TOUCHED");
-        return null;
-    }
-
-    public Actor findPuzzlePiece(float x, float y, PuzzlePiece current) {
-        Touchable stash = current.getTouchable();
-        current.setTouchable(Touchable.disabled);
-
-        Actor toReturn = super.hit(x, y, true);
-        current.setTouchable(stash);
-        return toReturn == current ? null : toReturn;
     }
 
     //finds piece at specified point that does not have the tabuId
-    public PuzzlePiece pieceAtPoint(float x, float y, int tabuId){
-        Rectangle point = new Rectangle(x,y,1,1);
-        for(PuzzlePiece piece: piecesMap.values()){
-            if(piece.getId()!=tabuId) {
-                Vector2 recalculatedCoords = new Vector2(piece.getX(),piece.getY());
+    public PuzzlePiece pieceAtPoint(float x, float y, int tabuId) {
+        Rectangle point = new Rectangle(x, y, 1, 1);
+        for (PuzzlePiece piece : piecesMap.values()) {
+            if (piece.getId() != tabuId) {
+                Vector2 recalculatedCoords = new Vector2(piece.getX(), piece.getY());
                 localToStageCoordinates(recalculatedCoords);
-                Rectangle currentPieceRectangle = new Rectangle(recalculatedCoords.x,recalculatedCoords.y , piece.getWidth(), piece.getHeight());
+                Rectangle currentPieceRectangle = new Rectangle(recalculatedCoords.x, recalculatedCoords.y, piece.getWidth(), piece.getHeight());
                 Rectangle intersectionRectangle = new Rectangle();
                 if (Intersector.intersectRectangles(point, currentPieceRectangle, intersectionRectangle)) {
                     return piece;
@@ -123,27 +101,99 @@ public class Grid extends Group {
         return null;
     }
 
-    public PuzzlePiece pieceAtPoint(float x, float y){
-        return pieceAtPoint(x,y,-1);
+    public PuzzlePiece pieceAtPoint(float x, float y) {
+        return pieceAtPoint(x, y, -1);
     }
 
-    public PuzzlePiece pieceIntersectingWithDragged(int draggedPieceId){
+    public PuzzlePiece pieceIntersectingWithDragged(int draggedPieceId) {
         PuzzlePiece draggedPiece = piecesMap.get(draggedPieceId);
-        Vector2 pointRecalculatedPoint = new Vector2(draggedPiece.getX(),draggedPiece.getY());
+        Vector2 pointRecalculatedPoint = new Vector2(draggedPiece.getX(), draggedPiece.getY());
         localToStageCoordinates(pointRecalculatedPoint);
-        return pieceAtPoint(pointRecalculatedPoint.x+draggedPiece.getWidth()/2,pointRecalculatedPoint.y+draggedPiece.getHeight()/2,draggedPieceId);
+        return pieceAtPoint(pointRecalculatedPoint.x + draggedPiece.getWidth() / 2, pointRecalculatedPoint.y + draggedPiece.getHeight() / 2, draggedPieceId);
     }
 
-    public void unscalePieces(int draggedPieceId,int pieceNotToUnscaleId){
-        for(PuzzlePiece piece: piecesMap.values()){
-            if(piece.getId()!=pieceNotToUnscaleId&&piece.getId()!=draggedPieceId){
+    public void unscalePieces(int draggedPieceId, int pieceNotToUnscaleId) {
+        for (PuzzlePiece piece : piecesMap.values()) {
+            if (piece.getId() != pieceNotToUnscaleId && piece.getId() != draggedPieceId) {
                 piece.setScale(1);
                 piece.setZIndex(1);
             }
         }
     }
 
+    public void switchPieces(PuzzlePiece draggedPiece, PuzzlePiece overlappedPiece,Action moveAction) {
+        if (draggedPiece != null) {
+            int draggedPieceActualPosition = draggedPiece.getActualPosition();
+            Pair<Float,Float> draggedPiecePositionInPixels = getPieceGridPositionInPixels(draggedPieceActualPosition);
+
+            if (overlappedPiece == null) {
+                Log.info(getClass(), "PIECE RELEASED ABOVE EMPTY AREA");
+                addAction(Actions.sequence(animatePieceInPosition(draggedPiece, draggedPiecePositionInPixels.getKey(), draggedPiecePositionInPixels.getValue()),moveAction));
+
+            } else {
+                Log.info(getClass(), "PIECE RELEASED ABOVE PIECE: " + overlappedPiece.toString());
+                int overlappedPieceActualPosition = overlappedPiece.getActualPosition();
+                Pair<Float,Float> overlappedPiecePositionInPixels = getPieceGridPositionInPixels(overlappedPieceActualPosition);
+                draggedPiece.setActualPosition(overlappedPieceActualPosition);
+                overlappedPiece.setActualPosition(draggedPieceActualPosition);
+                Log.info(getClass(),"Switching pieces at coordinates....Dragged toooo: "+overlappedPiecePositionInPixels.getKey()+", "+overlappedPiecePositionInPixels.getValue()+".....Overlapped to: "+draggedPiecePositionInPixels.getKey()+", "+draggedPiecePositionInPixels.getValue());
+                addAction(Actions.sequence(Actions.parallel(animatePieceInPosition(draggedPiece, overlappedPiecePositionInPixels.getKey(), overlappedPiecePositionInPixels.getValue()), animatePieceInPosition(overlappedPiece, draggedPiecePositionInPixels.getKey(), draggedPiecePositionInPixels.getValue())),moveAction));
+            }
+        }
+    }
+
+    private Action animatePieceInPosition(final PuzzlePiece piece, final float x, final float y) {
+        Action action = new Action() {
+            @Override
+            public boolean act(float delta) {
+                Action finalAction = new Action() {
+                    @Override
+                    public boolean act(float delta) {
+                        piece.setZIndex(1);
+                        piece.setScale(1);
+                        return true;
+                    }
+                };
+                piece.addAction(Actions.sequence(Actions.moveTo(x, y, DragAndRotateActorListener.MOVETO_ANIMATION_DURATION),finalAction));
+                return true;
+            }
+        };
+        return action;
+    }
+
+    public boolean allPiecesInCorrectPositions(){
+        for(PuzzlePiece piece: piecesMap.values()){
+            float pieceRotation = piece.getRotation()%360;
+            if(piece.getActualPosition()!=piece.getCorrectPosition()||pieceRotation!=0){
+                return false;
+            }
+        }
+        return true;
+    }
+
+    //returns the position of piece inside grid according to piece's actual position
+    private Pair<Float,Float> getPieceGridPositionInPixels(int actualPositionInGrid){
+        float pieceSize = getWidth() / (float) numberOfColumns;
+        Pair<Integer,Integer> pieceOrderNumbers = getPieceOrderNumbers(actualPositionInGrid);
 
+        Log.info(getClass(),"Piece order numbers: "+pieceOrderNumbers.getKey()+", "+pieceOrderNumbers.getValue());
+
+        return new Pair<Float, Float>(pieceOrderNumbers.getKey() * pieceSize, getHeight() - ((1 + pieceOrderNumbers.getValue()) * pieceSize));
+    }
 
+    //Pieces are placed from upper left corner, method returns relative positions according to number of rows and columns
+    private Pair<Float,Float> getPieceRelativePosition(int actualPositionInGrid){
+        Pair<Integer,Integer> pieceOrderNumbers = getPieceOrderNumbers(actualPositionInGrid);
+        float relativeXPosition = (float) pieceOrderNumbers.getKey() / (float) numberOfColumns;
+        float relativeYPosition = (float) pieceOrderNumbers.getValue() / (float) numberOfColumns;
 
+        return  new Pair<Float, Float>(relativeXPosition,relativeYPosition);
+    }
+
+    private Pair<Integer,Integer> getPieceOrderNumbers(int actualPositionInGrid){
+        int xOrderCoord = (actualPositionInGrid % numberOfColumns);
+        int yOrderCoord = (actualPositionInGrid / numberOfColumns);
+
+        return new Pair<Integer, Integer>(xOrderCoord,yOrderCoord);
+    }
 }
diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/environment/PuzzlePiece.java b/core/src/cz/nic/tablexia/game/games/pursuit/environment/PuzzlePiece.java
index e0b37b043..52ae679f0 100644
--- a/core/src/cz/nic/tablexia/game/games/pursuit/environment/PuzzlePiece.java
+++ b/core/src/cz/nic/tablexia/game/games/pursuit/environment/PuzzlePiece.java
@@ -26,7 +26,6 @@ public class PuzzlePiece extends Image {
         super(texture);
         setOrigin(getWidth() / 2, getHeight() / 2);
         this.id = id;
-
         setTouchable(Touchable.disabled);
 
     }
@@ -43,16 +42,16 @@ public class PuzzlePiece extends Image {
         this.dragged = dragged;
     }
 
-    public static interface PieceSelectedListener {
-        public void pieceSelected(PuzzlePiece piece);
+    public interface PieceSelectedListener {
+        void pieceSelected(PuzzlePiece piece);
     }
 
-    public static interface PieceMovedListener {
-        public void pieceMoved(PuzzlePiece puzzlePiece, float x, float y);
+    public interface PieceMovedListener {
+        void pieceMoved(PuzzlePiece puzzlePiece, float x, float y);
     }
 
-    public static interface PieceDroppedListener {
-        public void pieceDropped(PuzzlePiece puzzlePiece, float x, float y);
+    public interface PieceDroppedListener {
+        void pieceDropped(PuzzlePiece puzzlePiece, float x, float y);
     }
 
     @Override
@@ -80,19 +79,10 @@ public class PuzzlePiece extends Image {
     //Overriden so there is no need to recalculate touch point after rotating the piece
     @Override
     public Vector2 parentToLocalCoordinates(Vector2 parentCoords) {
-        final float scaleX = getScaleX();
-        final float scaleY = getScaleY();
         final float childX = getX();
         final float childY = getY();
-        if (scaleX == 1 && scaleY == 1) {
-            parentCoords.x -= childX;
-            parentCoords.y -= childY;
-        } else {
-            final float originX = getOriginX();
-            final float originY = getOriginY();
-            parentCoords.x = (parentCoords.x - childX - originX) / scaleX + originX;
-            parentCoords.y = (parentCoords.y - childY - originY) / scaleY + originY;
-        }
+        parentCoords.x -= childX;
+        parentCoords.y -= childY;
         return parentCoords;
     }
 }
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 2253fe0c4..25043871e 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
@@ -4,12 +4,15 @@ import com.badlogic.gdx.math.MathUtils;
 
 import net.dermetfan.utils.Pair;
 
+import java.util.Random;
+
 import cz.nic.tablexia.util.Log;
 
 /**
  * Created by Václav Tarantík on 2.7.15.
  */
 public class ArithmeticsHelper {
+    public static final int CARDINAL_POINTS_COUNT = 4;
 
     public static double getAngleBetweenTwoPoints(Pair<Float,Float> firstPoint, Pair<Float,Float> secondPoint) {
         double degrees = Math.atan2(secondPoint.getKey() - firstPoint.getKey(), secondPoint.getValue() - firstPoint.getValue());
@@ -31,4 +34,9 @@ public class ArithmeticsHelper {
         }
             return nearestRightAngle;
     }
+
+    //returns right angle inside 360 degrees
+    public static float getRandomRightAngle(Random random){
+        return 90*(random.nextInt(CARDINAL_POINTS_COUNT));
+    }
 }
diff --git a/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java b/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java
index a8b06e0e5..98450c0a2 100644
--- a/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java
+++ b/core/src/cz/nic/tablexia/util/listener/DragAndRotateActorListener.java
@@ -17,11 +17,12 @@ import cz.nic.tablexia.util.Log;
  * Created by Vaclav Tarantik on 6/18/15.
  */
 public class DragAndRotateActorListener extends InputListener {
-    private float grabX, grabY, startX, startY, actorCenterX, actorCenterY;
+    private static final int DRAGGED_PIECE_ZINDEX = 8;
+    public static final float ROTATION_ANIMATION_DURATION = 0.3f;
+    public static final float MOVETO_ANIMATION_DURATION = 0.4f;
+    private float grabX, grabY;
     private float initialFingersAngle;
     private Actor actor;
-    private boolean bounceBack;
-
 
     private TreeMap<Integer, Pair<Float, Float>> activePointers;
 
@@ -31,17 +32,14 @@ public class DragAndRotateActorListener extends InputListener {
 
     public void selected(float x, float y) {
     }
-
     ;
 
     public void moved(float x, float y, Actor draggedPiece) {
     }
-
     ;
 
     public void dropped(float x, float y, Actor draggedPiece) {
     }
-
     ;
 
     @Override
@@ -50,14 +48,12 @@ public class DragAndRotateActorListener extends InputListener {
         selected(x, y);
         if (actor != null) {
             if (activePointers.size() == 1) {
-                actor.setZIndex(8);
+                actor.setZIndex(DRAGGED_PIECE_ZINDEX);
                 actor.setScale(1.2f);
                 Vector2 recalculatedCoords = new Vector2(x, y);
                 actor.stageToLocalCoordinates(recalculatedCoords);
                 grabX = recalculatedCoords.x;
                 grabY = recalculatedCoords.y;
-                startX = actor.getX();
-                startY = actor.getY();
 
             } else if (activePointers.size() == 2) {
                 initialFingersAngle = (float) ArithmeticsHelper.getAngleBetweenTwoPoints(activePointers.get(activePointers.firstKey()), activePointers.get(activePointers.higherKey(activePointers.firstKey())));
@@ -69,15 +65,13 @@ public class DragAndRotateActorListener extends InputListener {
     @Override
     public void touchDragged(InputEvent event, float x, float y, int pointer) {
         super.touchDragged(event, x, y, pointer);
-        if (actor != null) {
+        if (actor != null&&actor.getActions().size==0) {
             if (activePointers.size() == 1) {
                 //updating current pointer position
                 activePointers.put(pointer, new Pair(x, y));
                 Vector2 recalculatedCoords = new Vector2(x, y);
                 actor.stageToLocalCoordinates(recalculatedCoords);
-                Log.info(getClass(), "Event x: " + x + ", " + y + "Actor position: " + actor.getX() + ", " + actor.getY() + "width: " + actor.getWidth() + " height: " + actor.getHeight());
-                //Log.info(getClass(), "Recalc x: " + recalculatedCoords.x + ", y: " + recalculatedCoords.y);
-//            Log.info(getClass(), "GRAB x: " + grabX+", y: "+grabY);
+//                Log.info(getClass(), "Event x: " + x + ", " + y + "Actor position: " + actor.getX() + ", " + actor.getY() + "width: " + actor.getWidth() + " height: " + actor.getHeight());
                 float bx = actor.getX() + (recalculatedCoords.x - grabX);
                 float by = actor.getY() + (recalculatedCoords.y - grabY);
                 actor.setPosition(bx, by);
@@ -97,36 +91,31 @@ public class DragAndRotateActorListener extends InputListener {
 
     @Override
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
-        boolean draggingFingerLifted = activePointers.firstKey() == pointer;
-        boolean rotatingFingerLifted = false;
-        if (activePointers.higherKey(activePointers.firstKey()) != null) {
-            rotatingFingerLifted = activePointers.higherKey(activePointers.firstKey()) == pointer;
-        }
-        activePointers.remove(pointer);
-        if (activePointers.size() == 0) {
-            dropped(x, y, actor);
-        } else if (activePointers.size() >= 1) {
-            //if user raised the dragging finger, animate piece under
-            Pair<Float, Float> currentFirstPointer = activePointers.get(activePointers.firstKey());
-            if (draggingFingerLifted) {
-                actor.addAction(Actions.moveTo(currentFirstPointer.getKey(), currentFirstPointer.getValue()));
-            } else if (rotatingFingerLifted) {
-                actor.addAction(Actions.rotateTo(ArithmeticsHelper.getClosestRightAngle(actor.getRotation())));
-                //TODO after rotation recalculate grab point positions
-//                Pair<Float,Float> draggingFingerCoords = activePointers.get(activePointers.firstKey());
-//                Vector2 recalculatedCoords = new Vector2(draggingFingerCoords.getKey(),draggingFingerCoords.getValue());
-//                actor.stageToLocalCoordinates(recalculatedCoords);
-//                grabX = recalculatedCoords.x;
-//                grabY = recalculatedCoords.y;
-                Log.info(getClass(), "Actor: " + actor + " --> finished rotation");
+        if(actor!=null){
+            boolean draggingFingerLifted = activePointers.firstKey() == pointer;
+            boolean rotatingFingerLifted = false;
+            if (activePointers.higherKey(activePointers.firstKey()) != null) {
+                rotatingFingerLifted = activePointers.higherKey(activePointers.firstKey()) == pointer;
+            }
+            activePointers.remove(pointer);
+            if (activePointers.size() == 0) {
+                dropped(x, y, actor);
+            } else if (activePointers.size() >= 1) {
+                //if user raised the dragging finger, animate piece under second finger
+                Pair<Float, Float> currentFirstPointer = activePointers.get(activePointers.firstKey());
+                if (draggingFingerLifted) {
+                    Vector2 recalculatedCoords = new Vector2(currentFirstPointer.getKey(), currentFirstPointer.getValue());
+                    actor.stageToLocalCoordinates(recalculatedCoords);
+                    float bx = actor.getX() + (recalculatedCoords.x-(actor.getWidth()/2));
+                    float by = actor.getY() + (recalculatedCoords.y-(actor.getHeight()/2));
+                    actor.addAction(Actions.parallel(Actions.rotateTo(ArithmeticsHelper.getClosestRightAngle(actor.getRotation()), ROTATION_ANIMATION_DURATION), Actions.moveTo(bx,by, MOVETO_ANIMATION_DURATION)));
+                } else if (rotatingFingerLifted) {
+                    actor.addAction(Actions.rotateTo(ArithmeticsHelper.getClosestRightAngle(actor.getRotation()), ROTATION_ANIMATION_DURATION));
+                }
             }
         }
     }
 
-    public Pair<Float, Float> getStartingPosition() {
-        return new Pair<Float, Float>(startX, startY);
-    }
-
     public void setActor(Actor actor) {
         this.actor = actor;
     }
diff --git a/ios/robovm.xml b/ios/robovm.xml
index 77d5f1ae4..b0564fb81 100644
--- a/ios/robovm.xml
+++ b/ios/robovm.xml
@@ -33,11 +33,7 @@
     <pattern>org.apache.harmony.security.provider.crypto.CryptoProvider</pattern>
     <pattern>SQLite.**</pattern>
   </forceLinkClasses>
-  <libs>
-    <lib>build/libs/ios/libgdx-freetype.a</lib>
-    <lib>build/libs/ios/libgdx.a</lib>
-    <lib>build/libs/ios/libObjectAL.a</lib>
-  </libs>
+  <libs/>
   <frameworks>
     <framework>UIKit</framework>
     <framework>OpenGLES</framework>
-- 
GitLab