Added Game View.
This commit is contained in:
parent
47fe1a7d47
commit
5f85daa682
267
app/src/main/java/fr/iutfbleau/sae/GameView.java
Normal file
267
app/src/main/java/fr/iutfbleau/sae/GameView.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user