├── .classpath ├── .gitignore ├── .project ├── AndroidManifest.xml ├── LICENSE.md ├── README.md ├── assets └── fonts │ └── Molot.otf ├── extra_assets ├── player_unit.png ├── tiles │ ├── tile_boxbrown1.png │ ├── tile_brick10.png │ ├── tile_brick11.png │ ├── tile_brick12.png │ ├── tile_brick13.png │ ├── tile_brick15.png │ ├── tile_brick16.png │ ├── tile_brick17.png │ ├── tile_brick19.png │ ├── tile_brick20.png │ ├── tile_brick21.png │ ├── tile_brick22.png │ ├── tile_brick23.png │ ├── tile_brick24.png │ ├── tile_brick25.png │ ├── tile_brick26.png │ ├── tile_brick27.png │ ├── tile_brick28.png │ ├── tile_brick29.png │ ├── tile_brick30.png │ ├── tile_brick31.png │ ├── tile_brick32.png │ ├── tile_brick33.png │ ├── tile_brick34.png │ ├── tile_brick35.png │ ├── tile_brick36.png │ ├── tile_brick5.png │ ├── tile_button01_frame1.png │ ├── tile_button01_frame2.png │ ├── tile_button02_frame1.png │ ├── tile_button02_frame2.png │ ├── tile_energy_ball01.png │ ├── tile_exit1.png │ ├── tile_field_horizontal.png │ ├── tile_field_vertical.png │ ├── tile_goo1_frame1.png │ ├── tile_goo1_frame2.png │ ├── tile_goo2.png │ ├── tile_lasergate_horizontal.png │ └── tile_lasergate_vertical.png └── ui │ ├── canvas_bg_01.png │ ├── ctrl_beam_slider.png │ ├── ctrl_left_arrow.png │ ├── ctrl_message_close.png │ ├── ctrl_right_arrow.png │ ├── dialog_bg_01.png │ ├── icon.png │ ├── settings_btn_off.png │ ├── settings_btn_on.png │ └── ui_out_of_energy.png ├── project.properties ├── res ├── drawable-hdpi │ ├── canvas_bg_01.png │ ├── ctrl_down_arrow.png │ ├── ctrl_left_arrow.png │ ├── ctrl_right_arrow.png │ ├── ctrl_up_arrow.png │ ├── icon.png │ ├── player_unit.png │ ├── tile_01.png │ ├── tile_02.png │ ├── tile_03.png │ ├── tile_04.png │ ├── tile_05.png │ ├── tile_06.png │ ├── tile_07.png │ ├── tile_danger_01.png │ └── tile_exit.png ├── drawable-mdpi │ ├── canvas_bg_01.png │ ├── ctrl_down_arrow.png │ ├── ctrl_left_arrow.png │ ├── ctrl_right_arrow.png │ ├── ctrl_up_arrow.png │ ├── icon.png │ ├── player_unit.png │ ├── tile_01.png │ ├── tile_02.png │ ├── tile_03.png │ ├── tile_04.png │ ├── tile_05.png │ ├── tile_06.png │ ├── tile_07.png │ ├── tile_danger_01.png │ └── tile_exit.png ├── layout │ └── about.xml ├── menu │ └── menu.xml └── values │ ├── dimensions.xml │ └── strings.xml └── src └── org └── ruscoe └── example └── tilegame ├── About.java ├── GameImage.java ├── GameTile.java ├── GameUi.java ├── GameUnit.java ├── GameView.java ├── Play.java ├── PlayerUnit.java └── data ├── GameDAO.java ├── GameLevelTileData.java └── GameTileData.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /gen 3 | /libs 4 | lint.xml 5 | proguard.cfg -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Android Tile Based Game 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 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Dan Ruscoe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Tile-Based Game 2 | 3 | This is an example of a basic tile-based, 2D game using Android's Canvas. It can be used as a base for your own games. 4 | 5 | This code provides a simple way to build maps based on your own tiles, player movement / tracking and detection of collisions with any number of different tile types. 6 | ##mvc design pattern 7 | ![Android Tile-Based Game screen shot](http://ruscoe.org/assets/images/misc/github/android-tile-game.png) 8 | 9 | ## Requirements 10 | 11 | * [Android SDK](http://developer.android.com/sdk/index.html) 12 | * Android 2.2 platform 13 | 14 | ## Usage 15 | 16 | * Import the Android Tile-Based Game project into Eclipse. 17 | * Build the project as an Android application. 18 | 19 | ## Important Files 20 | 21 | ``` 22 | src/org/ruscoe/example/tilegame/data/GameDAO.java 23 | ``` 24 | 25 | This file populates the games database with tile and map data. 26 | 27 | The file contains an example of custom tile definitions and how to use those tiles to build custom maps for your game's levels. 28 | 29 | ``` 30 | src/org/ruscoe/example/tilegame/GameView.java 31 | ``` 32 | 33 | This generates the game view and handles all game logic and user input. 34 | 35 | The function ```parseGameLevelData``` shows how the tile and map data in the database is translated into a playable game level. 36 | 37 | ## License 38 | 39 | Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php). 40 | -------------------------------------------------------------------------------- /assets/fonts/Molot.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/assets/fonts/Molot.otf -------------------------------------------------------------------------------- /extra_assets/player_unit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/player_unit.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_boxbrown1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_boxbrown1.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick10.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick11.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick12.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick13.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick15.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick16.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick17.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick19.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick20.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick21.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick22.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick23.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick24.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick25.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick26.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick27.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick28.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick29.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick30.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick31.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick32.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick33.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick34.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick35.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick36.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_brick5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_brick5.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_button01_frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_button01_frame1.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_button01_frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_button01_frame2.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_button02_frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_button02_frame1.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_button02_frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_button02_frame2.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_energy_ball01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_energy_ball01.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_exit1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_exit1.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_field_horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_field_horizontal.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_field_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_field_vertical.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_goo1_frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_goo1_frame1.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_goo1_frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_goo1_frame2.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_goo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_goo2.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_lasergate_horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_lasergate_horizontal.png -------------------------------------------------------------------------------- /extra_assets/tiles/tile_lasergate_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/tiles/tile_lasergate_vertical.png -------------------------------------------------------------------------------- /extra_assets/ui/canvas_bg_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/canvas_bg_01.png -------------------------------------------------------------------------------- /extra_assets/ui/ctrl_beam_slider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/ctrl_beam_slider.png -------------------------------------------------------------------------------- /extra_assets/ui/ctrl_left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/ctrl_left_arrow.png -------------------------------------------------------------------------------- /extra_assets/ui/ctrl_message_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/ctrl_message_close.png -------------------------------------------------------------------------------- /extra_assets/ui/ctrl_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/ctrl_right_arrow.png -------------------------------------------------------------------------------- /extra_assets/ui/dialog_bg_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/dialog_bg_01.png -------------------------------------------------------------------------------- /extra_assets/ui/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/icon.png -------------------------------------------------------------------------------- /extra_assets/ui/settings_btn_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/settings_btn_off.png -------------------------------------------------------------------------------- /extra_assets/ui/settings_btn_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/settings_btn_on.png -------------------------------------------------------------------------------- /extra_assets/ui/ui_out_of_energy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/extra_assets/ui/ui_out_of_energy.png -------------------------------------------------------------------------------- /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 use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-8 12 | -------------------------------------------------------------------------------- /res/drawable-hdpi/canvas_bg_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/canvas_bg_01.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ctrl_down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/ctrl_down_arrow.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ctrl_left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/ctrl_left_arrow.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ctrl_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/ctrl_right_arrow.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ctrl_up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/ctrl_up_arrow.png -------------------------------------------------------------------------------- /res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-hdpi/player_unit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/player_unit.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_01.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_02.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_03.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_04.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_05.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_06.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_07.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_danger_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_danger_01.png -------------------------------------------------------------------------------- /res/drawable-hdpi/tile_exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-hdpi/tile_exit.png -------------------------------------------------------------------------------- /res/drawable-mdpi/canvas_bg_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/canvas_bg_01.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ctrl_down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/ctrl_down_arrow.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ctrl_left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/ctrl_left_arrow.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ctrl_right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/ctrl_right_arrow.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ctrl_up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/ctrl_up_arrow.png -------------------------------------------------------------------------------- /res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /res/drawable-mdpi/player_unit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/player_unit.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_01.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_02.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_03.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_04.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_05.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_06.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_07.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_danger_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_danger_01.png -------------------------------------------------------------------------------- /res/drawable-mdpi/tile_exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruscoe/Android-Tile-Based-Game/ea3b802fb72aa4a5519017dd4f40b3541777e24a/res/drawable-mdpi/tile_exit.png -------------------------------------------------------------------------------- /res/layout/about.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 24 | 25 | 34 | 35 | 45 | 46 | -------------------------------------------------------------------------------- /res/menu/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /res/values/dimensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20dp 4 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tile Game Example 4 | 5 | Tile game example using Android canvas. 6 | The code used to create this example is open-source: 7 | http://ruscoe.org/code/ 8 | 9 | About 10 | Exit 11 | 12 | a 13 | x 14 | 15 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/About.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import org.ruscoe.example.tilegame.R; 4 | import android.app.Activity; 5 | import android.os.Bundle; 6 | 7 | /** 8 | * Displays information about this application. 9 | * 10 | * @author Dan Ruscoe (ruscoe.org) 11 | * @version 1.0 12 | */ 13 | public class About extends Activity 14 | { 15 | /** Called when the activity is first created. */ 16 | @Override 17 | public void onCreate(Bundle savedInstanceState) 18 | { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.about); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/GameImage.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | 7 | /** 8 | * The GameImage class represents an image used in the game. 9 | * 10 | * Each instance contains a Bitmap image, a width / height 11 | * and an on-screen position. 12 | * 13 | * @author Dan Ruscoe (ruscoe.org) 14 | * @version 1.0 15 | */ 16 | public class GameImage 17 | { 18 | protected Bitmap mImg = null; 19 | protected int mX = 0; 20 | protected int mY = 0; 21 | protected int mWidth = 0; 22 | protected int mHeight = 0; 23 | 24 | public GameImage(Context context) 25 | { 26 | } 27 | 28 | public GameImage(Context context, int drawable) 29 | { 30 | this.setDrawable(context, drawable); 31 | } 32 | 33 | public void setDrawable(Context context, int drawable) 34 | { 35 | BitmapFactory.Options opts = new BitmapFactory.Options(); 36 | opts.inJustDecodeBounds = true; 37 | this.mImg = BitmapFactory.decodeResource(context.getResources(), drawable); 38 | 39 | mWidth = this.mImg.getWidth(); 40 | mHeight = this.mImg.getHeight(); 41 | } 42 | 43 | public void setBitmap(Bitmap bitmap) 44 | { 45 | if (bitmap != null) 46 | { 47 | this.mImg = bitmap; 48 | this.mWidth = bitmap.getWidth(); 49 | this.mHeight = bitmap.getHeight(); 50 | } 51 | } 52 | 53 | public Bitmap getBitmap() 54 | { 55 | return this.mImg; 56 | } 57 | 58 | public int getWidth() 59 | { 60 | return this.mWidth; 61 | } 62 | 63 | public int getHeight() 64 | { 65 | return this.mHeight; 66 | } 67 | 68 | void setX(int x) 69 | { 70 | this.mX = x; 71 | } 72 | 73 | public int getX() 74 | { 75 | return this.mX; 76 | } 77 | 78 | public void setY(int y) 79 | { 80 | this.mY = y; 81 | } 82 | 83 | public int getY() 84 | { 85 | return this.mY; 86 | } 87 | 88 | public void setCenterX(int centerX) 89 | { 90 | this.mX = (centerX - (this.getWidth() / 2)); 91 | } 92 | 93 | public int getCenterX() 94 | { 95 | return (mX + (this.getWidth() / 2)); 96 | } 97 | 98 | public void setCenterY(int centerY) 99 | { 100 | this.mY = (centerY - (this.getHeight() / 2)); 101 | } 102 | 103 | public int getCenterY() 104 | { 105 | return (mY + (this.getHeight() / 2)); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/GameTile.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import android.content.Context; 4 | import android.graphics.Point; 5 | import android.graphics.Rect; 6 | 7 | /** 8 | * An extension of GameImage, GameTile represents a tile used to build 9 | * a level in the game. 10 | * 11 | * In addition to the GameImage properties, game tiles include a unique 12 | * key, tile type identifier and visibility setting. 13 | * 14 | * @author Dan Ruscoe (ruscoe.org) 15 | * @version 1.0 16 | */ 17 | public class GameTile extends GameImage 18 | { 19 | public static final int TYPE_EMPTY = 0; 20 | public static final int TYPE_OBSTACLE = 1; 21 | public static final int TYPE_DANGEROUS = 2; 22 | public static final int TYPE_EXIT = 3; 23 | 24 | private int mKey = 0; 25 | private int mType = TYPE_EMPTY; 26 | 27 | private boolean mVisible = true; 28 | 29 | private Rect mCollisionRect = null; 30 | 31 | public GameTile(Context context, Point point) 32 | { 33 | super(context); 34 | 35 | this.mX = point.x; 36 | this.mY = point.y; 37 | } 38 | 39 | public GameTile(Context context, int drawable, Point point) 40 | { 41 | super(context, drawable); 42 | 43 | this.mX = point.x; 44 | this.mY = point.y; 45 | } 46 | 47 | public boolean isDangerous() 48 | { 49 | return (this.mType == TYPE_DANGEROUS); 50 | } 51 | 52 | public boolean getCollision(float x, float y, int width, int height) 53 | { 54 | if (this.mCollisionRect == null) 55 | { 56 | this.mCollisionRect = new Rect((int)x, (int)y, ((int)x + width), ((int)y + height)); 57 | } 58 | else 59 | { 60 | this.mCollisionRect.set((int)x, (int)y, ((int)x + width), ((int)y + height)); 61 | } 62 | 63 | return (this.mCollisionRect.intersects(this.mX, this.mY, (this.mX + getWidth()), (this.mY + getHeight()))); 64 | } 65 | 66 | public boolean getCollision(GameUnit gameUnit) 67 | { 68 | return (gameUnit.getRect().intersects(this.mX, this.mY, (this.mX + mWidth), (this.mY + mHeight))); 69 | } 70 | 71 | public int getKey() 72 | { 73 | return this.mKey; 74 | } 75 | 76 | public void setKey(int key) 77 | { 78 | this.mKey = key; 79 | } 80 | 81 | public int getType() 82 | { 83 | return this.mType; 84 | } 85 | 86 | public void setType(int type) 87 | { 88 | this.mType = type; 89 | } 90 | 91 | public int getX() 92 | { 93 | return this.mX; 94 | } 95 | 96 | public void setX(int x) 97 | { 98 | this.mX = x; 99 | } 100 | 101 | public int getY() 102 | { 103 | return this.mY; 104 | } 105 | 106 | public void setY(int y) 107 | { 108 | this.mY = y; 109 | } 110 | 111 | public boolean isVisible() 112 | { 113 | return this.mVisible; 114 | } 115 | 116 | public void setVisible(boolean visible) 117 | { 118 | this.mVisible = visible; 119 | } 120 | 121 | public boolean isCollisionTile() 122 | { 123 | return ((this.mType != GameTile.TYPE_EMPTY) && this.mVisible); 124 | } 125 | 126 | public boolean isBlockerTile() 127 | { 128 | if (this.mType == GameTile.TYPE_EMPTY) 129 | { 130 | return false; 131 | } 132 | 133 | return true; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/GameUi.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * An extension of GameImage, GameUi represents a UI element provided 7 | * for the user. 8 | * 9 | * In addition to the GameImage properties, UI elements include a 10 | * state identifier, allowing buttons to appear in different states 11 | * with associated drawables. 12 | * 13 | * @author Dan Ruscoe (ruscoe.org) 14 | * @version 1.0 15 | */ 16 | public class GameUi extends GameUnit 17 | { 18 | public static final int STATE_NORMAL = 1; 19 | public static final int STATE_INACTIVE = 2; 20 | public static final int STATE_ACTIVE = 3; 21 | public static final int STATE_READY = 4; 22 | 23 | private int mState = STATE_NORMAL; 24 | 25 | private int mDrawableStateNormal = 0; 26 | private int mDrawableStateInactive = 0; 27 | private int mDrawableStateActive = 0; 28 | private int mDrawableStateReady = 0; 29 | private boolean mVisible = true; 30 | 31 | private Context mContext = null; 32 | 33 | public GameUi(Context context, int drawable) 34 | { 35 | super(context, drawable); 36 | this.mContext = context; 37 | this.mDrawableStateNormal = drawable; 38 | } 39 | 40 | public void setStateNormal() 41 | { 42 | this.mState = STATE_NORMAL; 43 | 44 | if (this.mDrawableStateNormal > 0) 45 | { 46 | this.setDrawable(this.mContext, this.mDrawableStateNormal); 47 | } 48 | } 49 | 50 | public void setStateInactive() 51 | { 52 | this.mState = STATE_INACTIVE; 53 | 54 | if (this.mDrawableStateInactive > 0) 55 | { 56 | this.setDrawable(this.mContext, this.mDrawableStateInactive); 57 | } 58 | } 59 | 60 | public void setStateActive() 61 | { 62 | this.mState = STATE_ACTIVE; 63 | 64 | if (this.mDrawableStateActive > 0) 65 | { 66 | this.setDrawable(this.mContext, this.mDrawableStateActive); 67 | } 68 | } 69 | 70 | public void setStateReady() 71 | { 72 | this.mState = STATE_READY; 73 | 74 | if (this.mDrawableStateReady > 0) 75 | { 76 | this.setDrawable(this.mContext, this.mDrawableStateReady); 77 | } 78 | } 79 | 80 | public int getDrawableStateNormal() 81 | { 82 | return this.mDrawableStateNormal; 83 | } 84 | 85 | public void setDrawableStateNormal(int mDrawableStateNormal) 86 | { 87 | this.mDrawableStateNormal = mDrawableStateNormal; 88 | } 89 | 90 | public int getDrawableStateInactive() 91 | { 92 | return this.mDrawableStateInactive; 93 | } 94 | 95 | public void setDrawableStateInactive(int mDrawableStateInactive) 96 | { 97 | this.mDrawableStateInactive = mDrawableStateInactive; 98 | } 99 | 100 | public int getDrawableStateActive() 101 | { 102 | return this.mDrawableStateActive; 103 | } 104 | 105 | public void setDrawableStateActive(int mDrawableStateActive) 106 | { 107 | this.mDrawableStateActive = mDrawableStateActive; 108 | } 109 | 110 | public int getDrawableStateReady() 111 | { 112 | return this.mDrawableStateReady; 113 | } 114 | 115 | public void setDrawableStateReady(int mDrawableStateReady) 116 | { 117 | this.mDrawableStateReady = mDrawableStateReady; 118 | } 119 | 120 | public boolean isStateNormal() 121 | { 122 | return (this.mState == STATE_NORMAL); 123 | } 124 | 125 | public boolean isStateInactive() 126 | { 127 | return (this.mState == STATE_INACTIVE); 128 | } 129 | 130 | public boolean isVisible() 131 | { 132 | return this.mVisible; 133 | } 134 | 135 | public void setVisible(boolean visible) 136 | { 137 | this.mVisible = visible; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/GameUnit.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | 6 | /** 7 | * An extension of GameImage, GameUnit represents a playable or non-playable 8 | * unit in the game. 9 | * 10 | * In addition to the GameImage properties, game units include a unique ID, 11 | * based on a static count property. This is useful when creating, and later 12 | * modifying, multiple units. 13 | * 14 | * @author Dan Ruscoe (ruscoe.org) 15 | * @version 1.0 16 | */ 17 | public class GameUnit extends GameImage 18 | { 19 | private int id; 20 | private static int count = 1; 21 | 22 | public GameUnit(Context context, int drawable) 23 | { 24 | super(context, drawable); 25 | 26 | id=count; 27 | count++; 28 | } 29 | 30 | public Rect getRect() 31 | { 32 | Rect rect = new Rect((int)mX, (int)mY, ((int)mX + this.getWidth()), ((int)mY + this.getHeight())); 33 | return rect; 34 | } 35 | 36 | public boolean getCollision(int x, int y, int width, int height) 37 | { 38 | Rect rect = new Rect((int)x, (int)y, ((int)x + width), ((int)y + height)); 39 | return (rect.intersects((int)mX, (int)mY, ((int)mX + getWidth()), ((int)mY + getHeight()))); 40 | } 41 | 42 | public boolean getImpact(int x, int y) 43 | { 44 | if ((x >= mX) && (x <= (mX + this.getWidth()))) 45 | { 46 | if ((y >= mY) && (y <= (mY + this.getHeight()))) 47 | { 48 | return true; 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | 55 | public static int getCount() 56 | { 57 | return count; 58 | } 59 | 60 | public static void resetCount() 61 | { 62 | count = 1; 63 | } 64 | 65 | public int getId() 66 | { 67 | return id; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/GameView.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | import org.ruscoe.example.tilegame.PlayerUnit; 8 | import org.ruscoe.example.tilegame.R; 9 | import org.ruscoe.example.tilegame.data.GameLevelTileData; 10 | import org.ruscoe.example.tilegame.data.GameTileData; 11 | 12 | import android.content.Context; 13 | import android.content.res.Resources; 14 | import android.graphics.Bitmap; 15 | import android.graphics.BitmapFactory; 16 | import android.graphics.Canvas; 17 | import android.graphics.Color; 18 | import android.graphics.Paint; 19 | import android.graphics.Point; 20 | import android.graphics.Typeface; 21 | import android.os.Handler; 22 | import android.util.Log; 23 | import android.view.Display; 24 | import android.view.MotionEvent; 25 | import android.view.SurfaceHolder; 26 | import android.view.SurfaceView; 27 | 28 | /** 29 | * The game view and main game thread. 30 | * 31 | * GameView creates a new thread (GameThread) to handle all calculations 32 | * and drawing of game components. 33 | * 34 | * GameThread contains the run() function, which serves as the game loop, 35 | * updating each cycle while the game is running. 36 | * 37 | * To see how game level data is parsed and turned into a playable, tile level, 38 | * see the function GameView.parseGameLevelData. 39 | * 40 | * @author Dan Ruscoe (ruscoe.org) 41 | * @version 1.0 42 | */ 43 | public class GameView extends SurfaceView implements SurfaceHolder.Callback 44 | { 45 | private static final int CONTROLS_PADDING = 10; 46 | 47 | private static final int START_STAGE = 1; 48 | private static final int START_LEVEL = 1; 49 | 50 | private static final int DIRECTION_UP = 1; 51 | private static final int DIRECTION_DOWN = 2; 52 | private static final int DIRECTION_LEFT = 3; 53 | private static final int DIRECTION_RIGHT = 4; 54 | 55 | public static final int STATE_RUNNING = 1; 56 | public static final int STATE_PAUSED = 2; 57 | 58 | private int mScreenXMax = 0; 59 | private int mScreenYMax = 0; 60 | private int mScreenXCenter = 0; 61 | private int mScreenYCenter = 0; 62 | private int mScreenXOffset = 0; 63 | private int mScreenYOffset = 0; 64 | 65 | private float mScreenDensity; 66 | 67 | private Context mGameContext; 68 | private Play mGameActivity; 69 | private SurfaceHolder mGameSurfaceHolder = null; 70 | 71 | private boolean updatingGameTiles = false; 72 | 73 | private GameTileData mGameTileData = null; 74 | private GameLevelTileData mGameLevelTileData = null; 75 | 76 | private PlayerUnit mPlayerUnit = null; 77 | 78 | private int mPlayerStage = START_STAGE; 79 | private int mPlayerLevel = START_LEVEL; 80 | 81 | private Bitmap mBackgroundImage = null; 82 | 83 | private int mGameState; 84 | 85 | private boolean mGameRun = true; 86 | 87 | private boolean mPlayerMoving = false; 88 | private int mPlayerVerticalDirection = 0; 89 | private int mPlayerHorizontalDirection = 0; 90 | 91 | private GameUi mCtrlUpArrow = null; 92 | private GameUi mCtrlDownArrow = null; 93 | private GameUi mCtrlLeftArrow = null; 94 | private GameUi mCtrlRightArrow = null; 95 | 96 | private Paint mUiTextPaint = null; 97 | private String mLastStatusMessage = ""; 98 | 99 | /** 100 | * Templates defining all available game tiles. 101 | */ 102 | private HashMap> mGameTileTemplates = null; 103 | 104 | /** 105 | * Bitmap instances for each game tile type. 106 | */ 107 | private HashMap mGameTileBitmaps = new HashMap(); 108 | 109 | /** 110 | * GameTile instances for each game tile used by the current level. 111 | */ 112 | private List mGameTiles = new ArrayList(); 113 | 114 | private int mPlayerStartTileX = 0; 115 | private int mPlayerStartTileY = 0; 116 | 117 | private int mTileWidth = 0; 118 | private int mTileHeight = 0; 119 | 120 | class GameThread extends Thread 121 | { 122 | public GameThread(SurfaceHolder surfaceHolder, Context context, 123 | Handler handler) 124 | { 125 | mGameSurfaceHolder = surfaceHolder; 126 | mGameContext = context; 127 | 128 | Resources res = context.getResources(); 129 | 130 | mBackgroundImage = BitmapFactory.decodeResource(res, R.drawable.canvas_bg_01); 131 | 132 | Display display = mGameActivity.getWindowManager().getDefaultDisplay(); 133 | mScreenXMax = display.getWidth(); 134 | mScreenYMax = display.getHeight(); 135 | mScreenXCenter = (mScreenXMax / 2); 136 | mScreenYCenter = (mScreenYMax / 2); 137 | 138 | setGameStartState(); 139 | } 140 | 141 | /** 142 | * Callback invoked when the surface dimensions change. 143 | */ 144 | public void setSurfaceSize(int width, int height) 145 | { 146 | // synchronized to make sure these all change atomically 147 | synchronized (mGameSurfaceHolder) 148 | { 149 | mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, 150 | width, height, true); 151 | } 152 | } 153 | 154 | /** 155 | * Sets the run status of the game loop inside the game thread. 156 | * @param boolean run - true when game should run, false otherwise. 157 | */ 158 | public void setRunning(boolean run) 159 | { 160 | mGameRun = run; 161 | } 162 | 163 | /** 164 | * Sets the game state to running. 165 | */ 166 | public void doStart() 167 | { 168 | setState(STATE_RUNNING); 169 | } 170 | 171 | /** 172 | * Sets the game state 173 | * @param int mode - May be STATE_RUNNING or STATE_PAUSED 174 | */ 175 | public void setState(int state) 176 | { 177 | mGameState = state; 178 | } 179 | 180 | /** 181 | * Contains the main game loop, which updates all elements of the game. 182 | */ 183 | @Override 184 | public void run() 185 | { 186 | while (mGameRun) 187 | { 188 | Canvas c = null; 189 | try 190 | { 191 | c = mGameSurfaceHolder.lockCanvas(null); 192 | synchronized (mGameSurfaceHolder) 193 | { 194 | if (mGameState == STATE_RUNNING) 195 | { 196 | updatePlayerUnit(); 197 | } 198 | 199 | doDraw(c); 200 | } 201 | } finally 202 | { 203 | if (c != null) 204 | { 205 | mGameSurfaceHolder.unlockCanvasAndPost(c); 206 | } 207 | } 208 | } 209 | 210 | return; 211 | } 212 | 213 | /** 214 | * Pauses the game. 215 | */ 216 | public void pause() 217 | { 218 | synchronized (mGameSurfaceHolder) 219 | { 220 | if (mGameState == STATE_RUNNING) 221 | { 222 | setState(STATE_PAUSED); 223 | } 224 | } 225 | } 226 | 227 | /** 228 | * Unpauses the game. 229 | */ 230 | public void unpause() 231 | { 232 | synchronized (mGameSurfaceHolder) 233 | { 234 | if (mGameState != STATE_RUNNING) 235 | { 236 | setState(STATE_RUNNING); 237 | } 238 | } 239 | } 240 | 241 | /** 242 | * Centers the game view around the location of the player unit. 243 | */ 244 | private void centerView() 245 | { 246 | mPlayerUnit.setUnmodifiedX(mPlayerUnit.getX() + mScreenXCenter); 247 | mPlayerUnit.setUnmodifiedY(mPlayerUnit.getY() + mScreenYCenter); 248 | 249 | mScreenXOffset = (mPlayerUnit.getX() - mScreenXCenter); 250 | mScreenYOffset = (mPlayerUnit.getY() - mScreenYCenter); 251 | 252 | mPlayerUnit.setX(mScreenXCenter); 253 | mPlayerUnit.setY(mScreenYCenter); 254 | } 255 | 256 | /** 257 | * Draws all visual elements of the game. 258 | * @param Canvas canvas 259 | */ 260 | private void doDraw(Canvas canvas) 261 | { 262 | centerView(); 263 | 264 | if (canvas != null) 265 | { 266 | canvas.drawBitmap(mBackgroundImage, 0, 0, null); 267 | 268 | if (!updatingGameTiles) 269 | { 270 | drawGameTiles(canvas); 271 | } 272 | 273 | if (mPlayerUnit != null) 274 | { 275 | canvas.drawBitmap(mPlayerUnit.getBitmap(), mPlayerUnit.getX(), 276 | mPlayerUnit.getY(), null); 277 | } 278 | 279 | drawControls(canvas); 280 | 281 | canvas.drawText(mLastStatusMessage, 30, 50, mUiTextPaint); 282 | } 283 | } 284 | 285 | /** 286 | * Draws the game tiles used in the current level. 287 | * @param Canvas canvas 288 | */ 289 | private void drawGameTiles(Canvas canvas) 290 | { 291 | int gameTilesSize = mGameTiles.size(); 292 | for (int i = 0; i < gameTilesSize; i++) 293 | { 294 | if (mGameTiles.get(i) != null) 295 | { 296 | mGameTiles.get(i).setX( 297 | mGameTiles.get(i).getX() - mScreenXOffset); 298 | mGameTiles.get(i).setY( 299 | mGameTiles.get(i).getY() - mScreenYOffset); 300 | 301 | if (mGameTiles.get(i).isVisible()) 302 | { 303 | canvas.drawBitmap(mGameTiles.get(i).getBitmap(), 304 | mGameTiles.get(i).getX(), mGameTiles.get(i) 305 | .getY(), null); 306 | } 307 | } 308 | } 309 | } 310 | 311 | /** 312 | * Draws the game controls. 313 | * @param Canvas canvas 314 | */ 315 | private void drawControls(Canvas canvas) 316 | { 317 | canvas.drawBitmap(mCtrlUpArrow.getBitmap(), mCtrlUpArrow.getX(), mCtrlUpArrow.getY(), null); 318 | canvas.drawBitmap(mCtrlDownArrow.getBitmap(), mCtrlDownArrow.getX(), mCtrlDownArrow.getY(), null); 319 | canvas.drawBitmap(mCtrlLeftArrow.getBitmap(), mCtrlLeftArrow.getX(), mCtrlLeftArrow.getY(), null); 320 | canvas.drawBitmap(mCtrlRightArrow.getBitmap(), mCtrlRightArrow.getX(), mCtrlRightArrow.getY(), null); 321 | } 322 | 323 | /** 324 | * Updates the direction, position and state of the player unit. 325 | */ 326 | private void updatePlayerUnit() 327 | { 328 | GameTile collisionTile = null; 329 | 330 | if (mPlayerMoving) 331 | { 332 | int differenceX = 0; 333 | int differenceY = 0; 334 | int newX = mPlayerUnit.getX(); 335 | int newY = mPlayerUnit.getY(); 336 | 337 | if (mPlayerHorizontalDirection != 0) 338 | { 339 | differenceX = (mPlayerHorizontalDirection == DIRECTION_RIGHT) ? getPixelValueForDensity(PlayerUnit.SPEED) : getPixelValueForDensity(-PlayerUnit.SPEED); 340 | newX = (mPlayerUnit.getX() + differenceX); 341 | } 342 | 343 | if (mPlayerVerticalDirection != 0) 344 | { 345 | differenceY = (mPlayerVerticalDirection == DIRECTION_DOWN) ? getPixelValueForDensity(PlayerUnit.SPEED) : getPixelValueForDensity(-PlayerUnit.SPEED); 346 | newY = (mPlayerUnit.getY() + differenceY); 347 | } 348 | 349 | collisionTile = getCollisionTile(newX, newY, mPlayerUnit.getWidth(), mPlayerUnit .getHeight()); 350 | 351 | if ((collisionTile != null) 352 | && collisionTile.isBlockerTile()) 353 | { 354 | handleTileCollision(collisionTile); 355 | } else 356 | { 357 | mPlayerUnit.setX(newX); 358 | mPlayerUnit.setY(newY); 359 | } 360 | } 361 | } 362 | 363 | /** 364 | * Detects a collision between a game unit and a game tile, 365 | * returns the collision tile if available. 366 | * 367 | * @param x - The X (horizontal) position of the game unit. 368 | * @param y - The Y (vertical) position of the game unit. 369 | * @param width - The width of the game unit. 370 | * @param height - The height of the game unit. 371 | * @return GameTile - The collision game tile, if available. 372 | */ 373 | private GameTile getCollisionTile(int x, int y, int width, int height) 374 | { 375 | GameTile gameTile = null; 376 | 377 | int gameTilesSize = mGameTiles.size(); 378 | for (int i = 0; i < gameTilesSize; i++) 379 | { 380 | gameTile = (GameTile) mGameTiles.get(i); 381 | if ((gameTile != null) && gameTile.isCollisionTile()) 382 | { 383 | // Make sure tiles don't collide with themselves 384 | if ((gameTile.getX() == x) && (gameTile.getY() == y)) 385 | { 386 | continue; 387 | } 388 | 389 | if (gameTile.getCollision(x, y, width, height)) 390 | { 391 | return gameTile; 392 | } 393 | } 394 | } 395 | return null; 396 | } 397 | 398 | /** 399 | * Handles a collision between the player unit and a game tile. 400 | * @param GameTile gameTile - The collision game tile. 401 | */ 402 | private void handleTileCollision(GameTile gameTile) 403 | { 404 | if (gameTile != null) 405 | { 406 | switch (gameTile.getType()) 407 | { 408 | case GameTile.TYPE_DANGEROUS: 409 | handleDangerousTileCollision(); 410 | break; 411 | case GameTile.TYPE_EXIT: 412 | handleExitTileCollision(); 413 | break; 414 | default: 415 | mLastStatusMessage = "Collision with regular tile"; 416 | } 417 | } 418 | } 419 | 420 | /** 421 | * Handles a collision between the player unit and a dangerous 422 | * game tile. 423 | */ 424 | private void handleDangerousTileCollision() 425 | { 426 | mLastStatusMessage = "Collision with dangerous tile"; 427 | } 428 | 429 | /** 430 | * Handles a collision between the player unit and an exit 431 | * game tile. 432 | */ 433 | private void handleExitTileCollision() 434 | { 435 | mLastStatusMessage = "Collision with exit tile"; 436 | } 437 | } 438 | 439 | private GameThread thread; 440 | 441 | /** 442 | * The game view. 443 | * @param Context context 444 | * @param Activity activity 445 | * @param int stage - The stage to load. 446 | * @param int level - The level to load. 447 | * @param float screenDensity - The screen density. 448 | */ 449 | public GameView(Context context, Play activity, int stage, int level, float screenDensity) 450 | { 451 | super(context); 452 | 453 | mGameContext = context; 454 | mGameActivity = activity; 455 | 456 | mScreenDensity = screenDensity; 457 | 458 | mPlayerStage = stage; 459 | mPlayerLevel = level; 460 | 461 | mGameTileData = new GameTileData(context); 462 | mGameLevelTileData = new GameLevelTileData(context); 463 | 464 | mGameTileTemplates = mGameTileData.getTilesData(); 465 | 466 | SurfaceHolder holder = getHolder(); 467 | holder.addCallback(this); 468 | 469 | // create thread only; it's started in surfaceCreated() 470 | thread = new GameThread(holder, context, null); 471 | 472 | setFocusable(true); 473 | 474 | mUiTextPaint = new Paint(); 475 | mUiTextPaint.setStyle(Paint.Style.FILL); 476 | mUiTextPaint.setColor(Color.YELLOW); 477 | mUiTextPaint.setAntiAlias(true); 478 | 479 | Typeface uiTypeface = Typeface.createFromAsset(activity.getAssets(), "fonts/Molot.otf"); 480 | if (uiTypeface != null) 481 | { 482 | mUiTextPaint.setTypeface(uiTypeface); 483 | } 484 | mUiTextPaint.setTextSize(mGameContext.getApplicationContext().getResources().getDimensionPixelSize(R.dimen.ui_text_size)); 485 | 486 | startLevel(); 487 | thread.doStart(); 488 | } 489 | 490 | /** 491 | * Gets the game thread. 492 | * @return GameThread 493 | */ 494 | public GameThread getThread() 495 | { 496 | return thread; 497 | } 498 | 499 | /** 500 | * Callback invoked when the surface dimensions change. 501 | */ 502 | public void surfaceChanged(SurfaceHolder holder, int format, int width, 503 | int height) 504 | { 505 | thread.setSurfaceSize(width, height); 506 | } 507 | 508 | /* 509 | * Callback invoked when the Surface has been created and is ready to be 510 | * used. 511 | */ 512 | public void surfaceCreated(SurfaceHolder holder) 513 | { 514 | // start the thread here so that we don't busy-wait in run() 515 | // waiting for the surface to be created 516 | 517 | if (thread.getState() == Thread.State.TERMINATED) 518 | { 519 | thread = new GameThread(holder, getContext(), new Handler()); 520 | thread.setRunning(true); 521 | thread.start(); 522 | thread.doStart(); 523 | startLevel(); 524 | } 525 | else 526 | { 527 | thread.setRunning(true); 528 | thread.start(); 529 | } 530 | } 531 | 532 | /* 533 | * Callback invoked when the Surface has been destroyed. 534 | */ 535 | public void surfaceDestroyed(SurfaceHolder holder) 536 | { 537 | boolean retry = true; 538 | thread.setRunning(false); 539 | while (retry) 540 | { 541 | try 542 | { 543 | thread.join(); 544 | retry = false; 545 | } catch (InterruptedException e) 546 | { 547 | Log.e("Tile Game Example", e.getMessage()); 548 | } 549 | } 550 | } 551 | 552 | /** 553 | * Detects and handles touch events from the user. 554 | * @param MotionEvent event 555 | * @return boolean 556 | */ 557 | @Override 558 | public boolean onTouchEvent(MotionEvent event) 559 | { 560 | int eventAction = event.getAction(); 561 | 562 | switch (eventAction) 563 | { 564 | case MotionEvent.ACTION_DOWN: 565 | 566 | if (mGameState == STATE_RUNNING) 567 | { 568 | final int x = (int) event.getX(); 569 | final int y = (int) event.getY(); 570 | 571 | if (mCtrlUpArrow.getImpact(x, y)) 572 | { 573 | Log.d("Tile Game Example", "Pressed up arrow"); 574 | mLastStatusMessage = "Moving up"; 575 | mPlayerVerticalDirection = DIRECTION_UP; 576 | mPlayerMoving = true; 577 | } 578 | else if (mCtrlDownArrow.getImpact(x, y)) 579 | { 580 | Log.d("Tile Game Example", "Pressed down arrow"); 581 | mLastStatusMessage = "Moving down"; 582 | mPlayerVerticalDirection = DIRECTION_DOWN; 583 | mPlayerMoving = true; 584 | } 585 | else if (mCtrlLeftArrow.getImpact(x, y)) 586 | { 587 | Log.d("Tile Game Example", "Pressed left arrow"); 588 | mLastStatusMessage = "Moving left"; 589 | mPlayerHorizontalDirection = DIRECTION_LEFT; 590 | mPlayerMoving = true; 591 | } 592 | else if (mCtrlRightArrow.getImpact(x, y)) 593 | { 594 | Log.d("Tile Game Example", "Pressed right arrow"); 595 | mLastStatusMessage = "Moving right"; 596 | mPlayerHorizontalDirection = DIRECTION_RIGHT; 597 | mPlayerMoving = true; 598 | } 599 | } 600 | 601 | break; 602 | case MotionEvent.ACTION_UP: 603 | case MotionEvent.ACTION_CANCEL: 604 | mPlayerMoving = false; 605 | mPlayerVerticalDirection = 0; 606 | mPlayerHorizontalDirection = 0; 607 | break; 608 | } 609 | 610 | return true; 611 | } 612 | 613 | /** 614 | * Initializes and sets the on-screen position of the game controls. 615 | */ 616 | private void setControlsStart() 617 | { 618 | if (mCtrlDownArrow == null) 619 | { 620 | mCtrlDownArrow = new GameUi(mGameContext, R.drawable.ctrl_down_arrow); 621 | 622 | mCtrlDownArrow.setX(mScreenXMax - ((mCtrlDownArrow.getWidth() * 2) + getPixelValueForDensity(CONTROLS_PADDING))); 623 | mCtrlDownArrow.setY(mScreenYMax - (mCtrlDownArrow.getHeight() + getPixelValueForDensity(CONTROLS_PADDING))); 624 | } 625 | 626 | if (mCtrlUpArrow == null) 627 | { 628 | mCtrlUpArrow = new GameUi(mGameContext, R.drawable.ctrl_up_arrow); 629 | 630 | mCtrlUpArrow.setX(mCtrlDownArrow.getX()); 631 | mCtrlUpArrow.setY(mCtrlDownArrow.getY() - (mCtrlUpArrow.getHeight() * 2)); 632 | } 633 | 634 | if (mCtrlLeftArrow == null) 635 | { 636 | mCtrlLeftArrow = new GameUi(mGameContext, R.drawable.ctrl_left_arrow); 637 | mCtrlLeftArrow.setX(mCtrlDownArrow.getX() - mCtrlLeftArrow.getWidth()); 638 | mCtrlLeftArrow.setY(mCtrlDownArrow.getY() - mCtrlLeftArrow.getHeight()); 639 | } 640 | 641 | if (mCtrlRightArrow == null) 642 | { 643 | mCtrlRightArrow = new GameUi(mGameContext, R.drawable.ctrl_right_arrow); 644 | 645 | mCtrlRightArrow.setX(mScreenXMax - (mCtrlLeftArrow.getWidth() + getPixelValueForDensity(CONTROLS_PADDING))); 646 | mCtrlRightArrow.setY(mCtrlLeftArrow.getY()); 647 | } 648 | } 649 | 650 | /** 651 | * Initializes and sets the starting location of the player unit. 652 | */ 653 | private void setPlayerStart() 654 | { 655 | if (mPlayerUnit == null) 656 | { 657 | mPlayerUnit = new PlayerUnit(mGameContext, R.drawable.player_unit); 658 | } 659 | 660 | int playerStartX = (mPlayerStartTileX * mPlayerUnit.getWidth()); 661 | int playerStartY = (mPlayerStartTileY * mPlayerUnit.getHeight()); 662 | 663 | Log.d("Tile Game Example", "Player unit starting at X: " + playerStartX + ", Y: " + playerStartY); 664 | 665 | mPlayerUnit.setX(playerStartX); 666 | mPlayerUnit.setY(playerStartY); 667 | mPlayerUnit.setUnmodifiedX(0); 668 | mPlayerUnit.setUnmodifiedY(0); 669 | } 670 | 671 | /** 672 | * Parses game level data to create a tile-based level. 673 | * Tile positioning logic expects all game tiles to 674 | * maintain a consistent width and height. 675 | */ 676 | private void parseGameLevelData() 677 | { 678 | updatingGameTiles = true; 679 | 680 | ArrayList gameLevelData = mGameLevelTileData.getGameLevelData(mPlayerStage, mPlayerLevel); 681 | 682 | String levelTileData = gameLevelData.get(GameLevelTileData.FIELD_ID_TILE_DATA); 683 | 684 | if (levelTileData == null) 685 | { 686 | return; 687 | } 688 | 689 | // Get player start position. 690 | mPlayerStartTileX = Integer.parseInt(gameLevelData.get(GameLevelTileData.FIELD_ID_PLAYER_START_TILE_X)); 691 | mPlayerStartTileY = Integer.parseInt(gameLevelData.get(GameLevelTileData.FIELD_ID_PLAYER_START_TILE_Y)); 692 | 693 | // Clear any existing loaded game tiles. 694 | mGameTiles.clear(); 695 | 696 | // Split level tile data by line. 697 | String[] tileLines = levelTileData.split(GameLevelTileData.TILE_DATA_LINE_BREAK); 698 | 699 | Bitmap bitmap = null; 700 | Point tilePoint = new Point(0, 0); 701 | int tileX = 0; 702 | int tileY = 0; 703 | 704 | int tileKey = 0; 705 | 706 | // Loop through each line of the level tile data. 707 | for (String tileLine : tileLines) 708 | { 709 | tileX = 0; 710 | 711 | // Split tile data line by tile delimiter, producing an array of tile IDs. 712 | String[] tiles = tileLine.split(","); 713 | 714 | // Loop through the tile IDs, creating a new GameTile instance for each one. 715 | for (String tile : tiles) 716 | { 717 | // Get tile definition for the current tile ID. 718 | ArrayList tileData = mGameTileTemplates.get(Integer.parseInt(tile)); 719 | 720 | // Check for valid tile data. 721 | if ((tileData != null) 722 | && (tileData.size() > 0) 723 | && (tileData.get(GameTileData.FIELD_ID_DRAWABLE) > 0)) 724 | { 725 | // Set tile position. 726 | tilePoint.x = tileX; 727 | tilePoint.y = tileY; 728 | 729 | GameTile gameTile = new GameTile(mGameContext, tilePoint); 730 | 731 | // Set tile bitmap. 732 | bitmap = setAndGetGameTileBitmap(tileData.get(GameTileData.FIELD_ID_DRAWABLE)); 733 | gameTile.setBitmap(bitmap); 734 | 735 | // Set tile type. 736 | gameTile.setType(tileData.get(GameTileData.FIELD_ID_TYPE)); 737 | 738 | // Set tile visibility. 739 | if (tileData.get(GameTileData.FIELD_ID_VISIBLE) == 0) 740 | { 741 | gameTile.setVisible(false); 742 | } 743 | 744 | gameTile.setKey(tileKey); 745 | 746 | // If undefined, set global tile width / height values. 747 | if (mTileWidth == 0) 748 | { 749 | mTileWidth = gameTile.getWidth(); 750 | } 751 | if (mTileHeight == 0) 752 | { 753 | mTileHeight = gameTile.getHeight(); 754 | } 755 | 756 | // Add new game tile to loaded game tiles. 757 | mGameTiles.add(gameTile); 758 | 759 | tileKey++; 760 | } 761 | 762 | // Increment next tile X (horizontal) position by tile width. 763 | tileX += mTileWidth; 764 | } 765 | 766 | // Increment next tile Y (vertical) position by tile width. 767 | tileY += mTileHeight; 768 | } 769 | 770 | updatingGameTiles = false; 771 | } 772 | 773 | /** 774 | * Sets the state for a new game. 775 | */ 776 | private void setGameStartState() 777 | { 778 | setControlsStart(); 779 | setPlayerStart(); 780 | } 781 | 782 | /** 783 | * Loads and starts the current level. 784 | */ 785 | private void startLevel() 786 | { 787 | parseGameLevelData(); 788 | setPlayerStart(); 789 | 790 | thread.unpause(); 791 | } 792 | 793 | /** 794 | * Stores a bitmap for use by a game tile in a level. 795 | * @param int resourceId - The bitmap resource ID. 796 | * @return Bitmap - The Bitmap instance for the given resource ID. 797 | */ 798 | private Bitmap setAndGetGameTileBitmap(int resourceId) 799 | { 800 | if (!mGameTileBitmaps.containsKey(resourceId)) 801 | { 802 | BitmapFactory.Options opts = new BitmapFactory.Options(); 803 | opts.inJustDecodeBounds = true; 804 | Bitmap bitmap = BitmapFactory.decodeResource(mGameContext 805 | .getResources(), resourceId); 806 | 807 | if (bitmap != null) 808 | { 809 | mGameTileBitmaps.put(resourceId, bitmap); 810 | } 811 | } 812 | 813 | return mGameTileBitmaps.get(resourceId); 814 | } 815 | 816 | private int getPixelValueForDensity(int pixels) 817 | { 818 | return (int) (pixels * mScreenDensity); 819 | } 820 | } 821 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/Play.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import org.ruscoe.example.tilegame.GameView; 4 | 5 | import android.app.Activity; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.util.DisplayMetrics; 10 | import android.util.Log; 11 | import android.view.Menu; 12 | import android.view.MenuInflater; 13 | import android.view.MenuItem; 14 | import android.view.Window; 15 | 16 | import org.ruscoe.example.tilegame.R; 17 | 18 | /** 19 | * The Play activity creates a new GameView instance and starts 20 | * the game. 21 | * 22 | * @author Dan Ruscoe (ruscoe.org) 23 | * @version 1.0 24 | */ 25 | public class Play extends Activity 26 | { 27 | private GameView mGameView = null; 28 | 29 | private DisplayMetrics mMetrics = new DisplayMetrics(); 30 | private float mScreenDensity; 31 | 32 | @Override 33 | public void onCreate(Bundle savedInstanceState) 34 | { 35 | super.onCreate(savedInstanceState); 36 | 37 | Context mContext = getApplicationContext(); 38 | 39 | /** 40 | * Get the screen density that all pixel values will be based on. 41 | * This allows scaling of pixel values over different screen sizes. 42 | * 43 | * See: http://developer.android.com/reference/android/util/DisplayMetrics.html 44 | */ 45 | requestWindowFeature(Window.FEATURE_NO_TITLE); 46 | getWindowManager().getDefaultDisplay().getMetrics(mMetrics); 47 | mScreenDensity = mMetrics.density; 48 | 49 | /** 50 | * There is only one stage / level in this example. 51 | * In a real game, the user's chosen stage / level should be 52 | * passed to this activity. 53 | */ 54 | int stage = 1; 55 | int level = 1; 56 | 57 | Log.d("Tile Game Example", "Starting game at stage: " + stage + ", level: " + level); 58 | mGameView = new GameView(mContext, this, stage, level, mScreenDensity); 59 | 60 | setContentView(mGameView); 61 | } 62 | 63 | @Override 64 | public boolean onCreateOptionsMenu(Menu menu) 65 | { 66 | super.onCreateOptionsMenu(menu); 67 | MenuInflater inflater = getMenuInflater(); 68 | inflater.inflate(R.menu.menu, menu); 69 | 70 | return true; 71 | } 72 | 73 | @Override 74 | public boolean onOptionsItemSelected(MenuItem item) 75 | { 76 | Intent i = null; 77 | 78 | switch (item.getItemId()) 79 | { 80 | case R.id.menuAbout: 81 | i = new Intent(this, About.class); 82 | startActivity(i); 83 | return true; 84 | case R.id.menuExit: 85 | finish(); 86 | return true; 87 | } 88 | 89 | return false; 90 | } 91 | 92 | /** 93 | * Invoked when the Activity loses user focus. 94 | */ 95 | @Override 96 | protected void onPause() 97 | { 98 | super.onPause(); 99 | 100 | mGameView.getThread().setState(GameView.STATE_PAUSED); // pause game when Activity pauses 101 | } 102 | } -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/PlayerUnit.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * An extension of GameUnit, PlayerUnit represents the player-controlled 7 | * unit in the game. 8 | * 9 | * @author Dan Ruscoe (ruscoe.org) 10 | * @version 1.0 11 | */ 12 | public class PlayerUnit extends GameUnit 13 | { 14 | public static final int SPEED = 3; 15 | 16 | Context mContext; 17 | 18 | private int mUnmodifiedX = 0; 19 | private int mUnmodifiedY = 0; 20 | 21 | public PlayerUnit(Context context, int drawable) 22 | { 23 | super(context, drawable); 24 | this.mContext = context; 25 | } 26 | 27 | public int getUnmodifiedX() 28 | { 29 | return this.mUnmodifiedX; 30 | } 31 | 32 | public void setUnmodifiedX(int unmodifiedX) 33 | { 34 | this.mUnmodifiedX = unmodifiedX; 35 | } 36 | 37 | public int getUnmodifiedY() 38 | { 39 | return this.mUnmodifiedY; 40 | } 41 | 42 | public void setUnmodifiedY(int unmodifiedY) 43 | { 44 | this.mUnmodifiedY = unmodifiedY; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/data/GameDAO.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame.data; 2 | 3 | import static android.provider.BaseColumns._ID; 4 | 5 | import org.ruscoe.example.tilegame.GameTile; 6 | import org.ruscoe.example.tilegame.R; 7 | 8 | import android.content.Context; 9 | import android.database.sqlite.SQLiteDatabase; 10 | import android.database.sqlite.SQLiteOpenHelper; 11 | import android.util.Log; 12 | 13 | /** 14 | * The GameDAO class provides access to the database layer of the game. 15 | * 16 | * The class includes the initial queries required to create the 17 | * database used by the game. 18 | * 19 | * @author Dan Ruscoe (ruscoe.org) 20 | * @version 1.0 21 | */ 22 | public class GameDAO extends SQLiteOpenHelper 23 | { 24 | private static final String DATABASE_NAME = "tilegame.db"; 25 | private static final int DATABASE_VERSION = 1; 26 | 27 | // Create table statements 28 | 29 | /** 30 | * The table containing the definitions of each available game tile type. 31 | */ 32 | private static final String CREATE_TABLE_GAME_TILES = "CREATE TABLE " + GameTileData.TABLE_NAME + " (" 33 | + _ID + " INTEGER PRIMARY KEY, " 34 | + GameTileData.NAME + " STRING," 35 | + GameTileData.TYPE + " INTEGER DEFAULT 0," 36 | + GameTileData.DRAWABLE + " INTEGER DEFAULT 0," 37 | + GameTileData.VISIBLE + " INTEGER DEFAULT 1" 38 | + ");"; 39 | 40 | /** 41 | * The table containing the definitions of each level. 42 | */ 43 | private static final String CREATE_TABLE_GAME_LEVEL_TILES = "CREATE TABLE " + GameLevelTileData.TABLE_NAME + " (" 44 | + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT," 45 | + GameLevelTileData.STAGE + " INTEGER DEFAULT 0," 46 | + GameLevelTileData.LEVEL + " INTEGER DEFAULT 0," 47 | + GameLevelTileData.PLAYER_START_TILE_X + " INTEGER DEFAULT 0," 48 | + GameLevelTileData.PLAYER_START_TILE_Y + " INTEGER DEFAULT 0," 49 | + GameLevelTileData.TILE_DATA + " TEXT NOT NULL" 50 | + ");"; 51 | 52 | // Populate table statements 53 | 54 | /** 55 | * Populates the game tile definition table. Each row contains: 56 | * - A unique ID, specified instead of generated by AUTOINCREMENT so tile definitions 57 | * are easier to reference when populating the level data table 58 | * - The tile name. 59 | * - The tile type ID. 60 | * - The tile drawable resource ID. 61 | * - The tile visibility option (1 = visible, 0 = invisible.) 62 | */ 63 | private static final String[] POPULATE_TABLE_GAME_TILES = { 64 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 65 | + "(1,\"Tile 01\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_01 + ",1);", 66 | 67 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 68 | + "(2,\"Tile 02\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_02 + ",1);", 69 | 70 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 71 | + "(3,\"Tile 03\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_03 + ",1);", 72 | 73 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 74 | + "(4,\"Tile 04\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_04 + ",1);", 75 | 76 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 77 | + "(5,\"Tile 05\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_05 + ",1);", 78 | 79 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 80 | + "(6,\"Tile 06\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_06 + ",1);", 81 | 82 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 83 | + "(7,\"Tile 07\"," + GameTile.TYPE_OBSTACLE + "," + R.drawable.tile_07 + ",1);", 84 | 85 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 86 | + "(8,\"Dangerous Tile 01\"," + GameTile.TYPE_DANGEROUS + "," + R.drawable.tile_danger_01 + ",1);", 87 | 88 | "INSERT INTO " + GameTileData.TABLE_NAME + " VALUES " 89 | + "(9,\"Exit Tile\"," + GameTile.TYPE_EXIT + "," + R.drawable.tile_exit + ",1);" 90 | }; 91 | 92 | /** 93 | * Populates the level data definition table. Each row contains: 94 | * - An automatically generated unique ID. 95 | * - The stage ID. 96 | * - The level ID. 97 | * - The player start tile X (horizontal) location. 98 | * - The player start tile Y (vertical) location. 99 | * - The level tile data. 100 | * Level tile data consists of rows of comma-delimited game tile IDs. 101 | * The tile IDs used correspond to the unique IDs found in the game 102 | * tile definition table. 103 | * 104 | * The position of each game tile ID corresponds to the position the 105 | * tile will be drawn in the game. 106 | */ 107 | private static final String[] POPULATE_TABLE_GAME_LEVEL_TILES = { 108 | "INSERT INTO " + GameLevelTileData.TABLE_NAME + " VALUES " 109 | + "(null,1,1,7,3,\"" 110 | // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 111 | /* 1 */+ "01,01,01,01,01,01,01,01,01,01,01,01,01,01,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 112 | /* 2 */+ "01,03,03,03,03,03,03,03,03,03,03,03,03,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 113 | /* 3 */+ "01,03,00,00,00,00,00,00,00,00,00,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 114 | /* 4 */+ "01,03,00,00,00,00,00,00,00,00,00,07,07,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 115 | /* 5 */+ "01,03,07,00,00,00,00,00,00,00,07,07,07,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 116 | /* 6 */+ "01,03,05,05,06,05,00,00,00,05,06,05,05,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 117 | /* 7 */+ "01,03,03,00,08,00,00,00,00,00,08,00,03,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 118 | /* 8 */+ "01,03,00,00,00,00,00,00,00,00,00,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 119 | /* 9 */+ "01,03,00,00,00,00,00,00,00,00,00,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 120 | /* 10 */+ "01,03,00,00,00,00,04,04,04,00,00,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 121 | /* 11 */+ "01,03,00,00,04,04,03,03,03,04,04,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 122 | /* 12 */+ "01,03,00,00,03,00,00,00,00,00,03,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 123 | /* 13 */+ "01,03,00,00,00,00,00,00,00,00,00,00,00,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 124 | /* 14 */+ "01,03,00,00,00,00,00,09,00,00,00,00,07,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 125 | /* 15 */+ "01,03,03,00,00,00,02,02,02,00,00,00,03,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 126 | /* 16 */+ "01,03,03,04,04,04,02,02,02,04,04,04,03,03,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 127 | /* 17 */+ "01,01,01,01,01,01,01,01,01,01,01,01,01,01,01" + GameLevelTileData.TILE_DATA_LINE_BREAK 128 | + "\");" 129 | }; 130 | 131 | public GameDAO(Context ctx) 132 | { 133 | super(ctx, DATABASE_NAME, null, DATABASE_VERSION); 134 | } 135 | 136 | @Override 137 | public void onCreate(SQLiteDatabase db) 138 | { 139 | // Create game tables 140 | 141 | Log.d("Tile Game Example", "Creating DB tables"); 142 | 143 | db.execSQL(CREATE_TABLE_GAME_TILES); 144 | db.execSQL(CREATE_TABLE_GAME_LEVEL_TILES); 145 | 146 | // Populate game tables 147 | 148 | Log.d("Tile Game Example", "Populating DB tables"); 149 | 150 | for (String query : POPULATE_TABLE_GAME_TILES) 151 | { 152 | db.execSQL(query); 153 | } 154 | 155 | for (String query : POPULATE_TABLE_GAME_LEVEL_TILES) 156 | { 157 | db.execSQL(query); 158 | } 159 | } 160 | 161 | @Override 162 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 163 | { 164 | db.execSQL("DROP TABLE IF EXISTS " + GameTileData.TABLE_NAME); 165 | db.execSQL("DROP TABLE IF EXISTS " + GameLevelTileData.TABLE_NAME); 166 | 167 | onCreate(db); 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/data/GameLevelTileData.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame.data; 2 | 3 | import static android.provider.BaseColumns._ID; 4 | 5 | import java.util.ArrayList; 6 | 7 | import android.content.Context; 8 | import android.database.Cursor; 9 | import android.database.sqlite.SQLiteDatabase; 10 | 11 | /** 12 | * The GameTileData class represents a definition of a game 13 | * level stored in the database. 14 | * 15 | * @author Dan Ruscoe (ruscoe.org) 16 | * @version 1.0 17 | */ 18 | public class GameLevelTileData extends GameDAO 19 | { 20 | public static final String TABLE_NAME = "gameLevelTileData"; 21 | 22 | public static final String STAGE = "stage"; 23 | public static final String LEVEL = "level"; 24 | public static final String PLAYER_START_TILE_X = "playerStartTileX"; 25 | public static final String PLAYER_START_TILE_Y = "playerStartTileY"; 26 | public static final String TILE_DATA = "tileData"; 27 | 28 | public static final int FIELD_ID_ID = 0; 29 | public static final int FIELD_ID_STAGE = 1; 30 | public static final int FIELD_ID_LEVEL = 2; 31 | public static final int FIELD_ID_PLAYER_START_TILE_X = 3; 32 | public static final int FIELD_ID_PLAYER_START_TILE_Y = 4; 33 | public static final int FIELD_ID_TILE_DATA = 5; 34 | 35 | public static final String TILE_DATA_LINE_BREAK = "//"; 36 | 37 | public GameLevelTileData(Context ctx) 38 | { 39 | super(ctx); 40 | } 41 | 42 | /** 43 | * Gets an array of game level data for a given stage and level. 44 | * @param int stage - The game stage. 45 | * @param level - The game level, relative to the stage. 46 | * @return ArrayList 47 | */ 48 | public ArrayList getGameLevelData(int stage, int level) 49 | { 50 | SQLiteDatabase db = this.getReadableDatabase(); 51 | 52 | String[] from = { _ID, STAGE, LEVEL, PLAYER_START_TILE_X, PLAYER_START_TILE_Y, TILE_DATA }; 53 | String where = STAGE + " = " + stage + " AND " + LEVEL + " = " + level; 54 | 55 | Cursor cursor = db.query(TABLE_NAME, from, where, null, null, null, null); 56 | 57 | ArrayList levelData = new ArrayList(); 58 | 59 | if (cursor != null) 60 | { 61 | while (cursor.moveToNext()) 62 | { 63 | levelData.add(cursor.getString(FIELD_ID_ID)); 64 | levelData.add(cursor.getString(FIELD_ID_STAGE)); 65 | levelData.add(cursor.getString(FIELD_ID_LEVEL)); 66 | levelData.add(cursor.getString(FIELD_ID_PLAYER_START_TILE_X)); 67 | levelData.add(cursor.getString(FIELD_ID_PLAYER_START_TILE_Y)); 68 | levelData.add(cursor.getString(FIELD_ID_TILE_DATA)); 69 | } 70 | cursor.close(); 71 | } 72 | 73 | db.close(); 74 | return levelData; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/org/ruscoe/example/tilegame/data/GameTileData.java: -------------------------------------------------------------------------------- 1 | package org.ruscoe.example.tilegame.data; 2 | 3 | import static android.provider.BaseColumns._ID; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | 8 | import android.content.Context; 9 | import android.database.Cursor; 10 | import android.database.sqlite.SQLiteDatabase; 11 | 12 | /** 13 | * The GameTileData class represents a definition of a game 14 | * tile stored in the database. 15 | * 16 | * @author Dan Ruscoe (ruscoe.org) 17 | * @version 1.0 18 | */ 19 | public class GameTileData extends GameDAO 20 | { 21 | public static final String TABLE_NAME = "gameTileData"; 22 | 23 | public static final String NAME = "name"; 24 | public static final String TYPE = "type"; 25 | public static final String DRAWABLE = "drawable"; 26 | public static final String VISIBLE = "visible"; 27 | 28 | public static final int FIELD_ID_ID = 0; 29 | public static final int FIELD_ID_NAME = 1; 30 | public static final int FIELD_ID_TYPE = 2; 31 | public static final int FIELD_ID_DRAWABLE = 3; 32 | public static final int FIELD_ID_VISIBLE = 4; 33 | 34 | public GameTileData(Context ctx) 35 | { 36 | super(ctx); 37 | } 38 | 39 | /** 40 | * Gets a map containing definitions for all available game tiles. 41 | * @return HashMap 42 | */ 43 | public HashMap> getTilesData() 44 | { 45 | SQLiteDatabase db = this.getReadableDatabase(); 46 | 47 | String[] from = { _ID, NAME, TYPE, DRAWABLE, VISIBLE }; 48 | Cursor cursor = db.query(TABLE_NAME, from, null, null, null, null, null); 49 | 50 | HashMap> tiles = new HashMap>(); 51 | 52 | if (cursor != null) 53 | { 54 | while (cursor.moveToNext()) 55 | { 56 | ArrayList arrayList = new ArrayList(); 57 | 58 | arrayList.add(cursor.getInt(FIELD_ID_ID)); 59 | arrayList.add(cursor.getInt(FIELD_ID_NAME)); 60 | arrayList.add(cursor.getInt(FIELD_ID_TYPE)); 61 | arrayList.add(cursor.getInt(FIELD_ID_DRAWABLE)); 62 | arrayList.add(cursor.getInt(FIELD_ID_VISIBLE)); 63 | 64 | tiles.put(cursor.getInt(FIELD_ID_ID), arrayList); 65 | } 66 | cursor.close(); 67 | } 68 | 69 | db.close(); 70 | 71 | return tiles; 72 | } 73 | } 74 | --------------------------------------------------------------------------------