improve grabability

master
agp8x 2017-08-11 16:18:17 +02:00
parent 58f55f19bf
commit 9f23ba4a60
9 changed files with 118 additions and 47 deletions

View File

@ -16,13 +16,8 @@ public class FillGrid extends AppCompatActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fill_grid); setContentView(R.layout.activity_fill_grid);
//GridObject<String> sgo = new GridBlock<>("asdf");
//GridObject<Asdf> ago = new GridBlock<>(Asdf.A);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.mainLayout); RelativeLayout layout = (RelativeLayout) findViewById(R.id.mainLayout);
/* Pair<Float, Float> fp = new Pair<>(1.0f, 2.0f);
Pair<Integer, Integer> ip = new Pair<>(1, 2);
ip = new Pair<>(fp.first.intValue(), fp.second.intValue());*/
FillGridView gridview = new FillGridView(this); FillGridView gridview = new FillGridView(this);
layout.addView(gridview); layout.addView(gridview);
gridview.setScoreView((TextView) findViewById(R.id.textView)); gridview.setScoreView((TextView) findViewById(R.id.textView));

View File

@ -3,9 +3,7 @@ package org.agp8x.android.games.fillgrid;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.widget.TextViewCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -21,8 +19,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.agp8x.android.games.fillgrid.Util.TAG;
/** /**
* Created by clemensk on 07.04.17. * Created by clemensk on 07.04.17.
*/ */
@ -34,6 +30,9 @@ public class FillGridView extends View {
protected GridBoard<GridBlock<GroupCell>, GroupCell> board; protected GridBoard<GridBlock<GroupCell>, GroupCell> board;
protected List<GridBlock<GroupCell>> blocks; protected List<GridBlock<GroupCell>> blocks;
protected Map<Offset, GroupCell> background; protected Map<Offset, GroupCell> background;
/**
* relative positioning
*/
protected Map<Offset, GridBlock<GroupCell>> spawnGrid; protected Map<Offset, GridBlock<GroupCell>> spawnGrid;
protected GroupGridPainter<GroupCell> painter; protected GroupGridPainter<GroupCell> painter;
protected GroupGridPainter<GroupCell> bgPainter; protected GroupGridPainter<GroupCell> bgPainter;
@ -42,6 +41,9 @@ public class FillGridView extends View {
private SpawnPainterGroup<GridBlock<GroupCell>, GroupCell> spawnPainter; private SpawnPainterGroup<GridBlock<GroupCell>, GroupCell> spawnPainter;
private Dragging dragging; private Dragging dragging;
private Offset dimensions; private Offset dimensions;
/**
* on-screen coordinates, updated by onDraw
*/
private Map<GridBlock<GroupCell>, Pair<Integer, Integer>> spawnPositions; private Map<GridBlock<GroupCell>, Pair<Integer, Integer>> spawnPositions;
private TextView scoreView; private TextView scoreView;
private int score = 0; private int score = 0;
@ -122,6 +124,7 @@ public class FillGridView extends View {
grid.getObjects().put(new Offset(0, 1), new GroupCell(0)); grid.getObjects().put(new Offset(0, 1), new GroupCell(0));
grid.getObjects().put(new Offset(1, 0), new GroupCell(0)); grid.getObjects().put(new Offset(1, 0), new GroupCell(0));
grid.getObjects().put(new Offset(1, 1), new GroupCell(0)); grid.getObjects().put(new Offset(1, 1), new GroupCell(0));
grid.setCenter(new Offset(1, 1));
blocks.add(grid); blocks.add(grid);
return grid; return grid;
} }
@ -133,6 +136,7 @@ public class FillGridView extends View {
grid.getObjects().put(new Offset(2, 2), new GroupCell(1)); grid.getObjects().put(new Offset(2, 2), new GroupCell(1));
grid.getObjects().put(new Offset(2, 1), new GroupCell(1)); grid.getObjects().put(new Offset(2, 1), new GroupCell(1));
grid.getObjects().put(new Offset(2, 0), new GroupCell(1)); grid.getObjects().put(new Offset(2, 0), new GroupCell(1));
grid.setCenter(new Offset(3, 3));
blocks.add(grid); blocks.add(grid);
return grid; return grid;
} }
@ -150,7 +154,6 @@ public class FillGridView extends View {
painter.draw(canvas, board.getGrid(), contentSize); painter.draw(canvas, board.getGrid(), contentSize);
spawnPositions = spawnPainter.draw(canvas, spawnGrid, spawnBoundaries); spawnPositions = spawnPainter.draw(canvas, spawnGrid, spawnBoundaries);
if (dragging.object != null) { if (dragging.object != null) {
Log.d(TAG, "draw dragging");
spawnPainter.drawDragging(canvas, dragging.xy, dragging.object); spawnPainter.drawDragging(canvas, dragging.xy, dragging.object);
} }
} }
@ -175,7 +178,11 @@ public class FillGridView extends View {
} }
contentSize = new Pair<>(contentHeight, contentWidth); contentSize = new Pair<>(contentHeight, contentWidth);
spawnSize = new Pair<>(spawnHeight, spawnWidth); spawnSize = new Pair<>(spawnHeight, spawnWidth);
spawnBoundaries = new Area(contentHeight, paddingLeft, spawnHeight + contentHeight, spawnWidth); spawnBoundaries = new Area(
contentHeight,
paddingLeft,
spawnHeight + contentHeight,
spawnWidth);
} }
private int divideSide(int sideLength) { private int divideSide(int sideLength) {
@ -193,7 +200,9 @@ public class FillGridView extends View {
} }
private Offset coordinate2offset(Pair<Float, Float> xy) { private Offset coordinate2offset(Pair<Float, Float> xy) {
return new Offset((int) ((xy.second / contentSize.first) * dimensions.y), (int) ((xy.first / contentSize.second) * dimensions.y)); return new Offset((int) (
(xy.second / contentSize.first) * dimensions.y),
(int) ((xy.first / contentSize.second) * dimensions.y));
} }
private Offset coordinate2spawnOffset(Pair<Float, Float> xy) { private Offset coordinate2spawnOffset(Pair<Float, Float> xy) {
@ -245,10 +254,17 @@ public class FillGridView extends View {
boolean updated = false; boolean updated = false;
// spawnPositions.entrySet().stream().filter(entry -> selects(position, entry.getValue())).findFirst().ifPresent(entry -> startDragging(entry, position)); // spawnPositions.entrySet().stream().filter(entry -> selects(position, entry.getValue())).findFirst().ifPresent(entry -> startDragging(entry, position));
for (Map.Entry<GridBlock<GroupCell>, Pair<Integer, Integer>> entry : spawnPositions.entrySet()) { for (Map.Entry<GridBlock<GroupCell>, Pair<Integer, Integer>> entry : spawnPositions.entrySet()) {
if (selects(position, entry.getValue())) { if (selects(position, entry)) {
dragging.object = entry.getKey(); dragging.object = entry.getKey();
dragging.xy = position; dragging.xy = position;
dragging.origin = entry.getValue();
updated = true; updated = true;
spawnGrid.entrySet().
stream().
filter(offset_block -> offset_block.getValue() == dragging.object).
findFirst().
ifPresent(offsetGridBlockEntry -> dragging.key = offsetGridBlockEntry.getKey());
spawnGrid.remove(dragging.key);
break; break;
} }
} }
@ -261,17 +277,13 @@ public class FillGridView extends View {
if (dragging.object != null) { if (dragging.object != null) {
if (board.drop(coordinate2offset(position), dragging.object)) { if (board.drop(coordinate2offset(position), dragging.object)) {
//Offset key = spawnGrid.entrySet().stream().filter(entry -> entry==dragging.object).findFirst().get().getKey(); //Offset key = spawnGrid.entrySet().stream().filter(entry -> entry==dragging.object).findFirst().get().getKey();
Offset key = null;
for (Map.Entry<Offset, GridBlock<GroupCell>> entry : spawnGrid.entrySet()) {
if (entry.getValue() == dragging.object) {
key = entry.getKey();
break;
}
}
spawnGrid.remove(key);
spawnPositions.remove(dragging.object); spawnPositions.remove(dragging.object);
}else{
spawnGrid.put(dragging.key,dragging.object);
} }
dragging.object = null; dragging.object = null;
dragging.origin = null;
dragging.key = null;
if (spawnGrid.isEmpty()) { if (spawnGrid.isEmpty()) {
populateSpawnArea(); populateSpawnArea();
} }
@ -294,15 +306,18 @@ public class FillGridView extends View {
dragging.xy = position; dragging.xy = position;
}*/ }*/
private boolean selects(Pair<Float, Float> eventPos, Pair<Integer, Integer> spawnPos) { private boolean selects(Pair<Float, Float> eventPos, Map.Entry<GridBlock<GroupCell>, Pair<Integer, Integer>> spawnPos) {
float xdiff = Math.abs(eventPos.first - spawnPos.first); Pair<Float, Float> center = Util.offsetToScreen(spawnPos.getKey().getCenter(), dimensions);
float ydiff = Math.abs(eventPos.second - spawnPos.second); float xdiff = Math.abs(eventPos.first - (spawnPos.getValue().first + center.first));
return xdiff < 40 && ydiff < 40; float ydiff = Math.abs(eventPos.second - (spawnPos.getValue().second + center.second));
return xdiff < 100 && ydiff < 100;
} }
} }
private class Dragging { private class Dragging {
GridBlock<GroupCell> object; GridBlock<GroupCell> object;
Pair<Float, Float> xy; Pair<Float, Float> xy;
Pair<Integer, Integer> origin;
Offset key;
} }
} }

View File

@ -1,6 +1,7 @@
package org.agp8x.android.games.fillgrid; package org.agp8x.android.games.fillgrid;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.support.annotation.NonNull;
import android.util.Pair; import android.util.Pair;
import org.agp8x.android.games.fillgrid.data.GroupCell; import org.agp8x.android.games.fillgrid.data.GroupCell;
@ -31,7 +32,8 @@ public class GroupGridPainter<C extends GroupCell> implements GridPainter<C> {
} }
private void drawCell(Canvas canvas, Offset offset, C cell, Pair<Integer, Integer> realDimensions) { private void drawCell(Canvas canvas, Offset offset, C cell, Pair<Integer, Integer> realDimensions) {
Pair<Float, Float> origin = new Pair<>((offset.x / (float) dimensions.x) * realDimensions.first, (offset.y / (float) dimensions.y) * realDimensions.second); Pair<Float, Float> origin = Util.offsetToScreen(offset, realDimensions, dimensions);
canvas.drawCircle(origin.second + margin, origin.first + margin, radius, styleInfo.getPaint(cell)); canvas.drawCircle(origin.second + margin, origin.first + margin, radius, styleInfo.getPaint(cell));
} }
} }

View File

@ -21,6 +21,7 @@ public class SpawnPainterGroup<G extends GridObject<C>, C extends GroupCell> imp
private CellPaintProvider<C> styleInfo; private CellPaintProvider<C> styleInfo;
private int diameter; private int diameter;
private Map<G, Pair<Integer, Integer>> positions; private Map<G, Pair<Integer, Integer>> positions;
private Offset dragOffset;
public SpawnPainterGroup(CellPaintProvider<C> styleInfo) { public SpawnPainterGroup(CellPaintProvider<C> styleInfo) {
this.styleInfo = styleInfo; this.styleInfo = styleInfo;
@ -28,6 +29,7 @@ public class SpawnPainterGroup<G extends GridObject<C>, C extends GroupCell> imp
margin = radius * 3 + radius / 4; margin = radius * 3 + radius / 4;
diameter = radius * 2; diameter = radius * 2;
positions = new HashMap<>(); positions = new HashMap<>();
dragOffset = new Offset(0,0);
} }
@Override @Override
@ -56,7 +58,7 @@ public class SpawnPainterGroup<G extends GridObject<C>, C extends GroupCell> imp
} }
private void drawCellDragging(Canvas canvas, Pair<Float, Float> xy, Offset offset, C c) { private void drawCellDragging(Canvas canvas, Pair<Float, Float> xy, Offset offset, C c) {
canvas.drawCircle(xy.first + diameter * offset.y, xy.second + diameter * offset.x, radius, styleInfo.getPaint(c)); canvas.drawCircle(xy.first + diameter * (offset.y+dragOffset.y), xy.second + diameter * (offset.x+dragOffset.x), radius, styleInfo.getPaint(c));
} }
private void drawBlock(Canvas canvas, G groupCellGridBlock) { private void drawBlock(Canvas canvas, G groupCellGridBlock) {

View File

@ -1,9 +1,12 @@
package org.agp8x.android.games.fillgrid; package org.agp8x.android.games.fillgrid;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.view.MotionEvent; import android.view.MotionEvent;
import org.agp8x.android.games.fillgrid.data.Offset;
/** /**
* Created by clemensk on 09.04.17. * Created by clemensk on 09.04.17.
*/ */
@ -16,9 +19,18 @@ public class Util {
} }
public static boolean in(Pair<Float, Float> probe, Area area) { public static boolean in(Pair<Float, Float> probe, Area area) {
Log.d(TAG,"probe: "+probe+" ;area: "+area); Log.d(TAG, "probe: " + probe + " ;area: " + area);
Log.d(TAG, "("+(area.top < probe.second)+" && "+(probe.second < area.bottom)+") && ("+(area.left < probe.first) +" && "+ (probe.first < area.right)+")"); Log.d(TAG, "(" + (area.top < probe.second) + " && " + (probe.second < area.bottom) + ") && (" + (area.left < probe.first) + " && " + (probe.first < area.right) + ")");
boolean contained = (area.top < probe.second && probe.second < area.bottom) && (area.left < probe.first && probe.first < area.right); boolean contained = (area.top < probe.second && probe.second < area.bottom) && (area.left < probe.first && probe.first < area.right);
return contained; return contained;
} }
public static Pair<Float, Float> offsetToScreen(Offset offset, Offset dimensions) {
return offsetToScreen(offset, new Pair<>(1, 1), dimensions);
}
@NonNull
public static Pair<Float, Float> offsetToScreen(Offset offset, Pair<Integer, Integer> realDimensions, Offset dimensions) {
return new Pair<>((offset.x / (float) dimensions.x) * realDimensions.first, (offset.y / (float) dimensions.y) * realDimensions.second);
}
} }

View File

@ -1,5 +1,7 @@
package org.agp8x.android.games.fillgrid.data; package org.agp8x.android.games.fillgrid.data;
import org.agp8x.android.games.fillgrid.Area;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -9,6 +11,7 @@ import java.util.Map;
public class GridBlock<C extends Cell> implements GridObject<C> { public class GridBlock<C extends Cell> implements GridObject<C> {
private final Map<Offset, C> content; private final Map<Offset, C> content;
private Offset center;
public GridBlock() { public GridBlock() {
content = new HashMap<>(); content = new HashMap<>();
@ -18,6 +21,11 @@ public class GridBlock<C extends Cell> implements GridObject<C> {
this.content = new HashMap<>(content); this.content = new HashMap<>(content);
} }
public GridBlock(Map<Offset, C> content, Offset center) {
this.content = new HashMap<>(content);
this.center = center;
}
@Override @Override
public Map<Offset, C> getObjects() { public Map<Offset, C> getObjects() {
return content; return content;
@ -30,22 +38,19 @@ public class GridBlock<C extends Cell> implements GridObject<C> {
@Override @Override
public GridObject<C> duplicate() { public GridObject<C> duplicate() {
return new GridBlock<>(content); return new GridBlock<>(content, center);
} }
@Override @Override
public Offset getDimensions() { public Offset getCenter() {
if (content.isEmpty()) { if (center == null) {
return new Offset(0, 0); return new Offset(0, 0);
} }
Offset min = content.keySet().stream().findFirst().get(); return this.center;
Offset max = min; }
for (Offset offset : content.keySet()) {
min = Offset.min(min, offset); public void setCenter(Offset center) {
max = Offset.max(max, offset); this.center = center;
}
System.out.println(max);
System.out.println(min);
return new Offset(1 + max.x - min.x, 1 + max.y - min.y);
} }
} }

View File

@ -13,5 +13,5 @@ public interface GridObject<C extends Cell> {
GridObject<C> duplicate(); GridObject<C> duplicate();
Offset getDimensions(); Offset getCenter();
} }

View File

@ -1,5 +1,6 @@
package org.agp8x.android.games.fillgrid.data; package org.agp8x.android.games.fillgrid.data;
import org.agp8x.android.games.fillgrid.Area;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -25,13 +26,13 @@ public class GridBlockTest {
public void getDimensions() throws Exception { public void getDimensions() throws Exception {
/* /*
* oox * oox
* oxo- * oXo-
* oox * oox
*/ */
assertEquals(new Offset(2, 3), grid.getDimensions()); assertEquals(new Offset(2, 3), grid.getDimensions());
/* /*
* xxx * xxx
* oxo- * oXo-
* oox * oox
*/ */
grid.getObjects().put(new Offset(-1, 1), new StringCell("top-left")); grid.getObjects().put(new Offset(-1, 1), new StringCell("top-left"));
@ -39,7 +40,7 @@ public class GridBlockTest {
assertEquals(new Offset(3, 3), grid.getDimensions()); assertEquals(new Offset(3, 3), grid.getDimensions());
/* /*
* ooxxx * ooxxx
* oox * oOx
* oox * oox
*/ */
grid.getObjects().clear(); grid.getObjects().clear();
@ -51,7 +52,7 @@ public class GridBlockTest {
assertEquals(new Offset(3, 3), grid.getDimensions()); assertEquals(new Offset(3, 3), grid.getDimensions());
/* /*
* ooxxx * ooxxx
* ooo * oOo
* ooo * ooo
*/ */
grid.getObjects().remove(new Offset(1, 0), new StringCell("center-right")); grid.getObjects().remove(new Offset(1, 0), new StringCell("center-right"));
@ -59,4 +60,43 @@ public class GridBlockTest {
assertEquals(new Offset(3, 1), grid.getDimensions()); assertEquals(new Offset(3, 1), grid.getDimensions());
} }
@Test
public void toArea() throws Exception {
/*
* oox
* oXo-
* oox
*/
assertEquals(new Area(-1,0,1,1), grid.toArea());
/*
* xxx
* oXo-
* oox
*/
grid.getObjects().put(new Offset(-1, 1), new StringCell("top-left"));
grid.getObjects().put(new Offset(0, 1), new StringCell("top-center"));
assertEquals(new Area(-1,-1,1,1), grid.toArea());
/*
* oxxx
* Ox
* ox
*/
grid.getObjects().clear();
grid.getObjects().put(new Offset(1, 1), new StringCell("top-right"));
grid.getObjects().put(new Offset(2, 1), new StringCell("top-right2"));
grid.getObjects().put(new Offset(3, 1), new StringCell("top-right3"));
grid.getObjects().put(new Offset(1, 0), new StringCell("center-right"));
grid.getObjects().put(new Offset(1, 2), new StringCell("bottom-right"));
assertEquals(new Area(0,1,2,3), grid.toArea());
/*
* oxxx
* Oo
* oo
*/
grid.getObjects().remove(new Offset(1, 0), new StringCell("center-right"));
grid.getObjects().remove(new Offset(1, -1), new StringCell("bottom-right"));
assertEquals(new Area(0,1,2,3), grid.toArea());
}
} }

View File

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.3.1' classpath 'com.android.tools.build:gradle:2.3.3'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files