From e4bf9bf3c4b297f8de4d81142d4682486795a49a Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Wed, 2 Apr 2014 02:09:19 +0200 Subject: [PATCH 01/10] Add license - Apache v2 it is --- LICENSE.txt | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..c756169 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Stefan Hoth + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From d991583b12dc54afec572ca2e4c6c46252c5dcf7 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Wed, 2 Apr 2014 10:43:53 +0200 Subject: [PATCH 02/10] Log new highscore remotely and check if persistence works --- .../fragments/PlayingFieldFragment.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java index 8bb3f55..6438b69 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java @@ -20,6 +20,8 @@ import android.widget.TextView; import android.widget.Toast; +import com.deploygate.sdk.DeployGate; + import butterknife.ButterKnife; import butterknife.InjectView; import de.stefanhoth.android.got2048.R; @@ -320,6 +322,32 @@ private void announceMovement(MOVE_DIRECTION direction) { } + + private void checkHighscore() { + + if (mCurrentScore > mHighscore) { + //TODO do something visually fancy + Toast.makeText(getActivity().getBaseContext(), "NEW HIGHSCORE!", Toast.LENGTH_SHORT).show(); + mHighscore = mCurrentScore; + + String username = DeployGate.getLoginUsername(); + String message = String.format("%s just reached a new highscore: %d", (username == null) ? "UNKNOWN" : username, mHighscore); + DeployGate.logInfo(message); + + if (!SettingsHelper.storeSettings(getActivity().getBaseContext(), mCurrentScore)) { + Log.e(TAG, "checkHighscore: Could not persist highscore into shared prefs."); + return; + } + + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mTvHighscore.setText(String.valueOf(mCurrentScore)); + } + }); + } + } + // Broadcast receiver for receiving status updates from the IntentService private class McpEventReceiver extends BroadcastReceiver { @@ -392,20 +420,4 @@ private void handleGameWon(Intent intent) { mGameStatus.setText("YOU WON!"); } } - - private void checkHighscore() { - - if (mCurrentScore > mHighscore) { - //TODO do something visually fancy - Toast.makeText(getActivity().getBaseContext(), "NEW HIGHSCORE!", Toast.LENGTH_SHORT).show(); - SettingsHelper.storeSettings(getActivity().getBaseContext(), mCurrentScore); - - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - mTvHighscore.setText(String.valueOf(mCurrentScore)); - } - }); - } - } } \ No newline at end of file From c0442a2a947eef406a5eb653ce3f1c707ff7b71a Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 16:41:16 +0200 Subject: [PATCH 03/10] Ignore keys --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a36c879..3640f2b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ *.iml .DS_Store -secret.properties \ No newline at end of file +secret.properties +/deployment \ No newline at end of file From fcb509f26d5880c8cd9c0e6fd988828950cfd318 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 16:47:15 +0200 Subject: [PATCH 04/10] Update actions with more appropriate icons --- .../ic_action_playback_schuffle.png | Bin 0 -> 1027 bytes .../main/res/drawable-hdpi/ic_action_redo.png | Bin 0 -> 729 bytes .../main/res/drawable-hdpi/ic_action_refresh.png | Bin 663 -> 0 bytes .../res/drawable-hdpi/ic_action_view_as_grid.png | Bin 255 -> 0 bytes .../ic_action_playback_schuffle.png | Bin 0 -> 739 bytes .../main/res/drawable-mdpi/ic_action_redo.png | Bin 0 -> 481 bytes .../main/res/drawable-mdpi/ic_action_refresh.png | Bin 508 -> 0 bytes .../res/drawable-mdpi/ic_action_view_as_grid.png | Bin 255 -> 0 bytes .../ic_action_playback_schuffle.png | Bin 0 -> 1358 bytes .../main/res/drawable-xhdpi/ic_action_redo.png | Bin 0 -> 886 bytes .../res/drawable-xhdpi/ic_action_refresh.png | Bin 895 -> 0 bytes .../drawable-xhdpi/ic_action_view_as_grid.png | Bin 293 -> 0 bytes .../ic_action_playback_schuffle.png | Bin 0 -> 2050 bytes .../main/res/drawable-xxhdpi/ic_action_redo.png | Bin 0 -> 1345 bytes .../res/drawable-xxhdpi/ic_action_refresh.png | Bin 1239 -> 0 bytes .../drawable-xxhdpi/ic_action_view_as_grid.png | Bin 310 -> 0 bytes app/src/main/res/menu/game.xml | 4 ++-- 17 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_action_playback_schuffle.png create mode 100644 app/src/main/res/drawable-hdpi/ic_action_redo.png delete mode 100644 app/src/main/res/drawable-hdpi/ic_action_refresh.png delete mode 100644 app/src/main/res/drawable-hdpi/ic_action_view_as_grid.png create mode 100644 app/src/main/res/drawable-mdpi/ic_action_playback_schuffle.png create mode 100644 app/src/main/res/drawable-mdpi/ic_action_redo.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_action_refresh.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_action_view_as_grid.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_playback_schuffle.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_redo.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_action_refresh.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_action_view_as_grid.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_playback_schuffle.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_redo.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_refresh.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_view_as_grid.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_playback_schuffle.png b/app/src/main/res/drawable-hdpi/ic_action_playback_schuffle.png new file mode 100644 index 0000000000000000000000000000000000000000..56932678793e92f69d83ddc639f3b56f9d336320 GIT binary patch literal 1027 zcmV+e1pNDnP)a^o1(hrez5+goG46t* zXb{1Lpdmg$H;Rcba3LtZagm7e6^*VWh)R?gjZPql2%-x&!3QdtL`3kB!HnAN;&hvy znyTumnx1qC{cpPK-h1l)f8TS@{cjI7n@#^`4ELMBOfeA9Zwv(V8v_CTMqLDqU~!ee zx(Jwy&A6m&U|j^j(RdtdF;q0DP67zxYw?5-)D?9T(8h9+Qm1qqm?hv^ti)Lu6`SmE zV=-RA#d(8>AK`4A6cqOvtN8(bf!Wk(OZN!TyacARc9Fx-b6+XgkDSZ=oK=B>-hpahNC*hG_e)0;d{)(&cu6u5G(dg9+9f&Kof7`YHUyR zEyb~|?r{NRapbL3sevti&d+|c+c^o(6XOU));K+{gyKz0f$a&`$ z+=1VU5U5&(lGunJ1+jftjdiAanq957$!XDnNs)Tn%1m5!59HxGQ6@VvCdmJl5i=L3 zi49!}z4k(@O((w-cgrSE?5RJhOxQ~SSBYP_6CYr`NYyp6JyrWYkn4NW&>qK4mR zYREJs>qx>=E~Yy?KM``oGW)aX99Zr+0R`S7?Ze_HxmHItln)*pJ<1f@b4BPz576 xQQU(|p)LX{qpq8{Fa`qpje&rEV<4d4_!s0e%@sAUKkEPh002ovPDHLkV1jJ%(Z>J) literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_action_redo.png b/app/src/main/res/drawable-hdpi/ic_action_redo.png new file mode 100644 index 0000000000000000000000000000000000000000..f52a806766476400d6acc186ba72a8fe8fbaa095 GIT binary patch literal 729 zcmV;~0w(>5P)xK~!jg?btnN6hRoq@n52`vJi`WX|PB{45(mdWo0LpHYye> zL{Mx@rC5j-VrQcUL$I*16l=l8GC_r)XbKA(5lNx(BbZps9@${-c4se_IpzMa+`P-a z?>^7$&Fsu}EiW(om+4L|pjkQwQqwVznvQ|gq&6^wDeSCTAf~z=E!2*S+Oze z+tc;S4D|s4IIYNti2=%e-a_E5yyp|u2JjxLh+QFMz`TgE`DVF#2>?WF8+>7cv-eU z83SjqJ!^lk`t{!oM{pHgSzHr86H}y&fdjerZTyP4K?6SHXV(59h@XxvQe>bk zDmQ4rj39bmMe!65;$bWE{d?=z`!%M8aj;OeK+zKz&9!H%-lTxa;%T47TxE(3Rz z?o|mXGB9UlX)uBKz=Z00000 LNkvXXu0mjf(pE)) literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_action_refresh.png b/app/src/main/res/drawable-hdpi/ic_action_refresh.png deleted file mode 100644 index dae27903e9ba3415808d48e6ac20afd6de64907b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 663 zcmV;I0%-k-P)RI}s=BK%nX zlUx%QIv80pc1(T;vVlKX)Vx1|;n|hBVn^gfP_BsCW76<^*ogv|EgstVEbOtsZ1pcL zlxj9#id5*3d^awHe#@2VtpWK|BL5rURme>gU_=6$qQDWzPtV~B!U*IqVR%)hjSibG zF(9lNt2zE$$Ws;Inv@y!NrBNhD?o{X4`u2aT&VO^Bm7vu&Si}ifX%KvRAn3LHwRJA zK{?2bDkKL`Py3=(5PK%CyUdksvyg9$oLazhXCl!YoOz!tFw=B0`k{c-AdqorI&+xC zhq8*yp{t}GfxzBiUv8QKZHjtMT(>kJzo@7;8Z)4c1vZ4bl~k#r+oYOGO%y$Mlq-vk z1)4V963KHUugm)>^}ZE5j>X2Tf#vC}#uZm}Z5bCXG>2hMSei>CC&W*QLGQjMwp73b zImV6gwZ%mY6qrVBdZZ#)*VOKYD+>rW$RzTjz%Q|DH%2!}2ywEbrrE9(_#~)ndZpbV8Fv*en^~A;=q9ojl36*wRb5Jgxn?Ob_I?ijLq0Muumf3=E`FXPyVy>gnp|vd$@?2>_5+SU>;( diff --git a/app/src/main/res/drawable-mdpi/ic_action_playback_schuffle.png b/app/src/main/res/drawable-mdpi/ic_action_playback_schuffle.png new file mode 100644 index 0000000000000000000000000000000000000000..d360956cceccc5555af382377506d10bff25a6aa GIT binary patch literal 739 zcmV<90v!E`P)HDZ4xxER#C#rGcO%;%YN zjyiHc=7tZ>_q@+}?)yA{?-@v>u@^5X3AI5g+xUKxWVl<* zUP@5MCVWv!^Do}Rk8S*x;O}n1?sO5ojL!@CKiG-K@viCqXyOpob&c3#>K7#0ndE#) z`Q{oRP%jaHTUN_5RBk; z)z*A^7N1GHt>p)_6L3p)5&cnAAIC2pi0c?oHQ%_I8M&e=-K81MH36f=@uqu6!*mZ^ z#BSB(%s~Az`h5$vR(>?B|=F@?Q2(aGswpAm)7C{B5eMpkl~Q;K>!3JIS8h3kC) zy-4^F8m@DNL~;=g3L>tS>ku7LNPdc)lMQBXZr9oi_e&;kG4IU#Waj;2BvGV>3XMJh z_{#uGz*tcLtH36(>jRMoz!~riR4l~kZv)%_HQ>buBCi~{jzP>MK^V_YSO!8M0H%Rb z3aG0X)Q5(<95TQ%umOyu2pZS8y~7*80NcPEAm9*a0xjUtBVYyCBYOHfU=4Ws;w8zo zRwP|WI+9dP@cV8}NjkCT4;w1RoLyzuAS$&Gzl2MzzMY1*)&`FK+yPqF&KCvH z0A7Jbpjre#n`nR-U@K3Eq+#^A71!yl6=w$MK>WlonoSGPQPy#s86Y?HZ6g{0{2zdK X0)Gr=#}C9k00000NkvXXu0mjfF@CxO literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_action_refresh.png b/app/src/main/res/drawable-mdpi/ic_action_refresh.png deleted file mode 100644 index 94ab6f4c5dd8f3a082b2a84d6e08f2564a589d94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 508 zcmV-z^uNgfEYJ?X0v;e4!2PF!d%e@SmQ!PVe6+gr*@umuEKASwcC)f< z|GWWrF_jO)uwTspfWO^ZxARn*Qddzc&{8(7&^q)l<2?OSBuUZ-8$gO4se3R$x#Vc0 zf!eXo&j9TD2<2QfcDex=pHGFcp8*2+=+0Nutyp`amRUUWKGy>W20re%Az(?_vju$q z5zvlG>PiOwMBqwTTjT6);!MTFVL-=r)DrmFaZI@g;K%^c1Ee%(;8zJ802*px6z zlwg&mXlX(#B5nCr5nu)5G*ZoW6*o6x#QO-Y29R_M_BPg=Ye0`&o~~q2>vvI_8SAE^ yG?c!76r+gfb>ugXi>NOna_8m$aT-&;1Q-A|?2p+^qB;uz0000}1B}lL?P7vWSNI0VY^Z)<)WQEio=UDiKt8{SO1ARcuhp_eIv^E!8EIM0$R1uJedX&avOWS&&vWs$O=&He7pi#Zmr z8WdxN=CxjX-r}`Gw<75G&5M`vM0%PWc^Q~^7?w^^YG%vOGzU7C!PC{xWt~$(697?7 BUM~Ou diff --git a/app/src/main/res/drawable-xhdpi/ic_action_playback_schuffle.png b/app/src/main/res/drawable-xhdpi/ic_action_playback_schuffle.png new file mode 100644 index 0000000000000000000000000000000000000000..315ed003fcfa45531c4066ff00be6f461a9ed834 GIT binary patch literal 1358 zcmV-U1+n^xP);aT~izf@Xrh?Dweh(MO18UB1kMD2q{G(2r4KN zTS!DzQv0r!h&7_6RZ6KPhzKGQBehj4ZET?-6-!&uN-Rmy8ExtKV(|hl`ckY|H zneo2K&AfT%oZtQazV~;2=bYbtEuEd6{?BNwnn2ZP3Q#qHs?ijnY64ZGDL~Z(szy_Q zstHt$fh@qtMi?2$0z8ca${HES0t~}+OekYyAPWGS;7Uxvklq*==mK=%1kA$rMF$QR z0bnmYgZ+vO8cYJfaLmAIc?Yy)6hw~0&-kVGcXe5I4aP@x+F!-pSew-;OMsp?_{#=C zR$?ALKu0~MeS~@fz+zk_cqgKW07+Pb1(+)Y>FX%j4oBiB9GG*=uR?^+lN!qk&>d?< zM9jeV1;=J#2jTEI?1PqG*jR^q@p8|GO-oVxFNO%BN8klKs$4{DjZ1N|^2s_?w5$lY z4I@Nm9f55N68R0&@H&c=o?CDdCSjWb5 z9!BGO?46fX9W22W_$jSJ5do60BgWzwF+bC=5|i;wMxSxGUG|oC9X`YxxT_AgHry%_ zbt=jV&>drOxez4@?YKd#7Cmu}2>G`DI0kHhK#5 z#1OHZ?uLu7O3d>qI6h^}98Aq&yK4$ODGDQbqGTiVwE%>}TZ!b=g6l9orSEK!!17?e z$ntHa$o2E<@vCuqO4}?vQoz<2u{xAOBe%l!Fj>0uGx1nKdq0+=6X>sk$RwPd(l*@& z=Qk^0a}IVbLyG;zk^s(mqu@MPm2Z zy{P#T?!(_1_PbVrPCPEAQDJBLN`TQ~uRbcJ{Xy|!gK&D5jknPC4pBXKg7a{b*bU}J zUrd4VVr@=y{s9}DCthqMogelW5pqz@`yQ?rd7)7e(1L?;CJsyK^AGOFiwSLKiCtpa zs`Rl~BDkvUUv>WwAYKpYxzY6e3^C z*}n^|V(C0z?+Tzjv0PMz5(~ABtO|F>B5~ARTEfO?TqvTftPt%Y65i|C(CAfQksy7E za?Zoo;_NU1Z>m$;s)H@CXHr8WB4C9mRkdlr;Uoh?#LJLF#Y(et&T*^7(|i3G1|JgHv+Me!W@uGjh81I;*otSqoayg+KqHYB0fo*6 z{aFv_547VJu~Eu}!6d+P@q3}~iVPYozYtjS5@JGEI@}Sug@)G zWFW5syW`ukMh3C~4Z&bZg1tslfT{^pjivxq6Q~+Z0jefYHJSocO`vN03x^mocvbuF Qy#N3J07*qoM6N<$g5fu5djJ3c literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_action_redo.png b/app/src/main/res/drawable-xhdpi/ic_action_redo.png new file mode 100644 index 0000000000000000000000000000000000000000..71ec893695c294e3f3bf807bddc86f4b94bbe198 GIT binary patch literal 886 zcmV-+1Bv{JP)C-%Dz(Fs z1UQJx*pkv|DFPhC_n5$M_$HO(5(L;GBtKvRze^-S2?E@}Uy*H437gwGFF}C+alo($ z%Y;hU)W&%U0uV&_0e?sKfe0I$Ixa;3cqvrEqsYD-r?H`l(~<;$7uauh5zc5JLTLiP zbDkTchzqqx;l-%o|}(@c#7p1g@lVUgs;YIvQ76Y$W0} ze#E!9oziig3Rn@1$0-23k~n$F5?~~hxFM31Is(LtnRp>mB%J^??tK!C=bQj{qVYzd zM=zQ>0^Ac0CvAs8&$xU zbUgmq2v8K=hDh!Ja?=TrJAmAD0^|-LH=O{v1ISG$K<)r?Gv@{P0D~%@43*oCckPh%V0R3M2y&0fcAOnyAGC(sxGXNQY0rI3fagVyT<9`H*tvelU4-CJbC0VlE z2Nt+IL;@lKk$^}*Bp?znO}ShyPr=R{fM0=r1!(~QJcrAhkFk;)esl(xN6J>A;2~0ia@Ib@6GAwB|VR1RG@nRSrhnA zj=0q28)rQNFIpg;WKR~v1AYN=j-#;v0FN{N*L7wDA|n&6W_SW<);~ICJPAoWfk)rm zX!tp!Acr$nQ_yS3T5ybvt_y?Lr-Kq82~4~o$Xy%EB=;P+6=O-RbWIk65kO|I0^b7P z0q{mUGXIbGqjv!ncr@=<#f+2FLTJs0&G z3HWij0IkoW=!})yA%q>FN6FuJQ{7lGB|zx=Q=NTZ1WXpZ5dob@{mcJ@AV87z)l(+G zxf*m`hdq|#Dd(a`ot>hD-G>x{__Wn=&)_>lCKhleR?j2!`>b~YsI=XVbRy@H31fHf z0*Xqo4uSwC--SMfLcmG{UbixxdV4&RBxu^%>C`PiwryVBJpr^cwUkt++SzI1=|erm@*+zKXNh0OrE?o zV)}{!ZLjZ{Iri^6;~Aec(Gf4_1i3T2KLQgSXkIe?6CeD_(H@j+`Y@?J2#_9J?6lTZ zfvydZ$G$-KQJGap0-oTWT2<*Q2-XywDi)&L>PTCZ9wh$HP$VD{5DAC`ge?CA7yzOq VDq)Usy-@%F002ovPDHLkV1gKjk--1} diff --git a/app/src/main/res/drawable-xhdpi/ic_action_view_as_grid.png b/app/src/main/res/drawable-xhdpi/ic_action_view_as_grid.png deleted file mode 100644 index fcd564701b9caccb209396ffccc353a26a5e6400..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xj(fT|hE&{obHkVSkb^+OMcG55j0z0QTO0WV8u(ZOWN)ls zWD#NH(6BXsnQHcB(|gq=C)GBetkbk#DgxA<;dh0{|MC}~K0BpHdvCn9iGR1!+2zir z^c&%9ZzdJDPu-gL+B)I-uV@DbMiv1WAr<=D;EMWlJMHXR#v1`|}cHb zpGBUsN=knpM*h~Fz-w@3ec{HkH8=ES5AZ7@X=lj@etY=BggL+0t>I+_y5Yz6`3%eq Yj8Zb?0b>7`0RqNeW$*dYg!z)og741%=JfTqGFm3!(4KiSY+k$BZ*---IR`&ThfMU zs8*QEhB%@lw->Tm^>d4+)aKHho&V48dA&Z*=k;9vd0x*S@4^#)UQlISWe^Ai_3`#N zCH3%sq$n@Vf-(|PYH}&=K7oqT$W)9XOKYWM@8A^a{^UQBaW^Z!C~fMbdSX)pl44Rx z5$B^pBofIY?p#7jWJGebMbi1Rj%u>N&_O|YDgYBdZ` z0SwG^=^#&vF6=q~OTnEPcoEC;V-a@kBg5>@Wqv+dt`PX^Ji`1Wr}_@W;Arb@>sVik zvRjv$jclaag+3R*-_uN--if|tG=6D6Z-qVmQnI4A#KMh-Slhy&o%{{@t}kV~3D)JsTawf8nn9|k1U0FzrV@?eWlyohj=dl_)z4dV>Q7!_*t#69`$fOdjNbp62hj`Y};D>%(Px3Q0CzQb4mShW<5_&`;?s) z!6jcLSgzKuRerOQpQdDx7JiV?|GnDY#zO-JGU4{Ex>M?Kfu$fSD^!sQOyXPj=v|31 z*-t4(Pl*w8SKChMP9j_#GoHxsxJ}2V>3`HBVRd|?*&1+pc2D_w0S>BQ?CLl}M6esX z0vpR-T(o{rSTHu$uRV7SPD&Wd1KlF@zF<|!&%7lX;Vxs`^Iq!o7e9%9DSuqqYCs&NnBl zj9X!Hd}5Rheu9}EEhf5{$8}gHWldT-_7cqY`IGpH?SOw{R}f$~pQ!B<7ZR9*8v=md zI4o^MdLl4vb02yE$vu|+~mLlDQg5*{-jh5G6D{tgvf=gFO$Hw8xDI@)E`S|C`g<>U>Zw zbqDh>{+#)grMzjEkp7%;mClSNF8euORvdcQ4gn6anDwJQZltAdP%paR=-aNo z)_Mvgai+1eX`)aRer-y-cH@Ztd$HVHUGDW4G@UoY`_@NLG<3PYpc+x(6eQjWR>~r1 zjzbX%15w+46mnO1KsEKj5M%I!(szMA3wAbDEGhmD-+>9RR?$LBpmV3Wvo#T)asln* zxNT)_idV;9A7&=0cI>aXH~L+J>4h}wUejeF@9OU)2=TBz&YVNC)0_FPl(MiN$U**_ z5~KO-j9QPrUiaUS78N~m&b;(-L4834bdh`NMnF;p)Rg?R^0a2kp1G2W+l$#P+^93b z`HAwr&5?t=eihPaf{^t7+h85*)~&c`oeAkZ)|o+{+eck`D??AaReUuvc{^zR35+_i z?>w)?tBnZk54z#0Z^luBT)@-FIq6VI-qaZ8i1;j8g^0Fk0Gk8n7RY(e76fep&IdDQ z#hICB9{R>dYeTR`^1H9{o@tR=uA~JO8qIvUDIzvcah)DNq%u^?L0-kP!&z$63}*I^ z;W)!arYozd)cEt+Dzj(w)xg9uIV5JMMMZs@0odMKZP>f{z=xMbo;u`G{~_x&kT4V+ zkJZXIR!%Q@RbRJrU|5S$MJ-S|`Dn%<%wTjM$#iZcb%6ESaC$34`ijH9cA-u(uWucg zy@a*@*rLvjtnDb0Nh_-93p3q#yNcom0meVHd z+FSwAg>RShzr`+t(b~eyCoUU9*5U#+RKu?FTC;E;PDsw;Ll;+c3SUCXex+;pX)zvo zYYgs$kpGV)=BAj^Q%)fLcsHe`;d;$G1+_XHDSs&>r?8(rP*RW}ncc4c_#1nvLLNpso3DwU3veD)#Sh2R% z-=3Ed_>xMym2R|J97c3KR)kpER&w?L2r44pOM$4%(zE0oe`_1-o)aoA5`Lx8F4Kd_ zT4dL%*uRp0c`s1Sh#!uJ%NuvGgvBo0QbRUevxHM4j70_7TEu%a$V`gjv2`GIaqTX2 zi<&j1efaCTcjlA4YmNBbW}8}KDfp8Hd(Gs=!3L TFu*2Dc@6UM^z&f2hv)tc5JJH} literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_redo.png b/app/src/main/res/drawable-xxhdpi/ic_action_redo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ee0a355279766fa69fbf84f92893429ec15310a GIT binary patch literal 1345 zcmah}Yc!Mz82-M`j2UC(lFQ7vtj#4WGiSys*UEL78WNJ*W~`7LOhabUWrndfm#m3| ztZPfjPPtTM15J?y>x3bNx`Dz)DELeqsTEG3&Wk2xhlR- z5f+h9AqDI!2BK(OYjbD(SMnjfK`=$>?S0F8v^!$mLGT1%v@HLu#~`!J4#k6qdFuC6 zMvK~anPG0JUg|NY$MyFWT8K#tyzo_R^7Y#!4~z`rgm>acuU08;zz!>%qBbKn`GtN+ zzyO+DyIG=C?h~AK70E^0%}}M-wJL=wkp?pohWEz*D!5%4y)|Z@IO!tNl z3U>(Ss8TD5`*T-sxbvJ2`&~h_qa>&S@`gF*kg~yo=-qtNmI&(vd$L*s7zp|2T=KDa z{Y>Oj`AcVyO|=;vDh6MJ8-vTvwvDPK9^3RmEK?PSisqx?Kpg+U24}rBMT8zV)O*VFE;{lu7x-K3V`-OpPXV-;iFfH4!XvP2)<4iRlZ#)NOG)kZZH^zu2x(ICrd899 zG8>tOC+r|vuW3mvQ)dX|%vEAZy80AUWFp->YoPMnQAg@EvgY>Ud@xU;*4_@Mm3Y?b zjr9$9RdT|Tm)bwy4`&9N2EYW-dSpvXf~Y6TR6NIBIf_1z!O=`o+uxqHIXkV@BwZp5 zSvKvor1zcKzCeF$-&PsSKBYHv8m#9GlQk{jR}e{gHWd4Sa=6476gW=2vd%Tjz%bU= z1u?wFi~u7282xciem#LhC^d!_6XP3aE0iWVmxkeyMe!JHfVe2c#gytS`nXc*;6#yUQ?H^gcodA#ZQ*q zNsm8r-27(%x2!}6rkVknpDz3D^TPli@=E)$SbbJ^KY2a(ee8_z*y_cOoMB>RwZpCb zBF4kad7|-kZnh3=(i_pL&(t-@s?zhNsEohmOsIw3J(>mL@L&$!(|jqRZd)#hHbrV* j`QxqS|24sX3qoqkb)EbOY}KDt)Ez+e@NpNo($oJ1Nb^*} literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_refresh.png b/app/src/main/res/drawable-xxhdpi/ic_action_refresh.png deleted file mode 100644 index 44ee117ee91541ed71f27685dde0b03b51b89f7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1239 zcmV;|1StE7P) z5dr`J0000000000003wMK0iOlU?Cj&OWC$yA{_Z2)WC*+^3#HR9|H6uA>~fK3{<1{ zx9TJMcVE5FWjmGLALzB$>t!`#{^HAzC-VQuuTB6-#z?*lWgC?UZweA&FWb8$^H76) z!mN&nQ463fJ(caDWZAAk*8D0--5QX89Reugr;2!Apm6o7yyK}t@QoB;(@6m&@zm+L zXX5LERe&ULj9)N@8dqSwza)^=FVx@~0|uQDK$1_LS#ozOCiFa$|7_vXxk@E}=lGX$ zb9tSisuhN+*`}~Zd988O0$7lrt4w7tNjO<#STx9wn~EW?eIKm=4av_`_K`WdhrYUp zLE8jKT1Gxu{Fb+Mkv?Z6e-TR| zcH_A714GMutBO%J^{XIKHqUZ+Pi82)Wa2B=Cc9ad>)`Hx-zc06bN9JrtLsAQx;^H{e0&r zy5Iq3)}MiVUIBD7p2&PcdjM$mQwLna5j08F}_ENY*|b4D(*pbw1z z_Z=a7T`}HKqA_b@2$k5EUi_T?zSj zn$Hix1h^9DLeL2U@IqJZH;w{5aBE-d2#eWXcz~Y#k!}FCneBxDdguhOnrwss)z(i1 zm~Nrj9s=+oHTVuZfYJJO0_<#`_CbKlpoM0-IUwuvgph`ww|<&_elf^?tanc)9y;^2 zh#6E^R$o+ahWO`r8jf|QD)cN3zUpM5nU7tPZ^Hd_E>)g0ru_v=gUrX--eDhOfa}S+ z6C?SlFx%g-balESWzp8qF%rjSyd#J{w&Cwng{~| z2mtZ}3D5`m;YApM1poj50000000000fS~v#zyO={=$CR|bEp6S002ovPDHLkV1lVS BMRNcE diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_view_as_grid.png b/app/src/main/res/drawable-xxhdpi/ic_action_view_as_grid.png deleted file mode 100644 index bba7a0aecaeed34c6066bdb774ce0c72c738dafc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 310 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XZg{#lhE&{obL${)lY@Z6McKz!nYJ)UZ{U61z_iA#Y7ry% z1tuMa=MUzd_Un1Fx8+Ui8FbX&@pfDSprpiC{-zj6A|GTf__^CU^dhO?m<1N3xEMsK& zAhB!W@e8$yce1sASeo}2KAjT{WPGo#5WXjc(?FPu7=Gx>GqN$vD^Zeo7|m`C683cU Kb6Mw<&;$Ue9AhW| diff --git a/app/src/main/res/menu/game.xml b/app/src/main/res/menu/game.xml index be78225..29fc9e0 100644 --- a/app/src/main/res/menu/game.xml +++ b/app/src/main/res/menu/game.xml @@ -3,10 +3,10 @@ tools:context="de.stefanhoth.android.got2048.activities.GameActivity" > From 578e58b6614c2c26aec653b76987de460637c6d4 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 17:28:37 +0200 Subject: [PATCH 05/10] Add restart action --- .../android/got2048/logic/MCPTest.java | 2 +- .../android/got2048/GameEngineService.java | 22 +++++++++++++-- .../got2048/activities/GameActivity.java | 27 ++++++++++++++++++- .../fragments/NavigationDrawerFragment.java | 19 ++++++------- .../fragments/PlayingFieldFragment.java | 7 ++++- .../stefanhoth/android/got2048/logic/MCP.java | 10 ++++++- .../got2048/logic/model/MovementChanges.java | 11 ++++++++ app/src/main/res/menu/game.xml | 8 +++--- app/src/main/res/values/strings.xml | 3 +++ 9 files changed, 91 insertions(+), 18 deletions(-) diff --git a/app/src/androidTest/java/de/stefanhoth/android/got2048/logic/MCPTest.java b/app/src/androidTest/java/de/stefanhoth/android/got2048/logic/MCPTest.java index abcec14..7b27440 100644 --- a/app/src/androidTest/java/de/stefanhoth/android/got2048/logic/MCPTest.java +++ b/app/src/androidTest/java/de/stefanhoth/android/got2048/logic/MCPTest.java @@ -46,7 +46,7 @@ public void testSetup() throws Exception { public void testStartCellsAdded() throws Exception { - mcp.addStartCells(); + mcp.addStartCells(false); assertEquals("Active cells", MCP.DEFAULT_START_FIELDS, mcp.getPlaylingField().getActiveCells()); } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/GameEngineService.java b/app/src/main/java/de/stefanhoth/android/got2048/GameEngineService.java index 610f335..ba1e6f7 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/GameEngineService.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/GameEngineService.java @@ -18,6 +18,7 @@ public class GameEngineService extends IntentService { private static final String ACTION_MOVE = GameEngineService.class.getPackage() + ".action.MOVE"; private static final String ACTION_START_GAME = GameEngineService.class.getPackage() + ".action.START_GAME"; + private static final String ACTION_RESTART_GAME = GameEngineService.class.getPackage() + ".action.RESTART_GAME"; private static final String EXTRA_DIRECTION = GameEngineService.class.getPackage() + ".extra.PARAM1"; @@ -27,6 +28,12 @@ public static void startActionStartGame(Context context) { context.startService(intent); } + public static void startActionRestartGame(Context context) { + Intent intent = new Intent(context, GameEngineService.class); + intent.setAction(ACTION_RESTART_GAME); + context.startService(intent); + } + /** * Starts this service to perform action Foo with the given parameters. If * the service is already performing a task this action will be queued. @@ -50,6 +57,8 @@ protected void onHandleIntent(Intent intent) { final String action = intent.getAction(); if (ACTION_START_GAME.equals(action)) { handleActionStartGame(); + } else if (ACTION_RESTART_GAME.equals(action)) { + handleActionRestartGame(); } else if (ACTION_MOVE.equals(action)) { try { final MOVE_DIRECTION direction = MOVE_DIRECTION.values()[intent.getIntExtra(EXTRA_DIRECTION, 0)]; @@ -72,7 +81,17 @@ private void handleActionStartGame() { return; } - ((Got2048App) getApplication()).getMCP().addStartCells(); + ((Got2048App) getApplication()).getMCP().addStartCells(false); + } + + private void handleActionRestartGame() { + + if (getApplication() == null || !(getApplication() instanceof Got2048App)) { + Log.e(TAG, "handleActionMove: Could not access application object"); + return; + } + + ((Got2048App) getApplication()).getMCP().restartGame(); } /** @@ -91,5 +110,4 @@ private void handleActionMove(MOVE_DIRECTION direction) { ((Got2048App) getApplication()).getMCP().move(direction); } - } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java b/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java index 86eb873..2187912 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java @@ -2,7 +2,9 @@ import android.app.ActionBar; import android.app.Activity; +import android.app.AlertDialog; import android.app.FragmentManager; +import android.content.DialogInterface; import android.os.Bundle; import android.support.v4.widget.DrawerLayout; import android.util.Log; @@ -105,12 +107,35 @@ public boolean onOptionsItemSelected(MenuItem item) { // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); - if (id == R.id.action_settings) { + if (id == R.id.action_restart) { + handleRestart(); return true; } return super.onOptionsItemSelected(item); } + private void handleRestart() { + + new AlertDialog.Builder(this) + .setTitle(R.string.action_restart) + .setMessage(R.string.dialog_restart_question) + .setPositiveButton(R.string.dialog_restart_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + GameEngineService.startActionRestartGame(getBaseContext()); + } + }) + .setNegativeButton(R.string.dialog_restart_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .create() + .show(); + } + @Override public void onMovementRecognized(MOVE_DIRECTION direction) { diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java index 97513bf..78e7226 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java @@ -1,16 +1,16 @@ package de.stefanhoth.android.got2048.fragments; -import android.app.Activity; import android.app.ActionBar; +import android.app.Activity; import android.app.Fragment; -import android.support.v4.app.ActionBarDrawerToggle; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.ActionBarDrawerToggle; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -82,7 +82,7 @@ public void onCreate(Bundle savedInstanceState) { } @Override - public void onActivityCreated (Bundle savedInstanceState) { + public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Indicate that this fragment would like to influence the set of actions in the action bar. setHasOptionsMenu(true); @@ -90,7 +90,7 @@ public void onActivityCreated (Bundle savedInstanceState) { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { mDrawerListView = (ListView) inflater.inflate( R.layout.fragment_navigation_drawer, container, false); mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @@ -108,7 +108,8 @@ public void onItemClick(AdapterView parent, View view, int position, long id) getString(R.string.title_achievements), getString(R.string.title_about), getString(R.string.action_settings) - })); + } + )); mDrawerListView.setItemChecked(mCurrentSelectedPosition, true); return mDrawerListView; } @@ -250,10 +251,10 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } - if (item.getItemId() == R.id.action_refresh) { + if (item.getItemId() == R.id.action_restart) { Toast.makeText(getActivity(), "How refreshing!", Toast.LENGTH_SHORT).show(); return true; - }else if(item.getItemId() == R.id.action_random) { + } else if (item.getItemId() == R.id.action_random) { Toast.makeText(getActivity(), "How random!", Toast.LENGTH_SHORT).show(); return true; } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java index 6438b69..dd9142e 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java @@ -397,8 +397,13 @@ private void handleMoveDone(Intent intent) { mSquareGridView.updateGrid(changes.gridStatus); mSquareGridView.addCells(changes.getAddedCells(), changes.addedCellsValue); + + if (changes.isRestart()) { + mCurrentScore = 0; + } else { + mCurrentScore += changes.pointsEarned; + } //TODO animate new points - mCurrentScore += changes.pointsEarned; mTvCurrentScore.setText(String.valueOf(mCurrentScore)); } catch (Exception e) { diff --git a/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java b/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java index e60e879..5792ca2 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java @@ -52,7 +52,7 @@ protected Grid getPlaylingField() { return playlingField; } - public void addStartCells() { + public void addStartCells(boolean isRestart) { MovementChanges changes = new MovementChanges(getPlaylingField().getGridStatus()); @@ -73,6 +73,8 @@ public void addStartCells() { changes.addCell(cell, DEFAULT_START_VALUE); } + changes.setIsRestart(isRestart); + updateMoveDoneListeners(changes); } @@ -136,6 +138,11 @@ protected void move(MOVE_DIRECTION direction, boolean spawnNewCell) { mCurrentlyMoving = false; } + public void restartGame() { + playlingField.reset(); + addStartCells(true); + } + private void updateMoveStartListeners(MOVE_DIRECTION direction) { Bundle extras = new Bundle(); @@ -187,4 +194,5 @@ private void sendLocalBroadcast(String action, Bundle extras) { LocalBroadcastManager.getInstance(mContext).sendBroadcast(localIntent); } + } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/logic/model/MovementChanges.java b/app/src/main/java/de/stefanhoth/android/got2048/logic/model/MovementChanges.java index 36754e6..fe9f51a 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/logic/model/MovementChanges.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/logic/model/MovementChanges.java @@ -21,6 +21,7 @@ public class MovementChanges implements Parcelable { public int[][] gridStatus; private List addedCells; public int addedCellsValue; + private boolean isRestart; public MovementChanges(int[][] gridStatus) { cellsMoved = false; @@ -38,6 +39,7 @@ public int describeContents() { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByte(cellsMoved ? (byte) 1 : (byte) 0); + dest.writeByte(isRestart ? (byte) 1 : (byte) 0); dest.writeInt(this.pointsEarned); dest.writeSerializable(this.gridStatus); dest.writeInt(this.addedCellsValue); @@ -46,6 +48,7 @@ public void writeToParcel(Parcel dest, int flags) { private MovementChanges(Parcel in) { this.cellsMoved = in.readByte() != 0; + this.isRestart = in.readByte() != 0; this.pointsEarned = in.readInt(); this.gridStatus = (int[][]) in.readSerializable(); this.addedCellsValue = in.readInt(); @@ -71,4 +74,12 @@ public void addCell(Cell cell, int startValue) { public List getAddedCells() { return addedCells; } + + public void setIsRestart(boolean isRestart) { + this.isRestart = isRestart; + } + + public boolean isRestart() { + return isRestart; + } } diff --git a/app/src/main/res/menu/game.xml b/app/src/main/res/menu/game.xml index 29fc9e0..3ea5e4a 100644 --- a/app/src/main/res/menu/game.xml +++ b/app/src/main/res/menu/game.xml @@ -1,11 +1,13 @@ - + - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 19d98dc..c3e2901 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,5 +13,8 @@ Hello blank fragment Current Score Best Score + Are you sure you want to restart the game? You current progress will be lost. \n\nBut maybe that\'s for the better anyway… + Yes, restart now + No, keep my game From dda91dc3a644d2c0f3f63d2d7d3571b97e889647 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 17:59:25 +0200 Subject: [PATCH 06/10] Migrate action handling over to Fragment --- .../got2048/activities/GameActivity.java | 38 ------------------- .../fragments/PlayingFieldFragment.java | 36 ++++++++++++++++++ app/src/main/res/values/strings.xml | 5 +-- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java b/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java index 2187912..1e77aeb 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java @@ -2,14 +2,11 @@ import android.app.ActionBar; import android.app.Activity; -import android.app.AlertDialog; import android.app.FragmentManager; -import android.content.DialogInterface; import android.os.Bundle; import android.support.v4.widget.DrawerLayout; import android.util.Log; import android.view.Menu; -import android.view.MenuItem; import de.stefanhoth.android.got2048.GameEngineService; import de.stefanhoth.android.got2048.Got2048App; @@ -101,41 +98,6 @@ public boolean onCreateOptionsMenu(Menu menu) { return super.onCreateOptionsMenu(menu); } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - int id = item.getItemId(); - if (id == R.id.action_restart) { - handleRestart(); - return true; - } - return super.onOptionsItemSelected(item); - } - - private void handleRestart() { - - new AlertDialog.Builder(this) - .setTitle(R.string.action_restart) - .setMessage(R.string.dialog_restart_question) - .setPositiveButton(R.string.dialog_restart_yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - GameEngineService.startActionRestartGame(getBaseContext()); - } - }) - .setNegativeButton(R.string.dialog_restart_no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }) - .create() - .show(); - } - @Override public void onMovementRecognized(MOVE_DIRECTION direction) { diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java index dd9142e..7e31d1d 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java @@ -3,9 +3,11 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; +import android.app.AlertDialog; import android.app.Fragment; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; @@ -13,6 +15,7 @@ import android.util.Log; import android.view.GestureDetector; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -24,6 +27,7 @@ import butterknife.ButterKnife; import butterknife.InjectView; +import de.stefanhoth.android.got2048.GameEngineService; import de.stefanhoth.android.got2048.R; import de.stefanhoth.android.got2048.helpers.SettingsHelper; import de.stefanhoth.android.got2048.logic.MCP; @@ -250,6 +254,38 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + if (id == R.id.action_restart) { + handleRestart(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void handleRestart() { + + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.action_restart) + .setMessage(R.string.dialog_restart_question) + .setPositiveButton(R.string.dialog_restart_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + GameEngineService.startActionRestartGame(getActivity().getBaseContext()); + } + }) + .setNegativeButton(R.string.dialog_restart_no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .create() + .show(); + } + private void announceReady() { if (mReadyAnnounced) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c3e2901..e1f676e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,10 +7,9 @@ About Open navigation drawer Close navigation drawer - Random - Restart + Random move + Restart game Settings - Hello blank fragment Current Score Best Score Are you sure you want to restart the game? You current progress will be lost. \n\nBut maybe that\'s for the better anyway… From 872d0996ef9ad4fca9334e0d46ede01825eb19bb Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 18:14:13 +0200 Subject: [PATCH 07/10] Add action to do a random move (because you are too lazy to swipe) --- .../got2048/activities/GameActivity.java | 1 - .../fragments/NavigationDrawerFragment.java | 9 --------- .../fragments/PlayingFieldFragment.java | 20 +++++++++++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java b/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java index 1e77aeb..124e198 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/activities/GameActivity.java @@ -91,7 +91,6 @@ public boolean onCreateOptionsMenu(Menu menu) { // Only show items in the action bar relevant to this screen // if the drawer is not showing. Otherwise, let the drawer // decide what to show in the action bar. - getMenuInflater().inflate(R.menu.game, menu); restoreActionBar(); return true; } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java index 78e7226..543f2ca 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/NavigationDrawerFragment.java @@ -20,7 +20,6 @@ import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; -import android.widget.Toast; import de.stefanhoth.android.got2048.R; @@ -251,14 +250,6 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } - if (item.getItemId() == R.id.action_restart) { - Toast.makeText(getActivity(), "How refreshing!", Toast.LENGTH_SHORT).show(); - return true; - } else if (item.getItemId() == R.id.action_random) { - Toast.makeText(getActivity(), "How random!", Toast.LENGTH_SHORT).show(); - return true; - } - return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java index 7e31d1d..c29db45 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java @@ -15,6 +15,8 @@ import android.util.Log; import android.view.GestureDetector; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; @@ -25,6 +27,8 @@ import com.deploygate.sdk.DeployGate; +import java.util.Random; + import butterknife.ButterKnife; import butterknife.InjectView; import de.stefanhoth.android.got2048.GameEngineService; @@ -139,6 +143,8 @@ public boolean onTouch(View v, MotionEvent event) { mSquareGridView.setOnTouchListener(mGestureListener); + setHasOptionsMenu(true); + return view; } @@ -254,13 +260,27 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve } + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.game, menu); + + super.onCreateOptionsMenu(menu, inflater); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); + Log.d(TAG, "onOptionsItemSelected: id=" + id); + if (id == R.id.action_restart) { handleRestart(); return true; + } else if (id == R.id.action_random) { + Toast.makeText(getActivity().getBaseContext(), "Making a move…", Toast.LENGTH_SHORT).show(); + announceMovement(MOVE_DIRECTION.values()[new Random().nextInt(MOVE_DIRECTION.values().length)]); + return true; } + return super.onOptionsItemSelected(item); } From 8f0aa8994e9e431bbb1b2916a6f722722495eb25 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 18:20:07 +0200 Subject: [PATCH 08/10] Fix restart to really reset the system completely --- .../android/got2048/fragments/PlayingFieldFragment.java | 5 +++-- .../main/java/de/stefanhoth/android/got2048/logic/MCP.java | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java index c29db45..ca0b129 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java @@ -273,7 +273,7 @@ public boolean onOptionsItemSelected(MenuItem item) { Log.d(TAG, "onOptionsItemSelected: id=" + id); if (id == R.id.action_restart) { - handleRestart(); + handleRestartAction(); return true; } else if (id == R.id.action_random) { Toast.makeText(getActivity().getBaseContext(), "Making a move…", Toast.LENGTH_SHORT).show(); @@ -284,7 +284,7 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } - private void handleRestart() { + private void handleRestartAction() { new AlertDialog.Builder(getActivity()) .setTitle(R.string.action_restart) @@ -456,6 +456,7 @@ private void handleMoveDone(Intent intent) { if (changes.isRestart()) { mCurrentScore = 0; + mGameStatus.setText(""); } else { mCurrentScore += changes.pointsEarned; } diff --git a/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java b/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java index 5792ca2..3bfdd99 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/logic/MCP.java @@ -140,6 +140,8 @@ protected void move(MOVE_DIRECTION direction, boolean spawnNewCell) { public void restartGame() { playlingField.reset(); + this.mGameStopped = false; + addStartCells(true); } From dbd5ca15e569ecd148c5ff16d79ac883d19ab2a5 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 18:45:06 +0200 Subject: [PATCH 09/10] Make sure the movement hint is silenced after user proved he/she understood it --- .../fragments/PlayingFieldFragment.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java index ca0b129..96a27dd 100644 --- a/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java +++ b/app/src/main/java/de/stefanhoth/android/got2048/fragments/PlayingFieldFragment.java @@ -10,7 +10,9 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.GestureDetector; @@ -51,6 +53,7 @@ public class PlayingFieldFragment extends Fragment { private static final String KEY_HIGHSCORE = "KEY_HIGHSCORE"; private static final String TAG = PlayingFieldFragment.class.getName(); + private static final String PREF_USER_LEARNED_SWIPE = "PREF_USER_LEARNED_SWIPE"; private int mCurrentScore; private int mHighscore; @@ -72,6 +75,7 @@ public class PlayingFieldFragment extends Fragment { private View.OnTouchListener mGestureListener; private McpEventReceiver mMcpEventReceiver; private boolean mReadyAnnounced; + private boolean mUserLearnedSwipe; /** * Use this factory method to create a new instance of @@ -104,6 +108,11 @@ public void onCreate(Bundle savedInstanceState) { if (getArguments() != null) { mHighscore = getArguments().getInt(KEY_HIGHSCORE); } + + // Read in the flag indicating whether or not the user has demonstrated awareness of the + // drawer. See PREF_USER_LEARNED_SWIPE for details. + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); + mUserLearnedSwipe = sp.getBoolean(PREF_USER_LEARNED_SWIPE, false); } @Override @@ -240,7 +249,6 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve // return false; // } - String direction = ""; if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { //move up announceMovement(MOVE_DIRECTION.UP); @@ -255,6 +263,11 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve announceMovement(MOVE_DIRECTION.RIGHT); } + mUserLearnedSwipe = true; + SharedPreferences sp = PreferenceManager + .getDefaultSharedPreferences(getActivity()); + sp.edit().putBoolean(PREF_USER_LEARNED_SWIPE, mUserLearnedSwipe).apply(); + return true; } @@ -316,6 +329,16 @@ private void announceReady() { mPlayingFieldEventListener.onPlayingFieldReady(); } + mReadyAnnounced = true; + + teachSwipeMovement(); + } + + private void teachSwipeMovement() { + if (mUserLearnedSwipe) { + return; + } + float translateBy = 50f; int startDelay = 1000; int duration = 300; @@ -334,8 +357,6 @@ private void announceReady() { bouncer.setDuration(duration); bouncer.setInterpolator(new AccelerateDecelerateInterpolator()); bouncer.start(); - - mReadyAnnounced = true; } private void announceMovement(MOVE_DIRECTION direction) { From 505c02eaae25b6a1f94eef7dd57b01b2648662d7 Mon Sep 17 00:00:00 2001 From: Stefan Hoth Date: Fri, 4 Apr 2014 18:48:54 +0200 Subject: [PATCH 10/10] Bump version to 0.8 for release --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 88c599b..f463d49 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,8 +29,8 @@ android { defaultConfig { minSdkVersion 15 targetSdkVersion 19 - versionCode 10 - versionName "0.7" + versionCode 11 + versionName "0.8" } compileOptions {