Added rotation feature

This commit is contained in:
Arnaud Vergnet 2020-03-15 19:28:41 +01:00
parent 3aaf56a660
commit bb54186d9e
3 changed files with 70 additions and 9 deletions

View file

@ -19,6 +19,7 @@ export default class GameLogic {
gameTickInterval: IntervalID; gameTickInterval: IntervalID;
onTick: Function; onTick: Function;
endCallback: Function;
constructor(height: number, width: number) { constructor(height: number, width: number) {
this.height = height; this.height = height;
@ -114,6 +115,12 @@ export default class GameLogic {
} }
} }
tryRotateTetromino() {
this.currentObject.rotate(true);
if (!this.isTetrominoPositionValid())
this.currentObject.rotate(false);
}
onTick(callback: Function) { onTick(callback: Function) {
this.gameTime++; this.gameTime++;
this.score++; this.score++;
@ -131,6 +138,11 @@ export default class GameLogic {
callback(this.getFinalGrid()); callback(this.getFinalGrid());
} }
rotatePressed(callback: Function) {
this.tryRotateTetromino();
callback(this.getFinalGrid());
}
createTetromino() { createTetromino() {
let shape = Math.floor(Math.random() * 7); let shape = Math.floor(Math.random() * 7);
this.currentObject = new Tetromino(shape); this.currentObject = new Tetromino(shape);
@ -140,10 +152,12 @@ export default class GameLogic {
endGame() { endGame() {
console.log('Game Over!'); console.log('Game Over!');
this.gameRunning = false;
clearInterval(this.gameTickInterval); clearInterval(this.gameTickInterval);
this.endCallback(this.gameTime, this.score);
} }
startGame(callback: Function) { startGame(tickCallback: Function, endCallback: Function) {
if (this.gameRunning) if (this.gameRunning)
return; return;
this.gameRunning = true; this.gameRunning = true;
@ -151,8 +165,10 @@ export default class GameLogic {
this.score = 0; this.score = 0;
this.currentGrid = this.getEmptyGrid(); this.currentGrid = this.getEmptyGrid();
this.createTetromino(); this.createTetromino();
this.onTick = this.onTick.bind(this, callback); tickCallback(this.gameTime, this.score, this.getFinalGrid());
this.onTick = this.onTick.bind(this, tickCallback);
this.gameTickInterval = setInterval(this.onTick, this.gameTick); this.gameTickInterval = setInterval(this.onTick, this.gameTick);
this.endCallback = endCallback;
} }
} }

View file

@ -22,6 +22,7 @@ class TetrisScreen extends React.Component<Props, State> {
logic: GameLogic; logic: GameLogic;
onTick: Function; onTick: Function;
onGameEnd: Function;
updateGrid: Function; updateGrid: Function;
constructor(props) { constructor(props) {
@ -34,6 +35,7 @@ class TetrisScreen extends React.Component<Props, State> {
gameScore: 0, gameScore: 0,
}; };
this.onTick = this.onTick.bind(this); this.onTick = this.onTick.bind(this);
this.onGameEnd = this.onGameEnd.bind(this);
this.updateGrid = this.updateGrid.bind(this); this.updateGrid = this.updateGrid.bind(this);
const onScreenBlur = this.onScreenBlur.bind(this); const onScreenBlur = this.onScreenBlur.bind(this);
this.props.navigation.addListener('blur', onScreenBlur); this.props.navigation.addListener('blur', onScreenBlur);
@ -63,10 +65,17 @@ class TetrisScreen extends React.Component<Props, State> {
startGame() { startGame() {
if (!this.logic.isGameRunning()) { if (!this.logic.isGameRunning()) {
this.logic.startGame(this.onTick); this.logic.startGame(this.onTick, this.onGameEnd);
} }
} }
onGameEnd(time: number, score: number) {
this.setState({
gameTime: time,
gameScore: score,
})
}
render() { render() {
return ( return (
<View style={{ <View style={{
@ -104,8 +113,13 @@ class TetrisScreen extends React.Component<Props, State> {
<IconButton <IconButton
icon="format-rotate-90" icon="format-rotate-90"
size={40} size={40}
onPress={() => this.startGame()} onPress={() => this.logic.rotatePressed(this.updateGrid)}
/> />
<IconButton
icon="power"
size={40}
onPress={() => this.startGame()}
/>
</View> </View>
</View> </View>
); );

View file

@ -22,6 +22,11 @@ export default class Tetromino {
[0, 1, 0], [0, 1, 0],
[1, 1, 1], [1, 1, 1],
], ],
20: [
[1, 0],
[1, 1],
[1, 0],
],
3: [ 3: [
[0, 1, 1], [0, 1, 1],
[1, 1, 0], [1, 1, 0],
@ -48,14 +53,18 @@ export default class Tetromino {
4: '#ff000b', 4: '#ff000b',
5: '#1000ff', 5: '#1000ff',
6: '#ff9400', 6: '#ff9400',
} };
currentType: Tetromino.types; currentType: Object;
currentShape: Object;
currentRotation: number;
position: Object; position: Object;
constructor(type: Tetromino.types) { constructor(type: Tetromino.types) {
this.currentType = type; this.currentType = type;
this.currentShape = Tetromino.shapes[type];
this.currentRotation = 0;
this.position = {x: 0, y: 0}; this.position = {x: 0, y: 0};
} }
@ -65,15 +74,37 @@ export default class Tetromino {
getCellsCoordinates() { getCellsCoordinates() {
let coordinates = []; let coordinates = [];
for (let row = 0; row < Tetromino.shapes[this.currentType].length; row++) { for (let row = 0; row < this.currentShape.length; row++) {
for (let col = 0; col < Tetromino.shapes[this.currentType][row].length; col++) { for (let col = 0; col < this.currentShape[row].length; col++) {
if (Tetromino.shapes[this.currentType][row][col] === 1) if (this.currentShape[row][col] === 1)
coordinates.push({x: this.position.x + col, y: this.position.y + row}); coordinates.push({x: this.position.x + col, y: this.position.y + row});
} }
} }
return coordinates; return coordinates;
} }
rotate(isForward) {
this.currentRotation++;
if (this.currentRotation > 3)
this.currentRotation = 0;
if (this.currentRotation === 0) {
this.currentShape = Tetromino.shapes[this.currentType];
} else {
let result = [];
for(let i = 0; i < this.currentShape[0].length; i++) {
let row = this.currentShape.map(e => e[i]);
if (isForward)
result.push(row.reverse());
else
result.push(row);
}
this.currentShape = result;
}
}
move(x: number, y: number) { move(x: number, y: number) {
this.position.x += x; this.position.x += x;
this.position.y += y; this.position.y += y;