├── .classpath
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── AndroidManifest.xml
├── ant.properties
├── assets
├── audio
│ ├── game
│ │ ├── complete.wav
│ │ ├── goal.wav
│ │ └── music.mp3
│ └── menu
│ │ └── selection.wav
├── font
│ ├── game
│ │ └── Default.ttf
│ └── menu
│ │ └── Default.ttf
├── image
│ ├── game
│ │ ├── LevelIconComplete.png
│ │ ├── LevelIconIncomplete.png
│ │ ├── LevelNext.png
│ │ ├── LevelPrevious.png
│ │ ├── MenuExit.png
│ │ ├── MenuPause.png
│ │ ├── MenuReset.png
│ │ ├── MenuSoundOff.png
│ │ ├── MenuSoundOn.png
│ │ ├── MenuUndoDisabled.png
│ │ ├── MenuUndoEnabled.png
│ │ └── Sprites.png
│ └── menu
│ │ ├── Background.jpg
│ │ ├── Button.png
│ │ ├── Facebook.png
│ │ ├── Instructions.png
│ │ ├── Logo.png
│ │ ├── MenuCancel.png
│ │ ├── MenuConfirm.png
│ │ ├── Splash.jpg
│ │ ├── Twitter.png
│ │ └── Youtube.png
├── solved
│ ├── aEasy.txt
│ ├── bEasy.txt
│ ├── cEasy.txt
│ ├── dEasy.txt
│ ├── lMedium.txt
│ ├── mMedium.txt
│ ├── nMedium.txt
│ ├── oMedium.txt
│ ├── sHard.txt
│ ├── tHard.txt
│ ├── uHard.txt
│ └── vHard.txt
└── text
│ ├── aEasy.txt
│ ├── bEasy.txt
│ ├── cEasy.txt
│ ├── dEasy.txt
│ ├── lMedium.txt
│ ├── mMedium.txt
│ ├── nMedium.txt
│ ├── oMedium.txt
│ ├── sHard.txt
│ ├── tHard.txt
│ ├── uHard.txt
│ └── vHard.txt
├── bin
├── AndroidManifest.xml
├── R.txt
├── Sokoban.apk
├── classes.dex
├── dexedLibs
│ ├── androidframework-f7e2f39978d06bc9456c9f44f2627b49.jar
│ └── annotations-ac272055c18327fea198dc88f4e60a33.jar
├── res
│ └── crunch
│ │ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ │ └── drawable-xxxhdpi
│ │ └── ic_launcher.png
└── resources.ap_
├── build.xml
├── local.properties
├── private
└── cache
│ └── retriever
│ └── catalog.xml
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── drawable-xxxhdpi
│ └── ic_launcher.png
├── drawable
│ └── splash.jpg
├── layout
│ ├── main.xml
│ └── splash.xml
└── values
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── gamesbykevin
└── sokoban
├── MainActivity.java
├── Splash.java
├── ai
└── AI.java
├── assets
└── Assets.java
├── game
├── Game.java
├── IGame.java
└── controller
│ ├── Controller.java
│ └── IController.java
├── level
├── ILevel.java
├── ILevels.java
├── Level.java
├── LevelHelper.java
├── LevelInfo.java
├── Levels.java
└── tile
│ ├── Block.java
│ ├── Floor.java
│ ├── Goal.java
│ ├── Tile.java
│ ├── TileHelper.java
│ └── Wall.java
├── panel
└── GamePanel.java
├── player
├── IPlayer.java
├── Player.java
└── PlayerHelper.java
├── screen
├── ExitScreen.java
├── GameScreen.java
├── GameoverScreen.java
├── MenuScreen.java
├── OptionsScreen.java
├── PauseScreen.java
└── ScreenManager.java
├── storage
├── scorecard
│ ├── Score.java
│ └── ScoreCard.java
└── settings
│ └── Settings.java
├── target
└── Target.java
└── thread
└── MainThread.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sokoban
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/assets/audio/game/complete.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/audio/game/complete.wav
--------------------------------------------------------------------------------
/assets/audio/game/goal.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/audio/game/goal.wav
--------------------------------------------------------------------------------
/assets/audio/game/music.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/audio/game/music.mp3
--------------------------------------------------------------------------------
/assets/audio/menu/selection.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/audio/menu/selection.wav
--------------------------------------------------------------------------------
/assets/font/game/Default.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/font/game/Default.ttf
--------------------------------------------------------------------------------
/assets/font/menu/Default.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/font/menu/Default.ttf
--------------------------------------------------------------------------------
/assets/image/game/LevelIconComplete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/LevelIconComplete.png
--------------------------------------------------------------------------------
/assets/image/game/LevelIconIncomplete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/LevelIconIncomplete.png
--------------------------------------------------------------------------------
/assets/image/game/LevelNext.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/LevelNext.png
--------------------------------------------------------------------------------
/assets/image/game/LevelPrevious.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/LevelPrevious.png
--------------------------------------------------------------------------------
/assets/image/game/MenuExit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuExit.png
--------------------------------------------------------------------------------
/assets/image/game/MenuPause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuPause.png
--------------------------------------------------------------------------------
/assets/image/game/MenuReset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuReset.png
--------------------------------------------------------------------------------
/assets/image/game/MenuSoundOff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuSoundOff.png
--------------------------------------------------------------------------------
/assets/image/game/MenuSoundOn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuSoundOn.png
--------------------------------------------------------------------------------
/assets/image/game/MenuUndoDisabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuUndoDisabled.png
--------------------------------------------------------------------------------
/assets/image/game/MenuUndoEnabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/MenuUndoEnabled.png
--------------------------------------------------------------------------------
/assets/image/game/Sprites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/game/Sprites.png
--------------------------------------------------------------------------------
/assets/image/menu/Background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Background.jpg
--------------------------------------------------------------------------------
/assets/image/menu/Button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Button.png
--------------------------------------------------------------------------------
/assets/image/menu/Facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Facebook.png
--------------------------------------------------------------------------------
/assets/image/menu/Instructions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Instructions.png
--------------------------------------------------------------------------------
/assets/image/menu/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Logo.png
--------------------------------------------------------------------------------
/assets/image/menu/MenuCancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/MenuCancel.png
--------------------------------------------------------------------------------
/assets/image/menu/MenuConfirm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/MenuConfirm.png
--------------------------------------------------------------------------------
/assets/image/menu/Splash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Splash.jpg
--------------------------------------------------------------------------------
/assets/image/menu/Twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Twitter.png
--------------------------------------------------------------------------------
/assets/image/menu/Youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/assets/image/menu/Youtube.png
--------------------------------------------------------------------------------
/assets/text/cEasy.txt:
--------------------------------------------------------------------------------
1 | ####
2 | ## #
3 | ## #
4 | # $* #
5 | # * #
6 | # #* #
7 | # . #
8 | ## @ #
9 | #####
10 | ; 35
11 |
12 | #####
13 | ### ##
14 | # $ ##
15 | # $#* #
16 | # * @#
17 | # #* ##
18 | ####. ##
19 | #.##
20 | ###
21 | ; 6
22 |
23 | ####
24 | ## #
25 | # @ #
26 | # $ #
27 | # * #
28 | # * ##
29 | ##. #
30 | # # #
31 | # #
32 | #####
33 | ; 7
34 |
35 | ####
36 | ### #
37 | # .$ #
38 | # .* #
39 | ##*# #
40 | # #
41 | # $ #
42 | # # #
43 | # @ #
44 | #####
45 | ; 9
46 |
47 | #######
48 | # . #
49 | # $+$ #
50 | # * ##
51 | ## * ##
52 | ## * #
53 | # $.$ #
54 | # . #
55 | #######
56 | ; 12
57 |
58 | ########
59 | # # #
60 | # # #$.#
61 | # $.#
62 | # # #$.#
63 | # # #
64 | #####@ #
65 | ####
66 | ; 1
67 |
68 | ####
69 | # #####
70 | ### .# #
71 | #@ $ #
72 | # ##*#####
73 | # $ #
74 | ### . #
75 | # ###
76 | ####
77 | ; 2
78 |
79 | #####
80 | # + #
81 | #$.$#
82 | ## * #
83 | # * ##
84 | # * #
85 | # * #
86 | ### ##
87 | ####
88 | ; 4
89 |
90 | #######
91 | # #
92 | #.****##
93 | # #
94 | #### #
95 | #$$.#
96 | #@ ##
97 | ####
98 | ; 5
99 |
100 | ####
101 | ## #####
102 | # $$ #
103 | #@$ . ##
104 | ####.#.##
105 | # $ . #
106 | # ##
107 | #######
108 | ; 13
109 |
110 | #######
111 | # . #
112 | # # # #
113 | # $@$ #
114 | # # #.#
115 | # * #
116 | #######
117 | ; 11
118 |
119 | ####
120 | # @##
121 | # .*##
122 | # * #
123 | # $ #
124 | ## ##
125 | ####
126 | ; 14
127 |
128 | ######
129 | # #
130 | # ## ###
131 | # $ #
132 | #$.$ $ #
133 | #+.##$##
134 | #.. #
135 | #######
136 | ; 14
137 |
138 | ########
139 | # ##
140 | #.$### #
141 | #. * . #
142 | # # ##
143 | #*$*#*$#
144 | # @ #
145 | ########
146 | ; 20
147 |
148 | ####
149 | ## ##
150 | # $ ##
151 | # #* #
152 | # * #
153 | # * #
154 | # #* ##
155 | #@ . #
156 | ### #
157 | ####
158 | ; 38
159 |
160 | #####
161 | ## @ #
162 | # # #
163 | #$## #
164 | # # #
165 | ## .$ #
166 | # ** #
167 | # *##
168 | # #.#
169 | ######
170 | ; 44
171 |
172 | ###########
173 | #..# @#
174 | #..# $ $ ##
175 | # $ ##
176 | # # $ ##
177 | # # ##
178 | # ##
179 | ######
180 | ; soko2
181 |
182 | #####
183 | ##### .#
184 | # $ #
185 | # # # # #
186 | # $ #
187 | #####. @#
188 | #####
189 | ; soko47
190 |
191 | ########
192 | ## #
193 | ### $ # #
194 | ### # $ #
195 | #.. $ #$ #
196 | #+. # #
197 | #### ######
198 | # ##
199 | #####
200 | ; soko44
201 |
202 | #######
203 | #. .#
204 | # $$# #
205 | # $ #@#
206 | ##$ # #
207 | #. . #
208 | #######
209 | ; soko1
210 |
211 | #######
212 | ### @ ###
213 | # $ ##$ #
214 | # $.## .$ #
215 | # $ . $ #
216 | ###. . .###
217 | #######
218 | ; soko2
219 |
220 | #########
221 | ## # ##
222 | # $ $ #
223 | # $ #.## #
224 | # ##$# @#
225 | ## ... ##
226 | #########
227 | ; soko3
228 |
229 | ####
230 | # ########
231 | #$ # #
232 | ## ## #
233 | # .$#@# #
234 | #.$ ########
235 | # .##
236 | ####
237 | ; soko6
238 |
239 | #####
240 | #. .#
241 | # . #
242 | #### #
243 | # $ #
244 | ## $#$##
245 | #@ #
246 | ########
247 | ; soko28
248 |
249 |
250 | ####
251 | # #
252 | # #####
253 | # $ $ #
254 | ##$ $ $ #
255 | #. # #
256 | #.$.##.##
257 | ##.@.###
258 | #####
259 | ; soko4
260 |
261 | #####
262 | ## #
263 | ### $ #
264 | ## $ #
265 | ### $ ##
266 | #..$ ##
267 | #+. ###
268 | ######
269 | ; soko24
270 |
271 |
272 | ####
273 | ### #
274 | # .$ #
275 | # $ #
276 | #** @#
277 | # * ##
278 | # #.#
279 | # #
280 | #####
281 | ; 24
282 |
283 | ###
284 | #@######
285 | # #
286 | # ###$ #
287 | # # $ #
288 | # . $ #
289 | #.# ###
290 | # . #
291 | ######
292 | ; soko15
293 |
294 | ######
295 | # ##
296 | # #
297 | ##$# ##
298 | # $ #
299 | # ##. #
300 | # #. #
301 | # ##
302 | ##@###
303 | ###
304 | ; soko23
305 |
306 |
307 | ###
308 | ####@#
309 | #. ##
310 | #. * #
311 | #. #$ #
312 | ##$# #
313 | # $ ##
314 | # #
315 | #####
316 | ; soko16
317 |
318 |
319 | ######
320 | # ##
321 | ###$## #
322 | #. $ #
323 | #. ## #
324 | #+ ## #
325 | ## $ #
326 | # ##
327 | #######
328 | ; soko9
329 |
330 | #######
331 | # # #
332 | #+ * #
333 | ## # #
334 | # #
335 | # $####
336 | # #
337 | ####
338 | ; soko17
339 |
340 | ####
341 | # ###
342 | # # #
343 | # .*.#
344 | ##$####
345 | # $ ##
346 | # @#
347 | #######
348 | ; soko30
349 |
350 | ######
351 | ### #
352 | ## $@#
353 | #. $ ##
354 | #.$ ##
355 | #. ##
356 | ####
357 | ; soko32
358 |
359 | ########
360 | #..# ##
361 | # . $ #
362 | # #$ $ #
363 | # # $ #
364 | #. $ $ #
365 | #+.# ##
366 | ########
367 | ; soko18
368 |
369 | #######
370 | # #
371 | # $## #
372 | # $ #
373 | ## #$ #
374 | # # #
375 | # .####
376 | #.$.#
377 | # . #
378 | ## @#
379 | ####
380 | ; soko46
381 |
382 | ######
383 | # #
384 | # ###
385 | # # .#
386 | # ## @#
387 | # # .#
388 | # $ $##
389 | # #
390 | ######
391 | ; soko47
392 |
393 | ####
394 | ### #
395 | # $$ #
396 | # . #
397 | ## .##
398 | #* #
399 | #@##
400 | ###
401 | ; 233424
402 |
403 | ####
404 | #..##
405 | # $.####
406 | # $. $ #
407 | # $. $@#
408 | # #####
409 | ####
410 | ; 21291812
411 |
412 | ######
413 | # #
414 | # ## #
415 | # $@$#
416 | # .$ ##
417 | # .. #
418 | # .$ #
419 | # ####
420 | ####
421 | ; wed2233
422 |
423 | ####
424 | ## #
425 | ## #
426 | # $$ #
427 | # .##
428 | ##$.#
429 | #.@#
430 | ####
431 | ; 3232323
432 |
433 | ####
434 | #..#
435 | #..###
436 | #*. #
437 | #+.$ #
438 | ## # #
439 | # $ #
440 | # $ #
441 | ### $#
442 | # $ ##
443 | # $ $ #
444 | # #
445 | #######
446 | ; test
447 |
448 | #######
449 | ## #
450 | # $ ##
451 | #. # .#
452 | # $###$ #
453 | #. # .#
454 | # $ ##
455 | ## @ #
456 | #######
457 | ; soko48
458 |
459 | ####
460 | ## ##
461 | # #. #
462 | # $$ #
463 | # $+ #
464 | # .$.#
465 | # .*.#
466 | # $. #
467 | # $# #
468 | # $ #
469 | ## ##
470 | ####
471 | ; dsdscdd
472 |
473 | ####
474 | ## #
475 | ## $ #
476 | #.$ @#
477 | #$. ##
478 | #. ##
479 | ####
480 | ; soko49
481 |
482 | ###
483 | ##@##
484 | # $ ##
485 | # $ ###
486 | ## $.##
487 | ## $.#
488 | ## ..#
489 | #####
490 | ; soko50
491 |
492 | #####
493 | ###### #
494 | ##### $ @#
495 | #### $ ##
496 | ### $ ##
497 | #. $ ##
498 | #.$ ##
499 | #. ##
500 | #..##
501 | ####
502 | ; soko14
503 |
504 |
505 | ########
506 | # #
507 | # $## ###
508 | # ## $ ##
509 | #@ .#$ $ #
510 | ###. #
511 | #..######
512 | ####
513 | ; soko1
514 |
515 | ######
516 | ## . #
517 | # .#.#
518 | #@ . #
519 | ## ## #
520 | # $ #
521 | # $ #
522 | # #$ #
523 | # $ ##
524 | # #
525 | ######
526 | ; 25
527 |
528 | ###
529 | #.#
530 | #.###
531 | ##.$ ##
532 | # .$ #
533 | # .$ #
534 | ## $$ #
535 | ###@ #
536 | ####
537 | ; 234
538 |
539 | ####
540 | # #
541 | # $#
542 | # #
543 | ## $#
544 | # #
545 | # # ##
546 | # $.##
547 | ## *. #
548 | # #. #
549 | # ## #
550 | # ## #
551 | # @ #
552 | ######
553 | ; 15
554 |
555 | #####
556 | ## ##
557 | # @#
558 | #$#####
559 | # ...#
560 | # $ $ #
561 | #...$ #
562 | #### ##
563 | # #
564 | # $$ #
565 | ## ##
566 | #####
567 | ; 3
568 |
569 | ######
570 | # #
571 | # ## #
572 | # $ #
573 | # . #
574 | ## * ##
575 | # * #
576 | # *@ #
577 | # ## #
578 | # #
579 | ######
580 | ; 11
581 |
582 | #######
583 | # #
584 | #$$ $ #
585 | # $ #.#
586 | # #.#.#
587 | #.#+#.#
588 | #.#.# #
589 | # # $ #
590 | # $$$ #
591 | # #
592 | #######
593 | ; 2
594 |
595 | ######
596 | ## #
597 | # ## ##
598 | # #.. #
599 | # . @#
600 | # $## ##
601 | ## # #
602 | ## $ ##
603 | # $##
604 | # #
605 | # #
606 | # ##
607 | ####
608 | ; 1
609 |
610 | #########
611 | ####.####
612 | # * * #
613 | # ... #
614 | ###.#.###
615 | # .#. #
616 | # # #
617 | # $###$ #
618 | # $ #
619 | # $#$ #
620 | # $ $ $ #
621 | ## @ ##
622 | #########
623 | ; sdsds
624 |
625 | #######
626 | #.. *+#
627 | # $$$$#
628 | #.* * #
629 | # $ $ #
630 | # . .#
631 | #######
632 | ; Pegasus
633 |
634 | #######
635 | #+* ..#
636 | #$$$$ #
637 | # *.$.#
638 | # $ $ #
639 | #. . #
640 | #######
641 | ; Dorado
642 |
643 | #######
644 | #+* ..#
645 | #$$$$ #
646 | # $.$.#
647 | # $.$ #
648 | #. . #
649 | #######
650 | ; Cygnus
651 |
652 | #######
653 | ##. *+#
654 | # $$$$#
655 | #..$. #
656 | # $ #
657 | # $. .#
658 | #######
659 | ; Draco
660 |
661 | #######
662 | #.* ..#
663 | #.* # #
664 | # $ #
665 | #$$ $$#
666 | #+$. #
667 | #######
668 | ; Hydra
669 |
670 | ########
671 | ##.$.$@#
672 | # * .$$#
673 | # .$* #
674 | # # .$ #
675 | #..$ $.#
676 | # $ . #
677 | ########
678 | ; Phoenix
679 |
680 | ########
681 | #. ##
682 | #$## *##
683 | # $ $@#
684 | #.. .*.#
685 | # $*$ #
686 | # . $ #
687 | ########
688 | ; Cepheus
689 |
690 | ########
691 | #.$ . #
692 | # ## # #
693 | # $ $#
694 | #.. *..#
695 | #$$*$ #
696 | #@* #
697 | ########
698 | ; Chamaeleon
699 |
700 | ########
701 | # # . #
702 | # $. $#
703 | #. $#$.#
704 | ## . . #
705 | # .$$$ #
706 | # .$@##
707 | ########
708 | ; Carina
709 |
710 | #########
711 | #.*.* #
712 | #+$.. *#
713 | #.#.##$ #
714 | # $ $ #
715 | ##$##$ #
716 | ## $ #
717 | ### #
718 | #########
719 | ; Omicron
720 |
721 | ##########
722 | # $.#....#
723 | # ##*.###
724 | # $...* .#
725 | ## $# #
726 | # $@###$ #
727 | #$ # $ #
728 | # $ $$ $#
729 | #. #
730 | ##########
731 | ; Cancer
732 |
733 | ###########
734 | ###.. # #
735 | ## ... #
736 | # $#. #
737 | # # #
738 | # $ # #
739 | #@$ ## #
740 | # $$ ### #
741 | ## $ #
742 | ## # #
743 | ###########
744 | ; Piscis
745 |
746 | ########
747 | ## . ###
748 | ## * ###
749 | ##$. ###
750 | ## * ###
751 | ## . ###
752 | ##$* ###
753 | ## .$###
754 | ## $ ###
755 | ##$. ###
756 | ##. $ #
757 | # **..#
758 | # $$ #
759 | ##@ ####
760 | ########
761 | ; Crater
762 |
763 | ##############
764 | ###.##########
765 | ## * #########
766 | ## .$ $ $ #
767 | #@$.$.**.*.*.#
768 | # $ $ #
769 | ## ##########
770 | ##############
771 | ; Orion
772 |
773 | #########
774 | ###. $ #
775 | ## .$##@#
776 | ##$. ####
777 | ## * ####
778 | ## * ####
779 | ## * ####
780 | ##.*.####
781 | ## * ####
782 | ##.$ ####
783 | ## * ##
784 | # *.$ ##
785 | # $ $ ##
786 | ## ###
787 | #########
788 | ; Pisces
789 |
790 | #########
791 | ##@. ####
792 | ##$.$####
793 | ## * ####
794 | ## * ####
795 | ## * ####
796 | ## * ####
797 | ## * ####
798 | ## * ####
799 | ## *$ .#
800 | # * .###
801 | # $ ###
802 | ## #####
803 | #########
804 | ; Scorpius
805 |
806 |
807 | ###############
808 | ## . ##########
809 | ## .$ . #
810 | # $* **.$**.*.#
811 | # $ $ $ #
812 | ## @###########
813 | ###############
814 | ; Lepus
815 |
816 | ###########
817 | ###....####
818 | #####.. ###
819 | ### $###
820 | ### # $ #
821 | # . #$$ #
822 | # #@# #
823 | ### # $$ #
824 | ### $ #
825 | ### #
826 | ###########
827 | ;
828 |
829 | #########
830 | # #
831 | # $..$# #
832 | # #.$.$ #
833 | # $..$@ #
834 | # #.$.$ #
835 | # $..$# #
836 | # #
837 | #########
838 | ; sdsds
839 |
840 | #########
841 | # #
842 | # ..* #
843 | # * $ #
844 | # $.$ #
845 | # $+$ #
846 | # * $ #
847 | # ..* #
848 | # #
849 | #########
850 | ; sdsds
851 |
852 | #########
853 | # #
854 | # $..$$ #
855 | # #.$. #
856 | # $.#+$ #
857 | # #.$. #
858 | # $..$$ #
859 | # #
860 | #########
861 | ; sdsds
862 |
863 | #############
864 | # #
865 | # ... ... #
866 | # *$$ $.$ #
867 | # $*+$ $*$$ #
868 | # *$$ $.$ #
869 | # ... . #
870 | # #
871 | #############
872 | ; sdsds
873 |
874 | ##########
875 | # #
876 | # $.$$.$ #
877 | # .* . #
878 | # @. *. #
879 | # $.$$.$ #
880 | # #
881 | ##########
882 | ; sdsds
883 |
884 | #########
885 | # #
886 | # $.*.$ #
887 | # .$.$ #
888 | # #.*@# #
889 | # $.$. #
890 | # $.$.$ #
891 | # #
892 | #########
893 | ; sdsds
894 |
895 | ########
896 | # #
897 | # $..$ #
898 | # . . #
899 | # $+$$ #
900 | # $$.$ #
901 | # . . #
902 | # $..$ #
903 | # #
904 | ########
905 | ; sdsds
906 |
907 | #########
908 | # #
909 | # .*.*. #
910 | # .$.$. #
911 | # $.$ #
912 | # $$.$$ #
913 | # @ #
914 | #########
915 | ; sdsds
916 |
917 | #########
918 | # #
919 | # .$$$. #
920 | # .$. #
921 | # .$@$. #
922 | # $...$ #
923 | # $.$ #
924 | # #
925 | #########
926 | ; sdsds
927 |
--------------------------------------------------------------------------------
/bin/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/bin/R.txt:
--------------------------------------------------------------------------------
1 | int drawable ic_launcher 0x7f020000
2 | int drawable splash 0x7f020001
3 | int layout main 0x7f030000
4 | int layout splash 0x7f030001
5 | int string app_name 0x7f040000
6 | int style AppBaseTheme 0x7f050000
7 | int style AppTheme 0x7f050001
8 |
--------------------------------------------------------------------------------
/bin/Sokoban.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/Sokoban.apk
--------------------------------------------------------------------------------
/bin/classes.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/classes.dex
--------------------------------------------------------------------------------
/bin/dexedLibs/androidframework-f7e2f39978d06bc9456c9f44f2627b49.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/dexedLibs/androidframework-f7e2f39978d06bc9456c9f44f2627b49.jar
--------------------------------------------------------------------------------
/bin/dexedLibs/annotations-ac272055c18327fea198dc88f4e60a33.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/dexedLibs/annotations-ac272055c18327fea198dc88f4e60a33.jar
--------------------------------------------------------------------------------
/bin/res/crunch/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/res/crunch/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/bin/res/crunch/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/res/crunch/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/bin/res/crunch/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/res/crunch/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/bin/res/crunch/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/res/crunch/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/bin/res/crunch/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/res/crunch/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/bin/res/crunch/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/res/crunch/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/bin/resources.ap_:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/bin/resources.ap_
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 |
7 | # location of the SDK. This is only used by Ant
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | sdk.dir=C:\\Users\\GOD\\AppData\\Local\\Android\\android-sdk
11 |
--------------------------------------------------------------------------------
/private/cache/retriever/catalog.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/private/cache/retriever/catalog.xml
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-15
15 | android.library.reference.1=../AndroidFramework
16 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable/splash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamesbykevin/Sokoban-Android/6e963d0b7cf23776b01206f98f816bb14313ffc2/res/drawable/splash.jpg
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/res/layout/splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sokoban
4 |
5 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Bundle;
7 | import android.view.Window;
8 | import android.view.WindowManager;
9 |
10 | import com.gamesbykevin.sokoban.panel.GamePanel;
11 |
12 | public class MainActivity extends Activity
13 | {
14 | //our game panel
15 | private GamePanel panel;
16 |
17 | /**
18 | * Our web site address where more games can be found
19 | */
20 | public static final String WEBPAGE_MORE_GAMES_URL = "http://gamesbykevin.com";
21 |
22 | /**
23 | * The web address where this game can be rated
24 | */
25 | public static final String WEBPAGE_RATE_URL = "https://play.google.com/store/apps/details?id=com.gamesbykevin.sokoban";
26 |
27 | /**
28 | * The url that contains the instructions for the game
29 | */
30 | public static final String WEBPAGE_GAME_INSTRUCTIONS_URL = "http://gamesbykevin.com/2015/10/13/sokoban-2/";
31 |
32 | /**
33 | * The face book url
34 | */
35 | public static final String WEBPAGE_FACEBOOK_URL = "https://facebook.com/gamesbykevin";
36 |
37 | /**
38 | * The twitter url
39 | */
40 | public static final String WEBPAGE_TWITTER_URL = "https://twitter.com/gamesbykevin";
41 |
42 | /**
43 | * The youtube url
44 | */
45 | public static final String WEBPAGE_YOUTUBE_URL = "https://youtube.com/gamesbykevin";
46 |
47 | /**
48 | * Called when the activity is first created
49 | * @param savedInstanceState
50 | */
51 | @Override
52 | public void onCreate(Bundle savedInstanceState)
53 | {
54 | //turn the title off
55 | super.requestWindowFeature(Window.FEATURE_NO_TITLE);
56 |
57 | //set the screen to full screen
58 | super.getWindow().setFlags(
59 | WindowManager.LayoutParams.FLAG_FULLSCREEN,
60 | WindowManager.LayoutParams.FLAG_FULLSCREEN
61 | );
62 |
63 | //call parent create
64 | super.onCreate(savedInstanceState);
65 |
66 | //if the panel has not been created
67 | if (getGamePanel() == null)
68 | {
69 | //create the game panel
70 | setGamePanel(new GamePanel(this));
71 |
72 | //add callback to the game panel to intercept events
73 | getGamePanel().getHolder().addCallback(getGamePanel());
74 | }
75 |
76 | //set the content view to our game
77 | setContentView(getGamePanel());
78 | }
79 |
80 | /**
81 | * Override the finish call
82 | */
83 | @Override
84 | public void finish()
85 | {
86 | //cleanup game panel if it exists
87 | if (getGamePanel() != null)
88 | {
89 | getGamePanel().dispose();
90 | setGamePanel(null);
91 | }
92 |
93 | //call parent
94 | super.finish();
95 | }
96 |
97 | /**
98 | * Part of the activity life cycle
99 | */
100 | @Override
101 | public void onStart()
102 | {
103 | //call parent
104 | super.onStart();
105 | }
106 |
107 | /**
108 | * Part of the activity life cycle
109 | */
110 | @Override
111 | public void onStop()
112 | {
113 | //call parent
114 | super.onStop();
115 | }
116 |
117 | /**
118 | * Part of the activity life cycle
119 | */
120 | @Override
121 | public void onDestroy()
122 | {
123 | //finish the activity
124 | this.finish();
125 |
126 | //perform final cleanup
127 | super.onDestroy();
128 | }
129 |
130 | /**
131 | * Part of the activity life cycle
132 | */
133 | @Override
134 | public void onPause()
135 | {
136 | super.onPause();
137 | }
138 |
139 | /**
140 | * Navigate to the desired web page
141 | * @param url The desired url
142 | */
143 | public void openWebpage(final String url)
144 | {
145 | //create action view intent
146 | Intent intent = new Intent(Intent.ACTION_VIEW);
147 |
148 | //the content will be the web page
149 | intent.setData(Uri.parse(url));
150 |
151 | //start this new activity
152 | startActivity(intent);
153 | }
154 |
155 | /**
156 | * Get the game panel.
157 | * @return The object containing our game logic, assets, threads, etc...
158 | */
159 | private GamePanel getGamePanel()
160 | {
161 | return this.panel;
162 | }
163 |
164 | /**
165 | * Assign the game panel
166 | * @param panel The game panel
167 | */
168 | private void setGamePanel(final GamePanel panel)
169 | {
170 | this.panel = panel;
171 | }
172 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/Splash.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban;
2 |
3 | import com.gamesbykevin.sokoban.assets.Assets;
4 |
5 | import android.app.Activity;
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 | import android.os.Handler;
9 | import android.view.Window;
10 | import android.view.WindowManager;
11 |
12 | /**
13 | * Splash loading screen
14 | * @author GOD
15 | */
16 | public class Splash extends Activity
17 | {
18 | /**
19 | * Time delay to show the splash screen
20 | */
21 | private static final long TIME_DELAY = 1000L;
22 |
23 | /**
24 | * Called when the activity is first created
25 | * @param savedInstanceState
26 | */
27 | @Override
28 | public void onCreate(Bundle savedInstanceState)
29 | {
30 | //turn the title off
31 | super.requestWindowFeature(Window.FEATURE_NO_TITLE);
32 |
33 | //set the screen to full screen
34 | super.getWindow().setFlags(
35 | WindowManager.LayoutParams.FLAG_FULLSCREEN,
36 | WindowManager.LayoutParams.FLAG_FULLSCREEN
37 | );
38 |
39 | //call parent create
40 | super.onCreate(savedInstanceState);
41 |
42 | //set our content view to show the image
43 | super.setContentView(R.layout.splash);
44 |
45 | try
46 | {
47 | //load the game assets
48 | Assets.load(this);
49 | }
50 | catch (Exception e)
51 | {
52 | e.printStackTrace();
53 | }
54 | }
55 |
56 | /**
57 | * Override the finish call
58 | */
59 | @Override
60 | public void finish()
61 | {
62 | super.finish();
63 | }
64 |
65 | /**
66 | * Part of the activity life cycle
67 | */
68 | @Override
69 | public void onStart()
70 | {
71 | //call parent functionality
72 | super.onStart();
73 |
74 | //add a delay to show the splash image before starting main activity
75 | new Handler().postDelayed(new Runnable() {
76 |
77 | /**
78 | * Run will be executed once the time delay is over
79 | */
80 | @Override
81 | public void run() {
82 |
83 | //start our main activity
84 | startActivity(new Intent(Splash.this, MainActivity.class));
85 |
86 | //close this activity
87 | finish();
88 | }
89 | }, TIME_DELAY);
90 | }
91 |
92 | /**
93 | * Part of the activity life cycle
94 | */
95 | @Override
96 | public void onStop()
97 | {
98 | super.onStop();
99 | }
100 |
101 | /**
102 | * Part of the activity life cycle
103 | */
104 | @Override
105 | public void onDestroy()
106 | {
107 | //perform final cleanup
108 | super.onDestroy();
109 | }
110 |
111 | /**
112 | * Part of the activity life cycle
113 | */
114 | @Override
115 | public void onPause()
116 | {
117 | super.onPause();
118 | }
119 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/ai/AI.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.ai;
2 |
3 | import java.util.List;
4 |
5 | import com.gamesbykevin.androidframework.resources.Files;
6 | import com.gamesbykevin.sokoban.assets.Assets;
7 | import com.gamesbykevin.sokoban.level.Level;
8 | import com.gamesbykevin.sokoban.player.Player;
9 | import com.gamesbykevin.sokoban.player.PlayerHelper;
10 | import com.gamesbykevin.sokoban.thread.MainThread;
11 |
12 | /**
13 | * What he ai class will do is analyze a text file and move the player according to those instructions
14 | */
15 | public class AI
16 | {
17 | //list of instructions to follow
18 | private String instructions = "";
19 |
20 | //the position of the instructions String
21 | private int index = 0;
22 |
23 | /**
24 | * The string representing the instruction to move left
25 | */
26 | private static final String LEFT = "L";
27 |
28 | /**
29 | * The string representing the instruction to move right
30 | */
31 | private static final String RIGHT = "R";
32 |
33 | /**
34 | * The string representing the instruction to move down
35 | */
36 | private static final String DOWN = "D";
37 |
38 | /**
39 | * The string representing the instruction to move up
40 | */
41 | private static final String UP = "U";
42 |
43 | //the list of solutions for each level
44 | private List levels;
45 |
46 | /**
47 | * Create the ai to solve the level
48 | */
49 | public AI()
50 | {
51 | //set our list of levels
52 | this.setLevels(Assets.TextAiInstructionsKey.SOLVED_EASY_A);
53 |
54 | //start at the beginning
55 | this.reset(0);
56 | }
57 |
58 | /**
59 | * Assign the levels we want to solve
60 | * @param key The unique identifier of the list of levels we want to solve
61 | */
62 | public final void setLevels(Assets.TextAiInstructionsKey key)
63 | {
64 | //get all the lines in the text file
65 | this.levels = Files.getText(key).getLines();
66 | }
67 |
68 | /**
69 | * Reset the ai for the specified level
70 | * @param levelIndex The desired level to solve
71 | */
72 | public final void reset(final int levelIndex)
73 | {
74 | //set the text position back at 0
75 | this.index = 0;
76 |
77 | //get the data for this level
78 | String[] data = this.levels.get(levelIndex).split(" ");
79 |
80 | //the instructions are always the last piece of data
81 | this.instructions = data[data.length - 1].trim();
82 |
83 | if (MainThread.DEBUG)
84 | System.out.println("Index=" + index + ",Steps=" + instructions);
85 | }
86 |
87 | public void update(final Player player, final Level level)
88 | {
89 | //stay inbounds
90 | if (index >= instructions.length())
91 | return;
92 |
93 | //make sure we have not yet selected the player
94 | if (!player.isSelected())
95 | {
96 | //make sure the player is at the current target as well
97 | if (player.hasTarget())
98 | {
99 | //make sure blocks aren't moving
100 | if (!level.hasDestination())
101 | return;
102 |
103 | //flag selected true
104 | player.setSelected(true);
105 |
106 | //determine which direction we are moving
107 | if (instructions.substring(index, index + 1).equalsIgnoreCase(DOWN))
108 | {
109 | player.setTarget(player.getCol(), player.getRow() + 1);
110 | }
111 | else if (instructions.substring(index, index + 1).equalsIgnoreCase(UP))
112 | {
113 | player.setTarget(player.getCol(), player.getRow() - 1);
114 | }
115 | else if (instructions.substring(index, index + 1).equalsIgnoreCase(LEFT))
116 | {
117 | player.setTarget(player.getCol() - 1, player.getRow());
118 | }
119 | else if (instructions.substring(index, index + 1).equalsIgnoreCase(RIGHT))
120 | {
121 | player.setTarget(player.getCol() + 1, player.getRow());
122 | }
123 |
124 | //calculate the targets
125 | PlayerHelper.calculateTargets(player, level);
126 |
127 | //move to the next instruction
128 | this.index++;
129 | }
130 | }
131 | }
132 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/assets/Assets.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.assets;
2 |
3 | import android.app.Activity;
4 |
5 | import com.gamesbykevin.androidframework.resources.*;
6 |
7 | /**
8 | * This class will contain our game assets
9 | * @author GOD
10 | */
11 | public class Assets
12 | {
13 | /**
14 | * The directory where audio sound effect resources are kept
15 | */
16 | private static final String DIRECTORY_MENU_AUDIO = "audio/menu";
17 |
18 | /**
19 | * The directory where audio sound effect resources are kept
20 | */
21 | private static final String DIRECTORY_GAME_AUDIO = "audio/game";
22 |
23 | /**
24 | * The directory where image resources are kept for the menu
25 | */
26 | private static final String DIRECTORY_MENU_IMAGE = "image/menu";
27 |
28 | /**
29 | * The directory where image resources are kept for the game
30 | */
31 | private static final String DIRECTORY_GAME_IMAGE = "image/game";
32 |
33 | /**
34 | * The directory where font resources are kept
35 | */
36 | private static final String DIRECTORY_MENU_FONT = "font/menu";
37 |
38 | /**
39 | * The directory where font resources are kept
40 | */
41 | private static final String DIRECTORY_GAME_FONT = "font/game";
42 |
43 | /**
44 | * The directory where our text files are kept
45 | */
46 | private static final String DIRECTORY_TEXT = "text";
47 |
48 | /**
49 | * The directory where our text files containing the ai instructions are kept
50 | */
51 | private static final String DIRECTORY_TEXT_SOLVED = "solved";
52 |
53 | /**
54 | * The different fonts used in our game.
55 | * Order these according to the file name in the "font" assets folder.
56 | */
57 | public enum FontMenuKey
58 | {
59 | Default
60 | }
61 |
62 | /**
63 | * The different fonts used in our game.
64 | * Order these according to the file name in the "font" assets folder.
65 | */
66 | public enum FontGameKey
67 | {
68 | Default
69 | }
70 |
71 | /**
72 | * The different images for our menu items
73 | */
74 | public enum ImageMenuKey
75 | {
76 | Background,
77 | Button,
78 | Facebook,
79 | Instructions,
80 | Logo,
81 | Cancel,
82 | Confirm,
83 | Splash,
84 | Twitter,
85 | Youtube
86 | }
87 |
88 | /**
89 | * The different images in our game.
90 | * Order these according to the file name in the "image" assets folder.
91 | */
92 | public enum ImageGameKey
93 | {
94 | LevelIconComplete,
95 | LevelIconIncomplete,
96 | LevelNext,
97 | LevelPrevious,
98 | Exit,
99 | Pause,
100 | Reset,
101 | SoundOff,
102 | SoundOn,
103 | UndoDisabled,
104 | UndoEnabled,
105 | Sprites
106 | }
107 |
108 | /**
109 | * The key of each text file.
110 | * Order these according to the file name in the "text" assets folder.
111 | */
112 | public enum TextKey
113 | {
114 | Easy_A("Easy A"),
115 | Easy_B("Easy B"),
116 | Easy_C("Easy C"),
117 | Easy_D("Easy D"),
118 | Medium_A("Medium A"),
119 | Medium_B("Medium B"),
120 | Medium_C("Medium C"),
121 | Medium_D("Medium D"),
122 | Hard_A("Hard A"),
123 | Hard_B("Hard B"),
124 | Hard_C("Hard C"),
125 | Hard_D("Hard D");
126 |
127 | private final String desc;
128 |
129 | private TextKey(final String desc)
130 | {
131 | this.desc = desc;
132 | }
133 |
134 | public String getDesc()
135 | {
136 | return this.desc;
137 | }
138 | }
139 |
140 | public enum TextAiInstructionsKey
141 | {
142 | SOLVED_EASY_A, SOLVED_EASY_B, SOLVED_EASY_C, SOLVED_EASY_D,
143 | SOLVED_MEDIUM_A, SOLVED_MEDIUM_B, SOLVED_MEDIUM_C, SOLVED_MEDIUM_D,
144 | SOLVED_HARD_A, SOLVED_HARD_B, SOLVED_HARD_C, SOLVED_HARD_D
145 | }
146 |
147 | /**
148 | * The key of each sound in our game.
149 | * Order these according to the file name in the "audio" assets folder.
150 | */
151 | public enum AudioMenuKey
152 | {
153 | Selection
154 | }
155 |
156 | /**
157 | * The key of each sound in our game.
158 | * Order these according to the file name in the "audio" assets folder.
159 | */
160 | public enum AudioGameKey
161 | {
162 | LevelComplete,
163 | Goal,
164 | Music
165 | }
166 |
167 | /**
168 | * Load all assets
169 | * @param activity Object containing AssetManager needed to load assets
170 | * @throws Exception
171 | */
172 | public static final void load(final Activity activity) throws Exception
173 | {
174 | //load all images for the menu
175 | Images.load(activity, ImageMenuKey.values(), DIRECTORY_MENU_IMAGE, true);
176 |
177 | //load all fonts for the menu
178 | Font.load(activity, FontMenuKey.values(), DIRECTORY_MENU_FONT, true);
179 |
180 | //load all audio for the menu
181 | Audio.load(activity, AudioMenuKey.values(), DIRECTORY_MENU_AUDIO, true);
182 |
183 | //load images for the game
184 | Images.load(activity, ImageGameKey.values(), DIRECTORY_GAME_IMAGE, true);
185 |
186 | //load all audio for the game
187 | Audio.load(activity, AudioGameKey.values(), DIRECTORY_GAME_AUDIO, true);
188 |
189 | //load all fonts for the game
190 | Font.load(activity, FontGameKey.values(), DIRECTORY_GAME_FONT, true);
191 |
192 | //load all text files
193 | Files.load(activity, TextKey.values(), DIRECTORY_TEXT, true);
194 |
195 | //load the text files containing the ai instructions to solve a level
196 | Files.load(activity, TextAiInstructionsKey.values(), DIRECTORY_TEXT_SOLVED, true);
197 | }
198 |
199 | /**
200 | * Recycle assets
201 | */
202 | public static void recycle()
203 | {
204 | try
205 | {
206 | Images.dispose();
207 | Font.dispose();
208 | Audio.dispose();
209 | Files.dispose();
210 | }
211 | catch (Exception e)
212 | {
213 | e.printStackTrace();
214 | }
215 | }
216 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/game/IGame.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.game;
2 |
3 | import com.gamesbykevin.androidframework.resources.Disposable;
4 | import com.gamesbykevin.sokoban.assets.Assets;
5 |
6 | import android.graphics.Canvas;
7 |
8 | /**
9 | * Game interface methods
10 | * @author GOD
11 | */
12 | public interface IGame extends Disposable
13 | {
14 | /**
15 | * Logic to restart the game with the same settings
16 | * @param key Unique key of text file we want to load
17 | * @throws Exception
18 | */
19 | public void reset(final Assets.TextKey key) throws Exception;
20 |
21 | /**
22 | * Logic to render the game
23 | * @param canvas
24 | * @throws Exception
25 | */
26 | public void render(final Canvas canvas) throws Exception;
27 | }
28 |
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/game/controller/Controller.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.game.controller;
2 |
3 | import com.gamesbykevin.androidframework.awt.Button;
4 |
5 | import android.graphics.Canvas;
6 | import android.view.MotionEvent;
7 |
8 | import com.gamesbykevin.androidframework.resources.Audio;
9 | import com.gamesbykevin.androidframework.resources.Images;
10 |
11 | import com.gamesbykevin.sokoban.assets.Assets;
12 | import com.gamesbykevin.sokoban.game.Game;
13 | import com.gamesbykevin.sokoban.panel.GamePanel;
14 | import com.gamesbykevin.sokoban.screen.ScreenManager;
15 |
16 | import java.util.HashMap;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | /**
22 | * This class will be our game controller
23 | * @author GOD
24 | */
25 | public class Controller implements IController
26 | {
27 | //all of the buttons for the player to control
28 | private HashMap buttons;
29 |
30 | //our game object reference
31 | private final Game game;
32 |
33 | //location of reset button
34 | private final static int RESET_X = GamePanel.WIDTH - 64;
35 | private final static int RESET_Y = 0;
36 |
37 | //location of undo button
38 | private final static int UNDO_X = GamePanel.WIDTH - 64;
39 | private final static int UNDO_Y = 96;
40 |
41 | //is the undo button enabled
42 | private boolean enabled = false;
43 |
44 | /**
45 | * Default Constructor
46 | * @param game Object game object reference
47 | */
48 | public Controller(final Game game)
49 | {
50 | //assign object reference
51 | this.game = game;
52 |
53 | //create temp list
54 | List tmp = new ArrayList();
55 | tmp.add(Assets.ImageGameKey.SoundOff);
56 | tmp.add(Assets.ImageGameKey.SoundOn);
57 | tmp.add(Assets.ImageGameKey.Pause);
58 | tmp.add(Assets.ImageGameKey.Exit);
59 | tmp.add(Assets.ImageGameKey.Reset);
60 | tmp.add(Assets.ImageGameKey.UndoEnabled);
61 | tmp.add(Assets.ImageGameKey.UndoDisabled);
62 |
63 | //create new list of buttons
64 | this.buttons = new HashMap();
65 |
66 | //add button controls
67 | for (Assets.ImageGameKey key : tmp)
68 | {
69 | this.buttons.put(key, new Button(Images.getImage(key)));
70 | }
71 |
72 | //reset button
73 | this.buttons.get(Assets.ImageGameKey.Reset).setX(RESET_X);
74 | this.buttons.get(Assets.ImageGameKey.Reset).setY(RESET_Y);
75 |
76 | //undo button
77 | this.buttons.get(Assets.ImageGameKey.UndoEnabled).setX(UNDO_X);
78 | this.buttons.get(Assets.ImageGameKey.UndoEnabled).setY(UNDO_Y);
79 | this.buttons.get(Assets.ImageGameKey.UndoDisabled).setX(UNDO_X);
80 | this.buttons.get(Assets.ImageGameKey.UndoDisabled).setY(UNDO_Y);
81 |
82 | int x = 40;
83 | final int y = 710;
84 | final int incrementX = 160;
85 |
86 | this.buttons.get(Assets.ImageGameKey.SoundOff).setX(x);
87 | this.buttons.get(Assets.ImageGameKey.SoundOff).setY(y);
88 | this.buttons.get(Assets.ImageGameKey.SoundOn).setX(x);
89 | this.buttons.get(Assets.ImageGameKey.SoundOn).setY(y);
90 |
91 | x += incrementX;
92 | this.buttons.get(Assets.ImageGameKey.Pause).setX(x);
93 | this.buttons.get(Assets.ImageGameKey.Pause).setY(y);
94 |
95 | x += incrementX;
96 | this.buttons.get(Assets.ImageGameKey.Exit).setX(x);
97 | this.buttons.get(Assets.ImageGameKey.Exit).setY(y);
98 |
99 | //assign boundary
100 | for (Assets.ImageGameKey key : tmp)
101 | {
102 | this.buttons.get(key).updateBounds();
103 | }
104 | }
105 |
106 | /**
107 | * Get our game object reference
108 | * @return Our game object reference
109 | */
110 | private Game getGame()
111 | {
112 | return this.game;
113 | }
114 |
115 | /**
116 | * Update the controller based on the motion event
117 | * @param event Motion Event
118 | * @param x (x-coordinate)
119 | * @param y (y-coordinate)
120 | * @return true if motion event was applied, false otherwise
121 | * @throws Exception
122 | */
123 | public boolean update(final int action, final float x, final float y) throws Exception
124 | {
125 | //check if there was a change
126 | boolean change = false;
127 |
128 | //track the motion events
129 | if (action == MotionEvent.ACTION_UP)
130 | {
131 | //check each button in our list
132 | for (Button button : buttons.values())
133 | {
134 | if (button != null && button.isVisible() && button.contains(x, y))
135 | {
136 | if (button.isPressed())
137 | {
138 | //if contained within the coordinates flag released true
139 | button.setReleased(true);
140 |
141 | //flag change true
142 | change = true;
143 | }
144 | else
145 | {
146 | //if this button wasn't pressed previous, reset
147 | reset();
148 | }
149 | }
150 | else
151 | {
152 | //else flag released false
153 | button.setReleased(false);
154 | }
155 | }
156 | }
157 | else if (action == MotionEvent.ACTION_DOWN)
158 | {
159 | //check each button in our list
160 | for (Button button : buttons.values())
161 | {
162 | if (button != null && button.isVisible() && button.contains(x, y))
163 | {
164 | //if contained within the coordinates flag pressed true
165 | button.setPressed(true);
166 |
167 | //flag change true
168 | change = true;
169 | }
170 | else
171 | {
172 | //else flag pressed false
173 | button.setPressed(false);
174 | }
175 | }
176 | }
177 |
178 | //return if any change was made
179 | return change;
180 | }
181 |
182 | @Override
183 | public void reset()
184 | {
185 | if (buttons != null)
186 | {
187 | //determine which button is displayed
188 | buttons.get(Assets.ImageGameKey.SoundOn).setVisible(Audio.isAudioEnabled());
189 | buttons.get(Assets.ImageGameKey.SoundOff).setVisible(!Audio.isAudioEnabled());
190 |
191 | //reset all buttons
192 | for (Button button : buttons.values())
193 | {
194 | if (button != null)
195 | {
196 | button.setPressed(false);
197 | button.setReleased(false);
198 | }
199 | }
200 | }
201 |
202 | //disable the undo button
203 | setDisabled();
204 | }
205 |
206 | /**
207 | * Determined what button was pressed
208 | */
209 | public void update() throws Exception
210 | {
211 | //we can't continue if the list is null
212 | if (buttons == null)
213 | return;
214 |
215 | //check each button to see what changes
216 | for (Assets.ImageGameKey key : buttons.keySet())
217 | {
218 | //get the current button
219 | Button button = buttons.get(key);
220 |
221 | //if this button has been pressed and released
222 | if (button.isPressed() && button.isReleased())
223 | {
224 | //determine next steps
225 | switch (key)
226 | {
227 | case Pause:
228 | //change the state to paused
229 | getGame().getScreen().setState(ScreenManager.State.Paused);
230 | break;
231 |
232 | case Exit:
233 | //change to the exit confirm screen
234 | getGame().getScreen().setState(ScreenManager.State.Exit);
235 | break;
236 |
237 | case SoundOn:
238 | case SoundOff:
239 | //flip the audio setting
240 | Audio.setAudioEnabled(!Audio.isAudioEnabled());
241 |
242 | //make sure the correct button is showing
243 | if (Audio.isAudioEnabled())
244 | {
245 | //play song
246 | Audio.play(Assets.AudioGameKey.Music, true);
247 | }
248 | else
249 | {
250 | //if audio is not enabled, stop all sound
251 | Audio.stop();
252 | }
253 | break;
254 |
255 | case Reset:
256 | //reset current level
257 | getGame().flagLevelReset();
258 | break;
259 |
260 | case UndoEnabled:
261 | case UndoDisabled:
262 |
263 | //make sure the button is enabled
264 | if (this.enabled)
265 | {
266 | //disable button
267 | setDisabled();
268 |
269 | //undo the previous move
270 | getGame().undo();
271 | }
272 | break;
273 |
274 | default:
275 | throw new Exception("Key is not handled here: " + key.toString());
276 | }
277 |
278 | //reset all buttons
279 | reset();
280 | }
281 | }
282 | }
283 |
284 | /**
285 | * Make the undo button enabled
286 | */
287 | public void setEnabled()
288 | {
289 | this.enabled = true;
290 | }
291 |
292 | /**
293 | * Make the undo button disabled
294 | */
295 | public void setDisabled()
296 | {
297 | this.enabled = false;
298 | }
299 |
300 | /**
301 | * Recycle objects
302 | */
303 | @Override
304 | public void dispose()
305 | {
306 | if (buttons != null)
307 | {
308 | for (Button button : buttons.values())
309 | {
310 | if (button != null)
311 | {
312 | button.dispose();
313 | button = null;
314 | }
315 | }
316 |
317 | buttons.clear();
318 | buttons = null;
319 | }
320 | }
321 |
322 | /**
323 | * Render the controller
324 | * @param canvas Write pixel data to this canvas
325 | * @throws Exception
326 | */
327 | @Override
328 | public void render(final Canvas canvas) throws Exception
329 | {
330 | //draw the buttons
331 | if (buttons != null)
332 | {
333 | buttons.get(Audio.isAudioEnabled() ? Assets.ImageGameKey.SoundOn : Assets.ImageGameKey.SoundOff).render(canvas);
334 | buttons.get(Assets.ImageGameKey.Pause).render(canvas);
335 | buttons.get(Assets.ImageGameKey.Exit).render(canvas);
336 | buttons.get(Assets.ImageGameKey.Reset).render(canvas);
337 | buttons.get((enabled) ? Assets.ImageGameKey.UndoEnabled : Assets.ImageGameKey.UndoDisabled).render(canvas);
338 | }
339 | }
340 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/game/controller/IController.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.game.controller;
2 |
3 | import android.graphics.Canvas;
4 | import com.gamesbykevin.androidframework.resources.Disposable;
5 |
6 | /**
7 | * Each controller needs to have these methods
8 | * @author GOD
9 | */
10 | public interface IController extends Disposable
11 | {
12 | public void reset();
13 |
14 | /**
15 | * Update logic when motion event occurs
16 | * @param event Motion Event
17 | * @param x x-coordinate
18 | * @param y y-coordinate
19 | * @throws Exception
20 | * @return true if motion event was applied, false otherwise
21 | */
22 | public boolean update(final int action, final float x, final float y) throws Exception;
23 |
24 | /**
25 | * Common logic to update the controller
26 | */
27 | public void update() throws Exception;
28 |
29 | /**
30 | * Render our controller
31 | * @param canvas Object to write pixels to
32 | * @throws Exception
33 | */
34 | public void render(final Canvas canvas) throws Exception;
35 | }
36 |
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/ILevel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 | package com.gamesbykevin.sokoban.level;
7 |
8 | /**
9 | * Required methods for level
10 | * @author GOD
11 | */
12 | public interface ILevel
13 | {
14 | /**
15 | * Load the level with the given line
16 | * @param line The line containing characters for the layout of our level
17 | * @throws Exception if problem loading the current line
18 | */
19 | public void load(final String line) throws Exception;
20 |
21 | /**
22 | * Logic to update level
23 | */
24 | public void update();
25 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/ILevels.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level;
2 |
3 | import com.gamesbykevin.androidframework.resources.Disposable;
4 |
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 |
8 | /**
9 | * Required methods for a level
10 | * @author GOD
11 | */
12 | public interface ILevels extends Disposable
13 | {
14 | /**
15 | * Logic to reset the level
16 | * @throws Exception
17 | */
18 | public void reset() throws Exception;
19 |
20 | /**
21 | * Render the level
22 | * @param canvas Object where we write pixel data
23 | * @param paint Paint Object
24 | * @throws Exception
25 | */
26 | public void render(final Canvas canvas, final Paint paint) throws Exception;
27 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/LevelHelper.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level;
2 |
3 | import com.gamesbykevin.sokoban.level.tile.*;
4 | import com.gamesbykevin.sokoban.panel.GamePanel;
5 | import com.gamesbykevin.sokoban.target.Target;
6 |
7 | import java.util.HashMap;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * Level Helper methods
13 | * @author GOD
14 | */
15 | public class LevelHelper
16 | {
17 | private static final int WALL_COLOR_GRAY = 0;
18 | private static final int WALL_COLOR_BROWN = 1;
19 | private static final int WALL_COLOR_BLACK = 2;
20 | private static final int WALL_COLOR_BEIGE = 3;
21 |
22 | /**
23 | * Create the tiles and select animations
24 | * @param tiles The list of tiles for our level
25 | */
26 | public static void createTiles(final HashMap tiles)
27 | {
28 | //create new list of possible block styles
29 | List styles = new ArrayList();
30 |
31 | //pick random wall
32 | final int random = GamePanel.RANDOM.nextInt(4);
33 |
34 | //handle the animation accordingly
35 | switch (random)
36 | {
37 | case WALL_COLOR_GRAY:
38 |
39 | //create wall
40 | tiles.put(Tile.Type.Wall, new Wall(Wall.Style.Gray));
41 |
42 | //create floor
43 | tiles.put(Tile.Type.Floor, new Floor(GamePanel.RANDOM.nextBoolean() ? Floor.Style.Gray1 : Floor.Style.Gray2));
44 |
45 | //add possible styles
46 | styles.add(Block.Style.Red);
47 | styles.add(Block.Style.Yellow);
48 | styles.add(Block.Style.Blue);
49 | styles.add(Block.Style.Purple);
50 | styles.add(Block.Style.Black);
51 | styles.add(Block.Style.Brown);
52 | break;
53 |
54 | case WALL_COLOR_BROWN:
55 |
56 | //create wall
57 | tiles.put(Tile.Type.Wall, new Wall(Wall.Style.Brown));
58 |
59 | //create floor
60 | tiles.put(Tile.Type.Floor, new Floor(GamePanel.RANDOM.nextBoolean() ? Floor.Style.Brown1 : Floor.Style.Brown2));
61 |
62 | //add possible styles
63 | styles.add(Block.Style.Red);
64 | styles.add(Block.Style.Yellow);
65 | styles.add(Block.Style.Blue);
66 | styles.add(Block.Style.Purple);
67 | styles.add(Block.Style.Gray);
68 | styles.add(Block.Style.Black);
69 | break;
70 |
71 | case WALL_COLOR_BLACK:
72 |
73 | //create wall
74 | tiles.put(Tile.Type.Wall, new Wall(Wall.Style.Black));
75 |
76 | //create floor
77 | tiles.put(Tile.Type.Floor, new Floor(GamePanel.RANDOM.nextBoolean() ? Floor.Style.Green1 : Floor.Style.Green2));
78 |
79 | //add possible styles
80 | styles.add(Block.Style.Red);
81 | styles.add(Block.Style.Yellow);
82 | styles.add(Block.Style.Blue);
83 | styles.add(Block.Style.Purple);
84 | styles.add(Block.Style.Beige);
85 | styles.add(Block.Style.Gray);
86 | styles.add(Block.Style.Brown);
87 | break;
88 |
89 | default:
90 | case WALL_COLOR_BEIGE:
91 |
92 | //create wall
93 | tiles.put(Tile.Type.Wall, new Wall(Wall.Style.Beige));
94 |
95 | //create floor
96 | tiles.put(Tile.Type.Floor, new Floor(GamePanel.RANDOM.nextBoolean() ? Floor.Style.Beige1 : Floor.Style.Beige2));
97 |
98 | //add possible styles
99 | styles.add(Block.Style.Red);
100 | styles.add(Block.Style.Yellow);
101 | styles.add(Block.Style.Blue);
102 | styles.add(Block.Style.Purple);
103 | styles.add(Block.Style.Brown);
104 | styles.add(Block.Style.Black);
105 | break;
106 | }
107 |
108 | //pick random index
109 | final int index = GamePanel.RANDOM.nextInt(styles.size());
110 |
111 | //assign the goal color based on the random chosen block color
112 | switch (styles.get(index))
113 | {
114 | case Red:
115 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Red));
116 | break;
117 |
118 | case Yellow:
119 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Yellow));
120 | break;
121 |
122 | case Blue:
123 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Blue));
124 | break;
125 |
126 | case Purple:
127 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Purple));
128 | break;
129 |
130 | case Brown:
131 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Brown));
132 | break;
133 |
134 | case Black:
135 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Black));
136 | break;
137 |
138 | case Beige:
139 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Beige));
140 | break;
141 |
142 | default:
143 | case Gray:
144 | tiles.put(Tile.Type.Goal, new Goal(Goal.Style.Gray));
145 | break;
146 | }
147 |
148 | //add block to hash map
149 | tiles.put(Tile.Type.Block, new Block(styles.get(index)));
150 | }
151 |
152 | /**
153 | * Get the x-coordinate of the specified column
154 | * @param level Current level of play
155 | * @param col column location
156 | * @return coordinate of specified location
157 | */
158 | public static final double getX(final Level level, final double col)
159 | {
160 | return level.getStartX() + (col * TileHelper.DEFAULT_DIMENSION);
161 | }
162 |
163 | /**
164 | * Get the y-coordinate of the specified row
165 | * @param level Current level of play
166 | * @param row row location
167 | * @return coordinate of specified location
168 | */
169 | public static final double getY(final Level level, final double row)
170 | {
171 | return level.getStartY() + (row * TileHelper.DEFAULT_DIMENSION);
172 | }
173 |
174 | /**
175 | * Get the column
176 | * @param level Current level of game play
177 | * @param x x-coordinate
178 | * @return The columns of the specified coordinate
179 | */
180 | public static final double getCol(final Level level, final double x)
181 | {
182 | if (x < level.getStartX())
183 | return -1;
184 |
185 | return ((x - level.getStartX()) / TileHelper.DEFAULT_DIMENSION);
186 | }
187 |
188 | /**
189 | * Get the row
190 | * @param level Current level of game play
191 | * @param y y-coordinate
192 | * @return The row of the specified coordinate
193 | */
194 | public static final double getRow(final Level level, final double y)
195 | {
196 | if (y < level.getStartY())
197 | return -1;
198 |
199 | return ((y - level.getStartY()) / TileHelper.DEFAULT_DIMENSION);
200 | }
201 |
202 | /**
203 | * Has the level been completed?
204 | * @param level The current level we want to check
205 | * @return true if all blocks are at a goal, false otherwise
206 | */
207 | public static final boolean hasCompleted(final Level level)
208 | {
209 | //check all targets
210 | for (Target target : level.getCurrent())
211 | {
212 | //if 1 target is not at the goal, the level is not complete
213 | if (!target.hasGoal())
214 | return false;
215 | }
216 |
217 | //all targets are at a goal, return true
218 | return true;
219 | }
220 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/LevelInfo.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level;
2 |
3 | /**
4 | * This class will maintain the information of a level.
5 | * It will be used to help load a level from a given text file
6 | * @author GOD
7 | */
8 | public class LevelInfo
9 | {
10 | //the start and end line of a given level
11 | private final int start, end, cols, rows;
12 |
13 | //the text description of the level
14 | private final String levelDescription;
15 |
16 | public LevelInfo(final int start, final int end, final int cols, final String levelDescription)
17 | {
18 | this.start = start;
19 | this.end = end;
20 | this.cols = cols;
21 | this.rows = end - start + 1;
22 | this.levelDescription = levelDescription;
23 | }
24 |
25 | /**
26 | * The start line number
27 | * @return The line # in the text file where the level starts
28 | */
29 | public int getLineStart()
30 | {
31 | return this.start;
32 | }
33 |
34 | /**
35 | * The end line number
36 | * @return The line # in the text file where the level ends
37 | */
38 | public int getLineEnd()
39 | {
40 | return this.end;
41 | }
42 |
43 | /**
44 | * Get the columns
45 | * @return The number of columns for this level
46 | */
47 | public int getCols()
48 | {
49 | return this.cols;
50 | }
51 |
52 | /**
53 | * Get the rows
54 | * @return The number of rows for this level
55 | */
56 | public int getRows()
57 | {
58 | return this.rows;
59 | }
60 |
61 | /**
62 | * Get the level description
63 | * @return The level description text we want to display to the user
64 | */
65 | public String getLevelDescription()
66 | {
67 | return this.levelDescription;
68 | }
69 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/Levels.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.gamesbykevin.androidframework.awt.Button;
7 | import com.gamesbykevin.androidframework.level.Select;
8 | import com.gamesbykevin.androidframework.resources.Files;
9 | import com.gamesbykevin.androidframework.resources.Images;
10 | import com.gamesbykevin.sokoban.assets.Assets;
11 | import com.gamesbykevin.sokoban.level.tile.Tile;
12 | import com.gamesbykevin.sokoban.level.tile.TileHelper;
13 | import com.gamesbykevin.sokoban.panel.GamePanel;
14 |
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.List;
18 |
19 | /**
20 | * Manage a collection of levels
21 | * @author GOD
22 | */
23 | public final class Levels implements ILevels
24 | {
25 | //the tiles for the level
26 | private HashMap tiles;
27 |
28 | //the current level
29 | private Level level;
30 |
31 | //store the unique key of the text file used to create the levels
32 | private final Assets.TextKey key;
33 |
34 | //keep the list where all the levels are located in the text file
35 | private List trackers;
36 |
37 | //our level select object
38 | private Select levelSelect;
39 |
40 | //level select information
41 | private static final int LEVEL_SELECT_COLS = 5;
42 | private static final int LEVEL_SELECT_ROWS = 7;
43 | private static final int LEVEL_SELECT_DIMENSION = 64;
44 | private static final int LEVEL_SELECT_PADDING = (LEVEL_SELECT_DIMENSION / 2);
45 | private static final int LEVEL_SELECT_START_X = (GamePanel.WIDTH / 2) - (((LEVEL_SELECT_COLS * LEVEL_SELECT_DIMENSION) + ((LEVEL_SELECT_COLS - 1) * LEVEL_SELECT_PADDING)) / 2);
46 | private static final int LEVEL_SELECT_START_Y = 32;
47 |
48 | /**
49 | * Create levels
50 | * @param key The unique key of the desired text file
51 | * @throws Exception
52 | */
53 | public Levels(final Assets.TextKey key) throws Exception
54 | {
55 | //store text key
56 | this.key = key;
57 |
58 | //current level is null
59 | this.level = null;
60 |
61 | //create new list to track where each level is in a given text file
62 | this.trackers = new ArrayList();
63 |
64 | //load the location of all levels in the specified text file
65 | loadLevels();
66 |
67 | //create the level select object
68 | createLevelSelect();
69 |
70 | //create new list of tiles
71 | this.tiles = new HashMap();
72 | }
73 |
74 | /**
75 | * Create the level select object
76 | */
77 | private void createLevelSelect()
78 | {
79 | //create the level select screen
80 | this.levelSelect = new Select();
81 | getLevelSelect().setButtonNext(new Button(Images.getImage(Assets.ImageGameKey.LevelNext)));
82 | getLevelSelect().setButtonOpen(new Button(Images.getImage(Assets.ImageGameKey.LevelIconIncomplete)));
83 | getLevelSelect().setButtonPrevious(new Button(Images.getImage(Assets.ImageGameKey.LevelPrevious)));
84 | getLevelSelect().setButtonSolved(new Button(Images.getImage(Assets.ImageGameKey.LevelIconComplete)));
85 | getLevelSelect().setCols(LEVEL_SELECT_COLS);
86 | getLevelSelect().setRows(LEVEL_SELECT_ROWS);
87 | getLevelSelect().setDimension(LEVEL_SELECT_DIMENSION);
88 | getLevelSelect().setPadding(LEVEL_SELECT_PADDING);
89 | getLevelSelect().setStartX(LEVEL_SELECT_START_X);
90 | getLevelSelect().setStartY(LEVEL_SELECT_START_Y);
91 | getLevelSelect().setTotal(getLevelTrackers().size());
92 | }
93 |
94 | /**
95 | * Load the line # for each level so we will know how to load a specified level
96 | */
97 | private void loadLevels()
98 | {
99 | //did we find the first line
100 | boolean start = false;
101 |
102 | //start and finish of level
103 | int lineStart = 0;
104 |
105 | //longest length (width)
106 | int length = 0;
107 |
108 | //check each line in our text file to determine where the levels are
109 | for (int i = 0; i < Files.getText(getKey()).getLines().size(); i++)
110 | {
111 | //get the current line
112 | String line = Files.getText(getKey()).getLines().get(i);
113 |
114 | //each line in a level will have a wall somewhere, and make sure not at last line
115 | if (line.contains(Level.KEY_WALL) && i < Files.getText(getKey()).getLines().size() - 1)
116 | {
117 | //store the column width
118 | if (line.length() > length)
119 | length = line.length();
120 |
121 | //if we didn't start, this is the first line of the level
122 | if (!start)
123 | lineStart = i;
124 |
125 | //flag level start
126 | start = true;
127 | }
128 | else
129 | {
130 | //if we already started, we reached the end of the level
131 | if (start)
132 | {
133 | //the text description of the level
134 | String levelDescription = "";
135 |
136 | switch (this.key)
137 | {
138 | case Easy_A:
139 | levelDescription = "Easy A - Level " + (getLevelTrackers().size() + 1);
140 | break;
141 |
142 | case Easy_B:
143 | levelDescription = "Easy B - Level " + (getLevelTrackers().size() + 1);
144 | break;
145 |
146 | case Easy_C:
147 | levelDescription = "Easy C - Level " + (getLevelTrackers().size() + 1);
148 | break;
149 |
150 | case Easy_D:
151 | levelDescription = "Easy D - Level " + (getLevelTrackers().size() + 1);
152 | break;
153 |
154 | case Medium_A:
155 | levelDescription = "Medium A - Level " + (getLevelTrackers().size() + 1);
156 | break;
157 |
158 | case Medium_B:
159 | levelDescription = "Medium B - Level " + (getLevelTrackers().size() + 1);
160 | break;
161 |
162 | case Medium_C:
163 | levelDescription = "Medium C - Level " + (getLevelTrackers().size() + 1);
164 | break;
165 |
166 | case Medium_D:
167 | levelDescription = "Medium D - Level " + (getLevelTrackers().size() + 1);
168 | break;
169 |
170 | case Hard_A:
171 | levelDescription = "Hard A - Level " + (getLevelTrackers().size() + 1);
172 | break;
173 |
174 | case Hard_B:
175 | levelDescription = "Hard B - Level " + (getLevelTrackers().size() + 1);
176 | break;
177 |
178 | case Hard_C:
179 | levelDescription = "Hard C - Level " + (getLevelTrackers().size() + 1);
180 | break;
181 |
182 | case Hard_D:
183 | levelDescription = "Hard D - Level " + (getLevelTrackers().size() + 1);
184 | break;
185 | }
186 |
187 |
188 | if (i == Files.getText(getKey()).getLines().size() - 1)
189 | {
190 | //add the info for this level
191 | getLevelTrackers().add(new LevelInfo(lineStart, i, length, levelDescription));
192 | }
193 | else
194 | {
195 | //add the info for this level
196 | getLevelTrackers().add(new LevelInfo(lineStart, i - 1, length, levelDescription));
197 | }
198 |
199 | //flag start false
200 | start = false;
201 |
202 | //reset column size as well
203 | length = 0;
204 | }
205 | }
206 | }
207 | }
208 |
209 | /**
210 | * Get the level select
211 | * @return The level select object
212 | */
213 | public Select getLevelSelect()
214 | {
215 | return this.levelSelect;
216 | }
217 |
218 | /**
219 | * Get the unique text resource key
220 | * @return The unique key of the text resource used to create the levels
221 | */
222 | private Assets.TextKey getKey()
223 | {
224 | return this.key;
225 | }
226 |
227 | /**
228 | * Get the level tracker of the current level
229 | * @return Object containing level info
230 | */
231 | public LevelInfo getLevelTracker()
232 | {
233 | return getLevelTracker(getLevelSelect().getLevelIndex());
234 | }
235 |
236 | /**
237 | * Get the level tracker of the current level
238 | * @param index The index location of the desired level
239 | * @return Object containing level info
240 | */
241 | public LevelInfo getLevelTracker(final int index)
242 | {
243 | return trackers.get(index);
244 | }
245 |
246 | /**
247 | * Get the level trackers
248 | * @return The level trackers of all levels
249 | */
250 | public List getLevelTrackers()
251 | {
252 | return this.trackers;
253 | }
254 |
255 | /**
256 | * Create a new level with the current level tracker
257 | * @throws Exception
258 | */
259 | public void createLevel() throws Exception
260 | {
261 | //create new level
262 | this.level = new Level(getLevelTracker());
263 |
264 | //get the size from the level tracker info
265 | final int cols = getLevelTracker().getCols();
266 | final int rows = getLevelTracker().getRows();
267 |
268 | //now load each line into the level
269 | for (int i = getLevelTracker().getLineStart(); i <= getLevelTracker().getLineEnd(); i++)
270 | {
271 | getLevel().load(Files.getText(getKey()).getLines().get(i));
272 | }
273 |
274 | //if the level is small enough, we will display all on screen
275 | if (getLevel().canFitWindow())
276 | {
277 | //locate middle of screen
278 | final int middleX = (GamePanel.WIDTH / 2) - (TileHelper.DEFAULT_DIMENSION / 2) + (TileHelper.DEFAULT_DIMENSION / 2);
279 | final int middleY = (GamePanel.HEIGHT / 2) - (TileHelper.DEFAULT_DIMENSION / 2) + (TileHelper.DEFAULT_DIMENSION / 2);
280 |
281 | //set the start location (x,y) so the complete level is displayed
282 | getLevel().setStartLocation(
283 | middleX - (int)((cols * TileHelper.DEFAULT_DIMENSION) / 2),
284 | middleY - (int)((rows * TileHelper.DEFAULT_DIMENSION) / 2)
285 | );
286 | }
287 | else
288 | {
289 | //locate middle of screen
290 | final int middleX = (GamePanel.WIDTH / 2) - (TileHelper.DEFAULT_DIMENSION / 2);
291 | final int middleY = (GamePanel.HEIGHT / 2) - (TileHelper.DEFAULT_DIMENSION / 2);
292 |
293 | //set the start location (x,y) relative to where the player start is
294 | getLevel().setStartLocation(
295 | middleX - (int)(getLevel().getStart().getCol() * TileHelper.DEFAULT_DIMENSION),
296 | middleY - (int)(getLevel().getStart().getRow() * TileHelper.DEFAULT_DIMENSION)
297 | );
298 | }
299 | }
300 |
301 | /**
302 | * Recycle resources
303 | */
304 | @Override
305 | public void dispose()
306 | {
307 | if (tiles != null)
308 | {
309 | for (Tile tile : tiles.values())
310 | {
311 | if (tile != null)
312 | {
313 | tile.dispose();
314 | tile = null;
315 | }
316 | }
317 |
318 | tiles.clear();
319 | tiles = null;
320 | }
321 |
322 | if (level != null)
323 | {
324 | level.dispose();
325 | level = null;
326 | }
327 |
328 | if (trackers != null)
329 | {
330 | trackers.clear();
331 | trackers = null;
332 | }
333 |
334 | if (levelSelect != null)
335 | {
336 | levelSelect.dispose();
337 | levelSelect = null;
338 | }
339 | }
340 |
341 | /**
342 | * Get the current level
343 | * @return Get the current level
344 | */
345 | public Level getLevel()
346 | {
347 | return this.level;
348 | }
349 |
350 | /**
351 | * Reset the level.
352 | * A new style of tiles will be selected.
353 | * A new level will be created.
354 | * @throws Exception
355 | */
356 | @Override
357 | public final void reset() throws Exception
358 | {
359 | //generate random tiles
360 | LevelHelper.createTiles(tiles);
361 |
362 | //create new level
363 | createLevel();
364 | }
365 |
366 | /**
367 | * Render the level
368 | * @param canvas Object where we write pixel data
369 | * @param paint Paint object
370 | * @throws Exception
371 | */
372 | @Override
373 | public void render(final Canvas canvas, final Paint paint) throws Exception
374 | {
375 | //if a level has already been selected, render the level
376 | if (getLevelSelect().hasSelection())
377 | {
378 | if (getLevel() != null)
379 | {
380 | //render the level
381 | getLevel().render(canvas, tiles);
382 | }
383 | }
384 | else
385 | {
386 | //draw the level select screen
387 | getLevelSelect().render(canvas, paint);
388 | }
389 | }
390 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/tile/Block.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level.tile;
2 |
3 | import com.gamesbykevin.androidframework.anim.Animation;
4 | import com.gamesbykevin.androidframework.resources.Images;
5 | import com.gamesbykevin.sokoban.assets.Assets;
6 |
7 | /**
8 | * Block
9 | * @author GOD
10 | */
11 | public final class Block extends Tile
12 | {
13 | public enum Style
14 | {
15 | Yellow, Red, Beige, Black, Brown, Purple, Blue, Gray
16 | }
17 |
18 | /**
19 | * Most tiles will only have 1 animation, but the block will have an alternate
20 | */
21 | public enum State
22 | {
23 | Default, Alternate
24 | }
25 |
26 | /**
27 | * Create new block
28 | * @param style The color of the block
29 | */
30 | public Block(final Style style)
31 | {
32 | super(Tile.Type.Block);
33 |
34 | //set animation
35 | setAnimation(style);
36 | }
37 |
38 | public final void setAnimation(final Style style)
39 | {
40 | int x, y, d = TileHelper.ANIMATION_DIMENSION;
41 |
42 | final Assets.ImageGameKey key = Assets.ImageGameKey.Sprites;
43 |
44 | //set dimensions
45 | super.setWidth(d);
46 | super.setHeight(d);
47 |
48 | switch (style)
49 | {
50 | case Yellow:
51 | x = TileHelper.getSpriteSheetX(3);
52 | y = TileHelper.getSpriteSheetY(0);
53 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
54 |
55 | x = TileHelper.getSpriteSheetX(2);
56 | y = TileHelper.getSpriteSheetY(4);
57 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
58 | break;
59 |
60 | case Red:
61 | x = TileHelper.getSpriteSheetX(2);
62 | y = TileHelper.getSpriteSheetY(5);
63 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
64 |
65 | x = TileHelper.getSpriteSheetX(4);
66 | y = TileHelper.getSpriteSheetY(1);
67 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
68 | break;
69 |
70 | case Beige:
71 | x = TileHelper.getSpriteSheetX(3);
72 | y = TileHelper.getSpriteSheetY(1);
73 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
74 |
75 | x = TileHelper.getSpriteSheetX(5);
76 | y = TileHelper.getSpriteSheetY(1);
77 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
78 | break;
79 |
80 | case Black:
81 | x = TileHelper.getSpriteSheetX(3);
82 | y = TileHelper.getSpriteSheetY(2);
83 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
84 |
85 | x = TileHelper.getSpriteSheetX(5);
86 | y = TileHelper.getSpriteSheetY(0);
87 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
88 | break;
89 |
90 | case Brown:
91 | x = TileHelper.getSpriteSheetX(3);
92 | y = TileHelper.getSpriteSheetY(4);
93 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
94 |
95 | x = TileHelper.getSpriteSheetX(4);
96 | y = TileHelper.getSpriteSheetY(4);
97 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
98 | break;
99 |
100 | case Purple:
101 | x = TileHelper.getSpriteSheetX(4);
102 | y = TileHelper.getSpriteSheetY(2);
103 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
104 |
105 | x = TileHelper.getSpriteSheetX(4);
106 | y = TileHelper.getSpriteSheetY(0);
107 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
108 | break;
109 |
110 | case Blue:
111 | x = TileHelper.getSpriteSheetX(3);
112 | y = TileHelper.getSpriteSheetY(3);
113 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
114 |
115 | x = TileHelper.getSpriteSheetX(4);
116 | y = TileHelper.getSpriteSheetY(5);
117 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
118 | break;
119 |
120 | case Gray:
121 | x = TileHelper.getSpriteSheetX(3);
122 | y = TileHelper.getSpriteSheetY(5);
123 | getSpritesheet().add(State.Default, new Animation(Images.getImage(key), x, y, d, d));
124 |
125 | x = TileHelper.getSpriteSheetX(4);
126 | y = TileHelper.getSpriteSheetY(3);
127 | getSpritesheet().add(State.Alternate, new Animation(Images.getImage(key), x, y, d, d));
128 | break;
129 | }
130 | }
131 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/tile/Floor.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level.tile;
2 |
3 | import com.gamesbykevin.androidframework.anim.Animation;
4 | import com.gamesbykevin.androidframework.resources.Images;
5 | import com.gamesbykevin.sokoban.assets.Assets;
6 |
7 | /**
8 | * Floor
9 | * @author GOD
10 | */
11 | public final class Floor extends Tile
12 | {
13 | public enum Style
14 | {
15 | Beige1, Beige2,
16 | Green1, Green2,
17 | Brown1, Brown2,
18 | Gray1, Gray2
19 | }
20 |
21 | public Floor(final Style style)
22 | {
23 | super(Tile.Type.Floor);
24 |
25 | setAnimation(style);
26 | }
27 |
28 | public final void setAnimation(final Style style)
29 | {
30 | int x = 0, y = 0, d = TileHelper.ANIMATION_DIMENSION;
31 |
32 | //set dimensions
33 | super.setWidth(d);
34 | super.setHeight(d);
35 |
36 | switch (style)
37 | {
38 | case Beige1:
39 | x = TileHelper.getSpriteSheetX(1);
40 | y = TileHelper.getSpriteSheetY(2);
41 | break;
42 |
43 | case Beige2:
44 | x = TileHelper.getSpriteSheetX(2);
45 | y = TileHelper.getSpriteSheetY(0);
46 | break;
47 |
48 | case Green1:
49 | x = TileHelper.getSpriteSheetX(1);
50 | y = TileHelper.getSpriteSheetY(3);
51 | break;
52 |
53 | case Green2:
54 | x = TileHelper.getSpriteSheetX(2);
55 | y = TileHelper.getSpriteSheetY(1);
56 | break;
57 |
58 | case Brown1:
59 | x = TileHelper.getSpriteSheetX(1);
60 | y = TileHelper.getSpriteSheetY(4);
61 | break;
62 |
63 | case Brown2:
64 | x = TileHelper.getSpriteSheetX(2);
65 | y = TileHelper.getSpriteSheetY(2);
66 | break;
67 |
68 | case Gray1:
69 | x = TileHelper.getSpriteSheetX(1);
70 | y = TileHelper.getSpriteSheetY(5);
71 | break;
72 |
73 | case Gray2:
74 | x = TileHelper.getSpriteSheetX(2);
75 | y = TileHelper.getSpriteSheetY(3);
76 | break;
77 | }
78 |
79 | //if animation doesn't exist, add it
80 | if (getSpritesheet().get(style) == null)
81 | {
82 | //map the style
83 | getSpritesheet().add(style, new Animation(Images.getImage(Assets.ImageGameKey.Sprites), x, y, d, d));
84 | }
85 |
86 | //assign this style as the current
87 | getSpritesheet().setKey(style);
88 | }
89 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/tile/Goal.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level.tile;
2 |
3 | import com.gamesbykevin.androidframework.anim.Animation;
4 | import com.gamesbykevin.androidframework.resources.Images;
5 | import com.gamesbykevin.sokoban.assets.Assets;
6 |
7 | /**
8 | * Goal
9 | * @author GOD
10 | */
11 | public final class Goal extends Tile
12 | {
13 | public enum Style
14 | {
15 | Brown, Beige, Gray, Purple,
16 | Blue, Black, Red, Yellow,
17 | }
18 |
19 | public Goal(final Style style)
20 | {
21 | super(Tile.Type.Goal);
22 |
23 | setAnimation(style);
24 | }
25 |
26 | public final void setAnimation(final Style style)
27 | {
28 | int x = 0, y = 384, d = TileHelper.ANIMATION_GOAL_DIMENSION;
29 |
30 | //set dimensions
31 | super.setWidth(d);
32 | super.setHeight(d);
33 |
34 | switch (style)
35 | {
36 | case Brown:
37 | x = (0 * TileHelper.ANIMATION_GOAL_DIMENSION);
38 | break;
39 |
40 | case Beige:
41 | x = (1 * TileHelper.ANIMATION_GOAL_DIMENSION);
42 | break;
43 |
44 | case Gray:
45 | x = (2 * TileHelper.ANIMATION_GOAL_DIMENSION);
46 | break;
47 |
48 | case Purple:
49 | x = (3 * TileHelper.ANIMATION_GOAL_DIMENSION);
50 | break;
51 |
52 | case Blue:
53 | x = (4 * TileHelper.ANIMATION_GOAL_DIMENSION);
54 | break;
55 |
56 | case Black:
57 | x = (5 * TileHelper.ANIMATION_GOAL_DIMENSION);
58 | break;
59 |
60 | case Red:
61 | x = (6 * TileHelper.ANIMATION_GOAL_DIMENSION);
62 | break;
63 |
64 | case Yellow:
65 | x = (7 * TileHelper.ANIMATION_GOAL_DIMENSION);
66 | break;
67 | }
68 |
69 | //if animation doesn't exist, add it
70 | if (getSpritesheet().get(style) == null)
71 | {
72 | //map the style
73 | getSpritesheet().add(style, new Animation(Images.getImage(Assets.ImageGameKey.Sprites), x, y, d, d));
74 | }
75 |
76 | //assign this style as the current
77 | getSpritesheet().setKey(style);
78 | }
79 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/tile/Tile.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level.tile;
2 |
3 | import com.gamesbykevin.androidframework.base.Entity;
4 |
5 | /**
6 | * A single tile in the game
7 | * @author GOD
8 | */
9 | public abstract class Tile extends Entity
10 | {
11 | /**
12 | * The different types of tiles in our game
13 | */
14 | public enum Type
15 | {
16 | Floor,
17 | Wall,
18 | Block,
19 | Goal
20 | }
21 |
22 | //the type of tile
23 | private final Type type;
24 |
25 | /**
26 | * Create a new tile
27 | * @param type The type of tile
28 | */
29 | public Tile(final Type type)
30 | {
31 | this.type = type;
32 | }
33 |
34 | /**
35 | * Get the type
36 | * @return The type of tile this is "Floor, Wall, Goal, Block, etc..."
37 | */
38 | public Type getType()
39 | {
40 | return this.type;
41 | }
42 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/tile/TileHelper.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level.tile;
2 |
3 | /**
4 | * TileHelper methods
5 | * @author GOD
6 | */
7 | public class TileHelper
8 | {
9 | /**
10 | * The default dimension of a single animation for a tile
11 | */
12 | public static final int ANIMATION_DIMENSION = 64;
13 |
14 | /**
15 | * The default dimension of a tile
16 | */
17 | public static final int DEFAULT_DIMENSION = 64;
18 |
19 | /**
20 | * The default dimension of the goal
21 | */
22 | public static final int ANIMATION_GOAL_DIMENSION = 32;
23 |
24 | /**
25 | * Get the sprite sheet coordinate
26 | * @param col Column
27 | * @return The x coordinate where the animation resides on the sprite sheet
28 | */
29 | public static int getSpriteSheetX(final int col)
30 | {
31 | return (col * DEFAULT_DIMENSION);
32 | }
33 |
34 | /**
35 | * Get the sprite sheet coordinate
36 | * @param row Row
37 | * @return The y coordinate where the animation resides on the sprite sheet
38 | */
39 | public static int getSpriteSheetY(final int row)
40 | {
41 | return (row * DEFAULT_DIMENSION);
42 | }
43 |
44 |
45 | /**
46 | * Is this tile a wall?
47 | * @param tile The tile we want to check
48 | * @return true = yes, false = no
49 | */
50 | public static boolean isWall(final Tile tile)
51 | {
52 | return isWall(tile.getType());
53 | }
54 |
55 | /**
56 | * Is this tile a wall?
57 | * @param type The tile type we want to check
58 | * @return true = yes, false = no
59 | */
60 | public static boolean isWall(final Tile.Type type)
61 | {
62 | //if type is null, return false
63 | if (type == null)
64 | return false;
65 |
66 | switch (type)
67 | {
68 | case Wall:
69 | return true;
70 |
71 | default:
72 | return false;
73 | }
74 | }
75 |
76 | /**
77 | * Is this tile the floor?
78 | * @param tile The tile we want to check
79 | * @return true = yes, false = no
80 | */
81 | public static boolean isFloor(final Tile tile)
82 | {
83 | return isFloor(tile.getType());
84 | }
85 |
86 | /**
87 | * Is this tile the floor?
88 | * @param type The tile type we want to check
89 | * @return true = yes, false = no
90 | */
91 | public static boolean isFloor(final Tile.Type type)
92 | {
93 | //if type is null, return false
94 | if (type == null)
95 | return false;
96 |
97 | switch (type)
98 | {
99 | case Floor:
100 | return true;
101 |
102 | default:
103 | return false;
104 | }
105 | }
106 |
107 |
108 | /**
109 | * Is this tile a block?
110 | * @param tile The tile we want to check
111 | * @return true = yes, false = no
112 | */
113 | public static boolean isBlock(final Tile tile)
114 | {
115 | return isBlock(tile.getType());
116 | }
117 |
118 | /**
119 | * Is this tile a block?
120 | * @param type The tile type we want to check
121 | * @return true = yes, false = no
122 | */
123 | public static boolean isBlock(final Tile.Type type)
124 | {
125 | //if type is null, return false
126 | if (type == null)
127 | return false;
128 |
129 | switch (type)
130 | {
131 | case Block:
132 | return true;
133 |
134 | default:
135 | return false;
136 | }
137 | }
138 |
139 | /**
140 | * Is this tile the goal?
141 | * @param tile The tile we want to check
142 | * @return true = yes, false = no
143 | */
144 | public static boolean isGoal(final Tile tile)
145 | {
146 | return isGoal(tile.getType());
147 | }
148 |
149 | /**
150 | * Is this tile the goal?
151 | * @param type The tile type we want to check
152 | * @return true = yes, false = no
153 | */
154 | public static boolean isGoal(final Tile.Type type)
155 | {
156 | //if type is null, return false
157 | if (type == null)
158 | return false;
159 |
160 | switch (type)
161 | {
162 | case Goal:
163 | return true;
164 |
165 | default:
166 | return false;
167 | }
168 | }
169 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/level/tile/Wall.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.level.tile;
2 |
3 | import com.gamesbykevin.androidframework.anim.Animation;
4 | import com.gamesbykevin.androidframework.resources.Images;
5 | import com.gamesbykevin.sokoban.assets.Assets;
6 |
7 | /**
8 | * Wall
9 | * @author GOD
10 | */
11 | public final class Wall extends Tile
12 | {
13 | public enum Style
14 | {
15 | Gray, Brown, Black, Beige
16 | }
17 |
18 | public Wall(final Style style)
19 | {
20 | super(Tile.Type.Wall);
21 |
22 | setAnimation(style);
23 | }
24 |
25 | public final void setAnimation(final Style style)
26 | {
27 | int x = 0, y = 0, d = TileHelper.ANIMATION_DIMENSION;
28 |
29 | //set dimensions
30 | super.setWidth(d);
31 | super.setHeight(d);
32 |
33 | switch (style)
34 | {
35 | case Gray:
36 | x = TileHelper.getSpriteSheetX(0);
37 | y = TileHelper.getSpriteSheetY(4);
38 | break;
39 |
40 | case Brown:
41 | x = TileHelper.getSpriteSheetX(0);
42 | y = TileHelper.getSpriteSheetY(5);
43 | break;
44 |
45 | case Black:
46 | x = TileHelper.getSpriteSheetX(1);
47 | y = TileHelper.getSpriteSheetY(0);
48 | break;
49 |
50 | case Beige:
51 | x = TileHelper.getSpriteSheetX(1);
52 | y = TileHelper.getSpriteSheetY(1);
53 | break;
54 | }
55 |
56 | //if animation doesn't exist, add it
57 | if (getSpritesheet().get(style) == null)
58 | {
59 | //map the style
60 | getSpritesheet().add(style, new Animation(Images.getImage(Assets.ImageGameKey.Sprites), x, y, d, d));
61 | }
62 |
63 | //assign this style as the current
64 | getSpritesheet().setKey(style);
65 | }
66 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/panel/GamePanel.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.panel;
2 |
3 | import android.graphics.Canvas;
4 | import android.view.MotionEvent;
5 | import android.view.SurfaceHolder;
6 | import android.view.SurfaceView;
7 | import com.gamesbykevin.androidframework.resources.Audio;
8 | import com.gamesbykevin.androidframework.resources.Disposable;
9 | import com.gamesbykevin.sokoban.screen.ScreenManager.State;
10 | import com.gamesbykevin.sokoban.MainActivity;
11 | import com.gamesbykevin.sokoban.assets.Assets;
12 | import com.gamesbykevin.sokoban.screen.ScreenManager;
13 | import com.gamesbykevin.sokoban.thread.MainThread;
14 |
15 | import java.util.Random;
16 |
17 | /**
18 | * Game Panel class
19 | * @author GOD
20 | */
21 | public class GamePanel extends SurfaceView implements SurfaceHolder.Callback, Disposable
22 | {
23 | /**
24 | * Our random object used to make random decisions
25 | */
26 | public static Random RANDOM = new Random(System.nanoTime());
27 |
28 | //default dimensions of window for this game
29 | public static final int WIDTH = 480;
30 | public static final int HEIGHT = 800;
31 |
32 | //the reference to our activity
33 | private final MainActivity activity;
34 |
35 | //the object containing our game screens
36 | private ScreenManager screen;
37 |
38 | //our main game thread
39 | private MainThread thread;
40 |
41 | //did motion event down happen
42 | private boolean down = false;
43 |
44 | //get the ratio of the users screen compared to the default dimensions for the motion event
45 | private float scaleMotionX, scaleMotionY;
46 |
47 | //get the ratio of the users screen compared to the default dimensions for the render
48 | private float scaleRenderX, scaleRenderY;
49 |
50 | /**
51 | * Create a new game panel
52 | * @param activity Our main activity reference
53 | */
54 | public GamePanel(final MainActivity activity)
55 | {
56 | //call to parent constructor
57 | super(activity);
58 |
59 | //store context
60 | this.activity = activity;
61 |
62 | //make game panel focusable = true so it can handle events
63 | super.setFocusable(true);
64 | }
65 |
66 | /**
67 | * Get the main game thread.
68 | * If the main thread does not exist, it will be created
69 | * @return The main game thread
70 | */
71 | private MainThread getThread()
72 | {
73 | return this.thread;
74 | }
75 |
76 | /**
77 | * Get the screen manager
78 | * @return The screen manager containing all our screens
79 | */
80 | private ScreenManager getScreen()
81 | {
82 | return this.screen;
83 | }
84 |
85 | @Override
86 | public void dispose()
87 | {
88 | //it could take several attempts to stop the thread
89 | boolean retry = true;
90 |
91 | //count number of attempts to complete thread
92 | int count = 0;
93 |
94 | //here we will attempt to stop the thread
95 | while (retry && count <= MainThread.COMPLETE_THREAD_ATTEMPTS)
96 | {
97 | try
98 | {
99 | //increase count
100 | count++;
101 |
102 | if (getThread() != null)
103 | {
104 | //set running false, to stop the infinite loop
105 | getThread().setRunning(false);
106 |
107 | //wait for thread to finish
108 | getThread().join();
109 | }
110 |
111 | //if we made it here, we were successful
112 | retry = false;
113 | }
114 | catch (InterruptedException e)
115 | {
116 | e.printStackTrace();
117 | }
118 | }
119 |
120 | //make thread null
121 | this.thread = null;
122 |
123 | //assign null
124 | RANDOM = null;
125 |
126 | if (screen != null)
127 | {
128 | screen.dispose();
129 | screen = null;
130 | }
131 |
132 | //recycle all asset objects
133 | Assets.recycle();
134 | }
135 |
136 | /**
137 | * Get the activity
138 | * @return The activity reference
139 | */
140 | public final MainActivity getActivity()
141 | {
142 | return this.activity;
143 | }
144 |
145 | @Override
146 | public boolean performClick()
147 | {
148 | //call parent
149 | super.performClick();
150 |
151 | //return true
152 | return true;
153 | }
154 |
155 | @Override
156 | public boolean onTouchEvent(final MotionEvent event)
157 | {
158 | try
159 | {
160 | if (getScreen() != null)
161 | {
162 | //adjust the coordinates
163 | final float x = event.getRawX() * getScaleMotionX();
164 | final float y = event.getRawY() * getScaleMotionY();
165 |
166 | switch (event.getAction())
167 | {
168 | case MotionEvent.ACTION_DOWN:
169 |
170 | //flag motion down occurred
171 | down = true;
172 | break;
173 |
174 | case MotionEvent.ACTION_UP:
175 |
176 | //if we have previously action down
177 | if (down)
178 | {
179 | //flag false
180 | down = false;
181 |
182 | //perform click
183 | performClick();
184 | }
185 | break;
186 | }
187 |
188 | //update the screen/game etc.. with the specified motion events
189 | return getScreen().update(event.getActionMasked(), x, y);
190 | }
191 | }
192 | catch (Exception e)
193 | {
194 | e.printStackTrace();
195 | }
196 |
197 | return super.onTouchEvent(event);
198 | }
199 |
200 | /**
201 | * Now that the surface has been created we can create our game objects
202 | * @param holder Object used to track events
203 | */
204 | @Override
205 | public void surfaceCreated(SurfaceHolder holder)
206 | {
207 | try
208 | {
209 | //load assets
210 | Assets.load(getActivity());
211 |
212 | //create if null
213 | if (RANDOM == null)
214 | RANDOM = new Random(System.nanoTime());
215 |
216 | //create the thread if it doesn't exist
217 | if (getThread() == null)
218 | this.thread = new MainThread(getHolder(), this);
219 |
220 | //if the thread hasn't been started yet
221 | if (!getThread().isRunning())
222 | {
223 | //start the thread
224 | getThread().setRunning(true);
225 | getThread().start();
226 | }
227 |
228 | //flag the thread as not paused
229 | getThread().setPause(false);
230 |
231 | //store the ratio for the motion event
232 | this.scaleMotionX = (float)GamePanel.WIDTH / getWidth();
233 | this.scaleMotionY = (float)GamePanel.HEIGHT / getHeight();
234 |
235 | //store the ratio for the render
236 | this.scaleRenderX = getWidth() / (float)GamePanel.WIDTH;
237 | this.scaleRenderY = getHeight() / (float)GamePanel.HEIGHT;
238 | }
239 | catch (Exception e)
240 | {
241 | e.printStackTrace();
242 | }
243 | }
244 |
245 | @Override
246 | public void surfaceDestroyed(SurfaceHolder holder)
247 | {
248 | //pause the game
249 | if (getScreen() != null)
250 | {
251 | //stop all audio while paused
252 | Audio.stop();
253 |
254 | //flag the thread as paused
255 | getThread().setPause(false);
256 |
257 | //set the state
258 | getScreen().setState(State.Paused);
259 | }
260 | else
261 | {
262 | //if the screen does not exist, just exit the game
263 | getActivity().finish();
264 | }
265 | }
266 |
267 | @Override
268 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
269 | {
270 | //does anything need to be done here?
271 | }
272 |
273 | /**
274 | * Update the game state
275 | */
276 | public void update()
277 | {
278 | try
279 | {
280 | //make sure the screen is created first before the thread starts
281 | if (getScreen() == null)
282 | {
283 | //load all assets
284 | Assets.load(getActivity());
285 |
286 | //create new screen manager
287 | this.screen = new ScreenManager(this);
288 | }
289 | else
290 | {
291 | getScreen().update();
292 | }
293 | }
294 | catch (Exception e)
295 | {
296 | e.printStackTrace();
297 | }
298 | }
299 |
300 | /**
301 | * Get the x scale factor for the motion event
302 | * @return The x ratio of the user's width compared to the default width
303 | */
304 | private float getScaleMotionX()
305 | {
306 | return this.scaleMotionX;
307 | }
308 |
309 | /**
310 | * Get the y scale factor for the motion event
311 | * @return The y ratio of the user's height compared to the default height
312 | */
313 | private float getScaleMotionY()
314 | {
315 | return this.scaleMotionY;
316 | }
317 |
318 | /**
319 | * Get the x scale factor for the render
320 | * @return The x ratio of the user's width compared to the default width
321 | */
322 | private float getScaleRenderX()
323 | {
324 | return this.scaleRenderX;
325 | }
326 |
327 | /**
328 | * Get the y scale factor for the render
329 | * @return The y ratio of the user's height compared to the default height
330 | */
331 | private float getScaleRenderY()
332 | {
333 | return this.scaleRenderY;
334 | }
335 |
336 | @Override
337 | public void onDraw(Canvas canvas)
338 | {
339 | draw(canvas);
340 | }
341 |
342 | @Override
343 | public void draw(Canvas canvas)
344 | {
345 | if (canvas != null)
346 | {
347 | //store the canvas state
348 | final int savedState = canvas.save();
349 |
350 | try
351 | {
352 | //make sure the screen object exists
353 | if (getScreen() != null)
354 | {
355 | //scale to the screen size
356 | canvas.scale(getScaleRenderX(), getScaleRenderY());
357 |
358 | //render the main screen containing the game and other screens
359 | getScreen().render(canvas);
360 | }
361 | }
362 | catch (Exception e)
363 | {
364 | e.printStackTrace();
365 | }
366 |
367 | //restore previous canvas state
368 | canvas.restoreToCount(savedState);
369 | }
370 | }
371 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/player/IPlayer.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.player;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.gamesbykevin.androidframework.resources.Disposable;
7 | import com.gamesbykevin.sokoban.level.Level;
8 |
9 | /**
10 | * Player interface
11 | * @author GOD
12 | */
13 | public interface IPlayer extends Disposable
14 | {
15 | /**
16 | * Logic to reset player
17 | * @param level The current level
18 | */
19 | public void reset(final Level level);
20 |
21 | /**
22 | * Update the player
23 | * @param level The current level
24 | */
25 | public void update(final Level level);
26 |
27 | /**
28 | * Render the player
29 | * @param canvas Object used to write pixel data
30 | * @param paint Object containing font metrics
31 | * @throws Exception
32 | */
33 | public void render(final Canvas canvas, final Paint paint) throws Exception;
34 | }
35 |
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/player/Player.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.player;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.gamesbykevin.androidframework.anim.Animation;
7 | import com.gamesbykevin.androidframework.base.Cell;
8 | import com.gamesbykevin.androidframework.base.Entity;
9 | import com.gamesbykevin.androidframework.resources.Images;
10 | import com.gamesbykevin.androidframework.text.TimeFormat;
11 | import com.gamesbykevin.sokoban.assets.Assets;
12 | import com.gamesbykevin.sokoban.level.Level;
13 | import com.gamesbykevin.sokoban.level.LevelHelper;
14 | import com.gamesbykevin.sokoban.level.tile.TileHelper;
15 | import com.gamesbykevin.sokoban.panel.GamePanel;
16 | import com.gamesbykevin.sokoban.thread.MainThread;
17 |
18 | /**
19 | * The player that moves the blocks
20 | * @author GOD
21 | */
22 | public class Player extends Entity implements IPlayer
23 | {
24 | //the target for the player when it is moved
25 | private Cell target;
26 |
27 | //did the user select the player
28 | private boolean selected = false;
29 |
30 | //speed to move
31 | public static final double VELOCITY = 0.25;
32 |
33 | //player velocity when debugging
34 | public static final double VELOCITY_DEBUG = 0.1;
35 |
36 | //the number of moves the player has made
37 | public int moves = 0;
38 |
39 | //store the previous location in case we want to undo
40 | private double previousCol, previousRow;
41 |
42 | /**
43 | * The different animations for the player
44 | */
45 | public enum Key
46 | {
47 | WalkEast,
48 | WalkWest,
49 | WalkNorth,
50 | WalkSouth,
51 | IdleEast,
52 | IdleWest,
53 | IdleNorth,
54 | IdleSouth
55 | }
56 |
57 | //track the time (milliseconds)
58 | private long totalTime = 0L;
59 |
60 | /**
61 | * The amount of milliseconds that is passed per update
62 | */
63 | private static final long TIME_LAPSED_UPDATE = (1000 / MainThread.FPS);
64 |
65 | /**
66 | * Location where player stat's are rendered
67 | */
68 | public static final int INFO_X = 5;
69 |
70 | /**
71 | * Location where player stat's are rendered
72 | */
73 | public static final int INFO_Y = 25;
74 |
75 | /**
76 | * Location where a player's personal best stat's are rendered
77 | */
78 | public static final int PERSONAL_BEST_INFO_X = 250;
79 |
80 | /**
81 | * Location where a player's personal best stat's are rendered
82 | */
83 | public static final int PERSONAL_BEST_INFO_Y = 25;
84 |
85 | /**
86 | * Create a new player
87 | */
88 | public Player()
89 | {
90 | //create new destination
91 | this.target = new Cell();
92 |
93 | //delay between each frame
94 | final int delay = 250;
95 |
96 | //sprite key
97 | final Assets.ImageGameKey key = Assets.ImageGameKey.Sprites;
98 |
99 | //our animation object
100 | Animation animation;
101 |
102 | //walk east animation
103 | animation = new Animation(Images.getImage(key), 320, 128, 42, 58, 2, 1, 2);
104 | animation.setDelay(delay);
105 | animation.setLoop(true);
106 | getSpritesheet().add(Key.WalkEast, animation);
107 |
108 | //walk west animation
109 | animation = new Animation(Images.getImage(key), 320, 187, 42, 58, 2, 1, 2);
110 | animation.setDelay(delay);
111 | animation.setLoop(true);
112 | getSpritesheet().add(Key.WalkWest, animation);
113 |
114 | //walk north animation
115 | animation = new Animation(Images.getImage(key), 320, 305, 37, 60, 2, 1, 2);
116 | animation.setDelay(delay);
117 | animation.setLoop(true);
118 | getSpritesheet().add(Key.WalkNorth, animation);
119 |
120 | //walk south animation
121 | animation = new Animation(Images.getImage(key), 320, 245, 37, 59, 2, 1, 2);
122 | animation.setDelay(delay);
123 | animation.setLoop(true);
124 | getSpritesheet().add(Key.WalkSouth, animation);
125 |
126 | //idle facing east animation
127 | animation = new Animation(Images.getImage(key), 320, 128, 42, 58);
128 | getSpritesheet().add(Key.IdleEast, animation);
129 |
130 | //idle facing west animation
131 | animation = new Animation(Images.getImage(key), 320, 187, 42, 58);
132 | getSpritesheet().add(Key.IdleWest, animation);
133 |
134 | //idle facing north animation
135 | animation = new Animation(Images.getImage(key), 384, 0, 37, 60);
136 | getSpritesheet().add(Key.IdleNorth, animation);
137 |
138 | //idle facing south animation
139 | animation = new Animation(Images.getImage(key), 384, 65, 37, 59);
140 | getSpritesheet().add(Key.IdleSouth, animation);
141 |
142 | //default animation
143 | setAnimation(Key.IdleSouth);
144 | }
145 |
146 | @Override
147 | public void reset(final Level level)
148 | {
149 | //default animation
150 | setAnimation(Key.IdleSouth);
151 |
152 | //player is not selected
153 | setSelected(false);
154 |
155 | //set start location
156 | setCol(level.getStart());
157 | setRow(level.getStart());
158 |
159 | //set target
160 | setTarget(getCol(), getRow());
161 |
162 | //reset location
163 | updateXY(level);
164 |
165 | //reset moves back to 0
166 | setMoves(0);
167 |
168 | //reset timer
169 | this.totalTime = 0;
170 | }
171 |
172 | /**
173 | * Get the time
174 | * @return The total time elapsed
175 | */
176 | public long getTime()
177 | {
178 | return this.totalTime;
179 | }
180 |
181 | /**
182 | * Get the moves count
183 | * @return The total number of moves
184 | */
185 | public int getMoves()
186 | {
187 | return this.moves;
188 | }
189 |
190 | /**
191 | * Set the moves
192 | * @param moves The moves count
193 | */
194 | public void setMoves(final int moves)
195 | {
196 | this.moves = moves;
197 | }
198 |
199 | /**
200 | * Is the player selected
201 | * @return true=yes, false=no
202 | */
203 | public boolean isSelected()
204 | {
205 | return this.selected;
206 | }
207 |
208 | /**
209 | * Flag the player as selected
210 | * @param selected true=yes, false=no
211 | */
212 | public void setSelected(final boolean selected)
213 | {
214 | this.selected = selected;
215 | }
216 |
217 | /**
218 | * Assign the animation
219 | * @param key The key of the animation we want
220 | */
221 | public final void setAnimation(final Key key)
222 | {
223 | //assign animation
224 | getSpritesheet().setKey(key);
225 |
226 | //assign the dimensions based on the image dimensions
227 | super.setWidth(getSpritesheet().get().getImage().getWidth());
228 | super.setHeight(getSpritesheet().get().getImage().getHeight());
229 | }
230 |
231 | /**
232 | * Get the animation
233 | * @return The animation of the current key, if not set null is returned
234 | */
235 | public final Key getAnimation()
236 | {
237 | if (getSpritesheet().getKey() == null)
238 | return null;
239 |
240 | //return result
241 | return (Key)getSpritesheet().getKey();
242 | }
243 |
244 | /**
245 | * Do we have the target?
246 | * @return true if the player location matches the target location, false otherwise
247 | */
248 | public boolean hasTarget()
249 | {
250 | return (getCol() == getTarget().getCol() && getRow() == getTarget().getRow());
251 | }
252 |
253 | /**
254 | * Get the destination
255 | * @return The location where the player is headed
256 | */
257 | public Cell getTarget()
258 | {
259 | return this.target;
260 | }
261 |
262 | /**
263 | * Set the destination, and store the current location
264 | * @param col Column
265 | * @param row Row
266 | */
267 | public void setTarget(final double col, final double row)
268 | {
269 | //store in case we use the undo button
270 | this.previousCol = getCol();
271 | this.previousRow = getRow();
272 |
273 | this.target.setCol(col);
274 | this.target.setRow(row);
275 | }
276 |
277 | /**
278 | * Reset the location to the previous
279 | */
280 | public void undo()
281 | {
282 | setCol(this.previousCol);
283 | setRow(this.previousRow);
284 |
285 | setTarget(getCol(), getRow());
286 | }
287 |
288 | /**
289 | * Update the (x,y) location for the player
290 | * @param level The level we are interacting with
291 | */
292 | public void updateXY(final Level level)
293 | {
294 | //get start destination
295 | final double x = LevelHelper.getX(level, getCol());
296 | final double y = LevelHelper.getY(level, getRow());
297 |
298 | //place in the center
299 | setX(x + (TileHelper.DEFAULT_DIMENSION / 2) - (getWidth() / 2));
300 | setY(y + (TileHelper.DEFAULT_DIMENSION / 2) - (getHeight() / 2));
301 | }
302 |
303 | /**
304 | * Update the player
305 | * @param level The current level
306 | */
307 | public void update(final Level level)
308 | {
309 | //add the difference to the total time
310 | this.totalTime += TIME_LAPSED_UPDATE;
311 |
312 | if (!hasTarget())
313 | {
314 | //update the current animation
315 | getSpritesheet().get().update();
316 |
317 | //assign appropriate walking animation
318 | PlayerHelper.startWalking(this);
319 |
320 | //else the player can move, so update velocity and (column, row) since we can move
321 | PlayerHelper.manageVelocity(this);
322 |
323 | //if we made it to the target
324 | if (hasTarget())
325 | {
326 | //player is no longer selected
327 | setSelected(false);
328 |
329 | //stop the walking animation
330 | PlayerHelper.stopWalking(this);
331 | }
332 |
333 | updateRenderCoordinates(level);
334 | }
335 | }
336 |
337 | public void updateRenderCoordinates(final Level level)
338 | {
339 | if (level.canFitWindow())
340 | {
341 | //update (x,y) render coordinates
342 | updateXY(level);
343 | }
344 | else
345 | {
346 | //locate middle of screen
347 | final int middleX = (GamePanel.WIDTH / 2) - (TileHelper.DEFAULT_DIMENSION / 2);
348 | final int middleY = (GamePanel.HEIGHT / 2) - (TileHelper.DEFAULT_DIMENSION / 2);
349 |
350 | //set the start location (x,y) relative to where the player start is
351 | level.setStartLocation(
352 | middleX - (int)(getCol() * TileHelper.DEFAULT_DIMENSION),
353 | middleY - (int)(getRow() * TileHelper.DEFAULT_DIMENSION));
354 |
355 | //update (x,y) render coordinates
356 | updateXY(level);
357 | }
358 | }
359 |
360 | @Override
361 | public void dispose()
362 | {
363 | super.dispose();
364 |
365 | target = null;
366 | }
367 |
368 | @Override
369 | public void render(final Canvas canvas, final Paint paint) throws Exception
370 | {
371 | //render player animation
372 | super.render(canvas);
373 |
374 | //render current move count
375 | canvas.drawText("" + getMoves(), INFO_X, INFO_Y * 2, paint);
376 |
377 | //draw timer
378 | canvas.drawText(TimeFormat.getDescription(TimeFormat.FORMAT_3, getTime()), INFO_X, INFO_Y * 3, paint);
379 | }
380 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/player/PlayerHelper.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.player;
2 |
3 | import com.gamesbykevin.sokoban.level.Level;
4 | import com.gamesbykevin.sokoban.level.tile.TileHelper;
5 | import com.gamesbykevin.sokoban.target.Target;
6 | import com.gamesbykevin.sokoban.thread.MainThread;
7 |
8 | /**
9 | * Player helper methods
10 | * @author GOD
11 | */
12 | public class PlayerHelper
13 | {
14 | /**
15 | * Assign the specified player the correct walking animation
16 | * @param player The player we want to assign animation
17 | */
18 | public static void startWalking(final Player player)
19 | {
20 | if (player.getCol() != player.getTarget().getCol())
21 | {
22 | //if heading east
23 | if (player.getCol() < player.getTarget().getCol())
24 | {
25 | player.setAnimation(Player.Key.WalkEast);
26 | }
27 | else
28 | {
29 | player.setAnimation(Player.Key.WalkWest);
30 | }
31 | }
32 | else if (player.getRow() != player.getTarget().getRow())
33 | {
34 | //if heading south
35 | if (player.getRow() < player.getTarget().getRow())
36 | {
37 | player.setAnimation(Player.Key.WalkSouth);
38 | }
39 | else
40 | {
41 | player.setAnimation(Player.Key.WalkNorth);
42 | }
43 | }
44 | }
45 |
46 | /**
47 | * Assign the specified player the correct idle animation
48 | * @param player The player we want to assign animation
49 | */
50 | public static void stopWalking(final Player player)
51 | {
52 | //set idle animation
53 | switch (player.getAnimation())
54 | {
55 | case WalkEast:
56 | player.setAnimation(Player.Key.IdleEast);
57 | break;
58 |
59 | case WalkWest:
60 | player.setAnimation(Player.Key.IdleWest);
61 | break;
62 |
63 | case WalkNorth:
64 | player.setAnimation(Player.Key.IdleNorth);
65 | break;
66 |
67 | case WalkSouth:
68 | default:
69 | player.setAnimation(Player.Key.IdleSouth);
70 | break;
71 | }
72 | }
73 |
74 | /**
75 | * Manage the specified player's velocity and update (col, row) location
76 | * @param player The player we want to manage
77 | */
78 | public static void manageVelocity(final Player player)
79 | {
80 | //velocity will depend if debugging
81 | final double velocity = (MainThread.DEBUG) ? Player.VELOCITY_DEBUG : Player.VELOCITY;
82 |
83 | if (player.getCol() < player.getTarget().getCol())
84 | {
85 | if (player.getCol() + velocity >= player.getTarget().getCol())
86 | {
87 | player.setCol(player.getTarget().getCol());
88 | }
89 | else
90 | {
91 | player.setCol(player.getCol() + velocity);
92 | }
93 | }
94 | else if (player.getCol() > player.getTarget().getCol())
95 | {
96 | if (player.getCol() - velocity <= player.getTarget().getCol())
97 | {
98 | player.setCol(player.getTarget().getCol());
99 | }
100 | else
101 | {
102 | player.setCol(player.getCol() - velocity);
103 | }
104 | }
105 | else if (player.getRow() < player.getTarget().getRow())
106 | {
107 | if (player.getRow() + velocity >= player.getTarget().getRow())
108 | {
109 | player.setRow(player.getTarget().getRow());
110 | }
111 | else
112 | {
113 | player.setRow(player.getRow() + velocity);
114 | }
115 | }
116 | else if (player.getRow() > player.getTarget().getRow())
117 | {
118 | if (player.getRow() - velocity <= player.getTarget().getRow())
119 | {
120 | player.setRow(player.getTarget().getRow());
121 | }
122 | else
123 | {
124 | player.setRow(player.getRow() - velocity);
125 | }
126 | }
127 | }
128 |
129 | /**
130 | * Calculate the targets.
131 | * We will determine the target of the player, as well as the neighboring block (if exists)
132 | * @param player The player we are checking
133 | * @param level Current level in play
134 | */
135 | public static void calculateTargets(final Player player, final Level level)
136 | {
137 | //make sure all targets in a level have the current destination marked
138 | for (Target block : level.getCurrent())
139 | {
140 | //assign current location so the undo is correct
141 | block.setDestination(block.getCol(), block.getRow());
142 | }
143 |
144 | //the neighboring locations
145 | final int col1, row1;
146 | final int col2, row2;
147 |
148 | //determine where the neighbor locations are
149 | if (player.getCol() < player.getTarget().getCol())
150 | {
151 | col1 = (int)player.getCol() + 1;
152 | row1 = (int)player.getRow();
153 | col2 = col1 + 1;
154 | row2 = row1;
155 | }
156 | else if (player.getCol() > player.getTarget().getCol())
157 | {
158 | col1 = (int)player.getCol() - 1;
159 | row1 = (int)player.getRow();
160 | col2 = col1 - 1;
161 | row2 = row1;
162 | }
163 | else if (player.getRow() < player.getTarget().getRow())
164 | {
165 | col1 = (int)player.getCol();
166 | row1 = (int)player.getRow() + 1;
167 | col2 = col1;
168 | row2 = row1 + 1;
169 | }
170 | else
171 | {
172 | //(player.getRow() > player.getTarget().getRow())
173 | col1 = (int)player.getCol();
174 | row1 = (int)player.getRow() - 1;
175 | col2 = col1;
176 | row2 = row1 - 1;
177 | }
178 |
179 | //if there is a wall directly next door
180 | if (TileHelper.isWall(level.getType(col1, row1)))
181 | {
182 | //we won't move the target
183 | player.setTarget(player.getCol(), player.getRow());
184 | }
185 | else
186 | {
187 | //if there is a block next door, lets see if we can move it
188 | if (level.getBlock(col1, row1) != null)
189 | {
190 | //if there is a wall or block on the other end, the player won't be able to move
191 | if (TileHelper.isWall(level.getType(col2, row2)) || level.getBlock(col2, row2) != null)
192 | {
193 | //we won't move the target
194 | player.setTarget(player.getCol(), player.getRow());
195 | }
196 | else
197 | {
198 | //player can move to the next location
199 | player.setTarget(col1, row1);
200 |
201 | //move the block as well
202 | level.getBlock(col1, row1).setDestination(col2, row2);
203 |
204 | //increase move count
205 | player.setMoves(player.getMoves() + 1);
206 | }
207 | }
208 | else
209 | {
210 | //player can move to the next location
211 | player.setTarget(col1, row1);
212 |
213 | //increase move count
214 | player.setMoves(player.getMoves() + 1);
215 | }
216 | }
217 | }
218 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/screen/ExitScreen.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.screen;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.view.MotionEvent;
8 |
9 | import com.gamesbykevin.androidframework.awt.Button;
10 | import com.gamesbykevin.androidframework.resources.Audio;
11 | import com.gamesbykevin.androidframework.resources.Disposable;
12 | import com.gamesbykevin.androidframework.resources.Images;
13 | import com.gamesbykevin.androidframework.screen.Screen;
14 | import com.gamesbykevin.sokoban.assets.Assets;
15 | import com.gamesbykevin.sokoban.panel.GamePanel;
16 | import java.util.HashMap;
17 |
18 | /**
19 | * The exit screen, when the player wants to go back to the menu
20 | * @author GOD
21 | */
22 | public class ExitScreen implements Screen, Disposable
23 | {
24 | /**
25 | * Custom message displayed on screen
26 | */
27 | private static final String MESSAGE = "Go back to menu?";
28 |
29 | //where our message is to be rendered
30 | private final int messageX, messageY;
31 |
32 | //our main screen reference
33 | private final ScreenManager screen;
34 |
35 | //object to paint background
36 | private Paint paint;
37 |
38 | //all of the buttons for the player to control
39 | private HashMap buttons;
40 |
41 | /**
42 | * The dimensions of the buttons
43 | */
44 | private static final int BUTTON_DIMENSION = 96;
45 |
46 | /**
47 | * Font size for the message
48 | */
49 | private static final float MESSAGE_FONT_SIZE = 28f;
50 |
51 | public ExitScreen(final ScreenManager screen)
52 | {
53 | //store our parent reference
54 | this.screen = screen;
55 |
56 | //create paint text object
57 | this.paint = new Paint(screen.getPaint());
58 | this.paint.setColor(Color.WHITE);
59 | this.paint.setTextSize(MESSAGE_FONT_SIZE);
60 |
61 | //create temporary rectangle
62 | Rect tmp = new Rect();
63 |
64 | //get the rectangle around the message
65 | paint.getTextBounds(MESSAGE, 0, MESSAGE.length(), tmp);
66 |
67 | //calculate where text message is to be rendered
68 | messageX = (GamePanel.WIDTH / 2) - (tmp.width() / 2);
69 | messageY = (GamePanel.HEIGHT / 2) - (tmp.height() / 2);
70 |
71 | //create buttons
72 | this.buttons = new HashMap();
73 | this.buttons.put(Assets.ImageMenuKey.Cancel, new Button(Images.getImage(Assets.ImageMenuKey.Cancel)));
74 | this.buttons.put(Assets.ImageMenuKey.Confirm, new Button(Images.getImage(Assets.ImageMenuKey.Confirm)));
75 |
76 | //position the buttons below the message
77 | final int y = messageY + tmp.height();
78 |
79 | //position buttons
80 | this.buttons.get(Assets.ImageMenuKey.Confirm).setX(messageX);
81 | this.buttons.get(Assets.ImageMenuKey.Confirm).setY(y);
82 | this.buttons.get(Assets.ImageMenuKey.Cancel).setX(messageX + tmp.width() - BUTTON_DIMENSION);
83 | this.buttons.get(Assets.ImageMenuKey.Cancel).setY(y);
84 |
85 | //set the bounds of each button
86 | for (Button button : buttons.values())
87 | {
88 | button.setWidth(BUTTON_DIMENSION);
89 | button.setHeight(BUTTON_DIMENSION);
90 | button.updateBounds();
91 | }
92 | }
93 |
94 | /**
95 | * Reset any necessary screen elements here
96 | */
97 | @Override
98 | public void reset()
99 | {
100 | //do we need anything here
101 | }
102 |
103 | @Override
104 | public boolean update(final int action, final float x, final float y) throws Exception
105 | {
106 | if (action == MotionEvent.ACTION_UP)
107 | {
108 | if (buttons.get(Assets.ImageMenuKey.Cancel).contains(x, y))
109 | {
110 | //if cancel, go back to game
111 | screen.setState(ScreenManager.State.Running);
112 |
113 | //play sound effect
114 | Audio.play(Assets.AudioMenuKey.Selection);
115 |
116 | //return true;
117 | return false;
118 | }
119 | else if (buttons.get(Assets.ImageMenuKey.Confirm).contains(x, y))
120 | {
121 | //if confirm, go back to menu
122 | screen.setState(ScreenManager.State.Ready);
123 |
124 | //play sound effect
125 | Audio.play(Assets.AudioMenuKey.Selection);
126 |
127 | //return false;
128 | return false;
129 | }
130 | }
131 |
132 | //yes we want additional motion events
133 | return true;
134 | }
135 |
136 | @Override
137 | public void update() throws Exception
138 | {
139 | //nothing needed to update here
140 | }
141 |
142 | @Override
143 | public void render(final Canvas canvas) throws Exception
144 | {
145 | if (paint != null)
146 | {
147 | //draw text
148 | canvas.drawText(MESSAGE, messageX, messageY, paint);
149 | }
150 |
151 | buttons.get(Assets.ImageMenuKey.Cancel).render(canvas);
152 | buttons.get(Assets.ImageMenuKey.Confirm).render(canvas);
153 | }
154 |
155 | @Override
156 | public void dispose()
157 | {
158 | if (buttons != null)
159 | {
160 | for (Button button : buttons.values())
161 | {
162 | if (button != null)
163 | {
164 | button.dispose();
165 | button = null;
166 | }
167 | }
168 |
169 | buttons.clear();
170 | buttons = null;
171 | }
172 |
173 | if (paint != null)
174 | paint = null;
175 | }
176 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/screen/GameScreen.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.screen;
2 |
3 | import android.graphics.Canvas;
4 | import com.gamesbykevin.androidframework.resources.Disposable;
5 | import com.gamesbykevin.androidframework.screen.Screen;
6 | import com.gamesbykevin.sokoban.assets.Assets;
7 | import com.gamesbykevin.sokoban.game.Game;
8 |
9 | /**
10 | * The game screen that contains the game
11 | * @author GOD
12 | */
13 | public class GameScreen implements Screen, Disposable
14 | {
15 | //our object containing the main game functionality
16 | private Game game;
17 |
18 | //our main screen reference
19 | private final ScreenManager screen;
20 |
21 | public GameScreen(final ScreenManager screen)
22 | {
23 | this.screen = screen;
24 | }
25 |
26 | protected Game getGame()
27 | {
28 | return this.game;
29 | }
30 |
31 | /**
32 | * Create game object
33 | * @throws Exception
34 | */
35 | public void createGame() throws Exception
36 | {
37 | if (getGame() == null)
38 | this.game = new Game(screen);
39 |
40 | //reset the game
41 | getGame().reset(Assets.TextKey.values()[screen.getScreenOptions().getIndex(OptionsScreen.ButtonKey.Difficulty)]);
42 | }
43 |
44 | /**
45 | * Reset any necessary screen elements here
46 | */
47 | @Override
48 | public void reset()
49 | {
50 | //anything need to be reset here
51 | }
52 |
53 | @Override
54 | public boolean update(final int action, final float x, final float y) throws Exception
55 | {
56 | if (getGame() != null)
57 | getGame().update(action, x, y);
58 |
59 | return true;
60 | }
61 |
62 | @Override
63 | public void update() throws Exception
64 | {
65 | if (getGame() != null)
66 | getGame().update();
67 | }
68 |
69 | @Override
70 | public void render(final Canvas canvas) throws Exception
71 | {
72 | //render game if exists
73 | if (getGame() != null)
74 | getGame().render(canvas);
75 | }
76 |
77 | @Override
78 | public void dispose()
79 | {
80 | if (game != null)
81 | {
82 | game.dispose();
83 | game = null;
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/src/com/gamesbykevin/sokoban/screen/GameoverScreen.java:
--------------------------------------------------------------------------------
1 | package com.gamesbykevin.sokoban.screen;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Rect;
5 | import android.util.SparseArray;
6 | import android.view.MotionEvent;
7 |
8 | import com.gamesbykevin.androidframework.awt.Button;
9 | import com.gamesbykevin.androidframework.resources.Audio;
10 | import com.gamesbykevin.androidframework.resources.Disposable;
11 | import com.gamesbykevin.androidframework.resources.Images;
12 | import com.gamesbykevin.androidframework.screen.Screen;
13 | import com.gamesbykevin.sokoban.screen.MenuScreen;
14 | import com.gamesbykevin.sokoban.screen.ScreenManager;
15 | import com.gamesbykevin.sokoban.MainActivity;
16 | import com.gamesbykevin.sokoban.assets.Assets;
17 | import com.gamesbykevin.sokoban.panel.GamePanel;
18 |
19 | /**
20 | * The game over screen
21 | * @author GOD
22 | */
23 | public class GameoverScreen implements Screen, Disposable
24 | {
25 | //our main screen reference
26 | private final ScreenManager screen;
27 |
28 | //the message to display
29 | private String message = "";
30 |
31 | //where we draw the image
32 | private int messageX = 0, messageY = 0;
33 |
34 | //time we have displayed text
35 | private long time;
36 |
37 | /**
38 | * The amount of time to wait until we render the game over menu
39 | */
40 | private static final long DELAY_MENU_DISPLAY = 1250L;
41 |
42 | //do we display the menu
43 | private boolean display = false;
44 |
45 | /**
46 | * The text to display for the new game
47 | */
48 | private static final String BUTTON_TEXT_NEW_GAME = "Next";
49 |
50 | /**
51 | * The text to display to retry
52 | */
53 | private static final String BUTTON_TEXT_REPLAY = "Retry";
54 |
55 | /**
56 | * The text to display for level select
57 | */
58 | private static final String BUTTON_TEXT_LEVEL_SELECT = "Levels";
59 |
60 | /**
61 | * The text to display for the menu
62 | */
63 | private static final String BUTTON_TEXT_MENU = "Menu";
64 |
65 | //list of buttons
66 | private SparseArray