11package cz .destil .sliderpuzzle .ui ;
22
33import java .util .ArrayList ;
4- import java .util .HashSet ;
54
65import android .animation .Animator ;
76import android .animation .Animator .AnimatorListener ;
@@ -144,7 +143,7 @@ public boolean onTouch(View v, MotionEvent event) {
144143 // during the gesture
145144 } else if (event .getActionMasked () == MotionEvent .ACTION_MOVE ) {
146145 if (lastDragPoint != null ) {
147- moveDraggedTilesByMotionEventDelta (event );
146+ followFinger (event );
148147 }
149148 lastDragPoint = new PointF (event .getRawX (), event .getRawY ());
150149 // end of gesture
@@ -153,13 +152,13 @@ public boolean onTouch(View v, MotionEvent event) {
153152 currentMotionDescriptors = getTilesBetweenEmptyTileAndTile (movedTile );
154153 // if drag was over 50%, do the move
155154 if (lastDragPoint != null && lastDragMovedAtLeastHalfWay ()) {
156- animateCurrentMovedTilesToEmptySpace ();
155+ animateTilesToEmptySpace ();
157156 // if it was a click, do the move
158157 } else if (lastDragPoint == null || lastDragMovedMinimally ()) {
159- animateCurrentMovedTilesToEmptySpace ();
158+ animateTilesToEmptySpace ();
160159 // if it was a drag less than 50%, animate tiles back
161160 } else {
162- animateMovedTilesBackToOrigin ();
161+ animateTilesBackToOrigin ();
163162 }
164163 currentMotionDescriptors = null ;
165164 lastDragPoint = null ;
@@ -196,7 +195,13 @@ private boolean lastDragMovedMinimally() {
196195 return false ;
197196 }
198197
199- private void moveDraggedTilesByMotionEventDelta (MotionEvent event ) {
198+ /**
199+ * Follows finger while dragging all currently moved tiles.
200+ * Allows movement only along x axis for row and y axis for column.
201+ *
202+ * @param event
203+ */
204+ private void followFinger (MotionEvent event ) {
200205 boolean impossibleMove = true ;
201206 float dxTile , dyTile ;
202207 float dxEvent = event .getRawX () - lastDragPoint .x ;
@@ -206,21 +211,22 @@ private void moveDraggedTilesByMotionEventDelta(MotionEvent event) {
206211 tile = gameTileMotionDescriptor .tile ;
207212 dxTile = tile .getX () + dxEvent ;
208213 dyTile = tile .getY () + dyEvent ;
209-
214+ // detect if this move is valid
210215 RectF candidateRect = new RectF (dxTile , dyTile , dxTile + tile .getWidth (), dyTile + tile .getHeight ());
211- HashSet <TileView > tilesToCheck = null ;
216+ ArrayList <TileView > tilesToCheck = null ;
212217 if (tile .coordinate .row == emptyTile .coordinate .row ) {
213218 tilesToCheck = allTilesInRow (tile .coordinate .row );
214219 } else if (tile .coordinate .column == emptyTile .coordinate .column ) {
215220 tilesToCheck = allTilesInColumn (tile .coordinate .column );
216221 }
217222
218223 boolean candidateRectInGameboard = (gameboardRect .contains (candidateRect ));
219- boolean collides = candidateRectForTileCollidesWithAnyTileInSet (candidateRect , tile , tilesToCheck );
224+ boolean collides = collidesWithTitles (candidateRect , tile , tilesToCheck );
220225
221226 impossibleMove = impossibleMove && (!candidateRectInGameboard || collides );
222227 }
223228 if (!impossibleMove ) {
229+ // perform move for all moved tiles in the descriptors
224230 for (GameTileMotionDescriptor gameTileMotionDescriptor : currentMotionDescriptors ) {
225231 tile = gameTileMotionDescriptor .tile ;
226232 dxTile = tile .getX () + dxEvent ;
@@ -236,10 +242,18 @@ private void moveDraggedTilesByMotionEventDelta(MotionEvent event) {
236242 }
237243 }
238244
239- private boolean candidateRectForTileCollidesWithAnyTileInSet (RectF candidateRect , TileView tile ,
240- HashSet <TileView > set ) {
245+ /**
246+ * @param candidateRect
247+ * rectangle to check
248+ * @param tile
249+ * tile belonging to rectangle
250+ * @param tilesToCheck
251+ * list of tiles to check
252+ * @return Whether candidateRect collides with any tilesToCheck
253+ */
254+ private boolean collidesWithTitles (RectF candidateRect , TileView tile , ArrayList <TileView > tilesToCheck ) {
241255 RectF otherTileRect ;
242- for (TileView otherTile : set ) {
256+ for (TileView otherTile : tilesToCheck ) {
243257 if (!otherTile .isEmpty () && otherTile != tile ) {
244258 otherTileRect = new RectF (otherTile .getX (), otherTile .getY (), otherTile .getX () + otherTile .getWidth (),
245259 otherTile .getY () + otherTile .getHeight ());
@@ -251,7 +265,11 @@ private boolean candidateRectForTileCollidesWithAnyTileInSet(RectF candidateRect
251265 return false ;
252266 }
253267
254- private void animateCurrentMovedTilesToEmptySpace () {
268+ /**
269+ * Performs animation of currently moved tiles into empty space. Happens
270+ * when valid tile is clicked or is dragged over 50%.
271+ */
272+ private void animateTilesToEmptySpace () {
255273 emptyTile .setX (movedTile .getX ());
256274 emptyTile .setY (movedTile .getY ());
257275 emptyTile .coordinate = movedTile .coordinate ;
@@ -281,7 +299,11 @@ public void onAnimationEnd(Animator animation) {
281299 }
282300 }
283301
284- private void animateMovedTilesBackToOrigin () {
302+ /**
303+ * Performs animation of currently moved tiles back to origin. Happens when
304+ * the drag was less than 50%.
305+ */
306+ private void animateTilesBackToOrigin () {
285307 ObjectAnimator animator ;
286308 if (currentMotionDescriptors != null ) {
287309 for (final GameTileMotionDescriptor motionDescriptor : currentMotionDescriptors ) {
@@ -307,6 +329,14 @@ public void onAnimationEnd(Animator animation) {
307329 }
308330 }
309331
332+ /**
333+ * Finds tiles between checked tile and empty tile and initializes motion
334+ * descriptors for those tiles.
335+ *
336+ * @param tile
337+ * A tile to be checked
338+ * @return list of tiles between checked tile and empty tile
339+ */
310340 private ArrayList <GameTileMotionDescriptor > getTilesBetweenEmptyTileAndTile (TileView tile ) {
311341 ArrayList <GameTileMotionDescriptor > descriptors = new ArrayList <GameTileMotionDescriptor >();
312342 Coordinate coordinate , finalCoordinate ;
@@ -315,6 +345,7 @@ private ArrayList<GameTileMotionDescriptor> getTilesBetweenEmptyTileAndTile(Tile
315345 Rect finalRect , currentRect ;
316346 float axialDelta ;
317347 if (tile .isToRightOf (emptyTile )) {
348+ // add all tiles left of the tile
318349 for (int i = tile .coordinate .column ; i > emptyTile .coordinate .column ; i --) {
319350 coordinate = new Coordinate (tile .coordinate .row , i );
320351 foundTile = (tile .coordinate .matches (coordinate )) ? tile : getTileAtCoordinate (coordinate );
@@ -329,6 +360,7 @@ private ArrayList<GameTileMotionDescriptor> getTilesBetweenEmptyTileAndTile(Tile
329360 descriptors .add (motionDescriptor );
330361 }
331362 } else if (tile .isToLeftOf (emptyTile )) {
363+ // add all tiles right of the tile
332364 for (int i = tile .coordinate .column ; i < emptyTile .coordinate .column ; i ++) {
333365 coordinate = new Coordinate (tile .coordinate .row , i );
334366 foundTile = (tile .coordinate .matches (coordinate )) ? tile : getTileAtCoordinate (coordinate );
@@ -343,6 +375,7 @@ private ArrayList<GameTileMotionDescriptor> getTilesBetweenEmptyTileAndTile(Tile
343375 descriptors .add (motionDescriptor );
344376 }
345377 } else if (tile .isAbove (emptyTile )) {
378+ // add all tiles bellow the tile
346379 for (int i = tile .coordinate .row ; i < emptyTile .coordinate .row ; i ++) {
347380 coordinate = new Coordinate (i , tile .coordinate .column );
348381 foundTile = (tile .coordinate .matches (coordinate )) ? tile : getTileAtCoordinate (coordinate );
@@ -357,6 +390,7 @@ private ArrayList<GameTileMotionDescriptor> getTilesBetweenEmptyTileAndTile(Tile
357390 descriptors .add (motionDescriptor );
358391 }
359392 } else if (tile .isBelow (emptyTile )) {
393+ // add all tiles above the tile
360394 for (int i = tile .coordinate .row ; i > emptyTile .coordinate .row ; i --) {
361395 coordinate = new Coordinate (i , tile .coordinate .column );
362396 foundTile = (tile .coordinate .matches (coordinate )) ? tile : getTileAtCoordinate (coordinate );
@@ -374,6 +408,11 @@ private ArrayList<GameTileMotionDescriptor> getTilesBetweenEmptyTileAndTile(Tile
374408 return descriptors ;
375409 }
376410
411+ /**
412+ * @param coordinate
413+ * coordinate of the tile
414+ * @return tile at given coordinate
415+ */
377416 private TileView getTileAtCoordinate (Coordinate coordinate ) {
378417 for (TileView tile : tiles ) {
379418 if (tile .coordinate .matches (coordinate )) {
@@ -383,8 +422,13 @@ private TileView getTileAtCoordinate(Coordinate coordinate) {
383422 return null ;
384423 }
385424
386- private HashSet <TileView > allTilesInRow (int row ) {
387- HashSet <TileView > tilesInRow = new HashSet <TileView >();
425+ /**
426+ * @param row
427+ * number of row
428+ * @return list of tiles in the row
429+ */
430+ private ArrayList <TileView > allTilesInRow (int row ) {
431+ ArrayList <TileView > tilesInRow = new ArrayList <TileView >();
388432 for (TileView tile : tiles ) {
389433 if (tile .coordinate .row == row ) {
390434 tilesInRow .add (tile );
@@ -393,8 +437,13 @@ private HashSet<TileView> allTilesInRow(int row) {
393437 return tilesInRow ;
394438 }
395439
396- private HashSet <TileView > allTilesInColumn (int column ) {
397- HashSet <TileView > tilesInColumn = new HashSet <TileView >();
440+ /**
441+ * @param column
442+ * number of column
443+ * @return list of tiles in the column
444+ */
445+ private ArrayList <TileView > allTilesInColumn (int column ) {
446+ ArrayList <TileView > tilesInColumn = new ArrayList <TileView >();
398447 for (TileView tile : tiles ) {
399448 if (tile .coordinate .column == column ) {
400449 tilesInColumn .add (tile );
@@ -403,6 +452,10 @@ private HashSet<TileView> allTilesInColumn(int column) {
403452 return tilesInColumn ;
404453 }
405454
455+ /**
456+ * @param coordinate
457+ * @return Rectangle for given coordinate
458+ */
406459 private Rect rectForCoordinate (Coordinate coordinate ) {
407460 int gameboardY = (int ) Math .floor (gameboardRect .top );
408461 int gameboardX = (int ) Math .floor (gameboardRect .left );
@@ -411,10 +464,13 @@ private Rect rectForCoordinate(Coordinate coordinate) {
411464 return new Rect (left , top , left + tileSize , top + tileSize );
412465 }
413466
467+ /**
468+ * Describes movement of the tile. It is used to move several tiles at once.
469+ */
414470 public class GameTileMotionDescriptor {
415471
416472 public Rect finalRect ;
417- public String property ;
473+ public String property ; // "x" or "y"
418474 public TileView tile ;
419475 public float from , to , axialDelta ;
420476 public Coordinate finalCoordinate ;
@@ -427,6 +483,9 @@ public GameTileMotionDescriptor(TileView tile, String property, float from, floa
427483 this .property = property ;
428484 }
429485
486+ /**
487+ * @return current position of the tile
488+ */
430489 public float currentPosition () {
431490 if (property .equals ("x" )) {
432491 return tile .getX ();
@@ -436,6 +495,10 @@ public float currentPosition() {
436495 return 0 ;
437496 }
438497
498+ /**
499+ * @return original position of the tile. It is used in movement to
500+ * original position.
501+ */
439502 public float originalPosition () {
440503 Rect originalRect = rectForCoordinate (tile .coordinate );
441504 if (property .equals ("x" )) {
0 commit comments