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.

GameScreen.js 9.5KB

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