Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GameMainScreen.js 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // @flow
  2. import * as React from 'react';
  3. import {Alert, View} from 'react-native';
  4. import {IconButton, Text, withTheme} from 'react-native-paper';
  5. import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
  6. import GameLogic from "../logic/GameLogic";
  7. import type {Grid} from "../components/GridComponent";
  8. import GridComponent from "../components/GridComponent";
  9. import Preview from "../components/Preview";
  10. import i18n from "i18n-js";
  11. import MaterialHeaderButtons, {Item} from "../../../components/Overrides/CustomHeaderButton";
  12. import {StackNavigationProp} from "@react-navigation/stack";
  13. import type {CustomTheme} from "../../../managers/ThemeManager";
  14. type Props = {
  15. navigation: StackNavigationProp,
  16. theme: CustomTheme,
  17. }
  18. type State = {
  19. grid: Grid,
  20. gameRunning: boolean,
  21. gameTime: number,
  22. gameScore: number,
  23. gameLevel: number,
  24. }
  25. class GameMainScreen extends React.Component<Props, State> {
  26. logic: GameLogic;
  27. constructor(props) {
  28. super(props);
  29. this.logic = new GameLogic(20, 10, this.props.theme);
  30. this.state = {
  31. grid: this.logic.getCurrentGrid(),
  32. gameRunning: false,
  33. gameTime: 0,
  34. gameScore: 0,
  35. gameLevel: 0,
  36. };
  37. this.props.navigation.addListener('blur', this.onScreenBlur);
  38. this.props.navigation.addListener('focus', this.onScreenFocus);
  39. }
  40. componentDidMount() {
  41. this.props.navigation.setOptions({
  42. headerRight: this.getRightButton,
  43. });
  44. this.startGame();
  45. }
  46. getRightButton = () => {
  47. return <MaterialHeaderButtons>
  48. <Item title="pause" iconName="pause" onPress={this.togglePause}/>
  49. </MaterialHeaderButtons>;
  50. }
  51. /**
  52. * Remove any interval on un-focus
  53. */
  54. onScreenBlur = () => {
  55. if (!this.logic.isGamePaused())
  56. this.logic.togglePause();
  57. }
  58. onScreenFocus = () => {
  59. if (!this.logic.isGameRunning())
  60. this.startGame();
  61. else if (this.logic.isGamePaused())
  62. this.showPausePopup();
  63. }
  64. getFormattedTime(seconds: number) {
  65. let date = new Date();
  66. date.setHours(0);
  67. date.setMinutes(0);
  68. date.setSeconds(seconds);
  69. let format;
  70. if (date.getHours())
  71. format = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
  72. else if (date.getMinutes())
  73. format = date.getMinutes() + ':' + date.getSeconds();
  74. else
  75. format = date.getSeconds();
  76. return format;
  77. }
  78. onTick = (score: number, level: number, newGrid: Grid) => {
  79. this.setState({
  80. gameScore: score,
  81. gameLevel: level,
  82. grid: newGrid,
  83. });
  84. }
  85. onClock = (time: number) => {
  86. this.setState({
  87. gameTime: time,
  88. });
  89. }
  90. updateGrid = (newGrid: Grid) => {
  91. this.setState({
  92. grid: newGrid,
  93. });
  94. }
  95. updateGridScore = (newGrid: Grid, score: number) => {
  96. this.setState({
  97. grid: newGrid,
  98. gameScore: score,
  99. });
  100. }
  101. togglePause = () => {
  102. this.logic.togglePause();
  103. if (this.logic.isGamePaused())
  104. this.showPausePopup();
  105. }
  106. showPausePopup = () => {
  107. Alert.alert(
  108. i18n.t("screens.game.pause"),
  109. i18n.t("screens.game.pauseMessage"),
  110. [
  111. {text: i18n.t("screens.game.restart.text"), onPress: this.showRestartConfirm},
  112. {text: i18n.t("screens.game.resume"), onPress: this.togglePause},
  113. ],
  114. {cancelable: false},
  115. );
  116. }
  117. showRestartConfirm = () => {
  118. Alert.alert(
  119. i18n.t("screens.game.restart.confirm"),
  120. i18n.t("screens.game.restart.confirmMessage"),
  121. [
  122. {text: i18n.t("screens.game.restart.confirmNo"), onPress: this.showPausePopup},
  123. {text: i18n.t("screens.game.restart.confirmYes"), onPress: this.startGame},
  124. ],
  125. {cancelable: false},
  126. );
  127. }
  128. showGameOverConfirm() {
  129. let message = i18n.t("screens.game.gameOver.score") + this.state.gameScore + '\n';
  130. message += i18n.t("screens.game.gameOver.level") + this.state.gameLevel + '\n';
  131. message += i18n.t("screens.game.gameOver.time") + this.getFormattedTime(this.state.gameTime) + '\n';
  132. Alert.alert(
  133. i18n.t("screens.game.gameOver.text"),
  134. message,
  135. [
  136. {text: i18n.t("screens.game.gameOver.exit"), onPress: () => this.props.navigation.goBack()},
  137. {text: i18n.t("screens.game.restart.text"), onPress: this.startGame},
  138. ],
  139. {cancelable: false},
  140. );
  141. }
  142. startGame = () => {
  143. this.logic.startGame(this.onTick, this.onClock, this.onGameEnd);
  144. this.setState({
  145. gameRunning: true,
  146. });
  147. }
  148. onGameEnd = (time: number, score: number, isRestart: boolean) => {
  149. this.setState({
  150. gameTime: time,
  151. gameScore: score,
  152. gameRunning: false,
  153. });
  154. if (!isRestart)
  155. this.showGameOverConfirm();
  156. }
  157. render() {
  158. const colors = this.props.theme.colors;
  159. return (
  160. <View style={{
  161. width: '100%',
  162. height: '100%',
  163. }}>
  164. <View style={{
  165. flexDirection: 'row',
  166. position: 'absolute',
  167. top: 5,
  168. left: 10,
  169. }}>
  170. <MaterialCommunityIcons
  171. name={'timer'}
  172. color={colors.subtitle}
  173. size={20}/>
  174. <Text style={{
  175. marginLeft: 5,
  176. color: colors.subtitle
  177. }}>{this.getFormattedTime(this.state.gameTime)}</Text>
  178. </View>
  179. <View style={{
  180. flexDirection: 'row',
  181. position: 'absolute',
  182. top: 50,
  183. left: 10,
  184. }}>
  185. <MaterialCommunityIcons
  186. name={'gamepad'}
  187. color={colors.text}
  188. size={20}/>
  189. <Text style={{
  190. marginLeft: 5
  191. }}>{this.state.gameLevel}</Text>
  192. </View>
  193. <View style={{
  194. flexDirection: 'row',
  195. marginRight: 'auto',
  196. marginLeft: 'auto',
  197. }}>
  198. <MaterialCommunityIcons
  199. name={'star'}
  200. color={colors.tetrisScore}
  201. size={30}/>
  202. <Text style={{
  203. marginLeft: 5,
  204. fontSize: 22,
  205. }}>{this.state.gameScore}</Text>
  206. </View>
  207. <GridComponent
  208. width={this.logic.getWidth()}
  209. height={this.logic.getHeight()}
  210. containerMaxHeight={'80%'}
  211. containerMaxWidth={'60%'}
  212. grid={this.state.grid}
  213. backgroundColor={colors.tetrisBackground}
  214. />
  215. <View style={{
  216. position: 'absolute',
  217. top: 50,
  218. right: 5,
  219. }}>
  220. <Preview
  221. items={this.logic.getNextPiecesPreviews()}
  222. />
  223. </View>
  224. <View style={{
  225. position: 'absolute',
  226. bottom: 0,
  227. flexDirection: 'row',
  228. width: '100%',
  229. }}>
  230. <IconButton
  231. icon="rotate-right-variant"
  232. size={40}
  233. onPress={() => this.logic.rotatePressed(this.updateGrid)}
  234. style={{marginRight: 'auto'}}
  235. />
  236. <View style={{
  237. flexDirection: 'row',
  238. }}>
  239. <IconButton
  240. icon="arrow-left"
  241. size={40}
  242. onPress={() => this.logic.pressedOut()}
  243. onPressIn={() => this.logic.leftPressedIn(this.updateGrid)}
  244. />
  245. <IconButton
  246. icon="arrow-right"
  247. size={40}
  248. onPress={() => this.logic.pressedOut()}
  249. onPressIn={() => this.logic.rightPressed(this.updateGrid)}
  250. />
  251. </View>
  252. <IconButton
  253. icon="arrow-down"
  254. size={40}
  255. onPressIn={() => this.logic.downPressedIn(this.updateGridScore)}
  256. onPress={() => this.logic.pressedOut()}
  257. style={{marginLeft: 'auto'}}
  258. color={colors.tetrisScore}
  259. />
  260. </View>
  261. </View>
  262. );
  263. }
  264. }
  265. export default withTheme(GameMainScreen);