GameActivity.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. package com.jyc.threegames.activity;
  2. import android.app.Activity;
  3. import android.app.Dialog;
  4. import android.app.ProgressDialog;
  5. import android.content.Intent;
  6. import android.os.Bundle;
  7. import android.os.Handler;
  8. import android.os.Looper;
  9. import android.os.Message;
  10. import android.text.Html;
  11. import android.view.Gravity;
  12. import android.view.View;
  13. import android.widget.TextView;
  14. import androidx.annotation.NonNull;
  15. import androidx.constraintlayout.widget.ConstraintLayout;
  16. import com.jyc.threegames.App;
  17. import com.jyc.threegames.R;
  18. import com.jyc.threegames.activity.base.BaseActivity;
  19. import com.jyc.threegames.bean.GameInfo;
  20. import com.jyc.threegames.bean.result.ResGameInfo;
  21. import com.jyc.threegames.controller.GameController;
  22. import com.jyc.threegames.controller.LoginController;
  23. import com.jyc.threegames.net.SimpleRequest;
  24. import java.util.ArrayList;
  25. import java.util.Date;
  26. import java.util.List;
  27. import java.util.Locale;
  28. import butterknife.BindView;
  29. import butterknife.OnClick;
  30. import it.sephiroth.android.library.numberpicker.NumberPicker;
  31. public class GameActivity extends BaseActivity {
  32. private static final String PARAM_GAME_INFO = "gameInfo";
  33. private static final String PARAM_RES_GAME_INFO = "resGameInfo";
  34. private int mCurrentPreGameCountDown = 0;
  35. private Handler mPreGameHandler;
  36. private Integer[] mPractiseNumbers;
  37. private Handler mPractiseHandler;
  38. private int mCurrentPractiseIndex;
  39. private GameInfo mGameInfo;
  40. private ResGameInfo mResGameInfo;
  41. private int mSpecialNumberOne;
  42. private int mSpecialNumberTwo;
  43. @BindView(R.id.pre_game_hint)
  44. TextView mTVPreGameHint;
  45. @BindView(R.id.game_hint)
  46. TextView mTVGameHint;
  47. @BindView(R.id.number)
  48. TextView mTVNumber;
  49. @BindView(R.id.click_area)
  50. View mVClickArea;
  51. @BindView(R.id.form)
  52. ConstraintLayout mCLForm;
  53. @BindView(R.id.right)
  54. NumberPicker mNPRight;
  55. @BindView(R.id.grasp)
  56. NumberPicker mNPGrasp;
  57. private boolean mClickable = false;
  58. private long mClickTime = 0;
  59. private long mCurrentTime = 0;
  60. private List<Integer> mRecordList;
  61. private List<Long> mResponseList;
  62. private List<Integer> mPressRecordList;
  63. private long mStartTime = System.currentTimeMillis();
  64. private long mEndTime = 0;
  65. @Override
  66. protected void init(Bundle instance) {
  67. super.init(instance);
  68. if (instance == null) {
  69. mGameInfo = getIntent().getParcelableExtra(PARAM_GAME_INFO);
  70. mResGameInfo = getIntent().getParcelableExtra(PARAM_RES_GAME_INFO);
  71. }
  72. else {
  73. mGameInfo = instance.getParcelable(PARAM_GAME_INFO);
  74. mResGameInfo = getIntent().getParcelableExtra(PARAM_RES_GAME_INFO);
  75. }
  76. if (!LoginController.getInstance().isCurrentUserAdmin()){
  77. new SimpleRequest<>().request(this, GameController.getInstance().enterGame(mResGameInfo.playGameId));
  78. }
  79. startPrePractise();
  80. App.CAN_PLAY_GAME = false;
  81. }
  82. @Override
  83. protected void onSaveInstanceState(@NonNull Bundle outState) {
  84. super.onSaveInstanceState(outState);
  85. outState.putParcelable(PARAM_GAME_INFO, mGameInfo);
  86. outState.putParcelable(PARAM_RES_GAME_INFO, mResGameInfo);
  87. }
  88. @Override
  89. protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
  90. super.onRestoreInstanceState(savedInstanceState);
  91. mGameInfo = savedInstanceState.getParcelable(PARAM_GAME_INFO);
  92. mResGameInfo = savedInstanceState.getParcelable(PARAM_RES_GAME_INFO);
  93. }
  94. @Override
  95. protected int getRootLayout() {
  96. return R.layout.activity_game_one;
  97. }
  98. @Override
  99. protected void onDestroy() {
  100. super.onDestroy();
  101. App.CAN_PLAY_GAME = true;
  102. }
  103. @Override
  104. public void onBackPressed() {}
  105. @Override
  106. protected String getAlertText() {
  107. return "您好,\n閒置超時,\n請繼續操作!";
  108. }
  109. @OnClick(R.id.click_area)
  110. public void clickNumber(){
  111. if (mClickable && mClickTime == 0){
  112. mClickTime = System.currentTimeMillis();
  113. }
  114. }
  115. @OnClick(R.id.sure)
  116. public void clickSure(){
  117. if (LoginController.getInstance().isCurrentUserAdmin()){
  118. goFinish();
  119. }else{
  120. Dialog loading = new ProgressDialog(this);
  121. loading.setTitle("正在提交數據");
  122. loading.show();
  123. new SimpleRequest<>()
  124. .request(this, GameController.getInstance().addAnswer(mResGameInfo.playGameId, mPractiseNumbers, mRecordList, mResponseList, mPressRecordList, mSpecialNumberOne, mSpecialNumberTwo, mGameInfo.gameVersion, mStartTime, mEndTime, mNPRight.getProgress(), mNPGrasp.getProgress()), "提交數據失敗!請檢查網絡狀態", loading, new SimpleRequest.Executor<Object>() {
  125. @Override
  126. public void execute(Object obj) {
  127. goFinish();
  128. }
  129. });
  130. }
  131. }
  132. private void goFinish(){
  133. hideAllView();
  134. mTVPreGameHint.setGravity(Gravity.CENTER);
  135. mTVPreGameHint.setText("數據提交成功\n\n謝謝參與");
  136. mTVPreGameHint.setVisibility(View.VISIBLE);
  137. new Handler(Looper.getMainLooper(), new Handler.Callback() {
  138. @Override
  139. public boolean handleMessage(@NonNull Message message) {
  140. finish();
  141. return true;
  142. }
  143. }).sendEmptyMessageDelayed(0, 3000);
  144. }
  145. private void startPrePractise(){
  146. hideAllView();
  147. mSpecialNumberOne = getRandomNumber();
  148. mSpecialNumberTwo = getRandomNumber(mSpecialNumberOne);
  149. mCurrentPreGameCountDown = mGameInfo.getPractiseDurationSecond();
  150. mPreGameHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
  151. @Override
  152. public boolean handleMessage(@NonNull Message message) {
  153. if (mCurrentPreGameCountDown > 0){
  154. mTVPreGameHint.setVisibility(View.VISIBLE);
  155. mTVPreGameHint.setGravity(Gravity.START);
  156. mTVPreGameHint.setText(Html.fromHtml(getPrePractiseText(mSpecialNumberOne, mSpecialNumberTwo, mCurrentPreGameCountDown), Html.FROM_HTML_MODE_LEGACY));
  157. mCurrentPreGameCountDown --;
  158. mPreGameHandler.sendEmptyMessageDelayed(0, 1000);
  159. }else{
  160. mTVPreGameHint.setVisibility(View.GONE);
  161. startGame(true);
  162. }
  163. return true;
  164. }
  165. });
  166. mPreGameHandler.sendEmptyMessage(0);
  167. }
  168. private String getPreGameText(int countDown){
  169. return String.format(Locale.TRADITIONAL_CHINESE,"練習結束,<br/><br/><font color='#cc0000'>%1$d</font>秒后進入正式測試",
  170. countDown);
  171. }
  172. private String getPrePractiseText(int numberOne, int numberTwo, int countDown){
  173. switch (mGameInfo.gameVersion){
  174. case GameInfo.VERSION_GAME_ONE:
  175. return String.format(Locale.TRADITIONAL_CHINESE,"當屏幕出現數字<font color='#cc0000'>%1$d</font>的時候,<br/>請您以最快的速度按下<br/><br/>正式開始前,會有小段練習<br/><br/><font color='#cc0000'>%2$d</font>秒后進入練習", mSpecialNumberOne, countDown);
  176. case GameInfo.VERSION_GAME_TWO:
  177. return String.format(Locale.TRADITIONAL_CHINESE,"當數字<font color='#cc0000'>%1$d</font>,<font color='#cc0000'>%2$d</font>連續出現時,<br/><font color='#cc0000'>%1$d</font>出現時不要按下,<br/><font color='#cc0000'>%2$d</font>出現時,<br/>請您以最快的速度按下<br/><br/>正式開始前,會有小段練習<br/><br/><font color='#cc0000'>%3$d</font>秒后進入練習",
  178. numberOne, numberTwo, countDown);
  179. case GameInfo.VERSION_GAME_THREE:
  180. return String.format(Locale.TRADITIONAL_CHINESE,"除數字<font color='#cc0000'>%1$d</font>以外的數字出現時,<br/>請您以最快的速度按下<br/><br/>正式開始前,會有小段練習<br/><br/><font color='#cc0000'>%2$d</font>秒后進入練習",
  181. numberOne, countDown);
  182. default:
  183. return "";
  184. }
  185. }
  186. private void startGame(boolean isPractise){
  187. hideAllView();
  188. mPractiseNumbers = getPractiseNumbers(isPractise ? mGameInfo.practiseRightNumber : mGameInfo.correctNumberOccurrenceNumber, isPractise ? mGameInfo.practiseOccurrenceNumber : mGameInfo.errorNumberOccurrenceNumber);
  189. mRecordList = new ArrayList<>();
  190. mResponseList = new ArrayList<>();
  191. mPressRecordList = new ArrayList<>();
  192. mCurrentPractiseIndex = 0;
  193. restoreClickInfo(false);
  194. mPractiseHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
  195. @Override
  196. public boolean handleMessage(@NonNull Message message) {
  197. switch (message.what){
  198. case 0:
  199. if (mCurrentPractiseIndex == mPractiseNumbers.length){
  200. restoreClickInfo(false);
  201. if (isPractise)
  202. startPregame();
  203. else
  204. startFeedBack();
  205. }else{
  206. restoreClickInfo(true);
  207. mCurrentTime = System.currentTimeMillis();
  208. mTVNumber.setVisibility(View.VISIBLE);
  209. mTVGameHint.setVisibility(View.GONE);
  210. mTVNumber.setText(String.valueOf(mPractiseNumbers[mCurrentPractiseIndex]));
  211. mPractiseHandler.sendEmptyMessageDelayed(1, mGameInfo.displayDuration);
  212. }
  213. break;
  214. case 1:
  215. mTVNumber.setVisibility(View.GONE);
  216. if (isPractise) {
  217. mTVGameHint.setText(Html.fromHtml(getGameHint(), Html.FROM_HTML_MODE_LEGACY));
  218. mTVGameHint.setVisibility(View.VISIBLE);
  219. }else {
  220. int result = getClickResult();
  221. mRecordList.add(result);
  222. mPressRecordList.add(mClickTime == 0 ? 0 : 1);
  223. if (mClickTime != 0 && result == GameInfo.CLICK_RIGHT)
  224. mResponseList.add(mClickTime - mCurrentTime);
  225. else
  226. mResponseList.add(-1L);
  227. }
  228. restoreClickInfo(false);
  229. mCurrentPractiseIndex ++;
  230. mPractiseHandler.sendEmptyMessageDelayed(0, mGameInfo.intervalDuration);
  231. break;
  232. }
  233. return true;
  234. }
  235. });
  236. mPractiseHandler.sendEmptyMessage(0);
  237. }
  238. private void startPregame(){
  239. hideAllView();
  240. mCurrentPreGameCountDown = mGameInfo.getPractiseDurationSecond();
  241. mPreGameHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
  242. @Override
  243. public boolean handleMessage(@NonNull Message message) {
  244. if (mCurrentPreGameCountDown > 0){
  245. mTVPreGameHint.setVisibility(View.VISIBLE);
  246. mTVPreGameHint.setGravity(Gravity.CENTER);
  247. mTVPreGameHint.setText(Html.fromHtml(getPreGameText(mCurrentPreGameCountDown), Html.FROM_HTML_MODE_LEGACY));
  248. mCurrentPreGameCountDown --;
  249. mPreGameHandler.sendEmptyMessageDelayed(0, 1000);
  250. }else{
  251. mTVPreGameHint.setVisibility(View.GONE);
  252. startGame(false);
  253. }
  254. return true;
  255. }
  256. });
  257. mPreGameHandler.sendEmptyMessage(0);
  258. }
  259. private void startFeedBack(){
  260. hideAllView();
  261. mCLForm.setVisibility(View.VISIBLE);
  262. mEndTime = System.currentTimeMillis();
  263. startWatch();
  264. }
  265. private String getGameHint(){
  266. String result;
  267. int clickResult = getClickResult();
  268. result = clickResult == GameInfo.CLICK_RIGHT ? "正確" : (clickResult == GameInfo.CLICK_WRONG ? "錯誤" : "錯失");
  269. if (mClickTime != 0 && clickResult == GameInfo.CLICK_RIGHT)
  270. result += String.format(Locale.TRADITIONAL_CHINESE, "<br/>反應時間: <font color='#cc0000'>%1$d</font> 毫秒", mClickTime - mCurrentTime);
  271. return result;
  272. }
  273. private int getClickResult(){
  274. int preNumber = mCurrentPractiseIndex == 0 ? -1 : mPractiseNumbers[mCurrentPractiseIndex - 1];
  275. int currentNumber = mPractiseNumbers[mCurrentPractiseIndex];
  276. if (mGameInfo.gameVersion == GameInfo.VERSION_GAME_ONE){
  277. if (mClickTime == 0){
  278. if (mSpecialNumberOne == currentNumber)
  279. return GameInfo.CLICK_MISS;
  280. else
  281. return GameInfo.CLICK_RIGHT;
  282. }else{
  283. if (mSpecialNumberOne == currentNumber)
  284. return GameInfo.CLICK_RIGHT;
  285. else
  286. return GameInfo.CLICK_WRONG;
  287. }
  288. }else if(mGameInfo.gameVersion == GameInfo.VERSION_GAME_TWO){
  289. if (preNumber < 0 && mClickTime != 0)
  290. return GameInfo.CLICK_WRONG;
  291. if (mClickTime == 0){
  292. if (preNumber == mSpecialNumberOne && currentNumber == mSpecialNumberTwo)
  293. return GameInfo.CLICK_MISS;
  294. else
  295. return GameInfo.CLICK_RIGHT;
  296. }else{
  297. if (preNumber == mSpecialNumberOne && currentNumber == mSpecialNumberTwo)
  298. return GameInfo.CLICK_RIGHT;
  299. else
  300. return GameInfo.CLICK_WRONG;
  301. }
  302. }else if(mGameInfo.gameVersion == GameInfo.VERSION_GAME_THREE){
  303. if (mClickTime == 0){
  304. if (mSpecialNumberOne == currentNumber)
  305. return GameInfo.CLICK_RIGHT;
  306. else
  307. return GameInfo.CLICK_MISS;
  308. }else{
  309. if (mSpecialNumberOne == currentNumber)
  310. return GameInfo.CLICK_WRONG;
  311. else
  312. return GameInfo.CLICK_RIGHT;
  313. }
  314. }
  315. return GameInfo.CLICK_MISS;
  316. }
  317. private Integer[] getPractiseNumbers(int rightNumber, int otherNumberOccurrence){
  318. List<Integer> result = new ArrayList<>();
  319. for (int i = 0; i < otherNumberOccurrence; i ++)
  320. result.add(mGameInfo.gameVersion != GameInfo.VERSION_GAME_TWO ? getRandomNumber(mSpecialNumberOne) : getRandomNumber());
  321. int less = 0;
  322. if (mGameInfo.gameVersion == GameInfo.VERSION_GAME_TWO && result.size() > 1)
  323. for(int i = 0; i < result.size(); i ++){
  324. if (i != result.size() - 1){
  325. if (result.get(i) == mSpecialNumberOne && result.get(i + 1) == mSpecialNumberTwo)
  326. less ++;
  327. }
  328. }
  329. if (less > rightNumber)
  330. return getPractiseNumbers(rightNumber, otherNumberOccurrence);
  331. for (int i = 0; i < rightNumber - less; i ++) {
  332. int index = (int) (Math.random() * result.size());
  333. if (mGameInfo.gameVersion != GameInfo.VERSION_GAME_TWO)
  334. result.add(index, mSpecialNumberOne);
  335. else{
  336. if (index != result.size() - 1 && (result.get(index) == mSpecialNumberOne && result.get(index + 1) == mSpecialNumberTwo)){
  337. i--;
  338. continue;
  339. }
  340. result.add(index, mSpecialNumberOne);
  341. result.add(index + 1, mSpecialNumberTwo);
  342. }
  343. }
  344. return result.toArray(new Integer[0]);
  345. }
  346. private void restoreClickInfo(boolean clickable){
  347. mClickable = clickable;
  348. mClickTime = 0;
  349. mCurrentTime = 0;
  350. }
  351. private int getRandomNumber(){
  352. return (int)(Math.random() * 10);
  353. }
  354. private int getRandomNumber(int number){
  355. int value = getRandomNumber();
  356. return value == number ? getRandomNumber(number) : value;
  357. }
  358. private void hideAllView(){
  359. ConstraintLayout rootView = getWindow().getDecorView().findViewById(R.id.root);
  360. for (int i = 0; i < rootView.getChildCount(); i ++){
  361. if (rootView.getChildAt(i).getId() != R.id.click_area)
  362. rootView.getChildAt(i).setVisibility(View.GONE);
  363. }
  364. }
  365. public static void LAUNCH_GAME_ONE(Activity context, GameInfo gameInfo){
  366. Intent intent = new Intent(context, GameActivity.class);
  367. intent.putExtra(PARAM_GAME_INFO, gameInfo);
  368. context.startActivity(intent);
  369. }
  370. public static void LAUNCH_GAME(Activity context, ResGameInfo resGameInfo){
  371. Intent intent = new Intent(context, GameActivity.class);
  372. intent.putExtra(PARAM_GAME_INFO, resGameInfo.getGameInfo());
  373. intent.putExtra(PARAM_RES_GAME_INFO, resGameInfo);
  374. context.startActivity(intent);
  375. }
  376. }