Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Saturday, October 11, 2014

Using Android Accelerometer with Pygame

My son recently started to use the accelerometer functions in his Android phone to develop games with Python. He's building a variation of Swarm, a 2D tile map game that he wrote in middle school.

The accelerometer is easy to get working with pgs4a.

To pull the x,y,z axis, use this:


You will get a floating point number for each of the three axises.

Here's a simple way to set four directions, up, down, left, right:


In the example above, I'm holding the phone sideways, in landscape mode.  The left-right movement is controlled by the 2nd value in the list and the up-down movement is controlled by the 1st item in the list.

It would easy to set up 8 direction movement or even a greater range of movement.  Unlike Swarm, which used only 8 directions for bullets, we're using sin and cos to give the bullets a greater range of movement.

In order to test the application on my desktop, I've also created a virtual controller to simulate the accelerometer.

Here's the application running on my desktop with the virtual controller.


After you install the application on your Android phone, it is a bit more difficult to debug and test the accelerometer.   You can print out the value of the accelerometer and then tune your game so that the player moves with the sensitivity that works for your game. If you print out the accel_reading, you will see a three number tuple, with the numbers all in floating point.


I/python  (21058): Initialize Python for Android
I/python  (21058): ['/data/data/org.pychildren.accel/files/lib/python2.7/site-packages', '/data/data/org.pychildren.accel/files/lib/site-python']
I/python  (21058): Opening APK '/data/app/org.pychildren.accel-1.apk'
I/python  (21058): (-3.8019924163818359, -0.31603461503982544, 8.7819318771362305)
I/python  (21058): (-3.8019924163818359, -0.31603461503982544, 8.7819318771362305)
I/python  (21058): (-3.8019924163818359, -0.31603461503982544, 8.7819318771362305)

If you don't know how to see the output from your app when it is running on your phone, read my   post explaining how you can see the output of your print statements with adb.

Here's a demo of the character running on an old Samsung phone without the flock.   The controller in the lower right is for 360 degree bullet firing.


Monday, September 15, 2014

Overview of Teaching Python to Graph Output from Cloud API - Spitcast Surf


I've been working with my son to build a mobile app that displays graphs of tide charts and tables of surf forecasts for the Santa Cruz region.  The app runs on his Android Motorola Moto-G phone and my Samsung Galaxy Note 2.  He grabs the data using the Spitcast API and displays the output using Pygame.


The tide has a huge influence on the quality of surf in Eastside Santa Cruz.  The optimal tide conditions at my favorite spot is a tide that is rising from 2 feet to 3.5 feet.  The swell height and direction also plays a big role.  In the future, we'll use the API from OpenWeatherMap to pull the sunrise, sunset, and wind.

The steps are:
  1. Pull data from Spitcast using urllib2
  2. Read JSON data from API into program and then convert to a list of Python dictionaries using the json library


The lesson gets off to an exciting start. The student will realize the potential of accessing cloud-based APIs. Assuming the student has a basic understanding of Python data structures lists and dictionaries, they'll also understand how easy it is to parse the data. The simple idea to convert the tide values of feet into pixels is just to multiply feet by a constant number. In this case, I multiply the height of the wave in feet by 50 to get a pixel value. For example, a wave height of 5 feet will correspond to a screen height of 250 pixels. To generate the y coordinate for the Pygame screen, I subtract the pixel height from 550. Remember that a y value of 0 is the top of the screen. I set my screen height on the phone to 500 pixels. A wave height of 1 foot will equal screen height of 50 pixels. Subtracting this from 550 will yield a y position of 500.
  1. Build start and end points for a series of 23 vertical lines spaced evenly apart to create the x axis grid. 
  2.  Create a point list that will be used by pygame.draw.lines in a future section.



At this point, the student will have a list of points that they can then draw with pygame.draw.lines for the tide graph or pygame.draw.line x, y axis grids.
Here's the basic algorithms with a bit more bells and whistles.

In the main while loop, I have this code.
This is the android-presplash.jpg screen of the application.


In the future, we'll merge the features from my son's Weather App project into Santa Cruz Surf.





Below is a shot of the app developer benefiting from the application.




Thursday, May 15, 2014

Windows 8.1 and Pygame Subset for Android (pgs4a)

I recently got asked a question about Windows installation on the PyChildren forum.

Here's the question:

When I touch the icon, the screen turns black, and then it goes back to my apps page in my phone. I then run the logcat to find the problem, but all it gives me is this:


V/python ( 676): Extracting private assets.
I/python ( 676): extracting private.mp3 to /data/data/com.bennybear.fungame/files
The user was not using an mp3 sound file.  When the person extracted the Windows compressed package for pgs4a, the file got added into a sub-directory of the build.    Since I was helping my son to install pgs4a on his Windows 8.1 computer, I was able to replicate the problem.   I think that the process of unzipping or extracting the pgs4a file partially failed.  When I compared the pgs4a files on two different Windows 8.1 computers, I noticed they were different.

I then went to the pgs4a site and downloaded a tar.bz2 archive.  I used tar jxvf on cygwin to extract the files.

A working directory is shown below.




Note that inside of the pgs4a-0.9.6 directory, there is not another sub-directory called pgs4a-0.9.6.  In the failed builds, I noticed that there was a temporary pgs4a-0.9.6 file created in the same directory and all the files from that directory were not properly copied into the main directory.

Once I had the files properly extracted, I noticed that the python android.py installsdk script was giving me error messages.  The script was failing to install android-api-15 and android-api-8.  I used the android.bat program in the android-sdk\tools directory to update the android SDK APIs.  

If you get an error message indicating that ant cannot find the build.xml file, this usually indicates that you don't have the proper Google APIs installed from the Android SDK (not the pgs4a android.py installsdk script).  In almost all cases, I've had to install the Google APIs with the android sdk.  On windows, the android sdk manager is called android.bat

There is another pgs4a tool called android.py.  These tools are completely unrelated.

Once I had those installed, the build went fine.  In order to connect the Windows 8.1 laptop to my son's Motorola Moto G Android phone, I had to go to the Motorola site and install the driver.  With driver from Motorola, adb was able to detect the phone and install went smoothly.

I also installed it on my Samsung Galaxy phone from his Windows 8.1 laptop.


This seems like a pain in the rear, but I encourage you to keep going.  Pygame is fun because it makes it easy to bring the creative ideas from your brain into reality very quickly.   By putting these ideas, your works of art, on a phone, you can show your friends and help them to understand a bit more about how you think as a person.

My long term goal for my children is for technology to serve as a tool for creative expression, not a barrier.  It should be fun and frivolous.  Games are great learning tools.  The work and lessons here should not be viewed through the lens of making money or job-training.  These experiments with children are about developing creative thinking and techniques to express ideas.  Sure, it's a pain to get pgs4a to install sometimes.  I agree.  But, I still think it's the best way to get kids and adults up to speed to be able to take their ideas and prototype them on a mobile phone.  

Have fun!

If you have questions or would like to join the discussion, go to the PyChildren Forum.



Monday, March 17, 2014

Python Android App Debugging Tip: adb and python print statements

With the phone connected to the USB cable and in debug mode, open a new terminal window and type:

  $ adb logcat |grep python

Update 10/11/2014. Windows users, see below. An alternative to using grep:

$ adb  logcat python *:s


You can now view standard python output from applications running on your android phone with python print statements. Output of logcat
I/python  ( 2392): play sounds
I/python  ( 2392): play sounds
I/python  ( 2392): play sounds



The most common problems with Python Subset for Android Apps dying on the Android phone at startup:
  1. you didn't import the sound mixer module properly
  2. your fonts are not in the main program directory
  3. your sound files are not in the main program directory
  4. your graphic files or map files are not in the main program directory
  5. you are using a python module that is not in your main program directory
Note that there's a common theme here of a desktop program working because the assets exist somewhere on your desktop machine, but those assets don't get transferred to your phone.  Look at your sound, graphic, and font files to make sure they are in your main directory.

In the problems above, the adb logcat command will usually show you what asset the program fails to load.

You'll save time in the debugging process if you open up two terminals at once.  In one terminal, run the adb output.  In the other terminal, build and install your program onto your phone.  With the USB cable connected, run your application on your phone.

Check to make sure you are initializing the android library.


Make sure you are importing the mixer module as shown below. In previous versions of pgs4a, I had problems with audio files that weren't in *.wav format. I only use wav files now.

Another common problem is that your application is not named main.py.

Make sure you have called the application main.py and that you are building the application with the name of the directory that contains your application.

if you are using the sgc gui toolkit with android, you need to make sure that the fonts are loaded prior to setting up the sgc screen. I've had several occasions when I got the order wrong the my application worked on the desktop and crashed on the phone. This code below is only relevant if you use sgc, which is definitely not needed to make games on android. However, if you do use sgc to make your buttons and sliders, it can be a bit tricky to use on android.




Update: 10/11/2014 As my son is starting to do some development on Windows 8.1, I realized that he didn't have grep installed and didn't really need to go through the hassle of installing grep with cygwin. I looked at the filter options for adb logcat. The key is to set everything to silent except for strings containing python. Here's some docs built into adb that are somewhat difficult to understand. The only one that you need to use is the -s or *:s
Usage: logcat [options] [filterspecs]
options include:
  -s              Set default filter to silent.
                  Like specifying filterspec '*:s'
  -f    Log to file. Default to stdout
  -r []   Rotate log every kbytes. (16 if unspecified). Requires -f
  -n       Sets max number of rotated logs to , default 4
  -v      Sets the log print format, where  is one of:

                  brief process tag thread raw time threadtime long

  -c              clear (flush) the entire log and exit
  -d              dump the log and then exit (don't block)
  -t       print only the most recent  lines (implies -d)
  -g              get the size of the log's ring buffer and exit
  -b      Request alternate ring buffer, 'main', 'system', 'radio'
                  or 'events'. Multiple -b parameters are allowed and the
                  results are interleaved. The default is -b main -b system.
  -B              output the log in binary
filterspecs are a series of
  [:priority]

where  is a log component tag (or * for all) and priority is:
  V    Verbose
  D    Debug
  I    Info
  W    Warn
  E    Error
  F    Fatal
  S    Silent (supress all output)

'*' means '*:d' and  by itself means :v

If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
If no filterspec is found, filter defaults to '*:I'

If not specified with -v, format is set from ANDROID_PRINTF_LOG
or defaults to "brief"

Monday, February 17, 2014

Using the Android Keyboard with Pygame


I modified the GUI example I posted on GitHub yesterday to include an example of using the Android software keyboard  for text input.

I had to build my own text box input since I couldn't get it to work with SGC.   There's still a few glitches with the keyboard and I don't suggest you use the code in a production application, but it should be suitable for my son's next class.

I'm sure there's an easier way to handle the text from the keyboard and I would love to see another person's code.  However, since the whole purpose of my project is to teach my son programming, it should be useful to teach him to build a text input box with the Android keyboard. 

This only works with individual keys right now and it won't work with Swype.

On the pgs4a forum, there was some question as to whether or not the soft keyboard actually worked.  I thought I would create a quick example to show that it does work.






Sunday, November 24, 2013

Pygame on Android App Crashes on Start: FIXED

A good tileset in the wrong place at the wrong time
After catching Jack smelt in Capitola and seeing an amazing display of seals, dolphins, and school of tens of thousands of fish, my son worked on his 2D tile map game, Maze.  The Android app consistently crashed on start.  It would display the initial splash screen and then die, leaving no error message.

This has happened in the past with other games.  We usually solve the problem with adb, the Android debugger.  Today, the fix was easy.  However, since I know that it can be daunting to wade through the adb logcat, I'll provide a few tips specific to Python / Pygame Subset for Android debugging.

My son's game uses Python and pgs4a.  He also uses Tiled to export JSON map files. 

First, find adb on your system.  It's not something that python developers normally use from the command line.  adb is in the platform-tools sub-directory of the android-sdk main SDK directory.

 
 From the Linux command line, you can either just run adb logcat or you can run it through grep and look for references to python.

 

 A larger snippet of the log file is shown below.


 In this case, the error was an incorrect reference to the tileset graphic.
  

The error is caused by a relative reference to a non-existent file.  Although the program works on the desktop, it doesn't work on the phone.  The fix is to place the tileset files in the same directory or sub-directory of your main.py program and create a new map and tileset with tiled.  If you've already created an extensive map, you can also edit the json file with a text editor to have it reference the correct location.

In this example, the file is called grass_water_terrain.png.

In a previous game, my son had a similar problem with the app crashing when it tried to load a font file that was in the wrong location.  Fonts and graphics are the two most common problems.  If you have all your fonts and graphic files in the same directory and your program still doesn't work on Android, but works on your desktop, you may be trying to import a library another directory.  Everything needs to be in the directory where main.py is or in a sub-directory.

If the application works on your desktop and it builds and then loads onto your phone fine, but crashes on start, think through what files the application is trying to load on the Android phone.  Then, work backwards and think through the differences between the phone directory structure and your desktop.  Also, think about the obvious things.  Check that you imported the android library and you've initialized it android.init().

If the problem is not immediately obvious, fire up adb and look for references to python.

Checklist:

  • import android library
  • initialize android library
  • main game file is called, main.py
  • graphic files are in the main or sub-directory
  • font files are in the main or sub-directory
  • custom libraries that you wrote are in the main or sub-directory

Update: March 3, 2014
One of the viewers of my pychildren YouTube channel had a problem with sound.  The important section is to map pygame.mixer and android.mixer to mixer.


try:    import pygame.mixer as mixer except ImportError:    import android.mixer as mixer

The other problem with sound is that there may be problems with different types of sound formats.  I suggest you use .wav files.  Since sound is handled differently on Android and the desktop, a few problems occur.



Saturday, March 30, 2013

Lesson #4: Mouse and Touchscreen Control (taught by middle school student)



Middle school student, age 13, teaches you how to get mouse control working on the moving square.
  • Goes through event queue to check for the mouse button. event.type == MOUSEBUTTONDOWN:
  • Checks for point collision with a rectangle: collidepoint(mouse_pos)

Saturday, February 23, 2013

2D Android Tile Game "Swarm" is Finished


Disneyland, the winter flu, soccer, surfing, school and work, these are all normal family activities.  Learning to program in python often seems to fall down on the priority list, especially for my teenage son, who is often boiling over with energy.  He'd rather be out running, hiking, fishing, or playing a team sport.

My son blocked out some time today for python programming and he decided to complete development of Swarm after finishing the eighth level.  Each level now has a different map.  He also changed the game fonts to more stylistic fonts he downloaded from the Internet. The video above shows all eight levels of his game running on a SamSung Galaxy Note II.

The levels are created with python code only.  He decided not to use a map editor since the map size is small and manageable.

There is a story behind the game.  The blue boy goes through different areas of the world looking for a girl that is imprisoned in a haunted castle.  If the boy gets through eight levels, he saves the girl.  A hero screen appears with the boy and girl enjoying a sunrise.

The next game he's working on is a 2d side-scroller game.

The distribution file and source code for Swarm are here.



Monday, February 4, 2013

Pygame Performance on Android Phones


The performance of python games is fine on old, cheap Android phones.  My son has written several games for his cheap LG Optimus S phone with 170MB of memory.  Although the games are slower than on a desktop, there are no problems with the speed of simple games on the phone.

Sunday, December 2, 2012

Getting Android adb working with Pipo Smart S1



The Pipo Smart S1 is a 7" Android 4.1 tablet that costs under $100.  It works great and is quite fast.   It's comparable to the Nexus 7" at half the price.  I changed the firmware to rev3 with instructions from TopNotchTablets.  This download also got rid of the apps that had Chinese language, giving a more comfortable user experience.

The CPU is a Rockwell RK3066 1.6GHz chip.

Rooting the tablet and upgrading the firmware was fast and painless.

Getting the tablet to work with the Android Debug Bridge (adb) was trickier.

Pygame Subset for Android (PGS4A) relies on adb that is included in the platform-tools sub-directory of the Android SDK.




When I first connected the Pipo Smart S1 tablet to my Ubuntu box with a micro USB cable, the build worked, but the install failed.

After figuring out how to use adb, I started to use adb devices to see the connected devices.  It wasn't detecting the tablet.


I found out that adb needs a USB Vendor ID to work properly.  Pipo wasn't listed as a vendor.   I found that the Vendor ID for the RK3066 chip is 0x2207.

Using the Android Developer documentation on Hardware Devices, I created the file /etc/udev/rules.d/51-android.rules and inserted this:


SUBSYSTEM=="usb", ATTR{idVendor}=="0x2207", MODE="0666", GROUP="plugdev"

It still wasn't working for me.  I had USB debugging enabled on my tablet.

I then added the vendor ID code to ~/.android/adb_usb.ini

:~/.android$ cat adb_usb.ini 
# ANDROID 3RD PARTY USB VENDOR ID LIST -- DO NOT EDIT.
# USE 'android update adb' TO GENERATE.
# 1 USB VENDOR ID PER LINE.
0x2207

It's still not happening.  I check out lsusb and see some hope that the device is detected.  




I turn off wifi from the tablet.

I run adb devices again.


$ ./adb devices
List of devices attached 
???????????? no permissions


There's a bit more life.  I run it again as sudo.

$ sudo ./adb devices
[sudo] password for craig: 
List of devices attached 
???????????? no permissions

No go.

I kill the server. Then start it as root.
$ sudo ./adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached 
ZX7U17M3NX device

It found the device!

I build the Python app:

$ ./android.py build dad/dad_image release install

install:
     [echo] Installing /home/c/Documents/python/pgs4a-0.9.4/bin/dad_image-1-release.apk onto default emulator or device...
     [exec] 5391 KB/s (2741472 bytes in 0.496s)
     [exec] pkg: /data/local/tmp/dad_image-1-release.apk
     [exec] Success

BUILD SUCCESSFUL
Total time: 8 seconds

It looks like the build succeeded.  

Here's a screenshot of the game running on the Pipo Smart S1, transferred using a USB cable with adb.





After I got this working, I worked with my son, my only computer programming student,  to get a similar game working on his LG Optimus S phone.  The main learning points today:

  • using .append to fill a list of objects.   The list target_group contains all the enemies and all the bombs.
  • Set up triggers based on elapsed time use list slicing to control the number of targets on the screen.







After I wrote the blog post, I also found this  on slatedroid.com.  It covers many of the same steps.  I'm not sure if shutting off WiFi is needed.  The person below also seems to have adb working without having to run the adb server as root.  I may fiddle around with more things in the future.  The main thing is that I can connect my tablet to adb in debug mode and install the apk files easily.


Posted 21 November 2012 - 08:31 PM
Just a few tips to those are trying to connect to a RK3066 via ADB on linux.

  • Download & Install SDK
  • Edit udev rules (see step #3), the RK3066 Vendor ID is 2207
  • Restart udev (udevadm control --reload-rules)
  • Edit $HOME/.android/adb_usb.ini, add 0x2207 at the end of the file
  • Restart adb server (adb kill-server && adb start-server)
  • Plug & List your device (adb devices)


At step #2, you should get something like this
SUBSYSTEM=="usb", ATTR{idVendor}=="2207", MODE="0666", GROUP="plugdev"


At step #4, you should get something like this
# ANDROID 3RD PARTY USB VENDOR ID LIST -- DO NOT EDIT.
# USE 'android update adb' TO GENERATE.
# 1 USB VENDOR ID PER LINE.
0x2207

Sunday, November 25, 2012

Porting Pygame Apps to Android


Since my son is on Thanksgiving holiday, I taught him two classes today.  I'm sure he would have preferred fishing.   The first class covered how to port one of his earlier Pygame desktop applications to Android.  The process only took an hour.  The game now works on his LG Optimus S Android phone and he can enjoy playing it while lying on his bed or after school with his friends.

His game, dropper, does not use any raster graphics.  Dropper only uses the primitive shapes from the pygame.draw module.  Despite the simple graphics and lack of sound effects, it's one of the most playable games he's developed.  It works quite well on his phone.

Here's an overview of the simple changes.


  • import android module
  • change screen width and height to 480, 320 (low-end phone screen)
  • change player size to make it easier to dodge bullets on a smaller screen
  • change frame rate to 30 fps to slow down the movements and make the game easier.  The smaller screen makes it more difficult to avoid the bombs.
  • android.init()
  • map the ESCAPE key in pygame to the physical back button on the phone.  He uses this to exit the game loop.
    • android.key_map(android.KEYCODE_BACK, pygame.K_ESCAPE)
  • adjust the height of the text boxes for the Game Over screen and final score.
  • use free clip art to create the android-icon.png file for the Android app launcher
  • use free clip art to create the android-presplash.jpg file for the initial splash screen that shows up prior to the game starting. 
In the future, it might be rewarding for the student to use Inkscape to create a logo for a mock software company.

Since the original game used the keyboard for controls, he added mouse controls.  PGS4A maps the mouse to the touchscreen.  This is so nice.  For this game, he created active areas of the screen to control left and right movement.  There's no instructions, but it seems intuitive to most people playing the game.

The original game also used the default system fonts on Ubuntu.  He saved the fonts from 
/usr/share/fonts/truetype/freefont/FreeSansBold.ttf on Ubuntu to his build directory and packaged the font as part of the Android app bundle. 


Saturday, November 24, 2012

Sprites and Tiles


My son finished his shooter game and I started to research tiles for the next project.

During Thanksgiving break, I started with Tiled TMX Loader.  This initially proved quite rewarding since there were several nice examples of Pygame code that shipped with the library.    I used Tiled Map Editor to make the maps from tile sets.

Since my son wants to show his friends his games on his phone, I was planning to package the Pygame application for his phone using Pygame Subset for Android (PGS4A).    

Unfortunately, when I did the build, I realized that Pygame Subset for Android does not support the XML libraries that Tiled TMX Loader requires.  There does not appear to be an easy way to build the XML C libraries into PGS4A or include a Python library with the application.    Here is a discussion thread from the Pygame Subset for Android forum.  The workaround people were using involved converting the tmx maps to JSON files and loading the map into the Pygame on Android application using the JSON module that was supported by PGS4A. 

Although Tiled can output a tile map to JSON, I realized that all the python JSON library does is load the JSON file data into dictionaries and lists that can then be accessed by the program.  Taking this route, I'm going to need to develop all the map camera movements, layer management, and collision detection myself.  Bummer.   The data is there, but I didn't want to think about how to manipulate it.

Feeling that manipulating map data from JSON files was too much of a task, I instead started to research sprites, basically shelving the idea for a complex map and focusing on understanding smaller lists and dictionaries of tiles made up of 32 x 32 pixel tiles.

piman's sprite tutorial was the most useful.  The application above is basically an extension of piman's tutorial.  Instead of colored rectangles, I used pygame.image.load("filename") to create image surfaces.  I used a single grass tile as the background and simply repeated it.

The controls at the bottom select the character to move.  

def select_character(buttons, mouse_pos, selection):
    selected_char = selection
    for b in buttons:
        if b.rect.collidepoint(mouse_pos):
            selected_char = b.character
    return(selected_char)

I recently realized that I can use pygame.Rect.collidepoint instead of pygame.Rect.colliderect.  The rectangles are the same ones that you use to blit the images onto the screen.

It's easy to get the mouse position with pygame.mouse.get_pos().

In the main event loop, I simply check for the mouse button up or down:
  • elif event.type == pygame.MOUSEBUTTONDOWN:
  • elif event.type == pygame.MOUSEBUTTONUP