forked from vergnet/application-amicale
Update game to use TypeScript
This commit is contained in:
parent
c198a40148
commit
fde9a12ef9
18 changed files with 326 additions and 313 deletions
|
@ -19,11 +19,9 @@
|
|||
|
||||
// @flow
|
||||
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
|
||||
export type CoordinatesType = {
|
||||
x: number,
|
||||
y: number,
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
export type ShapeType = Array<Array<number>>;
|
||||
|
@ -40,14 +38,15 @@ export default class BaseShape {
|
|||
|
||||
position: CoordinatesType;
|
||||
|
||||
theme: CustomThemeType;
|
||||
theme: ReactNativePaper.Theme;
|
||||
|
||||
/**
|
||||
* Prevent instantiation if classname is BaseShape to force class to be abstract
|
||||
*/
|
||||
constructor(theme: CustomThemeType) {
|
||||
if (this.constructor === BaseShape)
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
if (this.constructor === BaseShape) {
|
||||
throw new Error("Abstract class can't be instantiated");
|
||||
}
|
||||
this.theme = theme;
|
||||
this.#rotation = 0;
|
||||
this.position = {x: 0, y: 0};
|
||||
|
@ -58,7 +57,6 @@ export default class BaseShape {
|
|||
* Gets this shape's color.
|
||||
* Must be implemented by child class
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getColor(): string {
|
||||
throw new Error("Method 'getColor()' must be implemented");
|
||||
}
|
||||
|
@ -69,7 +67,6 @@ export default class BaseShape {
|
|||
*
|
||||
* Used by tests to read private fields
|
||||
*/
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
throw new Error("Method 'getShapes()' must be implemented");
|
||||
}
|
||||
|
@ -98,7 +95,9 @@ export default class BaseShape {
|
|||
x: this.position.x + col,
|
||||
y: this.position.y + row,
|
||||
});
|
||||
} else coordinates.push({x: col, y: row});
|
||||
} else {
|
||||
coordinates.push({x: col, y: row});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,10 +110,16 @@ export default class BaseShape {
|
|||
* @param isForward Should we rotate clockwise?
|
||||
*/
|
||||
rotate(isForward: boolean) {
|
||||
if (isForward) this.#rotation += 1;
|
||||
else this.#rotation -= 1;
|
||||
if (this.#rotation > 3) this.#rotation = 0;
|
||||
else if (this.#rotation < 0) this.#rotation = 3;
|
||||
if (isForward) {
|
||||
this.#rotation += 1;
|
||||
} else {
|
||||
this.#rotation -= 1;
|
||||
}
|
||||
if (this.#rotation > 3) {
|
||||
this.#rotation = 0;
|
||||
} else if (this.#rotation < 0) {
|
||||
this.#rotation = 3;
|
||||
}
|
||||
this.#currentShape = this.getShapes()[this.#rotation];
|
||||
}
|
||||
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeI extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 3;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeI extends BaseShape {
|
|||
return this.theme.colors.tetrisI;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeJ extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 3;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeJ extends BaseShape {
|
|||
return this.theme.colors.tetrisJ;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeL extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 3;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeL extends BaseShape {
|
|||
return this.theme.colors.tetrisL;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeO extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 4;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeO extends BaseShape {
|
|||
return this.theme.colors.tetrisO;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeS extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 3;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeS extends BaseShape {
|
|||
return this.theme.colors.tetrisS;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeT extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 3;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeT extends BaseShape {
|
|||
return this.theme.colors.tetrisT;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import BaseShape from './BaseShape';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {ShapeType} from './BaseShape';
|
||||
|
||||
export default class ShapeZ extends BaseShape {
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
super(theme);
|
||||
this.position.x = 3;
|
||||
}
|
||||
|
@ -33,7 +30,6 @@ export default class ShapeZ extends BaseShape {
|
|||
return this.theme.colors.tetrisZ;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getShapes(): Array<ShapeType> {
|
||||
return [
|
||||
[
|
|
@ -17,35 +17,29 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import {withTheme} from 'react-native-paper';
|
||||
|
||||
export type CellType = {color: string, isEmpty: boolean, key: string};
|
||||
export type CellType = {color: string; isEmpty: boolean; key: string};
|
||||
|
||||
type PropsType = {
|
||||
cell: CellType,
|
||||
cell: CellType;
|
||||
};
|
||||
|
||||
class CellComponent extends React.PureComponent<PropsType> {
|
||||
render(): React.Node {
|
||||
const {props} = this;
|
||||
const item = props.cell;
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: item.isEmpty ? 'transparent' : item.color,
|
||||
borderColor: 'transparent',
|
||||
borderRadius: 4,
|
||||
borderWidth: 1,
|
||||
aspectRatio: 1,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
function CellComponent(props: PropsType) {
|
||||
const item = props.cell;
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: item.isEmpty ? 'transparent' : item.color,
|
||||
borderColor: 'transparent',
|
||||
borderRadius: 4,
|
||||
borderWidth: 1,
|
||||
aspectRatio: 1,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default withTheme(CellComponent);
|
||||
export default CellComponent;
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
|
||||
*
|
||||
* This file is part of Campus INSAT.
|
||||
*
|
||||
* Campus INSAT is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Campus INSAT is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import {withTheme} from 'react-native-paper';
|
||||
import type {ViewStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
||||
import type {CellType} from './CellComponent';
|
||||
import CellComponent from './CellComponent';
|
||||
|
||||
export type GridType = Array<Array<CellComponent>>;
|
||||
|
||||
type PropsType = {
|
||||
grid: Array<Array<CellType>>,
|
||||
height: number,
|
||||
width: number,
|
||||
style: ViewStyle,
|
||||
};
|
||||
|
||||
class GridComponent extends React.Component<PropsType> {
|
||||
getRow(rowNumber: number): React.Node {
|
||||
const {grid} = this.props;
|
||||
return (
|
||||
<View style={{flexDirection: 'row'}} key={rowNumber.toString()}>
|
||||
{grid[rowNumber].map(this.getCellRender)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
getCellRender = (item: CellType): React.Node => {
|
||||
return <CellComponent cell={item} key={item.key} />;
|
||||
};
|
||||
|
||||
getGrid(): React.Node {
|
||||
const {height} = this.props;
|
||||
const rows = [];
|
||||
for (let i = 0; i < height; i += 1) {
|
||||
rows.push(this.getRow(i));
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
const {style, width, height} = this.props;
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
aspectRatio: width / height,
|
||||
borderRadius: 4,
|
||||
...style,
|
||||
}}>
|
||||
{this.getGrid()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(GridComponent);
|
68
src/screens/Game/components/GridComponent.tsx
Normal file
68
src/screens/Game/components/GridComponent.tsx
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
|
||||
*
|
||||
* This file is part of Campus INSAT.
|
||||
*
|
||||
* Campus INSAT is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Campus INSAT is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {View, ViewStyle} from 'react-native';
|
||||
import type {CellType} from './CellComponent';
|
||||
import CellComponent from './CellComponent';
|
||||
|
||||
export type GridType = Array<Array<CellType>>;
|
||||
|
||||
type PropsType = {
|
||||
grid: GridType;
|
||||
height: number;
|
||||
width: number;
|
||||
style: ViewStyle;
|
||||
};
|
||||
|
||||
const getCellRender = (item: CellType) => {
|
||||
return <CellComponent cell={item} key={item.key} />;
|
||||
};
|
||||
|
||||
function getRow(grid: GridType, rowNumber: number) {
|
||||
return (
|
||||
<View style={{flexDirection: 'row'}} key={rowNumber.toString()}>
|
||||
{grid[rowNumber].map(getCellRender)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function getGrid(grid: GridType, height: number) {
|
||||
const rows = [];
|
||||
for (let i = 0; i < height; i += 1) {
|
||||
rows.push(getRow(grid, i));
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
function GridComponent(props: PropsType) {
|
||||
const {style, width, height, grid} = props;
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
aspectRatio: width / height,
|
||||
borderRadius: 4,
|
||||
...style,
|
||||
}}>
|
||||
{getGrid(grid, height)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export default GridComponent;
|
|
@ -17,53 +17,48 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import {withTheme} from 'react-native-paper';
|
||||
import type {ViewStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
||||
import {View, ViewStyle} from 'react-native';
|
||||
import type {GridType} from './GridComponent';
|
||||
import GridComponent from './GridComponent';
|
||||
|
||||
type PropsType = {
|
||||
items: Array<GridType>,
|
||||
style: ViewStyle,
|
||||
items: Array<GridType>;
|
||||
style: ViewStyle;
|
||||
};
|
||||
|
||||
function getGridRender(item: GridType, index: number) {
|
||||
return (
|
||||
<GridComponent
|
||||
width={item[0].length}
|
||||
height={item.length}
|
||||
grid={item}
|
||||
style={{
|
||||
marginRight: 5,
|
||||
marginLeft: 5,
|
||||
marginBottom: 5,
|
||||
}}
|
||||
key={index.toString()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function getGrids(items: Array<GridType>) {
|
||||
const grids: Array<React.ReactNode> = [];
|
||||
items.forEach((item: GridType, index: number) => {
|
||||
grids.push(getGridRender(item, index));
|
||||
});
|
||||
return grids;
|
||||
}
|
||||
|
||||
class Preview extends React.PureComponent<PropsType> {
|
||||
getGrids(): React.Node {
|
||||
const {items} = this.props;
|
||||
const grids = [];
|
||||
items.forEach((item: GridType, index: number) => {
|
||||
grids.push(Preview.getGridRender(item, index));
|
||||
});
|
||||
return grids;
|
||||
}
|
||||
|
||||
static getGridRender(item: GridType, index: number): React.Node {
|
||||
return (
|
||||
<GridComponent
|
||||
width={item[0].length}
|
||||
height={item.length}
|
||||
grid={item}
|
||||
style={{
|
||||
marginRight: 5,
|
||||
marginLeft: 5,
|
||||
marginBottom: 5,
|
||||
}}
|
||||
key={index.toString()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
render() {
|
||||
const {style, items} = this.props;
|
||||
if (items.length > 0) {
|
||||
return <View style={style}>{this.getGrids()}</View>;
|
||||
return <View style={style}>{getGrids(items)}</View>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(Preview);
|
||||
export default Preview;
|
|
@ -17,12 +17,9 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import Piece from './Piece';
|
||||
import ScoreManager from './ScoreManager';
|
||||
import GridManager from './GridManager';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {GridType} from '../components/GridComponent';
|
||||
|
||||
export type TickCallbackType = (
|
||||
|
@ -58,15 +55,15 @@ export default class GameLogic {
|
|||
|
||||
gameTime: number;
|
||||
|
||||
currentObject: Piece;
|
||||
currentObject?: Piece;
|
||||
|
||||
gameTick: number;
|
||||
|
||||
gameTickInterval: IntervalID;
|
||||
gameTickInterval?: NodeJS.Timeout;
|
||||
|
||||
gameTimeInterval: IntervalID;
|
||||
gameTimeInterval?: NodeJS.Timeout;
|
||||
|
||||
pressInInterval: TimeoutID;
|
||||
pressInInterval?: NodeJS.Timeout;
|
||||
|
||||
isPressedIn: boolean;
|
||||
|
||||
|
@ -78,15 +75,19 @@ export default class GameLogic {
|
|||
|
||||
nextPiecesCount: number;
|
||||
|
||||
tickCallback: TickCallbackType;
|
||||
tickCallback?: TickCallbackType;
|
||||
|
||||
clockCallback: ClockCallbackType;
|
||||
clockCallback?: ClockCallbackType;
|
||||
|
||||
endCallback: EndCallbackType;
|
||||
endCallback?: EndCallbackType;
|
||||
|
||||
theme: CustomThemeType;
|
||||
theme: ReactNativePaper.Theme;
|
||||
|
||||
constructor(height: number, width: number, theme: ReactNativePaper.Theme) {
|
||||
this.gameTime = 0;
|
||||
this.gameTick = 0;
|
||||
this.isPressedIn = false;
|
||||
|
||||
constructor(height: number, width: number, theme: CustomThemeType) {
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.gameRunning = false;
|
||||
|
@ -121,12 +122,16 @@ export default class GameLogic {
|
|||
}
|
||||
|
||||
onFreeze = () => {
|
||||
this.gridManager.freezeTetromino(this.currentObject, this.scoreManager);
|
||||
if (this.currentObject) {
|
||||
this.gridManager.freezeTetromino(this.currentObject, this.scoreManager);
|
||||
}
|
||||
this.createTetromino();
|
||||
};
|
||||
|
||||
setNewGameTick(level: number) {
|
||||
if (level >= GameLogic.levelTicks.length) return;
|
||||
if (level >= GameLogic.levelTicks.length) {
|
||||
return;
|
||||
}
|
||||
this.gameTick = GameLogic.levelTicks[level];
|
||||
this.stopTick();
|
||||
this.startTick();
|
||||
|
@ -145,11 +150,15 @@ export default class GameLogic {
|
|||
}
|
||||
|
||||
stopClock() {
|
||||
clearInterval(this.gameTimeInterval);
|
||||
if (this.gameTimeInterval) {
|
||||
clearInterval(this.gameTimeInterval);
|
||||
}
|
||||
}
|
||||
|
||||
stopTick() {
|
||||
clearInterval(this.gameTickInterval);
|
||||
if (this.gameTickInterval) {
|
||||
clearInterval(this.gameTickInterval);
|
||||
}
|
||||
}
|
||||
|
||||
stopGameTime() {
|
||||
|
@ -162,27 +171,34 @@ export default class GameLogic {
|
|||
this.startTick();
|
||||
}
|
||||
|
||||
onTick(callback: TickCallbackType) {
|
||||
this.currentObject.tryMove(
|
||||
0,
|
||||
1,
|
||||
this.gridManager.getCurrentGrid(),
|
||||
this.getWidth(),
|
||||
this.getHeight(),
|
||||
this.onFreeze,
|
||||
);
|
||||
callback(
|
||||
this.scoreManager.getScore(),
|
||||
this.scoreManager.getLevel(),
|
||||
this.gridManager.getCurrentGrid(),
|
||||
);
|
||||
if (this.scoreManager.canLevelUp())
|
||||
onTick(callback?: TickCallbackType) {
|
||||
if (this.currentObject) {
|
||||
this.currentObject.tryMove(
|
||||
0,
|
||||
1,
|
||||
this.gridManager.getCurrentGrid(),
|
||||
this.getWidth(),
|
||||
this.getHeight(),
|
||||
this.onFreeze,
|
||||
);
|
||||
}
|
||||
if (callback) {
|
||||
callback(
|
||||
this.scoreManager.getScore(),
|
||||
this.scoreManager.getLevel(),
|
||||
this.gridManager.getCurrentGrid(),
|
||||
);
|
||||
}
|
||||
if (this.scoreManager.canLevelUp()) {
|
||||
this.setNewGameTick(this.scoreManager.getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
onClock(callback: ClockCallbackType) {
|
||||
onClock(callback?: ClockCallbackType) {
|
||||
this.gameTime += 1;
|
||||
callback(this.gameTime);
|
||||
if (callback) {
|
||||
callback(this.gameTime);
|
||||
}
|
||||
}
|
||||
|
||||
canUseInput(): boolean {
|
||||
|
@ -210,15 +226,19 @@ export default class GameLogic {
|
|||
x: number,
|
||||
y: number,
|
||||
) {
|
||||
if (!this.canUseInput() || !this.isPressedIn) return;
|
||||
const moved = this.currentObject.tryMove(
|
||||
x,
|
||||
y,
|
||||
this.gridManager.getCurrentGrid(),
|
||||
this.getWidth(),
|
||||
this.getHeight(),
|
||||
this.onFreeze,
|
||||
);
|
||||
if (!this.canUseInput() || !this.isPressedIn) {
|
||||
return;
|
||||
}
|
||||
const moved =
|
||||
this.currentObject &&
|
||||
this.currentObject.tryMove(
|
||||
x,
|
||||
y,
|
||||
this.gridManager.getCurrentGrid(),
|
||||
this.getWidth(),
|
||||
this.getHeight(),
|
||||
this.onFreeze,
|
||||
);
|
||||
if (moved) {
|
||||
if (y === 1) {
|
||||
this.scoreManager.incrementScore();
|
||||
|
@ -226,7 +246,9 @@ export default class GameLogic {
|
|||
this.gridManager.getCurrentGrid(),
|
||||
this.scoreManager.getScore(),
|
||||
);
|
||||
} else callback(this.gridManager.getCurrentGrid());
|
||||
} else {
|
||||
callback(this.gridManager.getCurrentGrid());
|
||||
}
|
||||
}
|
||||
this.pressInInterval = setTimeout(
|
||||
() => {
|
||||
|
@ -238,20 +260,26 @@ export default class GameLogic {
|
|||
|
||||
pressedOut() {
|
||||
this.isPressedIn = false;
|
||||
clearTimeout(this.pressInInterval);
|
||||
if (this.pressInInterval) {
|
||||
clearTimeout(this.pressInInterval);
|
||||
}
|
||||
}
|
||||
|
||||
rotatePressed(callback: MovementCallbackType) {
|
||||
if (!this.canUseInput()) return;
|
||||
if (!this.canUseInput()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.currentObject &&
|
||||
this.currentObject.tryRotate(
|
||||
this.gridManager.getCurrentGrid(),
|
||||
this.getWidth(),
|
||||
this.getHeight(),
|
||||
)
|
||||
)
|
||||
) {
|
||||
callback(this.gridManager.getCurrentGrid());
|
||||
}
|
||||
}
|
||||
|
||||
getNextPiecesPreviews(): Array<GridType> {
|
||||
|
@ -266,7 +294,10 @@ export default class GameLogic {
|
|||
}
|
||||
|
||||
recoverNextPiece() {
|
||||
this.currentObject = this.nextPieces.shift();
|
||||
const next = this.nextPieces.shift();
|
||||
if (next) {
|
||||
this.currentObject = next;
|
||||
}
|
||||
this.generateNextPieces();
|
||||
}
|
||||
|
||||
|
@ -280,27 +311,36 @@ export default class GameLogic {
|
|||
this.pressedOut();
|
||||
this.recoverNextPiece();
|
||||
if (
|
||||
this.currentObject &&
|
||||
!this.currentObject.isPositionValid(
|
||||
this.gridManager.getCurrentGrid(),
|
||||
this.getWidth(),
|
||||
this.getHeight(),
|
||||
)
|
||||
)
|
||||
) {
|
||||
this.endGame(false);
|
||||
}
|
||||
}
|
||||
|
||||
togglePause() {
|
||||
if (!this.gameRunning) return;
|
||||
if (!this.gameRunning) {
|
||||
return;
|
||||
}
|
||||
this.gamePaused = !this.gamePaused;
|
||||
if (this.gamePaused) this.stopGameTime();
|
||||
else this.startGameTime();
|
||||
if (this.gamePaused) {
|
||||
this.stopGameTime();
|
||||
} else {
|
||||
this.startGameTime();
|
||||
}
|
||||
}
|
||||
|
||||
endGame(isRestart: boolean) {
|
||||
this.gameRunning = false;
|
||||
this.gamePaused = false;
|
||||
this.stopGameTime();
|
||||
this.endCallback(this.gameTime, this.scoreManager.getScore(), isRestart);
|
||||
if (this.endCallback) {
|
||||
this.endCallback(this.gameTime, this.scoreManager.getScore(), isRestart);
|
||||
}
|
||||
}
|
||||
|
||||
startGame(
|
||||
|
@ -308,7 +348,9 @@ export default class GameLogic {
|
|||
clockCallback: ClockCallbackType,
|
||||
endCallback: EndCallbackType,
|
||||
) {
|
||||
if (this.gameRunning) this.endGame(true);
|
||||
if (this.gameRunning) {
|
||||
this.endGame(true);
|
||||
}
|
||||
this.gameRunning = true;
|
||||
this.gamePaused = false;
|
||||
this.gameTime = 0;
|
|
@ -17,14 +17,11 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import Piece from './Piece';
|
||||
import ScoreManager from './ScoreManager';
|
||||
import type {CoordinatesType} from '../Shapes/BaseShape';
|
||||
import type {GridType} from '../components/GridComponent';
|
||||
import type {CellType} from '../components/CellComponent';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
|
||||
/**
|
||||
* Class used to manage the game grid
|
||||
|
@ -32,7 +29,7 @@ import type {CustomThemeType} from '../../../managers/ThemeManager';
|
|||
export default class GridManager {
|
||||
#currentGrid: GridType;
|
||||
|
||||
#theme: CustomThemeType;
|
||||
#theme: ReactNativePaper.Theme;
|
||||
|
||||
/**
|
||||
* Initializes a grid of the given size
|
||||
|
@ -41,7 +38,7 @@ export default class GridManager {
|
|||
* @param height The grid height
|
||||
* @param theme Object containing current theme
|
||||
*/
|
||||
constructor(width: number, height: number, theme: CustomThemeType) {
|
||||
constructor(width: number, height: number, theme: ReactNativePaper.Theme) {
|
||||
this.#theme = theme;
|
||||
this.#currentGrid = this.getEmptyGrid(height, width);
|
||||
}
|
||||
|
@ -121,7 +118,9 @@ export default class GridManager {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (isLineFull && rows.indexOf(pos[i].y) === -1) rows.push(pos[i].y);
|
||||
if (isLineFull && rows.indexOf(pos[i].y) === -1) {
|
||||
rows.push(pos[i].y);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
|
@ -17,8 +17,6 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import ShapeL from '../Shapes/ShapeL';
|
||||
import ShapeI from '../Shapes/ShapeI';
|
||||
import ShapeJ from '../Shapes/ShapeJ';
|
||||
|
@ -29,7 +27,6 @@ import ShapeZ from '../Shapes/ShapeZ';
|
|||
import type {CoordinatesType} from '../Shapes/BaseShape';
|
||||
import BaseShape from '../Shapes/BaseShape';
|
||||
import type {GridType} from '../components/GridComponent';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
|
||||
/**
|
||||
* Class used as an abstraction layer for shapes.
|
||||
|
@ -41,14 +38,14 @@ export default class Piece {
|
|||
|
||||
currentShape: BaseShape;
|
||||
|
||||
theme: CustomThemeType;
|
||||
theme: ReactNativePaper.Theme;
|
||||
|
||||
/**
|
||||
* Initializes this piece's color and shape
|
||||
*
|
||||
* @param theme Object containing current theme
|
||||
*/
|
||||
constructor(theme: CustomThemeType) {
|
||||
constructor(theme: ReactNativePaper.Theme) {
|
||||
this.currentShape = this.getRandomShape(theme);
|
||||
this.theme = theme;
|
||||
}
|
||||
|
@ -58,7 +55,7 @@ export default class Piece {
|
|||
*
|
||||
* @param theme Object containing current theme
|
||||
*/
|
||||
getRandomShape(theme: CustomThemeType): BaseShape {
|
||||
getRandomShape(theme: ReactNativePaper.Theme): BaseShape {
|
||||
return new this.shapes[Math.floor(Math.random() * 7)](theme);
|
||||
}
|
||||
|
||||
|
@ -72,7 +69,6 @@ export default class Piece {
|
|||
true,
|
||||
);
|
||||
pos.forEach((coordinates: CoordinatesType) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
grid[coordinates.y][coordinates.x] = {
|
||||
color: this.theme.colors.tetrisBackground,
|
||||
isEmpty: true,
|
||||
|
@ -92,7 +88,6 @@ export default class Piece {
|
|||
!isPreview,
|
||||
);
|
||||
pos.forEach((coordinates: CoordinatesType) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
grid[coordinates.y][coordinates.x] = {
|
||||
color: this.currentShape.getColor(),
|
||||
isEmpty: false,
|
||||
|
@ -150,21 +145,35 @@ export default class Piece {
|
|||
): boolean {
|
||||
let newX = x;
|
||||
let newY = y;
|
||||
if (x > 1) newX = 1; // Prevent moving from more than one tile
|
||||
if (x < -1) newX = -1;
|
||||
if (y > 1) newY = 1;
|
||||
if (y < -1) newY = -1;
|
||||
if (x !== 0 && y !== 0) newY = 0; // Prevent diagonal movement
|
||||
if (x > 1) {
|
||||
newX = 1;
|
||||
} // Prevent moving from more than one tile
|
||||
if (x < -1) {
|
||||
newX = -1;
|
||||
}
|
||||
if (y > 1) {
|
||||
newY = 1;
|
||||
}
|
||||
if (y < -1) {
|
||||
newY = -1;
|
||||
}
|
||||
if (x !== 0 && y !== 0) {
|
||||
newY = 0;
|
||||
} // Prevent diagonal movement
|
||||
|
||||
this.removeFromGrid(grid);
|
||||
this.currentShape.move(newX, newY);
|
||||
const isValid = this.isPositionValid(grid, width, height);
|
||||
|
||||
if (!isValid) this.currentShape.move(-newX, -newY);
|
||||
if (!isValid) {
|
||||
this.currentShape.move(-newX, -newY);
|
||||
}
|
||||
|
||||
const shouldFreeze = !isValid && newY !== 0;
|
||||
this.toGrid(grid, false);
|
||||
if (shouldFreeze) freezeCallback();
|
||||
if (shouldFreeze) {
|
||||
freezeCallback();
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
|
@ -17,8 +17,6 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* Class used to manage game score
|
||||
*/
|
||||
|
@ -83,7 +81,9 @@ export default class ScoreManager {
|
|||
* @param numberRemoved The number of lines removed at the same time
|
||||
*/
|
||||
addLinesRemovedPoints(numberRemoved: number) {
|
||||
if (numberRemoved < 1 || numberRemoved > 4) return;
|
||||
if (numberRemoved < 1 || numberRemoved > 4) {
|
||||
return;
|
||||
}
|
||||
this.#score +=
|
||||
this.#scoreLinesModifier[numberRemoved - 1] * (this.#level + 1);
|
||||
switch (numberRemoved) {
|
|
@ -17,8 +17,6 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import {Caption, IconButton, Text, withTheme} from 'react-native-paper';
|
||||
|
@ -32,27 +30,26 @@ import Preview from '../components/Preview';
|
|||
import MaterialHeaderButtons, {
|
||||
Item,
|
||||
} from '../../../components/Overrides/CustomHeaderButton';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import type {OptionsDialogButtonType} from '../../../components/Dialogs/OptionsDialog';
|
||||
import OptionsDialog from '../../../components/Dialogs/OptionsDialog';
|
||||
|
||||
type PropsType = {
|
||||
navigation: StackNavigationProp,
|
||||
route: {params: {highScore: number}},
|
||||
theme: CustomThemeType,
|
||||
navigation: StackNavigationProp<any>;
|
||||
route: {params: {highScore: number}};
|
||||
theme: ReactNativePaper.Theme;
|
||||
};
|
||||
|
||||
type StateType = {
|
||||
grid: GridType,
|
||||
gameTime: number,
|
||||
gameScore: number,
|
||||
gameLevel: number,
|
||||
grid: GridType;
|
||||
gameTime: number;
|
||||
gameScore: number;
|
||||
gameLevel: number;
|
||||
|
||||
dialogVisible: boolean,
|
||||
dialogTitle: string,
|
||||
dialogMessage: string,
|
||||
dialogButtons: Array<OptionsDialogButtonType>,
|
||||
onDialogDismiss: () => void,
|
||||
dialogVisible: boolean;
|
||||
dialogTitle: string;
|
||||
dialogMessage: string;
|
||||
dialogButtons: Array<OptionsDialogButtonType>;
|
||||
onDialogDismiss: () => void;
|
||||
};
|
||||
|
||||
class GameMainScreen extends React.Component<PropsType, StateType> {
|
||||
|
@ -62,11 +59,13 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
date.setMinutes(0);
|
||||
date.setSeconds(seconds);
|
||||
let format;
|
||||
if (date.getHours())
|
||||
if (date.getHours()) {
|
||||
format = `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
|
||||
else if (date.getMinutes())
|
||||
} else if (date.getMinutes()) {
|
||||
format = `${date.getMinutes()}:${date.getSeconds()}`;
|
||||
else format = date.getSeconds().toString();
|
||||
} else {
|
||||
format = date.getSeconds().toString();
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
|
@ -76,6 +75,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
|
||||
constructor(props: PropsType) {
|
||||
super(props);
|
||||
this.highScore = null;
|
||||
this.logic = new GameLogic(20, 10, props.theme);
|
||||
this.state = {
|
||||
grid: this.logic.getCurrentGrid(),
|
||||
|
@ -88,8 +88,9 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
dialogButtons: [],
|
||||
onDialogDismiss: () => {},
|
||||
};
|
||||
if (props.route.params != null)
|
||||
if (props.route.params != null) {
|
||||
this.highScore = props.route.params.highScore;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -104,7 +105,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
this.logic.endGame(true);
|
||||
}
|
||||
|
||||
getRightButton = (): React.Node => {
|
||||
getRightButton = () => {
|
||||
return (
|
||||
<MaterialHeaderButtons>
|
||||
<Item title="pause" iconName="pause" onPress={this.togglePause} />
|
||||
|
@ -136,15 +137,16 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
gameTime: time,
|
||||
gameScore: score,
|
||||
});
|
||||
if (!isRestart)
|
||||
if (!isRestart) {
|
||||
props.navigation.replace('game-start', {
|
||||
score: state.gameScore,
|
||||
level: state.gameLevel,
|
||||
time: state.gameTime,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getStatusIcons(): React.Node {
|
||||
getStatusIcons() {
|
||||
const {props, state} = this;
|
||||
return (
|
||||
<View
|
||||
|
@ -219,7 +221,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
);
|
||||
}
|
||||
|
||||
getScoreIcon(): React.Node {
|
||||
getScoreIcon() {
|
||||
const {props, state} = this;
|
||||
const highScore =
|
||||
this.highScore == null || state.gameScore > this.highScore
|
||||
|
@ -285,7 +287,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
);
|
||||
}
|
||||
|
||||
getControlButtons(): React.Node {
|
||||
getControlButtons() {
|
||||
const {props} = this;
|
||||
return (
|
||||
<View
|
||||
|
@ -353,8 +355,8 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
|
||||
updateGridScore = (newGrid: GridType, score?: number) => {
|
||||
this.setState((prevState: StateType): {
|
||||
grid: GridType,
|
||||
gameScore: number,
|
||||
grid: GridType;
|
||||
gameScore: number;
|
||||
} => ({
|
||||
grid: newGrid,
|
||||
gameScore: score != null ? score : prevState.gameScore,
|
||||
|
@ -363,7 +365,9 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
|
||||
togglePause = () => {
|
||||
this.logic.togglePause();
|
||||
if (this.logic.isGamePaused()) this.showPausePopup();
|
||||
if (this.logic.isGamePaused()) {
|
||||
this.showPausePopup();
|
||||
}
|
||||
};
|
||||
|
||||
showPausePopup = () => {
|
||||
|
@ -415,7 +419,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
|
|||
this.logic.startGame(this.onTick, this.onClock, this.onGameEnd);
|
||||
};
|
||||
|
||||
render(): React.Node {
|
||||
render() {
|
||||
const {props, state} = this;
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
|
@ -17,8 +17,6 @@
|
|||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {StackNavigationProp} from '@react-navigation/stack';
|
||||
import {
|
||||
|
@ -35,7 +33,6 @@ import i18n from 'i18n-js';
|
|||
import * as Animatable from 'react-native-animatable';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
||||
import Mascot, {MASCOT_STYLE} from '../../../components/Mascot/Mascot';
|
||||
import MascotPopup from '../../../components/Mascot/MascotPopup';
|
||||
import AsyncStorageManager from '../../../managers/AsyncStorageManager';
|
||||
|
@ -47,17 +44,17 @@ import SpeechArrow from '../../../components/Mascot/SpeechArrow';
|
|||
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
|
||||
|
||||
type GameStatsType = {
|
||||
score: number,
|
||||
level: number,
|
||||
time: number,
|
||||
score: number;
|
||||
level: number;
|
||||
time: number;
|
||||
};
|
||||
|
||||
type PropsType = {
|
||||
navigation: StackNavigationProp,
|
||||
navigation: StackNavigationProp<any>;
|
||||
route: {
|
||||
params: GameStatsType,
|
||||
},
|
||||
theme: CustomThemeType,
|
||||
params: GameStatsType;
|
||||
};
|
||||
theme: ReactNativePaper.Theme;
|
||||
};
|
||||
|
||||
class GameStartScreen extends React.Component<PropsType> {
|
||||
|
@ -65,21 +62,24 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
|
||||
scores: Array<number>;
|
||||
|
||||
gameStats: GameStatsType | null;
|
||||
gameStats?: GameStatsType;
|
||||
|
||||
isHighScore: boolean;
|
||||
|
||||
constructor(props: PropsType) {
|
||||
super(props);
|
||||
this.isHighScore = false;
|
||||
this.gridManager = new GridManager(4, 4, props.theme);
|
||||
this.scores = AsyncStorageManager.getObject(
|
||||
AsyncStorageManager.PREFERENCES.gameScores.key,
|
||||
);
|
||||
this.scores.sort((a: number, b: number): number => b - a);
|
||||
if (props.route.params != null) this.recoverGameScore();
|
||||
if (props.route.params != null) {
|
||||
this.recoverGameScore();
|
||||
}
|
||||
}
|
||||
|
||||
getPiecesBackground(): React.Node {
|
||||
getPiecesBackground() {
|
||||
const {theme} = this.props;
|
||||
const gridList = [];
|
||||
for (let i = 0; i < 18; i += 1) {
|
||||
|
@ -94,7 +94,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
width: '100%',
|
||||
height: '100%',
|
||||
}}>
|
||||
{gridList.map((item: GridType, index: number): React.Node => {
|
||||
{gridList.map((item: GridType, index: number) => {
|
||||
const size = 10 + Math.floor(Math.random() * 30);
|
||||
const top = Math.floor(Math.random() * 100);
|
||||
const rot = Math.floor(Math.random() * 360);
|
||||
|
@ -129,7 +129,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
);
|
||||
}
|
||||
|
||||
getPostGameContent(stats: GameStatsType): React.Node {
|
||||
getPostGameContent(stats: GameStatsType) {
|
||||
const {props} = this;
|
||||
return (
|
||||
<View
|
||||
|
@ -141,8 +141,8 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
animated={this.isHighScore}
|
||||
style={{
|
||||
width: this.isHighScore ? '50%' : '30%',
|
||||
marginLeft: this.isHighScore ? 'auto' : null,
|
||||
marginRight: this.isHighScore ? 'auto' : null,
|
||||
marginLeft: this.isHighScore ? 'auto' : undefined,
|
||||
marginRight: this.isHighScore ? 'auto' : undefined,
|
||||
}}
|
||||
/>
|
||||
<SpeechArrow
|
||||
|
@ -235,7 +235,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
);
|
||||
}
|
||||
|
||||
getWelcomeText(): React.Node {
|
||||
getWelcomeText() {
|
||||
const {props} = this;
|
||||
return (
|
||||
<View>
|
||||
|
@ -281,7 +281,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
);
|
||||
}
|
||||
|
||||
getPodiumRender(place: 1 | 2 | 3, score: string): React.Node {
|
||||
getPodiumRender(place: 1 | 2 | 3, score: string) {
|
||||
const {props} = this;
|
||||
let icon = 'podium-gold';
|
||||
let color = props.theme.colors.gameGold;
|
||||
|
@ -338,7 +338,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
<Text
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontWeight: place === 1 ? 'bold' : null,
|
||||
fontWeight: place === 1 ? 'bold' : undefined,
|
||||
fontSize,
|
||||
}}>
|
||||
{score}
|
||||
|
@ -347,7 +347,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
);
|
||||
}
|
||||
|
||||
getTopScoresRender(): React.Node {
|
||||
getTopScoresRender() {
|
||||
const gold = this.scores.length > 0 ? this.scores[0] : '-';
|
||||
const silver = this.scores.length > 1 ? this.scores[1] : '-';
|
||||
const bronze = this.scores.length > 2 ? this.scores[2] : '-';
|
||||
|
@ -371,7 +371,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
);
|
||||
}
|
||||
|
||||
getMainContent(): React.Node {
|
||||
getMainContent() {
|
||||
const {props} = this;
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
|
@ -415,7 +415,9 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (this.scores.length > 3) this.scores.splice(3, 1);
|
||||
if (this.scores.length > 3) {
|
||||
this.scores.splice(3, 1);
|
||||
}
|
||||
AsyncStorageManager.set(
|
||||
AsyncStorageManager.PREFERENCES.gameScores.key,
|
||||
this.scores,
|
||||
|
@ -423,7 +425,7 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
}
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
render() {
|
||||
const {props} = this;
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
|
@ -444,7 +446,6 @@ class GameStartScreen extends React.Component<PropsType> {
|
|||
message={i18n.t('screens.game.mascotDialog.message')}
|
||||
icon="gamepad-variant"
|
||||
buttons={{
|
||||
action: null,
|
||||
cancel: {
|
||||
message: i18n.t('screens.game.mascotDialog.button'),
|
||||
icon: 'check',
|
Loading…
Reference in a new issue