forked from vergnet/application-amicale
Improved game UI
This commit is contained in:
parent
fdf0fffabc
commit
4bff6e15a8
7 changed files with 179 additions and 123 deletions
|
@ -363,6 +363,9 @@
|
||||||
},
|
},
|
||||||
"game": {
|
"game": {
|
||||||
"title": "Game",
|
"title": "Game",
|
||||||
|
"score": "Score : %{score}",
|
||||||
|
"time": "Time :",
|
||||||
|
"level": "Level :",
|
||||||
"pause": "Game Paused",
|
"pause": "Game Paused",
|
||||||
"pauseMessage": "The game is paused",
|
"pauseMessage": "The game is paused",
|
||||||
"resume": "Resume",
|
"resume": "Resume",
|
||||||
|
|
|
@ -361,16 +361,19 @@
|
||||||
"homeButtonSubtitle": "Contacte le développeur de l'appli"
|
"homeButtonSubtitle": "Contacte le développeur de l'appli"
|
||||||
},
|
},
|
||||||
"game": {
|
"game": {
|
||||||
"title": "Le jeu trop ouf",
|
"title": "Le Jeu trop ouf",
|
||||||
|
"score": "Score : %{score}",
|
||||||
|
"time": "Temps :",
|
||||||
|
"level": "Niveau :",
|
||||||
"pause": "Pause",
|
"pause": "Pause",
|
||||||
"pauseMessage": "Le jeu est en pause",
|
"pauseMessage": "T'as fait pause, t'es nul",
|
||||||
"resume": "Continuer",
|
"resume": "Continuer",
|
||||||
"restart": {
|
"restart": {
|
||||||
"text": "Redémarrer",
|
"text": "Redémarrer",
|
||||||
"confirm": "Est-tu sûr de vouloir redémarrer ?",
|
"confirm": "T'es sûr de vouloir redémarrer ?",
|
||||||
"confirmMessage": "Tout ton progrès sera perdu, continuer ?",
|
"confirmMessage": "Tout ton progrès sera perdu, continuer ?",
|
||||||
"confirmYes": "Oui",
|
"confirmYes": "Oui",
|
||||||
"confirmNo": "Non"
|
"confirmNo": "Oula non"
|
||||||
},
|
},
|
||||||
"gameOver": {
|
"gameOver": {
|
||||||
"text": "Game Over",
|
"text": "Game Over",
|
||||||
|
|
|
@ -119,8 +119,7 @@ export default class ThemeManager {
|
||||||
tutorinsaColor: '#f93943',
|
tutorinsaColor: '#f93943',
|
||||||
|
|
||||||
// Tetris
|
// Tetris
|
||||||
tetrisBackground: '#e6e6e6',
|
tetrisBackground: '#f0f0f0',
|
||||||
tetrisBorder: '#2f2f2f',
|
|
||||||
tetrisScore: '#e2bd33',
|
tetrisScore: '#e2bd33',
|
||||||
tetrisI: '#3cd9e6',
|
tetrisI: '#3cd9e6',
|
||||||
tetrisO: '#ffdd00',
|
tetrisO: '#ffdd00',
|
||||||
|
@ -182,8 +181,7 @@ export default class ThemeManager {
|
||||||
tutorinsaColor: '#f93943',
|
tutorinsaColor: '#f93943',
|
||||||
|
|
||||||
// Tetris
|
// Tetris
|
||||||
tetrisBackground: '#2c2c2c',
|
tetrisBackground: '#181818',
|
||||||
tetrisBorder: '#1b1b1b',
|
|
||||||
tetrisScore: '#e2d707',
|
tetrisScore: '#e2d707',
|
||||||
tetrisI: '#30b3be',
|
tetrisI: '#30b3be',
|
||||||
tetrisO: '#c1a700',
|
tetrisO: '#c1a700',
|
||||||
|
|
|
@ -21,9 +21,8 @@ class CellComponent extends React.PureComponent<Props> {
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: item.isEmpty ? 'transparent' : item.color,
|
backgroundColor: item.isEmpty ? 'transparent' : item.color,
|
||||||
borderColor: item.isEmpty ? 'transparent' : this.props.theme.colors.tetrisBorder,
|
borderColor: 'transparent',
|
||||||
borderStyle: 'solid',
|
borderRadius: 4,
|
||||||
borderRadius: 2,
|
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
aspectRatio: 1,
|
aspectRatio: 1,
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -5,16 +5,15 @@ import {View} from 'react-native';
|
||||||
import {withTheme} from 'react-native-paper';
|
import {withTheme} from 'react-native-paper';
|
||||||
import type {Cell} from "./CellComponent";
|
import type {Cell} from "./CellComponent";
|
||||||
import CellComponent from "./CellComponent";
|
import CellComponent from "./CellComponent";
|
||||||
|
import type {ViewStyle} from "react-native/Libraries/StyleSheet/StyleSheet";
|
||||||
|
|
||||||
export type Grid = Array<Array<CellComponent>>;
|
export type Grid = Array<Array<CellComponent>>;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
grid: Array<Array<Object>>,
|
grid: Array<Array<Object>>,
|
||||||
backgroundColor: string,
|
|
||||||
height: number,
|
height: number,
|
||||||
width: number,
|
width: number,
|
||||||
containerMaxHeight: number | string,
|
style: ViewStyle,
|
||||||
containerMaxWidth: number | string,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridComponent extends React.Component<Props> {
|
class GridComponent extends React.Component<Props> {
|
||||||
|
@ -23,10 +22,7 @@ class GridComponent extends React.Component<Props> {
|
||||||
let cells = this.props.grid[rowNumber].map(this.getCellRender);
|
let cells = this.props.grid[rowNumber].map(this.getCellRender);
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{flexDirection: 'row',}}
|
||||||
flexDirection: 'row',
|
|
||||||
backgroundColor: this.props.backgroundColor,
|
|
||||||
}}
|
|
||||||
key={rowNumber.toString()}
|
key={rowNumber.toString()}
|
||||||
>
|
>
|
||||||
{cells}
|
{cells}
|
||||||
|
@ -49,12 +45,8 @@ class GridComponent extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={{
|
<View style={{
|
||||||
flexDirection: 'column',
|
|
||||||
maxWidth: this.props.containerMaxWidth,
|
|
||||||
maxHeight: this.props.containerMaxHeight,
|
|
||||||
aspectRatio: this.props.width / this.props.height,
|
aspectRatio: this.props.width / this.props.height,
|
||||||
marginLeft: 'auto',
|
...this.props.style
|
||||||
marginRight: 'auto',
|
|
||||||
}}>
|
}}>
|
||||||
{this.getGrid()}
|
{this.getGrid()}
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -5,9 +5,11 @@ import {View} from 'react-native';
|
||||||
import {withTheme} from 'react-native-paper';
|
import {withTheme} from 'react-native-paper';
|
||||||
import type {Grid} from "./GridComponent";
|
import type {Grid} from "./GridComponent";
|
||||||
import GridComponent from "./GridComponent";
|
import GridComponent from "./GridComponent";
|
||||||
|
import type {ViewStyle} from "react-native/Libraries/StyleSheet/StyleSheet";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
items: Array<Grid>,
|
items: Array<Grid>,
|
||||||
|
style: ViewStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
class Preview extends React.PureComponent<Props> {
|
class Preview extends React.PureComponent<Props> {
|
||||||
|
@ -25,9 +27,10 @@ class Preview extends React.PureComponent<Props> {
|
||||||
width={item[0].length}
|
width={item[0].length}
|
||||||
height={item.length}
|
height={item.length}
|
||||||
grid={item}
|
grid={item}
|
||||||
containerMaxHeight={50}
|
style={{
|
||||||
containerMaxWidth={50}
|
marginRight: 5,
|
||||||
backgroundColor={'transparent'}
|
marginLeft: 5,
|
||||||
|
}}
|
||||||
key={index.toString()}
|
key={index.toString()}
|
||||||
/>;
|
/>;
|
||||||
};
|
};
|
||||||
|
@ -35,7 +38,7 @@ class Preview extends React.PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
if (this.props.items.length > 0) {
|
if (this.props.items.length > 0) {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View style={this.props.style}>
|
||||||
{this.getGrids()}
|
{this.getGrids()}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {View} from 'react-native';
|
import {View} from 'react-native';
|
||||||
import {IconButton, Text, withTheme} from 'react-native-paper';
|
import {Caption, IconButton, Text, withTheme} from 'react-native-paper';
|
||||||
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
|
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import GameLogic from "../logic/GameLogic";
|
import GameLogic from "../logic/GameLogic";
|
||||||
import type {Grid} from "../components/GridComponent";
|
import type {Grid} from "../components/GridComponent";
|
||||||
|
@ -51,7 +51,8 @@ class GameMainScreen extends React.Component<Props, State> {
|
||||||
dialogTitle: "",
|
dialogTitle: "",
|
||||||
dialogMessage: "",
|
dialogMessage: "",
|
||||||
dialogButtons: [],
|
dialogButtons: [],
|
||||||
onDialogDismiss: () => {},
|
onDialogDismiss: () => {
|
||||||
|
},
|
||||||
};
|
};
|
||||||
this.props.navigation.addListener('blur', this.onScreenBlur);
|
this.props.navigation.addListener('blur', this.onScreenBlur);
|
||||||
this.props.navigation.addListener('focus', this.onScreenFocus);
|
this.props.navigation.addListener('focus', this.onScreenFocus);
|
||||||
|
@ -146,11 +147,11 @@ class GameMainScreen extends React.Component<Props, State> {
|
||||||
dialogMessage: i18n.t("screens.game.pauseMessage"),
|
dialogMessage: i18n.t("screens.game.pauseMessage"),
|
||||||
dialogButtons: [
|
dialogButtons: [
|
||||||
{
|
{
|
||||||
title: i18n.t("screens.game.restart.text"),
|
title: i18n.t("screens.game.restart.text"),
|
||||||
onPress: this.showRestartConfirm
|
onPress: this.showRestartConfirm
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("screens.game.resume"),
|
title: i18n.t("screens.game.resume"),
|
||||||
onPress: onDismiss
|
onPress: onDismiss
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -165,14 +166,14 @@ class GameMainScreen extends React.Component<Props, State> {
|
||||||
dialogMessage: i18n.t("screens.game.restart.confirmMessage"),
|
dialogMessage: i18n.t("screens.game.restart.confirmMessage"),
|
||||||
dialogButtons: [
|
dialogButtons: [
|
||||||
{
|
{
|
||||||
title: i18n.t("screens.game.restart.confirmYes"),
|
title: i18n.t("screens.game.restart.confirmYes"),
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
this.onDialogDismiss();
|
this.onDialogDismiss();
|
||||||
this.startGame();
|
this.startGame();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("screens.game.restart.confirmNo"),
|
title: i18n.t("screens.game.restart.confirmNo"),
|
||||||
onPress: this.showPausePopup
|
onPress: this.showPausePopup
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -194,11 +195,11 @@ class GameMainScreen extends React.Component<Props, State> {
|
||||||
dialogMessage: message,
|
dialogMessage: message,
|
||||||
dialogButtons: [
|
dialogButtons: [
|
||||||
{
|
{
|
||||||
title: i18n.t("screens.game.gameOver.exit"),
|
title: i18n.t("screens.game.gameOver.exit"),
|
||||||
onPress: () => this.props.navigation.goBack()
|
onPress: () => this.props.navigation.goBack()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("screens.game.resume"),
|
title: i18n.t("screens.game.resume"),
|
||||||
onPress: onDismiss
|
onPress: onDismiss
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -223,111 +224,168 @@ class GameMainScreen extends React.Component<Props, State> {
|
||||||
this.showGameOverConfirm();
|
this.showGameOverConfirm();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
getStatusIcons() {
|
||||||
const colors = this.props.theme.colors;
|
|
||||||
return (
|
return (
|
||||||
<View style={{
|
<View style={{
|
||||||
width: '100%',
|
flex: 1,
|
||||||
height: '100%',
|
marginTop: "auto",
|
||||||
|
marginBottom: "auto"
|
||||||
}}>
|
}}>
|
||||||
<View style={{
|
<View style={{
|
||||||
flexDirection: 'row',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 5,
|
|
||||||
left: 10,
|
|
||||||
}}>
|
|
||||||
<MaterialCommunityIcons
|
|
||||||
name={'timer'}
|
|
||||||
color={colors.subtitle}
|
|
||||||
size={20}/>
|
|
||||||
<Text style={{
|
|
||||||
marginLeft: 5,
|
|
||||||
color: colors.subtitle
|
|
||||||
}}>{this.getFormattedTime(this.state.gameTime)}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 50,
|
|
||||||
left: 10,
|
|
||||||
}}>
|
|
||||||
<MaterialCommunityIcons
|
|
||||||
name={'gamepad'}
|
|
||||||
color={colors.text}
|
|
||||||
size={20}/>
|
|
||||||
<Text style={{
|
|
||||||
marginLeft: 5
|
|
||||||
}}>{this.state.gameLevel}</Text>
|
|
||||||
</View>
|
|
||||||
<View style={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
}}>
|
}}>
|
||||||
<MaterialCommunityIcons
|
<Caption style={{
|
||||||
name={'star'}
|
marginLeft: "auto",
|
||||||
color={colors.tetrisScore}
|
marginRight: "auto",
|
||||||
size={30}/>
|
marginBottom: 5,
|
||||||
<Text style={{
|
}}>{i18n.t("screens.game.time")}</Caption>
|
||||||
marginLeft: 5,
|
<View style={{
|
||||||
fontSize: 22,
|
flexDirection: "row"
|
||||||
}}>{this.state.gameScore}</Text>
|
}}>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={'timer'}
|
||||||
|
color={this.props.theme.colors.subtitle}
|
||||||
|
size={20}/>
|
||||||
|
<Text style={{
|
||||||
|
marginLeft: 5,
|
||||||
|
color: this.props.theme.colors.subtitle
|
||||||
|
}}>{this.getFormattedTime(this.state.gameTime)}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
<GridComponent
|
<View style={{
|
||||||
width={this.logic.getWidth()}
|
marginLeft: 'auto',
|
||||||
height={this.logic.getHeight()}
|
marginRight: 'auto',
|
||||||
containerMaxHeight={'80%'}
|
marginTop: 20,
|
||||||
containerMaxWidth={'60%'}
|
}}>
|
||||||
grid={this.state.grid}
|
<Caption style={{
|
||||||
backgroundColor={colors.tetrisBackground}
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
marginBottom: 5,
|
||||||
|
}}>{i18n.t("screens.game.level")}</Caption>
|
||||||
|
<View style={{
|
||||||
|
flexDirection: "row"
|
||||||
|
}}>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={'gamepad-square'}
|
||||||
|
color={this.props.theme.colors.text}
|
||||||
|
size={20}/>
|
||||||
|
<Text style={{
|
||||||
|
marginLeft: 5
|
||||||
|
}}>{this.state.gameLevel}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getScoreIcon() {
|
||||||
|
return (
|
||||||
|
<View style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
}}>
|
||||||
|
<Text style={{
|
||||||
|
marginLeft: 5,
|
||||||
|
fontSize: 22,
|
||||||
|
}}>{i18n.t("screens.game.score", {score: this.state.gameScore})}</Text>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={'star'}
|
||||||
|
color={this.props.theme.colors.tetrisScore}
|
||||||
|
size={20}
|
||||||
|
style={{
|
||||||
|
marginTop: "auto",
|
||||||
|
marginBottom: "auto",
|
||||||
|
marginLeft: 5
|
||||||
|
}}/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getControlButtons() {
|
||||||
|
return (
|
||||||
|
<View style={{
|
||||||
|
height: 80,
|
||||||
|
flexDirection: "row"
|
||||||
|
}}>
|
||||||
|
<IconButton
|
||||||
|
icon="rotate-right-variant"
|
||||||
|
size={40}
|
||||||
|
onPress={() => this.logic.rotatePressed(this.updateGrid)}
|
||||||
|
style={{flex: 1}}
|
||||||
/>
|
/>
|
||||||
<View style={{
|
<View style={{
|
||||||
position: 'absolute',
|
|
||||||
top: 50,
|
|
||||||
right: 5,
|
|
||||||
}}>
|
|
||||||
<Preview
|
|
||||||
items={this.logic.getNextPiecesPreviews()}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={{
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
width: '100%',
|
flex: 4
|
||||||
}}>
|
}}>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="rotate-right-variant"
|
icon="chevron-left"
|
||||||
size={40}
|
size={40}
|
||||||
onPress={() => this.logic.rotatePressed(this.updateGrid)}
|
style={{flex: 1}}
|
||||||
style={{marginRight: 'auto'}}
|
onPress={() => this.logic.pressedOut()}
|
||||||
/>
|
onPressIn={() => this.logic.leftPressedIn(this.updateGrid)}
|
||||||
<View style={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
}}>
|
|
||||||
<IconButton
|
|
||||||
icon="arrow-left"
|
|
||||||
size={40}
|
|
||||||
onPress={() => this.logic.pressedOut()}
|
|
||||||
onPressIn={() => this.logic.leftPressedIn(this.updateGrid)}
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon="arrow-right"
|
icon="chevron-right"
|
||||||
size={40}
|
size={40}
|
||||||
onPress={() => this.logic.pressedOut()}
|
style={{flex: 1}}
|
||||||
onPressIn={() => this.logic.rightPressed(this.updateGrid)}
|
onPress={() => this.logic.pressedOut()}
|
||||||
|
onPressIn={() => this.logic.rightPressed(this.updateGrid)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<IconButton
|
||||||
|
icon="arrow-down-bold"
|
||||||
|
size={40}
|
||||||
|
onPressIn={() => this.logic.downPressedIn(this.updateGridScore)}
|
||||||
|
onPress={() => this.logic.pressedOut()}
|
||||||
|
style={{flex: 1}}
|
||||||
|
color={this.props.theme.colors.tetrisScore}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<View style={{
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "row",
|
||||||
|
}}>
|
||||||
|
{this.getStatusIcons()}
|
||||||
|
<View style={{flex: 4}}>
|
||||||
|
{this.getScoreIcon()}
|
||||||
|
<GridComponent
|
||||||
|
width={this.logic.getWidth()}
|
||||||
|
height={this.logic.getHeight()}
|
||||||
|
grid={this.state.grid}
|
||||||
|
style={{
|
||||||
|
backgroundColor: this.props.theme.colors.tetrisBackground,
|
||||||
|
flex: 1,
|
||||||
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<Preview
|
||||||
|
items={this.logic.getNextPiecesPreviews()}
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<IconButton
|
|
||||||
icon="arrow-down"
|
|
||||||
size={40}
|
|
||||||
onPressIn={() => this.logic.downPressedIn(this.updateGridScore)}
|
|
||||||
onPress={() => this.logic.pressedOut()}
|
|
||||||
style={{marginLeft: 'auto'}}
|
|
||||||
color={colors.tetrisScore}
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
|
{this.getControlButtons()}
|
||||||
|
|
||||||
<OptionsDialog
|
<OptionsDialog
|
||||||
visible={this.state.dialogVisible}
|
visible={this.state.dialogVisible}
|
||||||
title={this.state.dialogTitle}
|
title={this.state.dialogTitle}
|
||||||
|
|
Loading…
Reference in a new issue