application-amicale/screens/Tetris/GameLogic.js

175 lines
4.5 KiB
JavaScript
Raw Normal View History

2020-03-15 18:44:32 +01:00
// @flow
import Tetromino from "./Tetromino";
export default class GameLogic {
currentGrid: Array<Array<Object>>;
height: number;
width: number;
gameRunning: boolean;
gameTime: number;
score: number;
currentObject: Tetromino;
gameTick: number;
gameTickInterval: IntervalID;
onTick: Function;
2020-03-15 19:28:41 +01:00
endCallback: Function;
2020-03-15 18:44:32 +01:00
constructor(height: number, width: number) {
this.height = height;
this.width = width;
this.gameRunning = false;
this.gameTick = 250;
}
getHeight(): number {
return this.height;
}
getWidth(): number {
return this.width;
}
isGameRunning(): boolean {
return this.gameRunning;
}
getEmptyGrid() {
let grid = [];
for (let row = 0; row < this.getHeight(); row++) {
grid.push([]);
for (let col = 0; col < this.getWidth(); col++) {
grid[row].push({
color: '#fff',
isEmpty: true,
});
}
}
return grid;
}
getGridCopy() {
return JSON.parse(JSON.stringify(this.currentGrid));
}
getFinalGrid() {
let coord = this.currentObject.getCellsCoordinates();
let finalGrid = this.getGridCopy();
for (let i = 0; i < coord.length; i++) {
finalGrid[coord[i].y][coord[i].x] = {
color: this.currentObject.getColor(),
isEmpty: false,
};
}
return finalGrid;
}
freezeTetromino() {
let coord = this.currentObject.getCellsCoordinates();
for (let i = 0; i < coord.length; i++) {
this.currentGrid[coord[i].y][coord[i].x] = {
color: this.currentObject.getColor(),
isEmpty: false,
};
}
}
isTetrominoPositionValid() {
let isValid = true;
let coord = this.currentObject.getCellsCoordinates();
for (let i = 0; i < coord.length; i++) {
if (coord[i].x >= this.getWidth()
|| coord[i].x < 0
|| coord[i].y >= this.getHeight()
|| coord[i].y < 0
|| !this.currentGrid[coord[i].y][coord[i].x].isEmpty) {
isValid = false;
break;
}
}
return isValid;
}
tryMoveTetromino(x: number, y: number) {
if (x > 1) x = 1; // Prevent moving from more than one tile
if (x < -1) x = -1;
if (y > 1) y = 1;
if (y < -1) y = -1;
if (x !== 0 && y !== 0) y = 0; // Prevent diagonal movement
this.currentObject.move(x, y);
let isValid = this.isTetrominoPositionValid();
if (!isValid && x !== 0)
this.currentObject.move(-x, 0);
else if (!isValid && y !== 0) {
this.currentObject.move(0, -y);
this.freezeTetromino();
this.createTetromino();
}
}
2020-03-15 19:28:41 +01:00
tryRotateTetromino() {
this.currentObject.rotate(true);
if (!this.isTetrominoPositionValid())
this.currentObject.rotate(false);
}
2020-03-15 18:44:32 +01:00
onTick(callback: Function) {
this.gameTime++;
this.score++;
this.tryMoveTetromino(0, 1);
callback(this.gameTime, this.score, this.getFinalGrid());
}
rightPressed(callback: Function) {
this.tryMoveTetromino(1, 0);
callback(this.getFinalGrid());
}
leftPressed(callback: Function) {
this.tryMoveTetromino(-1, 0);
callback(this.getFinalGrid());
}
2020-03-15 19:28:41 +01:00
rotatePressed(callback: Function) {
this.tryRotateTetromino();
callback(this.getFinalGrid());
}
2020-03-15 18:44:32 +01:00
createTetromino() {
let shape = Math.floor(Math.random() * 7);
this.currentObject = new Tetromino(shape);
if (!this.isTetrominoPositionValid())
this.endGame();
}
endGame() {
console.log('Game Over!');
2020-03-15 19:28:41 +01:00
this.gameRunning = false;
2020-03-15 18:44:32 +01:00
clearInterval(this.gameTickInterval);
2020-03-15 19:28:41 +01:00
this.endCallback(this.gameTime, this.score);
2020-03-15 18:44:32 +01:00
}
2020-03-15 19:28:41 +01:00
startGame(tickCallback: Function, endCallback: Function) {
2020-03-15 18:44:32 +01:00
if (this.gameRunning)
return;
this.gameRunning = true;
this.gameTime = 0;
this.score = 0;
this.currentGrid = this.getEmptyGrid();
this.createTetromino();
2020-03-15 19:28:41 +01:00
tickCallback(this.gameTime, this.score, this.getFinalGrid());
this.onTick = this.onTick.bind(this, tickCallback);
2020-03-15 18:44:32 +01:00
this.gameTickInterval = setInterval(this.onTick, this.gameTick);
2020-03-15 19:28:41 +01:00
this.endCallback = endCallback;
2020-03-15 18:44:32 +01:00
}
}