├── .gitattributes
├── 9781484250303.jpg
├── Ch02
├── 1.KV_language
│ ├── main.py
│ └── test.kv
├── 2.load_model
│ ├── main.py
│ └── test1.kv
└── 3.load_string
│ └── main.py
├── Ch03
├── Flask Server
│ └── FlaskServer.py
└── Kivy Client
│ ├── main.py
│ └── pycam.kv
├── Ch04
├── Flask Server
│ └── CamShareServer.py
└── Kivy Client
│ ├── buildozer.spec
│ ├── icon.png
│ ├── logo.png
│ ├── main.py
│ ├── presplash.png
│ └── pycam.kv
├── Ch05-06
├── 0.png
├── 1.png
├── 10.png
├── 11.png
├── 12.png
├── 13.png
├── 14.png
├── 15.png
├── 16.png
├── 17.png
├── 2.png
├── 21.png
├── 22.png
├── 23.png
├── 24.png
├── 25.png
├── 26.png
├── 27.png
├── 28.png
├── 29.png
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 91.png
├── 92.png
├── 93.png
├── 94.png
├── 95.png
├── bg_cointex.png
├── buildozer.spec
├── coin.png
├── cointex_logo.png
├── cointex_presplash.png
├── fire.png
├── game_info
├── levels-bg
│ ├── bg_lvl1.jpg
│ ├── bg_lvl10.jpg
│ ├── bg_lvl11.jpg
│ ├── bg_lvl12.jpg
│ ├── bg_lvl13.jpg
│ ├── bg_lvl14.jpg
│ ├── bg_lvl15.jpg
│ ├── bg_lvl16.jpg
│ ├── bg_lvl17.jpg
│ ├── bg_lvl18.jpg
│ ├── bg_lvl19.jpg
│ ├── bg_lvl2.jpg
│ ├── bg_lvl20.jpg
│ ├── bg_lvl3.jpg
│ ├── bg_lvl3.png
│ ├── bg_lvl4.jpg
│ ├── bg_lvl4.png
│ ├── bg_lvl5.jpg
│ ├── bg_lvl5.png
│ ├── bg_lvl6.jpg
│ ├── bg_lvl6.png
│ ├── bg_lvl7.jpg
│ ├── bg_lvl8.jpg
│ └── bg_lvl9.jpg
├── levels-images
│ ├── 1.png
│ ├── 10.png
│ ├── 11.png
│ ├── 12.png
│ ├── 13.png
│ ├── 14.png
│ ├── 15.png
│ ├── 16.png
│ ├── 17.png
│ ├── 18.png
│ ├── 19.png
│ ├── 2.png
│ ├── 20.png
│ ├── 21.png
│ ├── 22.png
│ ├── 23.png
│ ├── 24.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ └── 9.png
├── main.py
├── music
│ ├── bg_music_piano.wav
│ ├── bg_music_piano_flute.wav
│ ├── char_death_flaute.wav
│ ├── coin.wav
│ └── level_completed_flaute.wav
├── other-images
│ ├── About-Us.png
│ ├── Congratulations-Passed.png
│ └── Main-Screen.png
└── test.kv
├── Ch07
└── 1.AudioApp
│ ├── audio.kv
│ ├── bg_music_piano.wav
│ ├── buildozer.spec
│ ├── icon.png
│ ├── main.py
│ └── presplash.png
├── Contributing.md
├── LICENSE.txt
├── README.md
└── errata.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/9781484250303.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/9781484250303.jpg
--------------------------------------------------------------------------------
/Ch02/1.KV_language/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 |
3 | class TestApp(kivy.app.App):
4 |
5 | def button1_press(self):
6 | self.root.ids['text_label'].text = self.root.ids['text_input1'].text
7 |
8 | def button2_press(self):
9 | self.root.ids['text_label'].text = self.root.ids['text_input2'].text
10 |
11 | app = TestApp()
12 | app.run()
13 |
--------------------------------------------------------------------------------
/Ch02/1.KV_language/test.kv:
--------------------------------------------------------------------------------
1 | BoxLayout:
2 | orientation: "vertical"
3 | Label:
4 | text: "Waiting for Button Press"
5 | id: text_label
6 | BoxLayout:
7 | orientation: "horizontal"
8 | TextInput:
9 | text: "TextInput 1"
10 | id: text_input1
11 | Button:
12 | text: "Click me"
13 | on_press: app.button1_press()
14 | BoxLayout:
15 | orientation: "horizontal"
16 | TextInput:
17 | text: "TextInput 2"
18 | id: text_input2
19 | Button:
20 | text: "Click me"
21 | on_press: app.button2_press()
22 |
--------------------------------------------------------------------------------
/Ch02/2.load_model/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 | import kivy.lang
3 |
4 | class TestApp(kivy.app.App):
5 |
6 | def button1_press(self):
7 | self.root.ids['text_label'].text = self.root.ids['text_input1'].text
8 |
9 | def button2_press(self):
10 | self.root.ids['text_label'].text = self.root.ids['text_input2'].text
11 |
12 | def build(self):
13 | return kivy.lang.Builder.load_file("test1.kv")
14 |
15 | app = TestApp()
16 | app.run()
17 |
--------------------------------------------------------------------------------
/Ch02/2.load_model/test1.kv:
--------------------------------------------------------------------------------
1 | BoxLayout:
2 | orientation: "vertical"
3 | Label:
4 | text: "Waiting for Button Press"
5 | id: text_label
6 | BoxLayout:
7 | orientation: "horizontal"
8 | TextInput:
9 | text: "TextInput 1"
10 | id: text_input1
11 | Button:
12 | text: "Click me"
13 | on_press: app.button1_press()
14 | BoxLayout:
15 | orientation: "horizontal"
16 | TextInput:
17 | text: "TextInput 2"
18 | id: text_input2
19 | Button:
20 | text: "Click me"
21 | on_press: app.button2_press()
22 |
--------------------------------------------------------------------------------
/Ch02/3.load_string/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 | import kivy.lang
3 |
4 | class TestApp(kivy.app.App):
5 |
6 | def button1_press(self):
7 | self.root.ids['text_label'].text = self.root.ids['text_input1'].text
8 |
9 | def button2_press(self):
10 | self.root.ids['text_label'].text = self.root.ids['text_input2'].text
11 |
12 | def build(self):
13 | return kivy.lang.Builder.load_string(
14 | """
15 | BoxLayout:
16 | orientation: "vertical"
17 | Label:
18 | text: "Waiting for Button Press"
19 | id: text_label
20 | BoxLayout:
21 | orientation: "horizontal"
22 | TextInput:
23 | text: "TextInput 1"
24 | id: text_input1
25 | Button:
26 | text: "Click me"
27 | on_press: app.button1_press()
28 | BoxLayout:
29 | orientation: "horizontal"
30 | TextInput:
31 | text: "TextInput 2"
32 | id: text_input2
33 | Button:
34 | text: "Click me"
35 | on_press: app.button2_press()
36 | """)
37 |
38 | app = TestApp()
39 | app.run()
40 |
--------------------------------------------------------------------------------
/Ch03/Flask Server/FlaskServer.py:
--------------------------------------------------------------------------------
1 | import flask
2 | import base64
3 | import PIL.Image
4 | import webbrowser
5 | import os
6 |
7 | app = flask.Flask(import_name="FlaskUpload")
8 |
9 | cam_width = 0
10 | cam_height = 0
11 |
12 | html_opened = False
13 |
14 | @app.route('/camSize', methods = ['GET', 'POST'])
15 | def cam_size():
16 | global cam_width
17 | global cam_height
18 |
19 | cam_width = int(float(flask.request.args["width"]))
20 | cam_height = int(float(flask.request.args["height"]))
21 |
22 | print('Width',cam_width,'& Height',cam_height,'Received Successfully.')
23 |
24 | return "OK"
25 |
26 | @app.route('/', methods = ['POST'])
27 | def upload_file():
28 | global cam_width
29 | global cam_height
30 | global html_opened
31 |
32 | file_to_upload = flask.request.files['media'].read()
33 |
34 | image = PIL.Image.frombytes(mode="RGBA", size=(cam_width, cam_height), data=file_to_upload)
35 | image = image.rotate(-90)
36 | image.save('out.png')
37 |
38 | print('File Uploaded Successfully.')
39 |
40 | f = open('out.png', 'rb')
41 | # im_base64 = base64.b64encode(image.tobytes())
42 | im_base64 = base64.b64encode(f.read())
43 |
44 | html_code = '
Displaying Uploaded ImageUploaded Image to the Flask Server
'
45 |
46 | html_url = os.getcwd()+"/templates/test.html"
47 | f = open(html_url,'w')
48 | f.write(html_code)
49 | f.close()
50 |
51 | if html_opened == False:
52 | webbrowser.open(html_url)
53 | html_opened = True
54 |
55 | return "SUCCESS"
56 |
57 | app.run(host="192.168.16.103", port=6666, debug=True)
58 |
--------------------------------------------------------------------------------
/Ch03/Kivy Client/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 | import requests
3 | import kivy.clock
4 | import kivy.uix.screenmanager
5 | import threading
6 |
7 | class Configure(kivy.uix.screenmanager.Screen):
8 | pass
9 |
10 | class Capture(kivy.uix.screenmanager.Screen):
11 | pass
12 |
13 | class PycamApp(kivy.app.App):
14 | num_images = 0
15 |
16 | def cam_size(self):
17 | camera = self.root.ids['camera']
18 | cam_width_height = {'width': camera.resolution[0], 'height': camera.resolution[1]}
19 |
20 | ip_addr = self.root.ids['ip_address'].text
21 | port_number = self.root.ids['port_number'].text
22 | url = 'http://' + ip_addr + ':' + port_number + '/camSize'
23 |
24 | try:
25 | self.root.ids['cam_size'].text = "Trying to Establish a Connection..."
26 | requests.post(url, params=cam_width_height)
27 | self.root.ids['cam_size'].text = "Done."
28 | self.root.current = "capture"
29 | except requests.exceptions.ConnectionError:
30 | self.root.ids['cam_size'].text = "Connection Error! Make Sure Server is Active."
31 |
32 | def capture(self):
33 | kivy.clock.Clock.schedule_interval(self.upload_images, 0.5)
34 |
35 | def upload_images(self, *args):
36 | self.num_images = self.num_images + 1
37 | print("Uploading image", self.num_images)
38 |
39 | camera = self.root.ids['camera']
40 |
41 | print("Image Size ", camera.resolution[0], camera.resolution[1])
42 | print("Image corner ", camera.x, camera.y)
43 |
44 | pixels_data = camera.texture.get_region(x=camera.x, y=camera.y, width=camera.resolution[0], height=camera.resolution[1]).pixels
45 |
46 | ip_addr = self.root.ids['ip_address'].text
47 | port_number = self.root.ids['port_number'].text
48 | url = 'http://' + ip_addr + ':' + port_number + '/'
49 | files = {'media': pixels_data}
50 |
51 | t = threading.Thread(target=self.send_files_server, args=(files, url))
52 | t.start()
53 |
54 | def build(self):
55 | pass
56 |
57 | def send_files_server(self, files, url):
58 | try:
59 | requests.post(url, files=files)
60 | except requests.exceptions.ConnectionError:
61 | self.root.ids['capture'].text = "Connection Error! Make Sure Server is Active."
62 |
63 | app = PycamApp()
64 | app.run()
65 |
--------------------------------------------------------------------------------
/Ch03/Kivy Client/pycam.kv:
--------------------------------------------------------------------------------
1 | BoxLayout:
2 | orientation: "vertical"
3 | Camera:
4 | id: camera
5 | size_hint_y: 18
6 | resolution: (1280, 720)
7 | play: True
8 | canvas.before:
9 | PushMatrix:
10 | Rotate:
11 | angle: -90
12 | origin: root.width/2, root.height/2
13 | canvas.after:
14 | PopMatrix:
15 | TextInput:
16 | text: "192.168.43.231"
17 | id: ip_address
18 | size_hint_y: 1
19 | TextInput:
20 | text: "6666"
21 | id: port_number
22 | size_hint_y: 1
23 | Button:
24 | id: capture
25 | text: "Capture"
26 | size_hint_y: 1
27 | on_press: app.capture()
28 | Button:
29 | id: cam_size
30 | text: "Configure Server"
31 | size_hint_y: 1
32 | on_press: app.cam_size()
--------------------------------------------------------------------------------
/Ch04/Flask Server/CamShareServer.py:
--------------------------------------------------------------------------------
1 | import flask
2 | import PIL.Image
3 | import base64
4 | import webbrowser
5 | import sys
6 | import os
7 |
8 | app = flask.Flask(import_name="FlaskUpload")
9 |
10 | cam_width = 0
11 | cam_height = 0
12 |
13 | html_opened = False
14 |
15 | @app.route('/camSize', methods = ['GET', 'POST'])
16 | def cam_size():
17 | global cam_width
18 | global cam_height
19 |
20 | cam_width = int(float(flask.request.args["width"]))
21 | cam_height = int(float(flask.request.args["height"]))
22 |
23 | print('Width',cam_width,'& Height',cam_height,'Received Successfully.')
24 |
25 | return "OK"
26 |
27 | @app.route('/', methods = ['POST'])
28 | def upload_file():
29 | global cam_width
30 | global cam_height
31 | global html_opened
32 |
33 | file_to_upload = flask.request.files['media'].read()
34 |
35 | image = PIL.Image.frombytes(mode="RGBA", size=(cam_width, cam_height), data=file_to_upload)
36 | image = image.rotate(-90)
37 | image.save('out.png')
38 |
39 | print('File Uploaded Successfully.')
40 |
41 | f = open('out.png', 'rb')
42 | # im_base64 = base64.b64encode(image.tobytes())
43 | im_base64 = base64.b64encode(f.read())
44 |
45 | html_code = 'Displaying Uploaded ImageUploaded Image to the Flask Server
'
46 |
47 | # The HTML page is not required to be opened from the Python code but open it yourself externally.
48 | html_url = os.getcwd()+"/templates/test.html"
49 | f = open(html_url,'w')
50 | f.write(html_code)
51 | f.close()
52 |
53 | if html_opened == False:
54 | webbrowser.open(html_url)
55 | html_opened = True
56 |
57 | return "SUCCESS"
58 |
59 | ip_address = sys.argv[1]#"192.168.43.231"
60 | port_number = int(sys.argv[2])#6666
61 | app.run(host=ip_address, port=port_number, debug=True, threaded=True)
62 |
63 |
--------------------------------------------------------------------------------
/Ch04/Kivy Client/buildozer.spec:
--------------------------------------------------------------------------------
1 | [app]
2 |
3 | # (str) Title of your application
4 | title = CamShare
5 |
6 | # (str) Package name
7 | package.name = myapp
8 |
9 | # (str) Package domain (needed for android/ios packaging)
10 | package.domain = camshare.camshare
11 |
12 | # (str) Source code where the main.py live
13 | source.dir = .
14 |
15 | # (list) Source files to include (let empty to include all the files)
16 | source.include_exts = py,png,jpg,kv,atlas
17 |
18 | # (list) List of inclusions using pattern matching
19 | #source.include_patterns = assets/*,images/*.png
20 |
21 | # (list) Source files to exclude (let empty to not exclude anything)
22 | #source.exclude_exts = spec
23 |
24 | # (list) List of directory to exclude (let empty to not exclude anything)
25 | source.exclude_dirs = temp, bin, CoinTex, CamShare
26 |
27 | # (list) List of exclusions using pattern matching
28 | #source.exclude_patterns = license,images/*/*.jpg
29 |
30 | # (str) Application versioning (method 1)
31 | version = 0.4
32 |
33 | # (str) Application versioning (method 2)
34 | # version.regex = __version__ = ['"](.*)['"]
35 | # version.filename = %(source.dir)s/main.py
36 |
37 | # (list) Application requirements
38 | # comma separated e.g. requirements = sqlite3,kivy
39 | requirements = requests,kivy
40 | #bootstrap = sdl2, pygame, opencv
41 | #requirements = plyer,kivy,opencv,numpy,pyjnius,ffmpeg, sqlite3, openssl
42 | #requirements.source.numpy = /home/ahmedgad/Desktop/numpy15
43 |
44 | # (str) Custom source folders for requirements
45 | # Sets custom source for any requirements with recipes
46 | # requirements.source.kivy = ../../kivy
47 |
48 | # (list) Garden requirements
49 | #garden_requirements =
50 |
51 | # (str) Presplash of the application
52 | presplash.filename = %(source.dir)s/presplash.png
53 |
54 | # (str) Icon of the application
55 | icon.filename = %(source.dir)s/icon.png
56 |
57 | # (str) Supported orientation (one of landscape, portrait or all)
58 | orientation = portrait
59 |
60 | # (list) List of service to declare
61 | #services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
62 |
63 | #
64 | # OSX Specific
65 | #
66 |
67 | #
68 | # author = © Copyright Info
69 |
70 | # change the major version of python used by the app
71 | osx.python_version = 3
72 |
73 | # Kivy version to use
74 | #osx.kivy_version = 1.9.1
75 |
76 | #
77 | # Android specific
78 | #
79 |
80 | # (bool) Indicate if the application should be fullscreen or not
81 | fullscreen = 1
82 |
83 | # (string) Presplash background color (for new android toolchain)
84 | # Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
85 | # red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
86 | # darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
87 | # olive, purple, silver, teal.
88 | #android.presplash_color = #FFFFFF
89 |
90 | # (list) Permissions
91 | android.permissions = CAMERA, INTERNET
92 |
93 | # (int) Android API to use
94 | android.api = 27
95 |
96 | # (int) Minimum API required
97 | android.minapi = 18
98 |
99 | # (int) Android SDK version to use
100 | android.sdk = 27
101 |
102 | # (str) Android NDK version to use
103 | #android.ndk = 9c
104 |
105 | # (bool) Use --private data storage (True) or --dir public storage (False)
106 | #android.private_storage = True
107 |
108 | # (str) Android NDK directory (if empty, it will be automatically downloaded.)
109 | android.ndk_path = /home/ahmedgad/.buildozer/android/platform/android-ndk-r18b
110 |
111 | # (str) Android SDK directory (if empty, it will be automatically downloaded.)
112 | android.sdk_path = /home/ahmedgad/.buildozer/android/platform/android-sdk-linux
113 |
114 | # (str) ANT directory (if empty, it will be automatically downloaded.)
115 | #android.ant_path = /home/ahmedgad/.buildozer/android/platform/android-sdk-linux/apache-ant-1.9.4
116 |
117 | # (str) ANT directory (if empty, it will be automatically downloaded.)
118 | #android.ant_path =
119 |
120 | # (bool) If True, then skip trying to update the Android sdk
121 | # This can be useful to avoid excess Internet downloads or save time
122 | # when an update is due and you just want to test/build your package
123 | # android.skip_update = False
124 |
125 | # (str) Android entry point, default is ok for Kivy-based app
126 | #android.entrypoint = org.renpy.android.PythonActivity
127 |
128 | # (list) Pattern to whitelist for the whole project
129 | #android.whitelist =
130 |
131 | # (str) Path to a custom whitelist file
132 | #android.whitelist_src =
133 |
134 | # (str) Path to a custom blacklist file
135 | #android.blacklist_src =
136 |
137 | # (list) List of Java .jar files to add to the libs so that pyjnius can access
138 | # their classes. Don't add jars that you do not need, since extra jars can slow
139 | # down the build process. Allows wildcards matching, for example:
140 | # OUYA-ODK/libs/*.jar
141 | #android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
142 |
143 | # (list) List of Java files to add to the android project (can be java or a
144 | # directory containing the files)
145 | #android.add_src =
146 |
147 | # (list) Android AAR archives to add (currently works only with sdl2_gradle
148 | # bootstrap)
149 | #android.add_aars =
150 |
151 | # (list) Gradle dependencies to add (currently works only with sdl2_gradle
152 | # bootstrap)
153 | #android.gradle_dependencies =
154 |
155 | # (list) Java classes to add as activities to the manifest.
156 | #android.add_activites = com.example.ExampleActivity
157 |
158 | # (str) python-for-android branch to use, defaults to stable
159 | #p4a.branch = stable
160 | p4a.source_dir=/home/ahmedgad/Desktop/python-for-android
161 |
162 | #p4a.source_dir=/home/ahmedgad/Desktop/testp4a/python-for-android
163 |
164 | # (str) OUYA Console category. Should be one of GAME or APP
165 | # If you leave this blank, OUYA support will not be enabled
166 | #android.ouya.category = GAME
167 |
168 | # (str) Filename of OUYA Console icon. It must be a 732x412 png image.
169 | #android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
170 |
171 | # (str) XML file to include as an intent filters in tag
172 | #android.manifest.intent_filters =
173 |
174 | # (str) launchMode to set for the main activity
175 | #android.manifest.launch_mode = standard
176 |
177 | # (list) Android additional libraries to copy into libs/armeabi
178 | #android.add_libs_armeabi = libs/android/*.so
179 | #android.add_libs_armeabi_v7a = libs/android-v7/*.so
180 | #android.add_libs_x86 = libs/android-x86/*.so
181 | #android.add_libs_mips = libs/android-mips/*.so
182 |
183 | # (bool) Indicate whether the screen should stay on
184 | # Don't forget to add the WAKE_LOCK permission if you set this to True
185 | #android.wakelock = False
186 |
187 | # (list) Android application meta-data to set (key=value format)
188 | #android.meta_data =
189 |
190 | # (list) Android library project to add (will be added in the
191 | # project.properties automatically.)
192 | #android.library_references =
193 |
194 | # (str) Android logcat filters to use
195 | #android.logcat_filters = *:S python:D
196 |
197 | # (bool) Copy library instead of making a libpymodules.so
198 | #android.copy_libs = 1
199 |
200 | # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86
201 | android.arch = armeabi-v7a
202 |
203 | #
204 | # Python for android (p4a) specific
205 | #
206 |
207 | # (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
208 | #p4a.source_dir =
209 |
210 | # (str) The directory in which python-for-android should look for your own build recipes (if any)
211 | #p4a.local_recipes =
212 |
213 | # (str) Filename to the hook for p4a
214 | #p4a.hook =
215 |
216 | # (str) Bootstrap to use for android builds
217 | # p4a.bootstrap = sdl2
218 |
219 | # (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
220 | #p4a.port =
221 |
222 |
223 | #
224 | # iOS specific
225 | #
226 |
227 | # (str) Path to a custom kivy-ios folder
228 | #ios.kivy_ios_dir = ../kivy-ios
229 |
230 | # (str) Name of the certificate to use for signing the debug version
231 | # Get a list of available identities: buildozer ios list_identities
232 | #ios.codesign.debug = "iPhone Developer: ()"
233 |
234 | # (str) Name of the certificate to use for signing the release version
235 | #ios.codesign.release = %(ios.codesign.debug)s
236 |
237 |
238 | [buildozer]
239 |
240 | # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
241 | log_level = 2
242 |
243 | # (int) Display warning if buildozer is run as root (0 = False, 1 = True)
244 | warn_on_root = 1
245 |
246 | # (str) Path to build artifact storage, absolute or relative to spec file
247 | # build_dir = ./.buildozer
248 |
249 | # (str) Path to build output (i.e. .apk, .ipa) storage
250 | # bin_dir = ./bin
251 |
252 | # -----------------------------------------------------------------------------
253 | # List as sections
254 | #
255 | # You can define all the "list" as [section:key].
256 | # Each line will be considered as a option to the list.
257 | # Let's take [app] / source.exclude_patterns.
258 | # Instead of doing:
259 | #
260 | #[app]
261 | #source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
262 | #
263 | # This can be translated into:
264 | #
265 | #[app:source.exclude_patterns]
266 | #license
267 | #data/audio/*.wav
268 | #data/images/original/*
269 | #
270 |
271 |
272 | # -----------------------------------------------------------------------------
273 | # Profiles
274 | #
275 | # You can extend section / key with a profile
276 | # For example, you want to deploy a demo version of your application without
277 | # HD content. You could first change the title to add "(demo)" in the name
278 | # and extend the excluded directories to remove the HD content.
279 | #
280 | #[app@demo]
281 | #title = My Application (demo)
282 | #
283 | #[app:source.exclude_patterns@demo]
284 | #images/hd/*
285 | #
286 | # Then, invoke the command line with the "demo" profile:
287 | #
288 | #buildozer --profile demo android debug
289 |
--------------------------------------------------------------------------------
/Ch04/Kivy Client/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch04/Kivy Client/icon.png
--------------------------------------------------------------------------------
/Ch04/Kivy Client/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch04/Kivy Client/logo.png
--------------------------------------------------------------------------------
/Ch04/Kivy Client/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 | import requests
3 | import kivy.clock
4 | import kivy.uix.screenmanager
5 | import threading
6 |
7 | class Configure(kivy.uix.screenmanager.Screen):
8 | pass
9 |
10 | class Capture(kivy.uix.screenmanager.Screen):
11 | pass
12 |
13 | class PycamApp(kivy.app.App):
14 | num_images = 0
15 |
16 | def cam_size(self):
17 | camera = self.root.screens[1].ids['camera']
18 | cam_width_height = {'width': camera.resolution[0], 'height': camera.resolution[1]}
19 |
20 | ip_addr = self.root.screens[0].ids['ip_address'].text
21 | port_number = self.root.screens[0].ids['port_number'].text
22 | url = 'http://'+ip_addr+':'+port_number+'/camSize'
23 |
24 | try:
25 | self.root.screens[0].ids['cam_size'].text = "Trying to Establish a Connection..."
26 | requests.post(url, params=cam_width_height)
27 | self.root.screens[0].ids['cam_size'].text = "Done."
28 | self.root.current = "capture"
29 | except requests.exceptions.ConnectionError:
30 | self.root.screens[0].ids['cam_size'].text = "Connection Error! Make Sure Server is Active."
31 |
32 | def capture(self):
33 | kivy.clock.Clock.schedule_interval(self.upload_images, 1.0)
34 |
35 | def upload_images(self, *args):
36 | self.num_images = self.num_images + 1
37 | print("Uploading image", self.num_images )
38 |
39 | camera = self.root.screens[1].ids['camera']
40 |
41 | print("Image Size ", camera.resolution[0], camera.resolution[1])
42 | print("Image corner ", camera.x, camera.y)
43 |
44 | pixels_data = camera.texture.get_region(x=camera.x, y=camera.y, width=camera.resolution[0],height=camera.resolution[1]).pixels
45 |
46 | ip_addr = self.root.screens[0].ids['ip_address'].text
47 | port_number = self.root.screens[0].ids['port_number'].text
48 | url = 'http://'+ip_addr+':'+port_number+'/'
49 | files = {'media': pixels_data}
50 |
51 | t = threading.Thread(target=self.send_files_server, args=(files, url))
52 | t.start()
53 |
54 | def build(self):
55 | pass
56 |
57 | def send_files_server(self, files, url):
58 | try:
59 | # self.root.screens[1].ids['capture'].text = "Trying to Establish a Connection..."
60 | requests.post(url, files=files)
61 | # self.root.screens[1].ids['capture'].text = "Capture Again!"
62 | except requests.exceptions.ConnectionError:
63 | self.root.screens[1].ids['capture'].text = "Connection Error! Make Sure Server is Active."
64 |
65 | if __name__ == "__main__":
66 | app = PycamApp()
67 | app.run()
68 |
--------------------------------------------------------------------------------
/Ch04/Kivy Client/presplash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch04/Kivy Client/presplash.png
--------------------------------------------------------------------------------
/Ch04/Kivy Client/pycam.kv:
--------------------------------------------------------------------------------
1 | ScreenManager:
2 | Configure:
3 | Capture:
4 |
5 | :
6 | name: "capture"
7 | BoxLayout:
8 | orientation: "vertical"
9 | Camera:
10 | id: camera
11 | size_hint_y: 18
12 | resolution: (1024, 1024)
13 | allow_stretch: True
14 | play: True
15 | canvas.before:
16 | PushMatrix:
17 | Rotate:
18 | angle: -90
19 | origin: root.width/2, root.height/2
20 | canvas.after:
21 | PopMatrix:
22 | Button:
23 | id: capture
24 | font_size: 30
25 | text: "Capture"
26 | size_hint_y: 1
27 | on_press: app.capture()
28 |
29 | :
30 | name: "configure"
31 | BoxLayout:
32 | orientation: "vertical"
33 | Label:
34 | text: "1) Enter the IPv4 address of the server.\n2) Enter the port number. \n3) Press the Configure Server button. \nMake sure that the server is active."
35 | font_size: 20
36 | text_size: self.width, None
37 | size_hint_y: 1
38 | TextInput:
39 | text: "192.168.43.231"
40 | font_size: 30
41 | id: ip_address
42 | size_hint_y: 1
43 | TextInput:
44 | text: "6666"
45 | font_size: 30
46 | id: port_number
47 | size_hint_y: 1
48 | Button:
49 | id: cam_size
50 | font_size: 30
51 | text_size: self.width, None
52 | text: "Configure Server"
53 | size_hint_y: 1
54 | on_press: app.cam_size()
55 |
56 |
--------------------------------------------------------------------------------
/Ch05-06/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/0.png
--------------------------------------------------------------------------------
/Ch05-06/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/1.png
--------------------------------------------------------------------------------
/Ch05-06/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/10.png
--------------------------------------------------------------------------------
/Ch05-06/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/11.png
--------------------------------------------------------------------------------
/Ch05-06/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/12.png
--------------------------------------------------------------------------------
/Ch05-06/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/13.png
--------------------------------------------------------------------------------
/Ch05-06/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/14.png
--------------------------------------------------------------------------------
/Ch05-06/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/15.png
--------------------------------------------------------------------------------
/Ch05-06/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/16.png
--------------------------------------------------------------------------------
/Ch05-06/17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/17.png
--------------------------------------------------------------------------------
/Ch05-06/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/2.png
--------------------------------------------------------------------------------
/Ch05-06/21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/21.png
--------------------------------------------------------------------------------
/Ch05-06/22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/22.png
--------------------------------------------------------------------------------
/Ch05-06/23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/23.png
--------------------------------------------------------------------------------
/Ch05-06/24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/24.png
--------------------------------------------------------------------------------
/Ch05-06/25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/25.png
--------------------------------------------------------------------------------
/Ch05-06/26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/26.png
--------------------------------------------------------------------------------
/Ch05-06/27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/27.png
--------------------------------------------------------------------------------
/Ch05-06/28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/28.png
--------------------------------------------------------------------------------
/Ch05-06/29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/29.png
--------------------------------------------------------------------------------
/Ch05-06/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/3.png
--------------------------------------------------------------------------------
/Ch05-06/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/4.png
--------------------------------------------------------------------------------
/Ch05-06/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/5.png
--------------------------------------------------------------------------------
/Ch05-06/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/6.png
--------------------------------------------------------------------------------
/Ch05-06/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/7.png
--------------------------------------------------------------------------------
/Ch05-06/91.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/91.png
--------------------------------------------------------------------------------
/Ch05-06/92.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/92.png
--------------------------------------------------------------------------------
/Ch05-06/93.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/93.png
--------------------------------------------------------------------------------
/Ch05-06/94.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/94.png
--------------------------------------------------------------------------------
/Ch05-06/95.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/95.png
--------------------------------------------------------------------------------
/Ch05-06/bg_cointex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/bg_cointex.png
--------------------------------------------------------------------------------
/Ch05-06/buildozer.spec:
--------------------------------------------------------------------------------
1 | [app]
2 |
3 | # (str) Title of your application
4 | title = CoinTex
5 |
6 | # (str) Package name
7 | #package.name = reactfast
8 |
9 | # (str) Package domain (needed for android/ios packaging)
10 | #package.domain = cointex.cointex
11 |
12 | #package.name = reactfast
13 | #package.domain = cointex.cointex
14 |
15 | package.name = cointexreactfast
16 | package.domain = coin.tex
17 |
18 | # (str) Source code where the main.py live
19 | source.dir = .
20 |
21 | # (list) Source files to include (let empty to include all the files)
22 | source.include_exts = py,png,jpg,kv,atlas,wav
23 |
24 | # (list) List of inclusions using pattern matching
25 | #source.include_patterns = assets/*,images/*.png
26 |
27 | # (list) Source files to exclude (let empty to not exclude anything)
28 | #source.exclude_exts = spec
29 |
30 | # (list) List of directory to exclude (let empty to not exclude anything)
31 | source.exclude_dirs = bin
32 |
33 | # (list) List of exclusions using pattern matching
34 | #source.exclude_patterns = license,images/*/*.jpg
35 |
36 | # (str) Application versioning (method 1)
37 | version = 1.1
38 |
39 | # (str) Application versioning (method 2)
40 | # version.regex = __version__ = ['"](.*)['"]
41 | # version.filename = %(source.dir)s/main.py
42 |
43 | # (list) Application requirements
44 | # comma separated e.g. requirements = sqlite3,kivy
45 | requirements = kivy
46 | #requirements.source.numpy = /home/ahmedgad/Desktop/numpy15
47 |
48 | # (str) Custom source folders for requirements
49 | # Sets custom source for any requirements with recipes
50 | # requirements.source.kivy = ../../kivy
51 |
52 | # (list) Garden requirements
53 | #garden_requirements =
54 |
55 | # (str) Presplash of the application
56 | presplash.filename = %(source.dir)s/cointex_presplash.png
57 |
58 | # (str) Icon of the application
59 | icon.filename = %(source.dir)s/cointex_logo.png
60 |
61 | # (str) Supported orientation (one of landscape, portrait or all)
62 | orientation = landscape
63 |
64 | # (list) List of service to declare
65 | #services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
66 |
67 | #
68 | # OSX Specific
69 | #
70 |
71 | #
72 | # author = © Copyright Info
73 |
74 | # change the major version of python used by the app
75 | osx.python_version = 2
76 |
77 | # Kivy version to use
78 | #osx.kivy_version = 1.9.1
79 |
80 | #
81 | # Android specific
82 | #
83 |
84 | # (bool) Indicate if the application should be fullscreen or not
85 | fullscreen = 1
86 |
87 | # (string) Presplash background color (for new android toolchain)
88 | # Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
89 | # red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
90 | # darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
91 | # olive, purple, silver, teal.
92 | #android.presplash_color = #FFFFFF
93 |
94 | # (list) Permissions
95 | #android.permissions = INTERNET
96 |
97 | # (int) Android API to use
98 | android.api = 19
99 |
100 | # (int) Minimum API required
101 | android.minapi = 19
102 |
103 | # (int) Android SDK version to use
104 | android.sdk = 27
105 |
106 | # (str) Android NDK version to use
107 | #android.ndk = 9c
108 | #android.ndk = 18b
109 |
110 | # (bool) Use --private data storage (True) or --dir public storage (False)
111 | #android.private_storage = True
112 |
113 | # (str) Android NDK directory (if empty, it will be automatically downloaded.)
114 | android.ndk_path = /home/ahmedgad/.buildozer/android/platform/android-ndk-r18b
115 | #android.ndk_path = /home/ahmedgad/.buildozer/android/platform/android-ndk-r9c
116 | #android.ndk_path = /home/ahmedgad/.buildozer/android/platform/android-ndk-r16b
117 |
118 | # (str) Android SDK directory (if empty, it will be automatically downloaded.)
119 | android.sdk_path = /home/ahmedgad/.buildozer/android/platform/android-sdk-linux
120 |
121 | # (str) Android NDK directory (if empty, it will be automatically downloaded.)
122 | #android.ndk_path =
123 |
124 | # (str) Android SDK directory (if empty, it will be automatically downloaded.)
125 | #android.sdk_path =
126 |
127 | # (str) ANT directory (if empty, it will be automatically downloaded.)
128 | #android.ant_path = /home/ahmedgad/.buildozer/android/platform/android-sdk-linux/apache-ant-1.9.4
129 |
130 | # (str) ANT directory (if empty, it will be automatically downloaded.)
131 | #android.ant_path =
132 |
133 | # (bool) If True, then skip trying to update the Android sdk
134 | # This can be useful to avoid excess Internet downloads or save time
135 | # when an update is due and you just want to test/build your package
136 | # android.skip_update = False
137 |
138 | # (str) Android entry point, default is ok for Kivy-based app
139 | #android.entrypoint = org.renpy.android.PythonActivity
140 |
141 | # (list) Pattern to whitelist for the whole project
142 | #android.whitelist =
143 |
144 | # (str) Path to a custom whitelist file
145 | #android.whitelist_src =
146 |
147 | # (str) Path to a custom blacklist file
148 | #android.blacklist_src =
149 |
150 | # (list) List of Java .jar files to add to the libs so that pyjnius can access
151 | # their classes. Don't add jars that you do not need, since extra jars can slow
152 | # down the build process. Allows wildcards matching, for example:
153 | # OUYA-ODK/libs/*.jar
154 | #android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
155 |
156 | # (list) List of Java files to add to the android project (can be java or a
157 | # directory containing the files)
158 | #android.add_src =
159 |
160 | # (list) Android AAR archives to add (currently works only with sdl2_gradle
161 | # bootstrap)
162 | #android.add_aars =
163 |
164 | # (list) Gradle dependencies to add (currently works only with sdl2_gradle
165 | # bootstrap)
166 | #android.gradle_dependencies =
167 |
168 | # (list) Java classes to add as activities to the manifest.
169 | #android.add_activites = com.example.ExampleActivity
170 |
171 | # (str) python-for-android branch to use, defaults to stable
172 | #p4a.branch = stable
173 |
174 | # (str) OUYA Console category. Should be one of GAME or APP
175 | # If you leave this blank, OUYA support will not be enabled
176 | #android.ouya.category = GAME
177 |
178 | # (str) Filename of OUYA Console icon. It must be a 732x412 png image.
179 | #android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
180 |
181 | # (str) XML file to include as an intent filters in tag
182 | #android.manifest.intent_filters =
183 |
184 | # (str) launchMode to set for the main activity
185 | #android.manifest.launch_mode = standard
186 |
187 | # (list) Android additional libraries to copy into libs/armeabi
188 | #android.add_libs_armeabi = libs/android/*.so
189 | #android.add_libs_armeabi_v7a = libs/android-v7/*.so
190 | #android.add_libs_x86 = libs/android-x86/*.so
191 | #android.add_libs_mips = libs/android-mips/*.so
192 |
193 | # (bool) Indicate whether the screen should stay on
194 | # Don't forget to add the WAKE_LOCK permission if you set this to True
195 | #android.wakelock = False
196 |
197 | # (list) Android application meta-data to set (key=value format)
198 | #android.meta_data =
199 |
200 | # (list) Android library project to add (will be added in the
201 | # project.properties automatically.)
202 | #android.library_references =
203 |
204 | # (str) Android logcat filters to use
205 | #android.logcat_filters = *:S python:D
206 |
207 | # (bool) Copy library instead of making a libpymodules.so
208 | #android.copy_libs = 1
209 |
210 | # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86
211 | android.arch = armeabi-v7a
212 |
213 | #
214 | # Python for android (p4a) specific
215 | #
216 |
217 | # (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
218 | #p4a.source_dir =
219 | p4a.source_dir=/home/ahmedgad/Desktop/python-for-android
220 | #p4a.source_dir=/home/ahmedgad/Desktop/testp4a/python-for-android
221 |
222 | # (str) The directory in which python-for-android should look for your own build recipes (if any)
223 | #p4a.local_recipes =
224 |
225 | # (str) Filename to the hook for p4a
226 | #p4a.hook =
227 |
228 | # (str) Bootstrap to use for android builds
229 | # p4a.bootstrap = sdl2
230 |
231 | # (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
232 | #p4a.port =
233 |
234 |
235 | #
236 | # iOS specific
237 | #
238 |
239 | # (str) Path to a custom kivy-ios folder
240 | #ios.kivy_ios_dir = ../kivy-ios
241 |
242 | # (str) Name of the certificate to use for signing the debug version
243 | # Get a list of available identities: buildozer ios list_identities
244 | #ios.codesign.debug = "iPhone Developer: ()"
245 |
246 | # (str) Name of the certificate to use for signing the release version
247 | #ios.codesign.release = %(ios.codesign.debug)s
248 |
249 |
250 | [buildozer]
251 |
252 | # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
253 | log_level = 2
254 |
255 | # (int) Display warning if buildozer is run as root (0 = False, 1 = True)
256 | warn_on_root = 1
257 |
258 | # (str) Path to build artifact storage, absolute or relative to spec file
259 | # build_dir = ./.buildozer
260 |
261 | # (str) Path to build output (i.e. .apk, .ipa) storage
262 | # bin_dir = ./bin
263 |
264 | # -----------------------------------------------------------------------------
265 | # List as sections
266 | #
267 | # You can define all the "list" as [section:key].
268 | # Each line will be considered as a option to the list.
269 | # Let's take [app] / source.exclude_patterns.
270 | # Instead of doing:
271 | #
272 | #[app]
273 | #source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
274 | #
275 | # This can be translated into:
276 | #
277 | #[app:source.exclude_patterns]
278 | #license
279 | #data/audio/*.wav
280 | #data/images/original/*
281 | #
282 |
283 |
284 | # -----------------------------------------------------------------------------
285 | # Profiles
286 | #
287 | # You can extend section / key with a profile
288 | # For example, you want to deploy a demo version of your application without
289 | # HD content. You could first change the title to add "(demo)" in the name
290 | # and extend the excluded directories to remove the HD content.
291 | #
292 | #[app@demo]
293 | #title = My Application (demo)
294 | #
295 | #[app:source.exclude_patterns@demo]
296 | #images/hd/*
297 | #
298 | # Then, invoke the command line with the "demo" profile:
299 | #
300 | #buildozer --profile demo android debug
301 |
--------------------------------------------------------------------------------
/Ch05-06/coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/coin.png
--------------------------------------------------------------------------------
/Ch05-06/cointex_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/cointex_logo.png
--------------------------------------------------------------------------------
/Ch05-06/cointex_presplash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/cointex_presplash.png
--------------------------------------------------------------------------------
/Ch05-06/fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/fire.png
--------------------------------------------------------------------------------
/Ch05-06/game_info:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/game_info
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl1.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl10.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl11.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl12.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl13.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl14.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl15.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl16.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl17.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl17.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl18.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl19.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl19.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl2.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl20.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl20.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl3.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl3.png
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl4.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl4.png
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl5.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl5.png
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl6.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl6.png
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl7.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl8.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-bg/bg_lvl9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-bg/bg_lvl9.jpg
--------------------------------------------------------------------------------
/Ch05-06/levels-images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/1.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/10.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/11.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/12.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/13.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/14.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/15.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/16.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/17.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/18.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/19.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/2.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/20.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/21.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/22.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/23.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/24.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/3.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/4.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/5.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/6.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/7.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/8.png
--------------------------------------------------------------------------------
/Ch05-06/levels-images/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/levels-images/9.png
--------------------------------------------------------------------------------
/Ch05-06/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 | import kivy.uix.screenmanager
3 | import kivy.uix.image
4 | import random
5 | import kivy.core.audio
6 | import os
7 | import functools
8 | import kivy.uix.behaviors
9 | import pickle
10 |
11 | class TestApp(kivy.app.App):
12 |
13 | def on_start(self):
14 | music_dir = os.getcwd()+"/music/"
15 | self.main_bg_music = kivy.core.audio.SoundLoader.load(music_dir+"bg_music_piano_flute.wav")
16 | self.main_bg_music.loop = True
17 | self.main_bg_music.play()
18 |
19 | next_level_num, congrats_displayed_once = self.read_game_info()
20 | self.activate_levels(next_level_num, congrats_displayed_once)
21 |
22 | def read_game_info(self):
23 | try:
24 | game_info_file = open("game_info",'rb')
25 | game_info = pickle.load(game_info_file)
26 | return game_info[0]['lastlvl'], game_info[0]['congrats_displayed_once']
27 | game_info_file.close()
28 | except:
29 | print("CoinTex FileNotFoundError: Game info file is not found. Game starts from level 1.")
30 | return 1, False
31 |
32 | def activate_levels(self, next_level_num, congrats_displayed_once):
33 | num_levels = len(self.root.screens[0].ids['lvls_imagebuttons'].children)
34 |
35 | levels_imagebuttons = self.root.screens[0].ids['lvls_imagebuttons'].children
36 | for i in range(num_levels-next_level_num, num_levels):
37 | levels_imagebuttons[i].disabled = False
38 | levels_imagebuttons[i].color = [1,1,1,1]
39 |
40 | for i in range(0, num_levels-next_level_num):
41 | levels_imagebuttons[i].disabled = True
42 | levels_imagebuttons[i].color = [1,1,1,0.5]
43 |
44 | if next_level_num == (num_levels+1) and congrats_displayed_once == False:
45 | self.root.current = "alllevelscompleted"
46 |
47 | def screen_on_pre_leave(self, screen_num):
48 | curr_screen = self.root.screens[screen_num]
49 | for i in range(curr_screen.num_monsters): curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)].pos_hint = {'x': 0.8, 'y': 0.8}
50 | curr_screen.ids['character_image_lvl'+str(screen_num)].pos_hint = {'x': 0.0, 'y': 0.0}
51 |
52 | next_level_num, congrats_displayed_once = self.read_game_info()
53 | self.activate_levels(next_level_num, congrats_displayed_once)
54 |
55 | def screen_on_pre_enter(self, screen_num):
56 | curr_screen = self.root.screens[screen_num]
57 | curr_screen.character_killed = False
58 | curr_screen.num_coins_collected = 0
59 | curr_screen.ids['character_image_lvl'+str(screen_num)].im_num = curr_screen.ids['character_image_lvl'+str(screen_num)].start_im_num
60 | for i in range(curr_screen.num_monsters): curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)].im_num = curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)].start_im_num
61 | curr_screen.ids['num_coins_collected_lvl'+str(screen_num)].text = "Coins 0/"+str(curr_screen.num_coins)
62 | curr_screen.ids['level_number_lvl'+str(screen_num)].text = "Level "+str(screen_num)
63 |
64 | curr_screen.num_collisions_hit = 0
65 | remaining_life_percent_lvl_widget = curr_screen.ids['remaining_life_percent_lvl'+str(screen_num)]
66 | remaining_life_percent_lvl_widget.size_hint = (remaining_life_percent_lvl_widget.remaining_life_size_hint_x, remaining_life_percent_lvl_widget.size_hint[1])
67 |
68 | for i in range(curr_screen.num_fires): curr_screen.ids['fire'+str(i+1)+'_lvl'+str(screen_num)].pos_hint = {'x': 1.1, 'y': 1.1}
69 |
70 | for key, coin in curr_screen.coins_ids.items():
71 | curr_screen.ids['layout_lvl'+str(screen_num)].remove_widget(coin)
72 | curr_screen.coins_ids = {}
73 |
74 | coin_width = 0.05
75 | coin_height = 0.05
76 |
77 | curr_screen = self.root.screens[screen_num]
78 |
79 | section_width = 1.0/curr_screen.num_coins
80 | for k in range(curr_screen.num_coins):
81 | x = random.uniform(section_width*k, section_width*(k+1)-coin_width)
82 | y = random.uniform(0, 1-coin_height)
83 | coin = kivy.uix.image.Image(source="coin.png", size_hint=(coin_width, coin_height), pos_hint={'x': x, 'y': y}, allow_stretch=True)
84 | curr_screen.ids['layout_lvl'+str(screen_num)].add_widget(coin, index=-1)
85 | curr_screen.coins_ids['coin'+str(k)] = coin
86 |
87 | def screen_on_enter(self, screen_num):
88 | music_dir = os.getcwd()+"/music/"
89 | self.bg_music = kivy.core.audio.SoundLoader.load(music_dir+"bg_music_piano.wav")
90 | self.bg_music.loop = True
91 |
92 | self.coin_sound = kivy.core.audio.SoundLoader.load(music_dir+"coin.wav")
93 | self.level_completed_sound = kivy.core.audio.SoundLoader.load(music_dir+"level_completed_flaute.wav")
94 | self.char_death_sound = kivy.core.audio.SoundLoader.load(music_dir+"char_death_flaute.wav")
95 |
96 | self.bg_music.play()
97 |
98 | curr_screen = self.root.screens[screen_num]
99 | for i in range(curr_screen.num_monsters):
100 | monster_image = curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)]
101 | new_pos = (random.uniform(0.0, 1 - monster_image.size_hint[0]/4), random.uniform(0.0, 1 - monster_image.size_hint[1]/4))
102 | self.start_monst_animation(monster_image=monster_image, new_pos=new_pos, anim_duration=random.uniform(monster_image.monst_anim_duration_low, monster_image.monst_anim_duration_high))
103 |
104 | for i in range(curr_screen.num_fires):
105 | fire_widget = curr_screen.ids['fire'+str(i+1)+'_lvl'+str(screen_num)]
106 | self.start_fire_animation(fire_widget=fire_widget, pos=(0.0, 0.5), anim_duration=5.0)
107 |
108 | def start_monst_animation(self, monster_image, new_pos, anim_duration):
109 | monst_anim = kivy.animation.Animation(pos_hint={'x': new_pos[0], 'y': new_pos[1]}, im_num=monster_image.end_im_num,duration=anim_duration)
110 | monst_anim.bind(on_complete=self.monst_animation_completed)
111 | monst_anim.start(monster_image)
112 |
113 | def monst_animation_completed(self, *args):
114 | monster_image = args[1]
115 | monster_image.im_num = monster_image.start_im_num
116 |
117 | new_pos = (random.uniform(0.0, 1 - monster_image.size_hint[0]/4), random.uniform(0.0, 1 - monster_image.size_hint[1]/4))
118 | self.start_monst_animation(monster_image=monster_image, new_pos= new_pos,anim_duration=random.uniform(monster_image.monst_anim_duration_low, monster_image.monst_anim_duration_high))
119 |
120 | def monst_pos_hint(self, monster_image):
121 | screen_num = int(monster_image.parent.parent.name[5:])
122 | curr_screen = self.root.screens[screen_num]
123 | character_image = curr_screen.ids['character_image_lvl'+str(screen_num)]
124 |
125 | character_center = character_image.center
126 | monster_center = monster_image.center
127 |
128 | gab_x = character_image.width / 2
129 | gab_y = character_image.height / 2
130 | if character_image.collide_widget(monster_image) and abs(character_center[0] - monster_center[0]) <= gab_x and abs(character_center[1] - monster_center[1]) <= gab_y:
131 | curr_screen.num_collisions_hit = curr_screen.num_collisions_hit + 1
132 | life_percent = float(curr_screen.num_collisions_hit)/float(curr_screen.num_collisions_level)
133 |
134 | # life_remaining_percent = 100-round(life_percent, 2)*100
135 | # remaining_life_percent_lvl_widget.text = str(int(life_remaining_percent))+"%"
136 | remaining_life_percent_lvl_widget=curr_screen.ids['remaining_life_percent_lvl'+str(screen_num)]
137 | remaining_life_size_hint_x = remaining_life_percent_lvl_widget.remaining_life_size_hint_x
138 | remaining_life_percent_lvl_widget.size_hint = (remaining_life_size_hint_x-remaining_life_size_hint_x*life_percent, remaining_life_percent_lvl_widget.size_hint[1])
139 |
140 | if curr_screen.num_collisions_hit == curr_screen.num_collisions_level:
141 | self.bg_music.stop()
142 | self.char_death_sound.play()
143 | curr_screen.character_killed = True
144 |
145 | kivy.animation.Animation.cancel_all(character_image)
146 | for i in range(curr_screen.num_monsters): kivy.animation.Animation.cancel_all(curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)])
147 | for i in range(curr_screen.num_fires): kivy.animation.Animation.cancel_all(curr_screen.ids['fire'+str(i+1)+'_lvl'+str(screen_num)])
148 |
149 | character_image.im_num = character_image.dead_start_im_num
150 | char_anim = kivy.animation.Animation(im_num=character_image.dead_end_im_num, duration=1.0)
151 | char_anim.start(character_image)
152 | kivy.clock.Clock.schedule_once(functools.partial(self.back_to_main_screen, curr_screen.parent), 3)
153 |
154 | def change_monst_im(self, monster_image):
155 | monster_image.source = str(int(monster_image.im_num)) + ".png"
156 |
157 | def touch_down_handler(self, screen_num, args):
158 | curr_screen = self.root.screens[screen_num]
159 | if curr_screen.character_killed == False:
160 | self.start_char_animation(screen_num, args[1].spos)
161 |
162 | def start_char_animation(self, screen_num, touch_pos):
163 | curr_screen = self.root.screens[screen_num]
164 | character_image = curr_screen.ids['character_image_lvl'+str(screen_num)]
165 | character_image.im_num = character_image.start_im_num
166 | char_anim = kivy.animation.Animation(pos_hint={'x': touch_pos[0] - character_image.size_hint[0] / 2,'y': touch_pos[1] - character_image.size_hint[1] / 2}, im_num=character_image.end_im_num, duration=curr_screen.char_anim_duration)
167 | char_anim.bind(on_complete=self.char_animation_completed)
168 | char_anim.start(character_image)
169 |
170 | def char_animation_completed(self, *args):
171 | character_image = args[1]
172 | character_image.im_num = character_image.start_im_num
173 |
174 | def char_pos_hint(self, character_image):
175 | screen_num = int(character_image.parent.parent.name[5:])
176 | character_center = character_image.center
177 |
178 | gab_x = character_image.width / 3
179 | gab_y = character_image.height / 3
180 | coins_to_delete = []
181 | curr_screen = self.root.screens[screen_num]
182 |
183 | for coin_key, curr_coin in curr_screen.coins_ids.items():
184 | curr_coin_center = curr_coin.center
185 | if character_image.collide_widget(curr_coin) and abs(character_center[0] - curr_coin_center[0]) <= gab_x and abs(character_center[1] - curr_coin_center[1]) <= gab_y:
186 | self.coin_sound.play()
187 | coins_to_delete.append(coin_key)
188 | curr_screen.ids['layout_lvl'+str(screen_num)].remove_widget(curr_coin)
189 | curr_screen.num_coins_collected = curr_screen.num_coins_collected + 1
190 | curr_screen.ids['num_coins_collected_lvl'+str(screen_num)].text = "Coins "+str(curr_screen.num_coins_collected)+"/"+str(curr_screen.num_coins)
191 | if curr_screen.num_coins_collected == curr_screen.num_coins:
192 | self.bg_music.stop()
193 | self.level_completed_sound.play()
194 | kivy.clock.Clock.schedule_once(functools.partial(self.back_to_main_screen, curr_screen.parent), 3)
195 | for i in range(curr_screen.num_monsters): kivy.animation.Animation.cancel_all(curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)])
196 | for i in range(curr_screen.num_fires): kivy.animation.Animation.cancel_all(curr_screen.ids['fire'+str(i+1)+'_lvl'+str(screen_num)])
197 |
198 | next_level_num, congrats_displayed_once = self.read_game_info()
199 | if (screen_num+1) > next_level_num:
200 | game_info_file = open("game_info",'wb')
201 | pickle.dump([{'lastlvl':screen_num+1, "congrats_displayed_once": False}], game_info_file)
202 | game_info_file.close()
203 | else:
204 | game_info_file = open("game_info",'wb')
205 | pickle.dump([{'lastlvl':next_level_num, "congrats_displayed_once": True}], game_info_file)
206 | game_info_file.close()
207 |
208 | if len(coins_to_delete) > 0:
209 | for coin_key in coins_to_delete:
210 | del curr_screen.coins_ids[coin_key]
211 |
212 | def change_char_im(self, character_image):
213 | character_image.source = str(int(character_image.im_num)) + ".png"
214 |
215 | def start_fire_animation(self, fire_widget, pos, anim_duration):
216 | fire_anim = kivy.animation.Animation(pos_hint=fire_widget.fire_start_pos_hint, duration=fire_widget.fire_anim_duration)+kivy.animation.Animation(pos_hint=fire_widget.fire_end_pos_hint, duration=fire_widget.fire_anim_duration)
217 | fire_anim.repeat = True
218 | fire_anim.start(fire_widget)
219 |
220 | def fire_pos_hint(self, fire_widget):
221 | screen_num = int(fire_widget.parent.parent.name[5:])
222 | curr_screen = self.root.screens[screen_num]
223 | character_image = curr_screen.ids['character_image_lvl'+str(screen_num)]
224 |
225 | character_center = character_image.center
226 | fire_center = fire_widget.center
227 |
228 | gab_x = character_image.width / 3
229 | gab_y = character_image.height / 3
230 | if character_image.collide_widget(fire_widget) and abs(character_center[0] - fire_center[0]) <= gab_x and abs(character_center[1] - fire_center[1]) <= gab_y:
231 | curr_screen.num_collisions_hit = curr_screen.num_collisions_hit + 1
232 | life_percent = float(curr_screen.num_collisions_hit)/float(curr_screen.num_collisions_level)
233 |
234 | remaining_life_percent_lvl_widget = curr_screen.ids['remaining_life_percent_lvl'+str(screen_num)]
235 | # life_remaining_percent = 100-round(life_percent, 2)*100
236 | # remaining_life_percent_lvl_widget.text = str(int(life_remaining_percent))+"%"
237 |
238 | remaining_life_size_hint_x = remaining_life_percent_lvl_widget.remaining_life_size_hint_x
239 | remaining_life_percent_lvl_widget.size_hint = (remaining_life_size_hint_x-remaining_life_size_hint_x*life_percent, remaining_life_percent_lvl_widget.size_hint[1])
240 |
241 | if curr_screen.num_collisions_hit == curr_screen.num_collisions_level:
242 | self.bg_music.stop()
243 | self.char_death_sound.play()
244 | curr_screen.character_killed = True
245 |
246 | kivy.animation.Animation.cancel_all(character_image)
247 | for i in range(curr_screen.num_monsters): kivy.animation.Animation.cancel_all(curr_screen.ids['monster'+str(i+1)+'_image_lvl'+str(screen_num)])
248 | for i in range(curr_screen.num_fires): kivy.animation.Animation.cancel_all(curr_screen.ids['fire'+str(i+1)+'_lvl'+str(screen_num)])
249 |
250 | character_image.im_num = character_image.dead_start_im_num
251 | char_anim = kivy.animation.Animation(im_num=character_image.dead_end_im_num, duration=1.0)
252 | char_anim.start(character_image)
253 | kivy.clock.Clock.schedule_once(functools.partial(self.back_to_main_screen, curr_screen.parent), 3)
254 |
255 | def back_to_main_screen(self, screenManager, *args):
256 | screenManager.current = "main"
257 |
258 | def main_screen_on_enter(self):
259 | self.main_bg_music.play()
260 |
261 | def main_screen_on_leave(self):
262 | self.main_bg_music.stop()
263 |
264 | class ImageButton(kivy.uix.behaviors.ButtonBehavior, kivy.uix.image.Image):
265 | pass
266 |
267 | class MainScreen(kivy.uix.screenmanager.Screen):
268 | pass
269 |
270 | class AboutUs(kivy.uix.screenmanager.Screen):
271 | pass
272 |
273 | class AllLevelsCompleted(kivy.uix.screenmanager.Screen):
274 | pass
275 |
276 | class Level1(kivy.uix.screenmanager.Screen):
277 | character_killed = False
278 | num_coins = 5
279 | num_coins_collected = 0
280 | coins_ids = {}
281 | char_anim_duration = 1.0
282 | num_monsters = 1
283 | num_fires = 0
284 | num_collisions_hit = 0
285 | num_collisions_level = 20
286 |
287 | class Level2(kivy.uix.screenmanager.Screen):
288 | character_killed = False
289 | num_coins = 8
290 | num_coins_collected = 0
291 | coins_ids = {}
292 | char_anim_duration = 1.1
293 | num_monsters = 1
294 | num_fires = 0
295 | num_collisions_hit = 0
296 | num_collisions_level = 30
297 |
298 | class Level3(kivy.uix.screenmanager.Screen):
299 | character_killed = False
300 | num_coins = 12
301 | num_coins_collected = 0
302 | coins_ids = {}
303 | char_anim_duration = 1.2
304 | num_monsters = 1
305 | num_fires = 0
306 | num_collisions_hit = 0
307 | num_collisions_level = 30
308 |
309 | class Level4(kivy.uix.screenmanager.Screen):
310 | character_killed = False
311 | num_coins = 10
312 | num_coins_collected = 0
313 | coins_ids = {}
314 | char_anim_duration = 1.2
315 | num_monsters = 1
316 | num_fires = 1
317 | num_collisions_hit = 0
318 | num_collisions_level = 20
319 |
320 | class Level5(kivy.uix.screenmanager.Screen):
321 | character_killed = False
322 | num_coins = 15
323 | num_coins_collected = 0
324 | coins_ids = {}
325 | char_anim_duration = 1.3
326 | num_monsters = 1
327 | num_fires = 2
328 | num_collisions_hit = 0
329 | num_collisions_level = 20
330 |
331 | class Level6(kivy.uix.screenmanager.Screen):
332 | character_killed = False
333 | num_coins = 12
334 | num_coins_collected = 0
335 | coins_ids = {}
336 | char_anim_duration = 1.3
337 | num_monsters = 1
338 | num_fires = 3
339 | num_collisions_hit = 0
340 | num_collisions_level = 20
341 |
342 | class Level7(kivy.uix.screenmanager.Screen):
343 | character_killed = False
344 | num_coins = 10
345 | num_coins_collected = 0
346 | coins_ids = {}
347 | char_anim_duration = 1.4
348 | num_monsters = 3
349 | num_fires = 0
350 | num_collisions_hit = 0
351 | num_collisions_level = 25
352 |
353 | class Level8(kivy.uix.screenmanager.Screen):
354 | character_killed = False
355 | num_coins = 15
356 | num_coins_collected = 0
357 | coins_ids = {}
358 | char_anim_duration = 1.4
359 | num_monsters = 2
360 | num_fires = 0
361 | num_collisions_hit = 0
362 | num_collisions_level = 25
363 |
364 | class Level9(kivy.uix.screenmanager.Screen):
365 | character_killed = False
366 | num_coins = 12
367 | num_coins_collected = 0
368 | coins_ids = {}
369 | char_anim_duration = 1.5
370 | num_monsters = 2
371 | num_fires = 0
372 | num_collisions_hit = 0
373 | num_collisions_level = 25
374 |
375 | class Level10(kivy.uix.screenmanager.Screen):
376 | character_killed = False
377 | num_coins = 14
378 | num_coins_collected = 0
379 | coins_ids = {}
380 | char_anim_duration = 1.5
381 | num_monsters = 3
382 | num_fires = 0
383 | num_collisions_hit = 0
384 | num_collisions_level = 30
385 |
386 | class Level11(kivy.uix.screenmanager.Screen):
387 | character_killed = False
388 | num_coins = 15
389 | num_coins_collected = 0
390 | coins_ids = {}
391 | char_anim_duration = 1.6
392 | num_monsters = 2
393 | num_fires = 1
394 | num_collisions_hit = 0
395 | num_collisions_level = 30
396 |
397 | class Level12(kivy.uix.screenmanager.Screen):
398 | character_killed = False
399 | num_coins = 12
400 | num_coins_collected = 0
401 | coins_ids = {}
402 | char_anim_duration = 1.6
403 | num_monsters = 2
404 | num_fires = 1
405 | num_collisions_hit = 0
406 | num_collisions_level = 30
407 |
408 | class Level13(kivy.uix.screenmanager.Screen):
409 | character_killed = False
410 | num_coins = 10
411 | num_coins_collected = 0
412 | coins_ids = {}
413 | char_anim_duration = 1.7
414 | num_monsters = 2
415 | num_fires = 2
416 | num_collisions_hit = 0
417 | num_collisions_level = 20
418 |
419 | class Level14(kivy.uix.screenmanager.Screen):
420 | character_killed = False
421 | num_coins = 15
422 | num_coins_collected = 0
423 | coins_ids = {}
424 | char_anim_duration = 1.7
425 | num_monsters = 0
426 | num_fires = 6
427 | num_collisions_hit = 0
428 | num_collisions_level = 30
429 |
430 | class Level15(kivy.uix.screenmanager.Screen):
431 | character_killed = False
432 | num_coins = 16
433 | num_coins_collected = 0
434 | coins_ids = {}
435 | char_anim_duration = 1.8
436 | num_monsters = 2
437 | num_fires = 3
438 | num_collisions_hit = 0
439 | num_collisions_level = 30
440 |
441 | class Level16(kivy.uix.screenmanager.Screen):
442 | character_killed = False
443 | num_coins = 15
444 | num_coins_collected = 0
445 | coins_ids = {}
446 | char_anim_duration = 1.8
447 | num_monsters = 3
448 | num_fires = 2
449 | num_collisions_hit = 0
450 | num_collisions_level = 35
451 |
452 | class Level17(kivy.uix.screenmanager.Screen):
453 | character_killed = False
454 | num_coins = 10
455 | num_coins_collected = 0
456 | coins_ids = {}
457 | char_anim_duration = 1.3
458 | num_monsters = 0
459 | num_fires = 4
460 | num_collisions_hit = 0
461 | num_collisions_level = 30
462 |
463 | class Level18(kivy.uix.screenmanager.Screen):
464 | character_killed = False
465 | num_coins = 15
466 | num_coins_collected = 0
467 | coins_ids = {}
468 | char_anim_duration = 1.5
469 | num_monsters = 3
470 | num_fires = 4
471 | num_collisions_hit = 0
472 | num_collisions_level = 30
473 |
474 | class Level19(kivy.uix.screenmanager.Screen):
475 | character_killed = False
476 | num_coins = 12
477 | num_coins_collected = 0
478 | coins_ids = {}
479 | char_anim_duration = 1.2
480 | num_monsters = 0
481 | num_fires = 6
482 | num_collisions_hit = 0
483 | num_collisions_level = 30
484 |
485 | class Level20(kivy.uix.screenmanager.Screen):
486 | character_killed = False
487 | num_coins = 15
488 | num_coins_collected = 0
489 | coins_ids = {}
490 | char_anim_duration = 1.1
491 | num_monsters = 0
492 | num_fires = 8
493 | num_collisions_hit = 0
494 | num_collisions_level = 30
495 |
496 | class Level20(kivy.uix.screenmanager.Screen):
497 | character_killed = False
498 | num_coins = 20
499 | num_coins_collected = 0
500 | coins_ids = {}
501 | char_anim_duration = 1.1
502 | num_monsters = 2
503 | num_fires = 4
504 | num_collisions_hit = 0
505 | num_collisions_level = 30
506 |
507 | class Level21(kivy.uix.screenmanager.Screen):
508 | character_killed = False
509 | num_coins = 18
510 | num_coins_collected = 0
511 | coins_ids = {}
512 | char_anim_duration = 1.3
513 | num_monsters = 2
514 | num_fires = 4
515 | num_collisions_hit = 0
516 | num_collisions_level = 30
517 |
518 | class Level22(kivy.uix.screenmanager.Screen):
519 | character_killed = False
520 | num_coins = 20
521 | num_coins_collected = 0
522 | coins_ids = {}
523 | char_anim_duration = 1.3
524 | num_monsters = 2
525 | num_fires = 4
526 | num_collisions_hit = 0
527 | num_collisions_level = 30
528 |
529 | class Level23(kivy.uix.screenmanager.Screen):
530 | character_killed = False
531 | num_coins = 25
532 | num_coins_collected = 0
533 | coins_ids = {}
534 | char_anim_duration = 1.1
535 | num_monsters = 2
536 | num_fires = 2
537 | num_collisions_hit = 0
538 | num_collisions_level = 30
539 |
540 | class Level24(kivy.uix.screenmanager.Screen):
541 | character_killed = False
542 | num_coins = 20
543 | num_coins_collected = 0
544 | coins_ids = {}
545 | char_anim_duration = 1.1
546 | num_monsters = 3
547 | num_fires = 2
548 | num_collisions_hit = 0
549 | num_collisions_level = 30
550 |
551 | app = TestApp(title="CoinTex")
552 | app.run()
553 |
554 |
--------------------------------------------------------------------------------
/Ch05-06/music/bg_music_piano.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/music/bg_music_piano.wav
--------------------------------------------------------------------------------
/Ch05-06/music/bg_music_piano_flute.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/music/bg_music_piano_flute.wav
--------------------------------------------------------------------------------
/Ch05-06/music/char_death_flaute.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/music/char_death_flaute.wav
--------------------------------------------------------------------------------
/Ch05-06/music/coin.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/music/coin.wav
--------------------------------------------------------------------------------
/Ch05-06/music/level_completed_flaute.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/music/level_completed_flaute.wav
--------------------------------------------------------------------------------
/Ch05-06/other-images/About-Us.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/other-images/About-Us.png
--------------------------------------------------------------------------------
/Ch05-06/other-images/Congratulations-Passed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/other-images/Congratulations-Passed.png
--------------------------------------------------------------------------------
/Ch05-06/other-images/Main-Screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch05-06/other-images/Main-Screen.png
--------------------------------------------------------------------------------
/Ch05-06/test.kv:
--------------------------------------------------------------------------------
1 | ScreenManager:
2 | MainScreen:
3 | Level1:
4 | Level2:
5 | Level3:
6 | Level4:
7 | Level5:
8 | Level6:
9 | Level7:
10 | Level8:
11 | Level9:
12 | Level10:
13 | Level11:
14 | Level12:
15 | Level13:
16 | Level14:
17 | Level15:
18 | Level16:
19 | Level17:
20 | Level18:
21 | Level19:
22 | Level20:
23 | Level21:
24 | Level22:
25 | Level23:
26 | Level24:
27 | AboutUs:
28 | AllLevelsCompleted:
29 |
30 | :
31 | name: "aboutus"
32 | GridLayout:
33 | rows: 2
34 | canvas.before:
35 | Color:
36 | rgba: (0.6, 0.6, 0.6, 0.8)
37 | Rectangle:
38 | pos: self.pos
39 | size: self.size
40 | source: "bg_cointex.png"
41 | Label:
42 | size_hint_y: 0.9
43 | text_size: self.size
44 | font_size: 20
45 | halign: 'left'
46 | valign: 'top'
47 | text: "CoinTex version 1.2 is developed by Ahmed Fawzy Gad who is interested in machine learning, deep learning, computer vision, and Python. The game is completely developed in Python using the Kivy cross-platform framework.\n\nFeel free to contact me for any questions or recommendations:\nE-mail: ahmed.f.gad@gmail.com\nFacebook: https://www.facebook.com/ahmed.f.gadd\nLinkedIn: https://www.linkedin.com/in/ahmedfgad\nTowardsDataScience: https://towardsdatascience.com/@ahmedfgad \nResearchGate: https://www.researchgate.net/profile/Ahmed_Gad13"
48 | ImageButton:
49 | size_hint_y: 0.1
50 | source: "other-images/Main-Screen.png"
51 | on_release: app.root.current="main"
52 |
53 | :
54 | name: "alllevelscompleted"
55 | GridLayout:
56 | rows: 2
57 | canvas.before:
58 | Color:
59 | rgba: (0.6, 0.6, 0.6, 0.8)
60 | Rectangle:
61 | pos: self.pos
62 | size: self.size
63 | source: "bg_cointex.png"
64 | Image:
65 | size_hint_y: 0.9
66 | source: "other-images/Congratulations-Passed.png"
67 | ImageButton:
68 | size_hint_y: 0.1
69 | source: "other-images/Main-Screen.png"
70 | on_release: app.root.current="main"
71 |
72 | :
73 | name: "main"
74 | on_enter: app.main_screen_on_enter()
75 | on_leave: app.main_screen_on_leave()
76 | BoxLayout:
77 | orientation: "vertical"
78 | BoxLayout:
79 | size_hint_y: 0.08
80 | ImageButton:
81 | source: "./other-images/About-Us.png"
82 | on_release: app.root.current="aboutus"
83 | GridLayout:
84 | id: lvls_imagebuttons
85 | cols: 4
86 | spacing: (5,5)
87 | size_hint_y: 0.92
88 | canvas.before:
89 | Rectangle:
90 | pos: self.pos
91 | size: self.size
92 | source: "bg_cointex.png"
93 | ImageButton:
94 | source: "levels-images/1.png"
95 | on_release: app.root.current="level1"
96 | ImageButton:
97 | source: "levels-images/2.png"
98 | on_release: app.root.current="level2"
99 | ImageButton:
100 | source: "levels-images/3.png"
101 | on_release: app.root.current="level3"
102 | ImageButton:
103 | source: "levels-images/4.png"
104 | on_release: app.root.current="level4"
105 | ImageButton:
106 | source: "levels-images/5.png"
107 | on_release: app.root.current="level5"
108 | ImageButton:
109 | source: "levels-images/6.png"
110 | on_release: app.root.current="level6"
111 | ImageButton:
112 | source: "levels-images/7.png"
113 | on_release: app.root.current="level7"
114 | ImageButton:
115 | source: "levels-images/8.png"
116 | on_release: app.root.current="level8"
117 | ImageButton:
118 | source: "levels-images/9.png"
119 | on_release: app.root.current="level9"
120 | ImageButton:
121 | source: "levels-images/10.png"
122 | on_release: app.root.current="level10"
123 | ImageButton:
124 | source: "levels-images/11.png"
125 | on_release: app.root.current="level11"
126 | ImageButton:
127 | source: "levels-images/12.png"
128 | on_release: app.root.current="level12"
129 | ImageButton:
130 | source: "levels-images/13.png"
131 | on_release: app.root.current="level13"
132 | ImageButton:
133 | source: "levels-images/14.png"
134 | on_release: app.root.current="level14"
135 | ImageButton:
136 | source: "levels-images/15.png"
137 | on_release: app.root.current="level15"
138 | ImageButton:
139 | source: "levels-images/16.png"
140 | on_release: app.root.current="level16"
141 | ImageButton:
142 | source: "levels-images/17.png"
143 | on_release: app.root.current="level17"
144 | ImageButton:
145 | source: "levels-images/18.png"
146 | on_release: app.root.current="level18"
147 | ImageButton:
148 | source: "levels-images/19.png"
149 | on_release: app.root.current="level19"
150 | ImageButton:
151 | source: "levels-images/20.png"
152 | on_release: app.root.current="level20"
153 | ImageButton:
154 | source: "levels-images/21.png"
155 | on_release: app.root.current="level21"
156 | ImageButton:
157 | source: "levels-images/22.png"
158 | on_release: app.root.current="level22"
159 | ImageButton:
160 | source: "levels-images/23.png"
161 | on_release: app.root.current="level23"
162 | ImageButton:
163 | source: "levels-images/24.png"
164 | on_release: app.root.current="level24"
165 |
166 | :
167 | name: "level1"
168 | on_pre_enter: app.screen_on_pre_enter(1)
169 | on_pre_leave: app.screen_on_pre_leave(1)
170 | on_enter: app.screen_on_enter(1)
171 | FloatLayout:
172 | id: layout_lvl1
173 | on_touch_down: app.touch_down_handler(1, args)
174 | canvas.before:
175 | Rectangle:
176 | pos: self.pos
177 | size: self.size
178 | source: "levels-bg/bg_lvl1.jpg"
179 | NumCollectedCoins:
180 | id: num_coins_collected_lvl1
181 | LevelNumber
182 | id: level_number_lvl1
183 | RemainingLifePercent
184 | id: remaining_life_percent_lvl1
185 | Monster:
186 | id: monster1_image_lvl1
187 | monst_anim_duration_low: 3.5
188 | monst_anim_duration_high: 4.5
189 | Character:
190 | id: character_image_lvl1
191 |
192 | :
193 | name: "level2"
194 | on_pre_enter: app.screen_on_pre_enter(2)
195 | on_pre_leave: app.screen_on_pre_leave(2)
196 | on_enter: app.screen_on_enter(2)
197 | FloatLayout:
198 | id: layout_lvl2
199 | on_touch_down: app.touch_down_handler(2, args)
200 | canvas.before:
201 | Rectangle:
202 | pos: self.pos
203 | size: self.size
204 | source: "levels-bg/bg_lvl2.jpg"
205 | NumCollectedCoins:
206 | id: num_coins_collected_lvl2
207 | LevelNumber
208 | id: level_number_lvl2
209 | RemainingLifePercent
210 | id: remaining_life_percent_lvl2
211 | Monster:
212 | id: monster1_image_lvl2
213 | monst_anim_duration_low: 2.5
214 | monst_anim_duration_high: 3.5
215 | Character:
216 | id: character_image_lvl2
217 |
218 | :
219 | name: "level3"
220 | on_pre_enter: app.screen_on_pre_enter(3)
221 | on_pre_leave: app.screen_on_pre_leave(3)
222 | on_enter: app.screen_on_enter(3)
223 | FloatLayout:
224 | id: layout_lvl3
225 | on_touch_down: app.touch_down_handler(3, args)
226 | canvas.before:
227 | Rectangle:
228 | pos: self.pos
229 | size: self.size
230 | source: "levels-bg/bg_lvl3.jpg"
231 | NumCollectedCoins:
232 | id: num_coins_collected_lvl3
233 | LevelNumber
234 | id: level_number_lvl3
235 | RemainingLifePercent
236 | id: remaining_life_percent_lvl3
237 | Monster:
238 | id: monster1_image_lvl3
239 | monst_anim_duration_low: 1.0
240 | monst_anim_duration_high: 1.5
241 | Character:
242 | id: character_image_lvl3
243 |
244 | :
245 | name: "level4"
246 | on_pre_enter: app.screen_on_pre_enter(4)
247 | on_pre_leave: app.screen_on_pre_leave(4)
248 | on_enter: app.screen_on_enter(4)
249 | FloatLayout:
250 | id: layout_lvl4
251 | on_touch_down: app.touch_down_handler(4, args)
252 | canvas.before:
253 | Rectangle:
254 | pos: self.pos
255 | size: self.size
256 | source: "levels-bg/bg_lvl4.jpg"
257 | NumCollectedCoins:
258 | id: num_coins_collected_lvl4
259 | LevelNumber
260 | id: level_number_lvl4
261 | RemainingLifePercent
262 | id: remaining_life_percent_lvl4
263 | Fire:
264 | id: fire1_lvl4
265 | fire_start_pos_hint: {'x': 1.5, 'y': 0.5}
266 | fire_end_pos_hint: {'x': -0.5, 'y': 0.5}
267 | fire_anim_duration: 2.5
268 | Monster:
269 | id: monster1_image_lvl4
270 | monst_anim_duration_low: 2.5
271 | monst_anim_duration_high: 3.5
272 | Character:
273 | id: character_image_lvl4
274 |
275 | :
276 | name: "level5"
277 | on_pre_enter: app.screen_on_pre_enter(5)
278 | on_pre_leave: app.screen_on_pre_leave(5)
279 | on_enter: app.screen_on_enter(5)
280 | FloatLayout:
281 | id: layout_lvl5
282 | on_touch_down: app.touch_down_handler(5, args)
283 | canvas.before:
284 | Rectangle:
285 | pos: self.pos
286 | size: self.size
287 | source: "levels-bg/bg_lvl5.jpg"
288 | NumCollectedCoins:
289 | id: num_coins_collected_lvl5
290 | LevelNumber
291 | id: level_number_lvl5
292 | RemainingLifePercent
293 | id: remaining_life_percent_lvl5
294 | Fire:
295 | id: fire1_lvl5
296 | fire_start_pos_hint: {'x': 1.5, 'y': 0.7}
297 | fire_end_pos_hint: {'x': -0.5, 'y': 0.7}
298 | fire_anim_duration: 3.0
299 | Fire:
300 | id: fire2_lvl5
301 | fire_start_pos_hint: {'x': 1.5, 'y': 0.3}
302 | fire_end_pos_hint: {'x': -0.5, 'y': 0.3}
303 | fire_anim_duration: 2.0
304 | Monster:
305 | id: monster1_image_lvl5
306 | monst_anim_duration_low: 1.0
307 | monst_anim_duration_high: 1.5
308 | Character:
309 | id: character_image_lvl5
310 |
311 | :
312 | name: "level6"
313 | on_pre_enter: app.screen_on_pre_enter(6)
314 | on_pre_leave: app.screen_on_pre_leave(6)
315 | on_enter: app.screen_on_enter(6)
316 | FloatLayout:
317 | id: layout_lvl6
318 | on_touch_down: app.touch_down_handler(6, args)
319 | canvas.before:
320 | Rectangle:
321 | pos: self.pos
322 | size: self.size
323 | source: "levels-bg/bg_lvl6.jpg"
324 | NumCollectedCoins:
325 | id: num_coins_collected_lvl6
326 | LevelNumber
327 | id: level_number_lvl6
328 | RemainingLifePercent
329 | id: remaining_life_percent_lvl6
330 | Fire:
331 | id: fire1_lvl6
332 | fire_start_pos_hint: {'x': 1.5, 'y': 0.8}
333 | fire_end_pos_hint: {'x': -0.5, 'y': 0.8}
334 | fire_anim_duration: 2.5
335 | Fire:
336 | id: fire2_lvl6
337 | fire_start_pos_hint: {'x': 1.5, 'y': 0.2}
338 | fire_end_pos_hint: {'x': -0.5, 'y': 0.2}
339 | fire_anim_duration: 2.0
340 | Fire:
341 | id: fire3_lvl6
342 | fire_start_pos_hint: {'x': 0.5, 'y': 1.5}
343 | fire_end_pos_hint: {'x': 0.5, 'y': -0.5}
344 | fire_anim_duration: 3.5
345 | Monster:
346 | id: monster1_image_lvl6
347 | monst_anim_duration_low: 2.5
348 | monst_anim_duration_high: 3.0
349 | Character:
350 | id: character_image_lvl6
351 |
352 | :
353 | name: "level7"
354 | on_pre_enter: app.screen_on_pre_enter(7)
355 | on_pre_leave: app.screen_on_pre_leave(7)
356 | on_enter: app.screen_on_enter(7)
357 | FloatLayout:
358 | id: layout_lvl7
359 | on_touch_down: app.touch_down_handler(7, args)
360 | canvas.before:
361 | Rectangle:
362 | pos: self.pos
363 | size: self.size
364 | source: "levels-bg/bg_lvl7.jpg"
365 | NumCollectedCoins:
366 | id: num_coins_collected_lvl7
367 | LevelNumber
368 | id: level_number_lvl7
369 | RemainingLifePercent
370 | id: remaining_life_percent_lvl7
371 | Monster:
372 | id: monster1_image_lvl7
373 | monst_anim_duration_low: 1.0
374 | monst_anim_duration_high: 1.5
375 | Monster:
376 | id: monster2_image_lvl7
377 | monst_anim_duration_low: 1.5
378 | monst_anim_duration_high: 2.5
379 | Monster:
380 | id: monster3_image_lvl7
381 | monst_anim_duration_low: 1.5
382 | monst_anim_duration_high: 2.5
383 | Character:
384 | id: character_image_lvl7
385 |
386 | :
387 | name: "level8"
388 | on_pre_enter: app.screen_on_pre_enter(8)
389 | on_pre_leave: app.screen_on_pre_leave(8)
390 | on_enter: app.screen_on_enter(8)
391 | FloatLayout:
392 | id: layout_lvl8
393 | on_touch_down: app.touch_down_handler(8, args)
394 | canvas.before:
395 | Rectangle:
396 | pos: self.pos
397 | size: self.size
398 | source: "levels-bg/bg_lvl8.jpg"
399 | NumCollectedCoins:
400 | id: num_coins_collected_lvl8
401 | LevelNumber
402 | id: level_number_lvl8
403 | RemainingLifePercent
404 | id: remaining_life_percent_lvl8
405 | Monster:
406 | id: monster1_image_lvl8
407 | monst_anim_duration_low: 1.5
408 | monst_anim_duration_high: 2.5
409 | Monster:
410 | id: monster2_image_lvl8
411 | monst_anim_duration_low: 1.0
412 | monst_anim_duration_high: 1.5
413 | Character:
414 | id: character_image_lvl8
415 |
416 | :
417 | name: "level9"
418 | on_pre_enter: app.screen_on_pre_enter(9)
419 | on_pre_leave: app.screen_on_pre_leave(9)
420 | on_enter: app.screen_on_enter(9)
421 | FloatLayout:
422 | id: layout_lvl9
423 | on_touch_down: app.touch_down_handler(9, args)
424 | canvas.before:
425 | Rectangle:
426 | pos: self.pos
427 | size: self.size
428 | source: "levels-bg/bg_lvl9.jpg"
429 | NumCollectedCoins:
430 | id: num_coins_collected_lvl9
431 | LevelNumber
432 | id: level_number_lvl9
433 | RemainingLifePercent
434 | id: remaining_life_percent_lvl9
435 | Monster:
436 | id: monster1_image_lvl9
437 | monst_anim_duration_low: 2.5
438 | monst_anim_duration_high: 3.5
439 | Monster2:
440 | id: monster2_image_lvl9
441 | monst_anim_duration_low: 1.2
442 | monst_anim_duration_high: 1.7
443 | Character:
444 | id: character_image_lvl9
445 |
446 | :
447 | name: "level10"
448 | on_pre_enter: app.screen_on_pre_enter(10)
449 | on_pre_leave: app.screen_on_pre_leave(10)
450 | on_enter: app.screen_on_enter(10)
451 | FloatLayout:
452 | id: layout_lvl10
453 | on_touch_down: app.touch_down_handler(10, args)
454 | canvas.before:
455 | Rectangle:
456 | pos: self.pos
457 | size: self.size
458 | source: "levels-bg/bg_lvl10.jpg"
459 | NumCollectedCoins:
460 | id: num_coins_collected_lvl10
461 | LevelNumber
462 | id: level_number_lvl10
463 | RemainingLifePercent
464 | id: remaining_life_percent_lvl10
465 | Monster:
466 | id: monster1_image_lvl10
467 | monst_anim_duration_low: 1.5
468 | monst_anim_duration_high: 2.5
469 | Monster2:
470 | id: monster2_image_lvl10
471 | monst_anim_duration_low: 0.8
472 | monst_anim_duration_high: 1.2
473 | Monster2:
474 | id: monster3_image_lvl10
475 | monst_anim_duration_low: 1.0
476 | monst_anim_duration_high: 1.5
477 | Character:
478 | id: character_image_lvl10
479 |
480 | :
481 | name: "level11"
482 | on_pre_enter: app.screen_on_pre_enter(11)
483 | on_pre_leave: app.screen_on_pre_leave(11)
484 | on_enter: app.screen_on_enter(11)
485 | FloatLayout:
486 | id: layout_lvl11
487 | on_touch_down: app.touch_down_handler(11, args)
488 | canvas.before:
489 | Rectangle:
490 | pos: self.pos
491 | size: self.size
492 | source: "levels-bg/bg_lvl11.jpg"
493 | NumCollectedCoins:
494 | id: num_coins_collected_lvl11
495 | LevelNumber
496 | id: level_number_lvl11
497 | RemainingLifePercent
498 | id: remaining_life_percent_lvl11
499 | Fire:
500 | id: fire1_lvl11
501 | fire_start_pos_hint: {'x': 1.5, 'y': 0.5}
502 | fire_end_pos_hint: {'x': -0.5, 'y': 0.5}
503 | fire_anim_duration: 3.5
504 | Monster:
505 | id: monster1_image_lvl11
506 | monst_anim_duration_low: 2.5
507 | monst_anim_duration_high: 3.5
508 | Monster2:
509 | id: monster2_image_lvl11
510 | monst_anim_duration_low: 2.0
511 | monst_anim_duration_high: 2.5
512 | Character:
513 | id: character_image_lvl11
514 |
515 | :
516 | name: "level12"
517 | on_pre_enter: app.screen_on_pre_enter(12)
518 | on_pre_leave: app.screen_on_pre_leave(12)
519 | on_enter: app.screen_on_enter(12)
520 | FloatLayout:
521 | id: layout_lvl12
522 | on_touch_down: app.touch_down_handler(12, args)
523 | canvas.before:
524 | Rectangle:
525 | pos: self.pos
526 | size: self.size
527 | source: "levels-bg/bg_lvl12.jpg"
528 | NumCollectedCoins:
529 | id: num_coins_collected_lvl12
530 | LevelNumber
531 | id: level_number_lvl12
532 | RemainingLifePercent
533 | id: remaining_life_percent_lvl12
534 | Fire:
535 | id: fire1_lvl12
536 | fire_start_pos_hint: {'x': 1.5, 'y': 0.5}
537 | fire_end_pos_hint: {'x': -0.5, 'y': 0.5}
538 | fire_anim_duration: 2.5
539 | Monster:
540 | id: monster1_image_lvl12
541 | monst_anim_duration_low: 2.5
542 | monst_anim_duration_high: 3.5
543 | Monster2:
544 | id: monster2_image_lvl12
545 | monst_anim_duration_low: 1.5
546 | monst_anim_duration_high: 2.0
547 | Character:
548 | id: character_image_lvl12
549 |
550 | :
551 | name: "level13"
552 | on_pre_enter: app.screen_on_pre_enter(13)
553 | on_pre_leave: app.screen_on_pre_leave(13)
554 | on_enter: app.screen_on_enter(13)
555 | FloatLayout:
556 | id: layout_lvl13
557 | on_touch_down: app.touch_down_handler(13, args)
558 | canvas.before:
559 | Rectangle:
560 | pos: self.pos
561 | size: self.size
562 | source: "levels-bg/bg_lvl13.jpg"
563 | NumCollectedCoins:
564 | id: num_coins_collected_lvl13
565 | LevelNumber
566 | id: level_number_lvl13
567 | RemainingLifePercent
568 | id: remaining_life_percent_lvl13
569 | Fire:
570 | id: fire1_lvl13
571 | fire_start_pos_hint: {'x': 1.5, 'y': 0.5}
572 | fire_end_pos_hint: {'x': -0.5, 'y': 0.5}
573 | fire_anim_duration: 2.5
574 | Fire:
575 | id: fire2_lvl13
576 | fire_start_pos_hint: {'x': 0.5, 'y': 1.5}
577 | fire_end_pos_hint: {'x': 0.5, 'y': -0.5}
578 | fire_anim_duration: 3.5
579 | Monster:
580 | id: monster1_image_lvl13
581 | monst_anim_duration_low: 2.5
582 | monst_anim_duration_high: 3.5
583 | Monster2:
584 | id: monster2_image_lvl13
585 | monst_anim_duration_low: 2.5
586 | monst_anim_duration_high: 3.0
587 | Character:
588 | id: character_image_lvl13
589 |
590 | :
591 | name: "level14"
592 | on_pre_enter: app.screen_on_pre_enter(14)
593 | on_pre_leave: app.screen_on_pre_leave(14)
594 | on_enter: app.screen_on_enter(14)
595 | FloatLayout:
596 | id: layout_lvl14
597 | on_touch_down: app.touch_down_handler(14, args)
598 | canvas.before:
599 | Rectangle:
600 | pos: self.pos
601 | size: self.size
602 | source: "levels-bg/bg_lvl14.jpg"
603 | NumCollectedCoins:
604 | id: num_coins_collected_lvl14
605 | LevelNumber
606 | id: level_number_lvl14
607 | RemainingLifePercent
608 | id: remaining_life_percent_lvl14
609 | Fire:
610 | id: fire1_lvl14
611 | fire_start_pos_hint: {'x': 1.5, 'y': 0.2}
612 | fire_end_pos_hint: {'x': -0.5, 'y': 0.2}
613 | fire_anim_duration: 2.5
614 | Fire:
615 | id: fire2_lvl14
616 | fire_start_pos_hint: {'x': 1.5, 'y': 0.8}
617 | fire_end_pos_hint: {'x': -0.5, 'y': 0.8}
618 | fire_anim_duration: 3.5
619 | Fire:
620 | id: fire3_lvl14
621 | fire_start_pos_hint: {'x': -1.5, 'y': 0.5}
622 | fire_end_pos_hint: {'x': -0.5, 'y': 0.5}
623 | fire_anim_duration: 3.5
624 | Fire:
625 | id: fire4_lvl14
626 | fire_start_pos_hint: {'x': 0.8, 'y': 1.5}
627 | fire_end_pos_hint: {'x': 0.8, 'y': -0.5}
628 | fire_anim_duration: 2.5
629 | Fire:
630 | id: fire5_lvl14
631 | fire_start_pos_hint: {'x': 0.2, 'y': 1.5}
632 | fire_end_pos_hint: {'x': 0.2, 'y': -0.5}
633 | fire_anim_duration: 3.5
634 | Fire:
635 | id: fire6_lvl14
636 | fire_start_pos_hint: {'x': 0.5, 'y': 1.5}
637 | fire_end_pos_hint: {'x': 0.5, 'y': -0.5}
638 | fire_anim_duration: 2.5
639 | Character:
640 | id: character_image_lvl14
641 |
642 | :
643 | name: "level15"
644 | on_pre_enter: app.screen_on_pre_enter(15)
645 | on_pre_leave: app.screen_on_pre_leave(15)
646 | on_enter: app.screen_on_enter(15)
647 | FloatLayout:
648 | id: layout_lvl15
649 | on_touch_down: app.touch_down_handler(15, args)
650 | canvas.before:
651 | Rectangle:
652 | pos: self.pos
653 | size: self.size
654 | source: "levels-bg/bg_lvl15.jpg"
655 | NumCollectedCoins:
656 | id: num_coins_collected_lvl15
657 | LevelNumber
658 | id: level_number_lvl15
659 | RemainingLifePercent
660 | id: remaining_life_percent_lvl15
661 | Fire:
662 | id: fire1_lvl15
663 | fire_start_pos_hint: {'x': 1.2, 'y': 0.2}
664 | fire_end_pos_hint: {'x': -0.5, 'y': 0.2}
665 | fire_anim_duration: 2.5
666 | Fire:
667 | id: fire2_lvl15
668 | fire_start_pos_hint: {'x': 1.5, 'y': 0.7}
669 | fire_end_pos_hint: {'x': -0.5, 'y': 0.7}
670 | fire_anim_duration: 3.5
671 | Fire:
672 | id: fire3_lvl15
673 | fire_start_pos_hint: {'x': 0.5, 'y': 1.5}
674 | fire_end_pos_hint: {'x': 0.5, 'y': -0.5}
675 | fire_anim_duration: 2.5
676 | Monster2:
677 | id: monster1_image_lvl15
678 | monst_anim_duration_low: 3.0
679 | monst_anim_duration_high: 3.5
680 | Monster2:
681 | id: monster2_image_lvl15
682 | monst_anim_duration_low: 3.0
683 | monst_anim_duration_high: 3.5
684 | Character:
685 | id: character_image_lvl15
686 |
687 | :
688 | name: "level16"
689 | on_pre_enter: app.screen_on_pre_enter(16)
690 | on_pre_leave: app.screen_on_pre_leave(16)
691 | on_enter: app.screen_on_enter(16)
692 | FloatLayout:
693 | id: layout_lvl16
694 | on_touch_down: app.touch_down_handler(16, args)
695 | canvas.before:
696 | Rectangle:
697 | pos: self.pos
698 | size: self.size
699 | source: "levels-bg/bg_lvl16.jpg"
700 | NumCollectedCoins:
701 | id: num_coins_collected_lvl16
702 | LevelNumber
703 | id: level_number_lvl16
704 | RemainingLifePercent
705 | id: remaining_life_percent_lvl16
706 | Fire:
707 | id: fire1_lvl16
708 | fire_start_pos_hint: {'x': 1.5, 'y': 0.2}
709 | fire_end_pos_hint: {'x': -0.5, 'y': 0.2}
710 | fire_anim_duration: 2.5
711 | Fire:
712 | id: fire2_lvl16
713 | fire_start_pos_hint: {'x': 1.5, 'y': 0.7}
714 | fire_end_pos_hint: {'x': -0.5, 'y': 0.7}
715 | fire_anim_duration: 1.5
716 | Monster:
717 | id: monster1_image_lvl16
718 | monst_anim_duration_low: 2.0
719 | monst_anim_duration_high: 3.5
720 | Monster2:
721 | id: monster2_image_lvl16
722 | monst_anim_duration_low: 3.0
723 | monst_anim_duration_high: 3.5
724 | Monster2:
725 | id: monster3_image_lvl16
726 | monst_anim_duration_low: 1.0
727 | monst_anim_duration_high: 1.5
728 | Character:
729 | id: character_image_lvl16
730 |
731 | :
732 | name: "level17"
733 | on_pre_enter: app.screen_on_pre_enter(17)
734 | on_pre_leave: app.screen_on_pre_leave(17)
735 | on_enter: app.screen_on_enter(17)
736 | FloatLayout:
737 | id: layout_lvl17
738 | on_touch_down: app.touch_down_handler(17, args)
739 | canvas.before:
740 | Rectangle:
741 | pos: self.pos
742 | size: self.size
743 | source: "levels-bg/bg_lvl17.jpg"
744 | NumCollectedCoins:
745 | id: num_coins_collected_lvl17
746 | LevelNumber
747 | id: level_number_lvl17
748 | RemainingLifePercent
749 | id: remaining_life_percent_lvl17
750 | Fire:
751 | id: fire1_lvl17
752 | fire_start_pos_hint: {'x': 1.5, 'y': 0.3}
753 | fire_end_pos_hint: {'x': -1.5, 'y': 0.3}
754 | fire_anim_duration: 1.5
755 | Fire:
756 | id: fire2_lvl17
757 | fire_start_pos_hint: {'x': 1.5, 'y': 0.8}
758 | fire_end_pos_hint: {'x': -1.5, 'y': 0.8}
759 | fire_anim_duration: 1.0
760 | Fire:
761 | id: fire3_lvl17
762 | fire_start_pos_hint: {'x': 0.8, 'y': -1.5}
763 | fire_end_pos_hint: {'x': 0.8, 'y': 1.5}
764 | fire_anim_duration: 1.5
765 | Fire:
766 | id: fire4_lvl17
767 | fire_start_pos_hint: {'x': 0.3, 'y': 1.5}
768 | fire_end_pos_hint: {'x': 0.3, 'y': -1.5}
769 | fire_anim_duration: 1.0
770 | Character:
771 | id: character_image_lvl17
772 |
773 | :
774 | name: "level18"
775 | on_pre_enter: app.screen_on_pre_enter(18)
776 | on_pre_leave: app.screen_on_pre_leave(18)
777 | on_enter: app.screen_on_enter(18)
778 | FloatLayout:
779 | id: layout_lvl18
780 | on_touch_down: app.touch_down_handler(18, args)
781 | canvas.before:
782 | Rectangle:
783 | pos: self.pos
784 | size: self.size
785 | source: "levels-bg/bg_lvl18.jpg"
786 | NumCollectedCoins:
787 | id: num_coins_collected_lvl18
788 | LevelNumber
789 | id: level_number_lvl18
790 | RemainingLifePercent
791 | id: remaining_life_percent_lvl18
792 | Fire:
793 | id: fire1_lvl18
794 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
795 | fire_end_pos_hint: {'x': 0.2, 'y': 0.3}
796 | fire_anim_duration: 1.2
797 | Fire:
798 | id: fire2_lvl18
799 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
800 | fire_end_pos_hint: {'x': 0.7, 'y': 0.8}
801 | fire_anim_duration: 1.3
802 | Fire:
803 | id: fire3_lvl18
804 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
805 | fire_end_pos_hint: {'x': 0.8, 'y': 0.7}
806 | fire_anim_duration: 1.2
807 | Fire:
808 | id: fire4_lvl18
809 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
810 | fire_end_pos_hint: {'x': 0.3, 'y': 0.2}
811 | fire_anim_duration: 1.0
812 | Monster:
813 | id: monster1_image_lvl18
814 | monst_anim_duration_low: 1.0
815 | monst_anim_duration_high: 1.6
816 | Monster2:
817 | id: monster2_image_lvl18
818 | monst_anim_duration_low: 1.0
819 | monst_anim_duration_high: 2.0
820 | Monster2:
821 | id: monster3_image_lvl18
822 | monst_anim_duration_low: 1.0
823 | monst_anim_duration_high: 1.2
824 | Character:
825 | id: character_image_lvl18
826 |
827 | :
828 | name: "level19"
829 | on_pre_enter: app.screen_on_pre_enter(19)
830 | on_pre_leave: app.screen_on_pre_leave(19)
831 | on_enter: app.screen_on_enter(19)
832 | FloatLayout:
833 | id: layout_lvl19
834 | on_touch_down: app.touch_down_handler(19, args)
835 | canvas.before:
836 | Rectangle:
837 | pos: self.pos
838 | size: self.size
839 | source: "levels-bg/bg_lvl19.jpg"
840 | NumCollectedCoins:
841 | id: num_coins_collected_lvl19
842 | LevelNumber
843 | id: level_number_lvl19
844 | RemainingLifePercent
845 | id: remaining_life_percent_lvl19
846 | Fire:
847 | id: fire1_lvl19
848 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
849 | fire_end_pos_hint: {'x': 0.2, 'y': 0.3}
850 | fire_anim_duration: 1.2
851 | Fire:
852 | id: fire2_lvl19
853 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
854 | fire_end_pos_hint: {'x': 0.7, 'y': 0.8}
855 | fire_anim_duration: 1.0
856 | Fire:
857 | id: fire3_lvl19
858 | fire_start_pos_hint: {'x': -1.5, 'y': 0.5}
859 | fire_end_pos_hint: {'x': 1.5, 'y': 0.5}
860 | fire_anim_duration: 1.5
861 | Fire:
862 | id: fire4_lvl19
863 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
864 | fire_end_pos_hint: {'x': 0.8, 'y': 0.7}
865 | fire_anim_duration: 1.2
866 | Fire:
867 | id: fire5_lvl19
868 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
869 | fire_end_pos_hint: {'x': 0.3, 'y': 0.2}
870 | fire_anim_duration: 1.3
871 | Fire:
872 | id: fire6_lvl19
873 | fire_start_pos_hint: {'x': 0.5, 'y': -1.5}
874 | fire_end_pos_hint: {'x': 0.5, 'y': 1.5}
875 | fire_anim_duration: 1.4
876 | Character:
877 | id: character_image_lvl19
878 |
879 | :
880 | name: "level20"
881 | on_pre_enter: app.screen_on_pre_enter(20)
882 | on_pre_leave: app.screen_on_pre_leave(20)
883 | on_enter: app.screen_on_enter(20)
884 | FloatLayout:
885 | id: layout_lvl20
886 | on_touch_down: app.touch_down_handler(20, args)
887 | canvas.before:
888 | Rectangle:
889 | pos: self.pos
890 | size: self.size
891 | source: "levels-bg/bg_lvl20.jpg"
892 | NumCollectedCoins:
893 | id: num_coins_collected_lvl20
894 | LevelNumber
895 | id: level_number_lvl20
896 | RemainingLifePercent
897 | id: remaining_life_percent_lvl20
898 | Fire:
899 | id: fire1_lvl20
900 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
901 | fire_end_pos_hint: {'x': 0.2, 'y': 0.3}
902 | fire_anim_duration: 1.5
903 | Fire:
904 | id: fire2_lvl20
905 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
906 | fire_end_pos_hint: {'x': 0.7, 'y': 0.8}
907 | fire_anim_duration: 1.3
908 | Fire:
909 | id: fire3_lvl20
910 | fire_start_pos_hint: {'x': -1.5, 'y': 0.5}
911 | fire_end_pos_hint: {'x': 1.5, 'y': 0.5}
912 | fire_anim_duration: 1.6
913 | Fire:
914 | id: fire4_lvl20
915 | fire_start_pos_hint: {'x': 0.1, 'y': 0.3}
916 | fire_end_pos_hint: {'x': 0.9, 'y': 0.3}
917 | fire_anim_duration: 1.5
918 | Fire:
919 | id: fire5_lvl20
920 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
921 | fire_end_pos_hint: {'x': 0.8, 'y': 0.7}
922 | fire_anim_duration: 1.5
923 | Fire:
924 | id: fire6_lvl20
925 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
926 | fire_end_pos_hint: {'x': 0.3, 'y': 0.2}
927 | fire_anim_duration: 1.3
928 | Fire:
929 | id: fire7_lvl20
930 | fire_start_pos_hint: {'x': 0.5, 'y': -1.5}
931 | fire_end_pos_hint: {'x': 0.5, 'y': 1.5}
932 | fire_anim_duration: 1.6
933 | Fire:
934 | id: fire8_lvl20
935 | fire_start_pos_hint: {'x': 0.5, 'y': 0.1}
936 | fire_end_pos_hint: {'x': 0.5, 'y': 0.9}
937 | fire_anim_duration: 1.3
938 | Character:
939 | id: character_image_lvl20
940 |
941 | :
942 | name: "level21"
943 | on_pre_enter: app.screen_on_pre_enter(21)
944 | on_pre_leave: app.screen_on_pre_leave(21)
945 | on_enter: app.screen_on_enter(21)
946 | FloatLayout:
947 | id: layout_lvl21
948 | on_touch_down: app.touch_down_handler(21, args)
949 | canvas.before:
950 | Rectangle:
951 | pos: self.pos
952 | size: self.size
953 | source: "levels-bg/bg_lvl1.jpg"
954 | NumCollectedCoins:
955 | id: num_coins_collected_lvl21
956 | LevelNumber
957 | id: level_number_lvl21
958 | RemainingLifePercent
959 | id: remaining_life_percent_lvl21
960 | Fire:
961 | id: fire1_lvl21
962 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
963 | fire_end_pos_hint: {'x': 0.2, 'y': 0.3}
964 | fire_anim_duration: 1.8
965 | Fire:
966 | id: fire2_lvl21
967 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
968 | fire_end_pos_hint: {'x': 0.7, 'y': 0.8}
969 | fire_anim_duration: 1.5
970 | Fire:
971 | id: fire3_lvl21
972 | fire_start_pos_hint: {'x': -1.5, 'y': 0.5}
973 | fire_end_pos_hint: {'x': 1.5, 'y': 0.5}
974 | fire_anim_duration: 2.0
975 | Fire:
976 | id: fire4_lvl21
977 | fire_start_pos_hint: {'x': 0.1, 'y': 0.3}
978 | fire_end_pos_hint: {'x': 0.9, 'y': 0.3}
979 | fire_anim_duration: 2.5
980 | Monster:
981 | id: monster1_image_lvl21
982 | monst_anim_duration_low: 1.0
983 | monst_anim_duration_high: 1.3
984 | Monster2:
985 | id: monster2_image_lvl21
986 | monst_anim_duration_low: 1.0
987 | monst_anim_duration_high: 1.5
988 | Character:
989 | id: character_image_lvl21
990 |
991 | :
992 | name: "level22"
993 | on_pre_enter: app.screen_on_pre_enter(22)
994 | on_pre_leave: app.screen_on_pre_leave(22)
995 | on_enter: app.screen_on_enter(22)
996 | FloatLayout:
997 | id: layout_lvl22
998 | on_touch_down: app.touch_down_handler(22, args)
999 | canvas.before:
1000 | Rectangle:
1001 | pos: self.pos
1002 | size: self.size
1003 | source: "levels-bg/bg_lvl2.jpg"
1004 | NumCollectedCoins:
1005 | id: num_coins_collected_lvl22
1006 | LevelNumber
1007 | id: level_number_lvl22
1008 | RemainingLifePercent
1009 | id: remaining_life_percent_lvl22
1010 | Fire:
1011 | id: fire1_lvl22
1012 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
1013 | fire_end_pos_hint: {'x': 0.2, 'y': 0.3}
1014 | fire_anim_duration: 1.9
1015 | Fire:
1016 | id: fire2_lvl22
1017 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
1018 | fire_end_pos_hint: {'x': 0.7, 'y': 0.8}
1019 | fire_anim_duration: 2.0
1020 | Fire:
1021 | id: fire3_lvl22
1022 | fire_start_pos_hint: {'x': -1.5, 'y': 0.5}
1023 | fire_end_pos_hint: {'x': 1.5, 'y': 0.5}
1024 | fire_anim_duration: 2.0
1025 | Fire:
1026 | id: fire4_lvl22
1027 | fire_start_pos_hint: {'x': 0.1, 'y': 0.3}
1028 | fire_end_pos_hint: {'x': 0.9, 'y': 0.3}
1029 | fire_anim_duration: 2.5
1030 | Monster:
1031 | id: monster1_image_lvl22
1032 | monst_anim_duration_low: 1.0
1033 | monst_anim_duration_high: 1.8
1034 | Monster2:
1035 | id: monster2_image_lvl22
1036 | monst_anim_duration_low: 1.0
1037 | monst_anim_duration_high: 2.0
1038 | Character:
1039 | id: character_image_lvl22
1040 |
1041 | :
1042 | name: "level23"
1043 | on_pre_enter: app.screen_on_pre_enter(23)
1044 | on_pre_leave: app.screen_on_pre_leave(23)
1045 | on_enter: app.screen_on_enter(23)
1046 | FloatLayout:
1047 | id: layout_lvl23
1048 | on_touch_down: app.touch_down_handler(23, args)
1049 | canvas.before:
1050 | Rectangle:
1051 | pos: self.pos
1052 | size: self.size
1053 | source: "levels-bg/bg_lvl3.jpg"
1054 | NumCollectedCoins:
1055 | id: num_coins_collected_lvl23
1056 | LevelNumber
1057 | id: level_number_lvl23
1058 | RemainingLifePercent
1059 | id: remaining_life_percent_lvl23
1060 | Fire:
1061 | id: fire1_lvl23
1062 | fire_start_pos_hint: {'x': -1.5, 'y': 0.3}
1063 | fire_end_pos_hint: {'x': -0.5, 'y': 0.3}
1064 | fire_anim_duration: 1.8
1065 | Fire:
1066 | id: fire2_lvl23
1067 | fire_start_pos_hint: {'x': -1.5, 'y': 0.8}
1068 | fire_end_pos_hint: {'x': -0.5, 'y': 0.8}
1069 | fire_anim_duration: 2.0
1070 | Monster:
1071 | id: monster1_image_lvl23
1072 | monst_anim_duration_low: 1.5
1073 | monst_anim_duration_high: 2.0
1074 | Monster2:
1075 | id: monster2_image_lvl23
1076 | monst_anim_duration_low: 1.5
1077 | monst_anim_duration_high: 2.5
1078 | Character:
1079 | id: character_image_lvl23
1080 |
1081 | :
1082 | name: "level24"
1083 | on_pre_enter: app.screen_on_pre_enter(24)
1084 | on_pre_leave: app.screen_on_pre_leave(24)
1085 | on_enter: app.screen_on_enter(24)
1086 | FloatLayout:
1087 | id: layout_lvl24
1088 | on_touch_down: app.touch_down_handler(24, args)
1089 | canvas.before:
1090 | Rectangle:
1091 | pos: self.pos
1092 | size: self.size
1093 | source: "levels-bg/bg_lvl4.jpg"
1094 | NumCollectedCoins:
1095 | id: num_coins_collected_lvl24
1096 | LevelNumber
1097 | id: level_number_lvl24
1098 | RemainingLifePercent
1099 | id: remaining_life_percent_lvl24
1100 | Fire:
1101 | id: fire1_lvl24
1102 | fire_start_pos_hint: {'x': 0.8, 'y': 0.3}
1103 | fire_end_pos_hint: {'x': 0.2, 'y': 0.3}
1104 | fire_anim_duration: 1.8
1105 | Fire:
1106 | id: fire2_lvl24
1107 | fire_start_pos_hint: {'x': 0.3, 'y': 0.8}
1108 | fire_end_pos_hint: {'x': 0.7, 'y': 0.8}
1109 | fire_anim_duration: 1.5
1110 | Monster:
1111 | id: monster1_image_lvl24
1112 | monst_anim_duration_low: 1.5
1113 | monst_anim_duration_high: 1.7
1114 | Monster2:
1115 | id: monster2_image_lvl24
1116 | monst_anim_duration_low: 1.8
1117 | monst_anim_duration_high: 2.5
1118 | Monster:
1119 | id: monster3_image_lvl24
1120 | monst_anim_duration_low: 1.5
1121 | monst_anim_duration_high: 2.0
1122 | Character:
1123 | id: character_image_lvl24
1124 |
1125 | :
1126 | size_hint: (0.1, 0.02)
1127 | pos_hint: {'x': 0.026, 'y': 0.97}
1128 | text: "Coins 0"
1129 | font_size: 20
1130 |
1131 | :
1132 | size_hint: (0.1, 0.02)
1133 | pos_hint: {'x': 0.15, 'y': 0.97}
1134 | text: "Level"
1135 | font_size: 20
1136 |
1137 | :
1138 | remaining_life_size_hint_x: 0.2
1139 | size_hint: (0.2, 0.022)
1140 | pos_hint: {'x': 0.3, 'y': 0.97}
1141 | font_size: 20
1142 | canvas:
1143 | Color:
1144 | rgb: (1, 0, 0)
1145 | Rectangle:
1146 | pos: self.pos
1147 | size: self.size
1148 |
1149 | :
1150 | size_hint: (0.15, 0.15)
1151 | pos_hint: {'x': 0.8, 'y': 0.8}
1152 | source: "10.png"
1153 | im_num: 10
1154 | start_im_num: 10
1155 | end_im_num: 17
1156 | allow_stretch: True
1157 | on_im_num: app.change_monst_im(self)
1158 | on_pos_hint: app.monst_pos_hint(self)
1159 |
1160 | :
1161 | size_hint: (0.15, 0.15)
1162 | pos_hint: {'x': 0.8, 'y': 0.8}
1163 | source: "21.png"
1164 | im_num: 21
1165 | start_im_num: 21
1166 | end_im_num: 29
1167 | allow_stretch: True
1168 | on_im_num: app.change_monst_im(self)
1169 | on_pos_hint: app.monst_pos_hint(self)
1170 |
1171 | :
1172 | size_hint: (0.15, 0.15)
1173 | pos_hint: {'x': 0.0, 'y': 0.0}
1174 | source: "0.png"
1175 | im_num: 0
1176 | start_im_num: 0
1177 | end_im_num: 7
1178 | dead_start_im_num: 91
1179 | dead_end_im_num: 95
1180 | allow_stretch: True
1181 | on_im_num: app.change_char_im(self)
1182 | on_pos_hint: app.char_pos_hint(self)
1183 |
1184 | :
1185 | pos_hint: {'x': 1.1, 'y': 1.1}
1186 | on_pos_hint: app.fire_pos_hint(self)
1187 | size_hint: (0.03, 0.03)
1188 | canvas:
1189 | Rectangle:
1190 | pos: self.pos
1191 | size: self.size
1192 | source: "fire.png"
1193 |
1194 | :
1195 | canvas.before:
1196 | Color:
1197 | rgba: (0.6, 0.6, 0.6, 0.5)
1198 | Rectangle:
1199 | pos: self.pos
1200 | size: self.size
1201 |
1202 |
--------------------------------------------------------------------------------
/Ch07/1.AudioApp/audio.kv:
--------------------------------------------------------------------------------
1 | BoxLayout:
2 | orientation: "vertical"
3 | Label:
4 | id: audio_pos
5 | size_hint_x: 0.0
6 | size: (0.0, 0.0)
7 | canvas.before:
8 | Color:
9 | rgb: (1, 0, 0)
10 | Rectangle:
11 | pos: self.pos
12 | size: self.size
13 | Label:
14 | font_size: 20
15 | id: audio_pos_info
16 | text: "Audio Position Info"
17 | Button:
18 | text: "Play"
19 | on_release: app.start_audio()
20 | Button:
21 | text: "Pause"
22 | on_release: app.pause_audio()
23 | Button:
24 | text: "Stop"
25 | on_release: app.stop_audio()
26 |
--------------------------------------------------------------------------------
/Ch07/1.AudioApp/bg_music_piano.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch07/1.AudioApp/bg_music_piano.wav
--------------------------------------------------------------------------------
/Ch07/1.AudioApp/buildozer.spec:
--------------------------------------------------------------------------------
1 | [app]
2 |
3 | # (str) Title of your application
4 | title = TestPlyer
5 |
6 | # (str) Package name
7 | package.name = addnum
8 |
9 | # (str) Package domain (needed for android/ios packaging)
10 | package.domain = com.gad
11 |
12 | # (str) Source code where the main.py live
13 | source.dir = .
14 |
15 | # (list) Source files to include (let empty to include all the files)
16 | source.include_exts = py,png,jpg,kv,atlas,wav
17 |
18 | # (list) List of inclusions using pattern matching
19 | #source.include_patterns = assets/*,images/*.png
20 |
21 | # (list) Source files to exclude (let empty to not exclude anything)
22 | #source.exclude_exts = spec
23 |
24 | # (list) List of directory to exclude (let empty to not exclude anything)
25 | source.exclude_dirs = temp, bin
26 |
27 | # (list) List of exclusions using pattern matching
28 | #source.exclude_patterns = license,images/*/*.jpg
29 |
30 | # (str) Application versioning (method 1)
31 | version = 0.1
32 |
33 | # (str) Application versioning (method 2)
34 | # version.regex = __version__ = ['"](.*)['"]
35 | # version.filename = %(source.dir)s/main.py
36 |
37 | # (list) Application requirements
38 | # comma separated e.g. requirements = sqlite3,kivy
39 | requirements = kivy,pyjnius
40 | #bootstrap = sdl2, pygame, opencv
41 | #requirements = plyer,kivy,opencv,numpy,pyjnius,ffmpeg, sqlite3, openssl
42 | #requirements.source.numpy = /home/ahmedgad/Desktop/numpy15
43 |
44 | # (str) Custom source folders for requirements
45 | # Sets custom source for any requirements with recipes
46 | # requirements.source.kivy = ../../kivy
47 |
48 | # (list) Garden requirements
49 | #garden_requirements =
50 |
51 | # (str) Presplash of the application
52 | presplash.filename = %(source.dir)s/presplash.png
53 |
54 | # (str) Icon of the application
55 | icon.filename = %(source.dir)s/icon.png
56 |
57 | # (str) Supported orientation (one of landscape, portrait or all)
58 | orientation = portrait
59 |
60 | # (list) List of service to declare
61 | #services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
62 |
63 | #
64 | # OSX Specific
65 | #
66 |
67 | #
68 | # author = © Copyright Info
69 |
70 | # change the major version of python used by the app
71 | osx.python_version = 3
72 |
73 | # Kivy version to use
74 | #osx.kivy_version = 1.9.1
75 |
76 | #
77 | # Android specific
78 | #
79 |
80 | # (bool) Indicate if the application should be fullscreen or not
81 | fullscreen = 0
82 |
83 | # (string) Presplash background color (for new android toolchain)
84 | # Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
85 | # red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
86 | # darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
87 | # olive, purple, silver, teal.
88 | #android.presplash_color = #FFFFFF
89 |
90 | # (list) Permissions
91 | android.permissions = CAMERA
92 |
93 | # (int) Android API to use
94 | android.api = 27
95 |
96 | # (int) Minimum API required
97 | android.minapi = 19
98 |
99 | # (int) Android SDK version to use
100 | android.sdk = 27
101 |
102 | # (str) Android NDK version to use
103 | #android.ndk = 9c
104 |
105 | # (bool) Use --private data storage (True) or --dir public storage (False)
106 | #android.private_storage = True
107 |
108 | # (str) Android NDK directory (if empty, it will be automatically downloaded.)
109 | android.ndk_path = /home/ahmedgad/.buildozer/android/platform/android-ndk-r16b
110 |
111 | # (str) Android SDK directory (if empty, it will be automatically downloaded.)
112 | android.sdk_path = /home/ahmedgad/.buildozer/android/platform/android-sdk-linux
113 |
114 | # (str) Android NDK directory (if empty, it will be automatically downloaded.)
115 | #android.ndk_path =
116 |
117 | # (str) Android SDK directory (if empty, it will be automatically downloaded.)
118 | #android.sdk_path =
119 |
120 | # (str) ANT directory (if empty, it will be automatically downloaded.)
121 | #android.ant_path = /home/ahmedgad/.buildozer/android/platform/android-sdk-linux/apache-ant-1.9.4
122 |
123 | # (str) ANT directory (if empty, it will be automatically downloaded.)
124 | #android.ant_path =
125 |
126 | # (bool) If True, then skip trying to update the Android sdk
127 | # This can be useful to avoid excess Internet downloads or save time
128 | # when an update is due and you just want to test/build your package
129 | # android.skip_update = False
130 |
131 | # (str) Android entry point, default is ok for Kivy-based app
132 | #android.entrypoint = org.renpy.android.PythonActivity
133 |
134 | # (list) Pattern to whitelist for the whole project
135 | #android.whitelist =
136 |
137 | # (str) Path to a custom whitelist file
138 | #android.whitelist_src =
139 |
140 | # (str) Path to a custom blacklist file
141 | #android.blacklist_src =
142 |
143 | # (list) List of Java .jar files to add to the libs so that pyjnius can access
144 | # their classes. Don't add jars that you do not need, since extra jars can slow
145 | # down the build process. Allows wildcards matching, for example:
146 | # OUYA-ODK/libs/*.jar
147 | #android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
148 |
149 | # (list) List of Java files to add to the android project (can be java or a
150 | # directory containing the files)
151 | #android.add_src =
152 |
153 | # (list) Android AAR archives to add (currently works only with sdl2_gradle
154 | # bootstrap)
155 | #android.add_aars =
156 |
157 | # (list) Gradle dependencies to add (currently works only with sdl2_gradle
158 | # bootstrap)
159 | #android.gradle_dependencies =
160 |
161 | # (list) Java classes to add as activities to the manifest.
162 | #android.add_activites = com.example.ExampleActivity
163 |
164 | # (str) python-for-android branch to use, defaults to stable
165 | #p4a.branch = stable
166 | p4a.source_dir=/home/ahmedgad/Desktop/python-for-android
167 |
168 | #p4a.source_dir=/home/ahmedgad/Desktop/testp4a/python-for-android
169 |
170 | # (str) OUYA Console category. Should be one of GAME or APP
171 | # If you leave this blank, OUYA support will not be enabled
172 | #android.ouya.category = GAME
173 |
174 | # (str) Filename of OUYA Console icon. It must be a 732x412 png image.
175 | #android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
176 |
177 | # (str) XML file to include as an intent filters in tag
178 | #android.manifest.intent_filters =
179 |
180 | # (str) launchMode to set for the main activity
181 | #android.manifest.launch_mode = standard
182 |
183 | # (list) Android additional libraries to copy into libs/armeabi
184 | #android.add_libs_armeabi = libs/android/*.so
185 | #android.add_libs_armeabi_v7a = libs/android-v7/*.so
186 | #android.add_libs_x86 = libs/android-x86/*.so
187 | #android.add_libs_mips = libs/android-mips/*.so
188 |
189 | # (bool) Indicate whether the screen should stay on
190 | # Don't forget to add the WAKE_LOCK permission if you set this to True
191 | #android.wakelock = False
192 |
193 | # (list) Android application meta-data to set (key=value format)
194 | #android.meta_data =
195 |
196 | # (list) Android library project to add (will be added in the
197 | # project.properties automatically.)
198 | #android.library_references =
199 |
200 | # (str) Android logcat filters to use
201 | #android.logcat_filters = *:S python:D
202 |
203 | # (bool) Copy library instead of making a libpymodules.so
204 | #android.copy_libs = 1
205 |
206 | # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86
207 | android.arch = armeabi-v7a
208 |
209 | #
210 | # Python for android (p4a) specific
211 | #
212 |
213 | # (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
214 | #p4a.source_dir =
215 |
216 | # (str) The directory in which python-for-android should look for your own build recipes (if any)
217 | #p4a.local_recipes =
218 |
219 | # (str) Filename to the hook for p4a
220 | #p4a.hook =
221 |
222 | # (str) Bootstrap to use for android builds
223 | # p4a.bootstrap = sdl2
224 |
225 | # (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
226 | #p4a.port =
227 |
228 |
229 | #
230 | # iOS specific
231 | #
232 |
233 | # (str) Path to a custom kivy-ios folder
234 | #ios.kivy_ios_dir = ../kivy-ios
235 |
236 | # (str) Name of the certificate to use for signing the debug version
237 | # Get a list of available identities: buildozer ios list_identities
238 | #ios.codesign.debug = "iPhone Developer: ()"
239 |
240 | # (str) Name of the certificate to use for signing the release version
241 | #ios.codesign.release = %(ios.codesign.debug)s
242 |
243 |
244 | [buildozer]
245 |
246 | # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
247 | log_level = 2
248 |
249 | # (int) Display warning if buildozer is run as root (0 = False, 1 = True)
250 | warn_on_root = 1
251 |
252 | # (str) Path to build artifact storage, absolute or relative to spec file
253 | # build_dir = ./.buildozer
254 |
255 | # (str) Path to build output (i.e. .apk, .ipa) storage
256 | # bin_dir = ./bin
257 |
258 | # -----------------------------------------------------------------------------
259 | # List as sections
260 | #
261 | # You can define all the "list" as [section:key].
262 | # Each line will be considered as a option to the list.
263 | # Let's take [app] / source.exclude_patterns.
264 | # Instead of doing:
265 | #
266 | #[app]
267 | #source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
268 | #
269 | # This can be translated into:
270 | #
271 | #[app:source.exclude_patterns]
272 | #license
273 | #data/audio/*.wav
274 | #data/images/original/*
275 | #
276 |
277 |
278 | # -----------------------------------------------------------------------------
279 | # Profiles
280 | #
281 | # You can extend section / key with a profile
282 | # For example, you want to deploy a demo version of your application without
283 | # HD content. You could first change the title to add "(demo)" in the name
284 | # and extend the excluded directories to remove the HD content.
285 | #
286 | #[app@demo]
287 | #title = My Application (demo)
288 | #
289 | #[app:source.exclude_patterns@demo]
290 | #images/hd/*
291 | #
292 | # Then, invoke the command line with the "demo" profile:
293 | #
294 | #buildozer --profile demo android debug
295 |
--------------------------------------------------------------------------------
/Ch07/1.AudioApp/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch07/1.AudioApp/icon.png
--------------------------------------------------------------------------------
/Ch07/1.AudioApp/main.py:
--------------------------------------------------------------------------------
1 | import kivy.app
2 | import jnius
3 | import os
4 |
5 | PythonActivity = jnius.autoclass("org.kivy.android.PythonActivity")
6 | mActivity = PythonActivity.mActivity
7 |
8 | class AudioApp(kivy.app.App):
9 | prepare_audio = False
10 |
11 | def start_audio(self):
12 | if AudioApp.prepare_audio == False:
13 | MediaPlayer = jnius.autoclass("android.media.MediaPlayer")
14 | self.mediaPlayer = MediaPlayer()
15 | try:
16 | fileName = os.getcwd()+"/bg_music_piano.wav"
17 | self.mediaPlayer.setDataSource(fileName)
18 | self.mediaPlayer.prepare()
19 |
20 | kivy.clock.Clock.schedule_interval(self.update_position, 0.1)
21 |
22 | self.mediaPlayer.start()
23 | AudioApp.prepare_audio = True
24 | mActivity.toastError("Playing")
25 | except:
26 | self.current_pos.text = "Error Playing the Audio File"
27 | print("Error Playing the Audio File")
28 | mActivity.toastError("Error Playing the Audio File")
29 | else:
30 | self.mediaPlayer.start()
31 | mActivity.toastError("Playing")
32 |
33 | def pause_audio(self):
34 | if AudioApp.prepare_audio == True:
35 | self.mediaPlayer.pause()
36 | mActivity.toastError("Paused")
37 |
38 | def stop_audio(self):
39 | if AudioApp.prepare_audio == True:
40 | self.mediaPlayer.stop()
41 | mActivity.toastError("Stopped")
42 | AudioApp.prepare_audio = False
43 |
44 | def update_position(self, *args):
45 | audioDuration = self.mediaPlayer.getDuration()
46 | currentPosition = self.mediaPlayer.getCurrentPosition()
47 | pos_percent = float(currentPosition)/float(audioDuration)
48 |
49 | self.root.ids['audio_pos'].size_hint_x = pos_percent
50 |
51 | self.root.ids['audio_pos_info'].text = "Duration: "+str(audioDuration) + "\nPosition: " + str(currentPosition)+"\nPercent (%): "+str(round(pos_percent*100, 2))
52 |
53 | app = AudioApp()
54 | app.run()
55 |
56 |
--------------------------------------------------------------------------------
/Ch07/1.AudioApp/presplash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/building-android-apps-in-python-using-kivy/d63872a8296d9edfe649bdf1fd5aa31126953b56/Ch07/1.AudioApp/presplash.png
--------------------------------------------------------------------------------
/Contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to Apress Source Code
2 |
3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers.
4 |
5 | ## How to Contribute
6 |
7 | 1. Make sure you have a GitHub account.
8 | 2. Fork the repository for the relevant book.
9 | 3. Create a new branch on which to make your change, e.g.
10 | `git checkout -b my_code_contribution`
11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted.
12 | 5. Submit a pull request.
13 |
14 | Thank you for your contribution!
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Freeware License, some rights reserved
2 |
3 | Copyright (c) 2019 Ahmed Fawzy Mohamed Gad
4 |
5 | Permission is hereby granted, free of charge, to anyone obtaining a copy
6 | of this software and associated documentation files (the "Software"),
7 | to work with the Software within the limits of freeware distribution and fair use.
8 | This includes the rights to use, copy, and modify the Software for personal use.
9 | Users are also allowed and encouraged to submit corrections and modifications
10 | to the Software for the benefit of other users.
11 |
12 | It is not allowed to reuse, modify, or redistribute the Software for
13 | commercial use in any way, or for a user’s educational materials such as books
14 | or blog articles without prior permission from the copyright holder.
15 |
16 | The above copyright notice and this permission notice need to be included
17 | in all copies or substantial portions of the software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apress Source Code
2 |
3 | This repository accompanies [*Building Android Apps in Python Using Kivy with Android Studio*](https://www.apress.com/9781484250303) by Ahmed Fawzy Mohamed Gad (Apress, 2019).
4 |
5 | [comment]: #cover
6 | 
7 |
8 | Download the files as a zip using the green button, or clone the repository to your machine using Git.
9 |
10 | ## Releases
11 |
12 | Release v1.0 corresponds to the code in the published book, without corrections or updates.
13 |
14 | ## Contributions
15 |
16 | See the file Contributing.md for more information on how you can contribute to this repository.
--------------------------------------------------------------------------------
/errata.md:
--------------------------------------------------------------------------------
1 | # Errata for *Book Title*
2 |
3 | On **page xx** [Summary of error]:
4 |
5 | Details of error here. Highlight key pieces in **bold**.
6 |
7 | ***
8 |
9 | On **page xx** [Summary of error]:
10 |
11 | Details of error here. Highlight key pieces in **bold**.
12 |
13 | ***
--------------------------------------------------------------------------------