├── .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