From 5f85daa6827b2a0e778b688da815d3338f35fdab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexe=C3=AF=20KADIR?= Date: Thu, 4 Apr 2024 02:12:58 +0200 Subject: [PATCH] Added Game View. --- .../main/java/fr/iutfbleau/sae/GameView.java | 267 ++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 app/src/main/java/fr/iutfbleau/sae/GameView.java diff --git a/app/src/main/java/fr/iutfbleau/sae/GameView.java b/app/src/main/java/fr/iutfbleau/sae/GameView.java new file mode 100644 index 0000000..6a212f9 --- /dev/null +++ b/app/src/main/java/fr/iutfbleau/sae/GameView.java @@ -0,0 +1,267 @@ +package fr.iutfbleau.sae; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class GameView extends View implements View.OnTouchListener { + + public static final int CELL_SIZE = 96; + + + public static final int LINE_SIZE = 12; + + + private GameModel model; + + + private final Point offset; + + + private final Paint paint; + + + private int linePointerId; + + + private int movementPointerId; + + + private float movementX; + + + private float movementY; + + + private GameListener listener; + + + public GameView(Context context, @Nullable AttributeSet attributes) { + super(context, attributes); + + this.offset = new Point(0, 0); + + this.paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + this.setOnTouchListener(this); + + this.linePointerId = -1; + this.movementPointerId = -1; + } + + + public void setModel(GameModel model) { + this.model = model; + } + + + public void setListener(GameListener listener) { + this.listener = listener; + } + + + public void applyOffset(int dx, int dy) { + this.offset.offset(dx, dy); + } + + + public void setOffset(int x, int y) { + this.offset.x = x; + this.offset.y = y; + } + + + public Point getOffset() { + return new Point(offset); + } + + + private Cell pixelToCell(float x, float y) { + int ox = this.offset.x + (this.getWidth() - this.model.getSize() * CELL_SIZE + CELL_SIZE) / 2; + int oy = this.offset.y + (this.getHeight() - this.model.getSize() * CELL_SIZE + CELL_SIZE) / 2; + + return new Cell(Math.round((x - ox) / CELL_SIZE), Math.round((y - oy) / CELL_SIZE)); + } + + + private Cell pixelToCell(Point point) { + return pixelToCell(point.x, point.y); + } + + + private Point cellToPixel(Cell cell) { + int ox = this.offset.x + (this.getWidth() - this.model.getSize() * CELL_SIZE + CELL_SIZE) / 2; + int oy = this.offset.y + (this.getHeight() - this.model.getSize() * CELL_SIZE + CELL_SIZE) / 2; + + return new Point(ox + cell.x * CELL_SIZE, oy + cell.y * CELL_SIZE); + } + + + private void drawGrid(Canvas canvas) { + int w = this.getWidth(); + int h = this.getHeight(); + + this.paint.setColor(this.getResources().getColor(R.color.grid)); + this.paint.setStrokeWidth(LINE_SIZE); + + Point pixelOffset = this.cellToPixel(new Cell(0, 0)); + + for (int x = pixelOffset.x % CELL_SIZE; x < w; x += CELL_SIZE) + canvas.drawLine(x, 0, x, h, this.paint); + + for (int y = pixelOffset.y % CELL_SIZE; y < h; y += CELL_SIZE) + canvas.drawLine(0, y, w, y, this.paint); + } + + + private void drawCrosses(Canvas canvas) { + this.paint.setColor(this.getResources().getColor(R.color.cross)); + this.paint.setStrokeWidth(LINE_SIZE); + + for (Cell cell : this.model.getCells()) + this.drawCross(canvas, cell); + } + + + private void drawCross(Canvas canvas, Cell cell) { + float size = CELL_SIZE / 4.0F; + + Point position = this.cellToPixel(cell); + + canvas.drawLine(position.x, position.y - size, position.x, position.y + size, this.paint); + canvas.drawLine(position.x - size, position.y, position.x + size, position.y, this.paint); + } + + + private void drawInputLine(Canvas canvas) { + if (!this.model.hasInputLine()) + return; + + if (this.model.isInputLineValid()) + this.paint.setColor(this.getResources().getColor(R.color.valid_input_line)); + else + this.paint.setColor(this.getResources().getColor(R.color.invalid_input_line)); + this.paint.setStrokeWidth(LINE_SIZE); + + Point start = this.cellToPixel(this.model.getInputLineStart()); + Point end = this.cellToPixel(this.model.getInputLineEnd()); + + canvas.drawLine(start.x, start.y, end.x, end.y, paint); + } + + + private void drawLines(Canvas canvas) { + this.paint.setColor(this.getResources().getColor(R.color.line)); + this.paint.setStrokeWidth(LINE_SIZE); + + for (Line line : this.model.getLines()) { + Point start = this.cellToPixel(line.getStart()); + Point end = this.cellToPixel(line.getEnd()); + + canvas.drawLine(start.x, start.y, end.x, end.y, paint); + } + } + + + @Override + protected void onDraw(@NonNull Canvas canvas) { + super.onDraw(canvas); + + this.drawGrid(canvas); + + if (this.model != null) + return; + + this.drawLines(canvas); + this.drawCrosses(canvas); + this.drawInputLine(canvas); + } + + + @Override + public boolean onTouch(View view, MotionEvent event) { + if (this != view) + return false; + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: { + if (this.linePointerId != -1) + break; + + int index = event.getActionIndex(); + + this.linePointerId = event.getPointerId(index); + + if (this.listener != null) + this.listener.onLineStarted(this, this.pixelToCell(event.getX(index), event.getY(index))); + + break; + } + + case MotionEvent.ACTION_POINTER_DOWN: { + if (this.movementPointerId != -1) + break; + + int index = event.getActionIndex(); + + this.movementPointerId = event.getPointerId(index); + this.movementX = event.getX(index); + this.movementY = event.getY(index); + + break; + } + + case MotionEvent.ACTION_MOVE: { + if (this.movementPointerId != -1) { + int index = event.findPointerIndex(this.movementPointerId); + + float x = event.getX(index); + float y = event.getY(index); + + if (x != this.movementX || y != this.movementY) { + this.applyOffset(Math.round(x - this.movementX), Math.round(y - this.movementY)); + + this.movementX = x; + this.movementY = y; + + this.invalidate(); + } + } + + if (this.linePointerId != -1) { + int index = event.findPointerIndex(this.linePointerId); + + if (this.listener != null) + this.listener.onLineEndMoved(this, this.pixelToCell(event.getX(index), event.getY(index))); + } + + break; + } + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: { + int index = event.getActionIndex(); + int id = event.getPointerId(index); + + if (this.linePointerId == id) { + this.linePointerId = -1; + + if (this.listener != null) + this.listener.onLineEnded(this, this.pixelToCell(event.getX(index), event.getY(index))); + } + + if (this.movementPointerId == id) + this.movementPointerId = -1; + } + } + + return true; + } +}