In my current prototype I have a fixed grid of rectangles I draw on the canvas in a loop, and a red square “gamePiece” which can be dragged around the screen by a player’s finger (screenshot below). My goal is to make it so that the player square can interact with the grey squares, but I’m not sure how to detect interactions between canvas objects. How can this be accomplished?
The relevant chunks of my code are below, but please let me know if there is anything else I can provide to help. I don’t expect anyone to make this for me, but if someone could point me towards good resources I would appreciate it a lot!!
Code
GamePiece (Red Square)
public class GamePiece implements GameObject { private Rect rectangle; private int color; public GamePiece(Rect rectangle, int color) { this.rectangle = rectangle; this.color = color; } @Override public void draw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(color); canvas.drawRect(rectangle, paint); } @Override public void update() { } public void update(Point point) { //ltrb rectangle.set(point.x - rectangle.width()/2, point.y - rectangle.height()/2, point.x + rectangle.width()/2, point.y + rectangle.height()/2); } }
GameTile (Individual Gray Squares)
public class GameTile implements GameObject{ private RectF rectangle; private int color; public static int tilesPerRow = 10; final public static int TILE_SIZE = (PolyGoneUtils.getScreenWidth() - (40 + 20 * tilesPerRow)) / tilesPerRow; public GameTile(RectF rectangle, int color) { this.rectangle = rectangle; this.color = color; } @Override public void draw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(color); canvas.drawRoundRect(rectangle, 10, 10, paint); } @Override public void update() { } @Override public void update(Point point) { rectangle.set(point.x - rectangle.width()/2, point.y - rectangle.height()/2, point.x + rectangle.width()/2, point.y + rectangle.height()/2); } }
GameBoard (makes the grid of GameTiles)
public class GameBoard extends View { private static final int originX = 30; private static final int originY = 400; private static final int tileSize = GameTile.TILE_SIZE; public GameBoard(Context context) { super(context); } public static void makeGameBoard(Canvas canvas) { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { GameTile gameTile = new GameTile(new RectF(originX + i * tileSize + (20 * i), originY + j * tileSize + (20 * j), originX + (i + 1) * tileSize + (20 * i), originY + (j + 1) * tileSize + (20 * j)), Color.DKGRAY); gameTile.draw(canvas); } //System.out.println("Squared Dimensions of the tiles are: " + tileSize); } } }
And Finally here is my GameView
public class GameView extends SurfaceView implements SurfaceHolder.Callback { private MainThread thread; Context context; private GamePiece gamePiece; private Point piecePoint; public GameView(Context context) { super(context); this.context = context; getHolder().addCallback(this); thread = new MainThread(getHolder(), this); setFocusable(true); gamePiece = new GamePiece(new Rect(300, 300, 384, 384), Color.rgb(255, 0, 0)); piecePoint = new Point(342, 342); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { thread = new MainThread(getHolder(), this); thread.setRunning(true); thread.start(); } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { boolean retry; retry = true; while(retry) { try { thread.setRunning(false); thread.join(); } catch (Exception e) {e.printStackTrace();} retry = false; } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //player pressing down case MotionEvent.ACTION_MOVE: //player moving their finger piecePoint.set((int)event.getX(), (int)event.getY() - 100); } return true; //return super.onTouchEvent(event); } public void update() { gamePiece.update(piecePoint); } @Override public void draw(Canvas canvas) { super.draw(canvas); canvas.drawColor(Color.parseColor("#201E36")); GameBoard.makeGameBoard(canvas); // Drawing GameBoard Grid gamePiece.draw(canvas); } }
Advertisement
Answer
Following @Mike M.’s suggestions I have implemented the following solution. Instead of creating my tiles and drawing them every loop, I have changed it to where I define my GameBoard tiles initially in GameView and store them to an ArrayList…
//Within GameBoard class public static void makeGameBoard() { tiles = new ArrayList<>(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { GameTile gameTile = new GameTile(new RectF(originX + i * tileSize + (20 * i), originY + j * tileSize + (20 * j), originX + (i + 1) * tileSize + (20 * i), originY + (j + 1) * tileSize + (20 * j)), Color.DKGRAY); tiles.add(gameTile); } } }
I then use a separate method to draw them from this ArrayList in draw…
//Within GameBoard class public static void drawGameBoard(Canvas canvas) { for (int i = 0; i < tiles.size(); i++) { tiles.get(i).draw(canvas); } }
Finally, to handle the interactions between the board’s gameTiles and the player’s gamePiece I simply check if the Point at the center of the gamePiece is within any of the gameBoard’s gameTiles in the tiles ArrayList with RectF’s built in .contains method.
//Within GameBoard class public static void doesTileInteract(Point gamePiecePoint) { for (int i = 0; i < tiles.size(); i++) { if (tiles.get(i).getRectangle().contains(gamePiecePoint.x, gamePiecePoint.y)) { System.out.println("The tiles are interacting!"); } } }
Which is called in the onTouchEvent method.
//Within GameView class @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //player pressing down wasClicked = gamePiece.getRectangle().contains((int) event.getX(), (int) event.getY()); case MotionEvent.ACTION_MOVE: //player moving their finger if (wasClicked) { gamePiecePoint.set((int) event.getX(), (int) event.getY() - 100); } GameBoard.doesTileInteract(gamePiecePoint); } return true; //return super.onTouchEvent(event); }
Thanks so much to @Mike M. for all his suggestions!! I really appreciate the help.