PyCon 2012 PyGame Tutorial Setup for OS X Lion

PyCon US 2012 had a talk given by Katie Cunningham and Richard Jones entitled “Introduction to Game Development“. I figured it would be fun to follow along.

I’ve written this guide as a quick-start to anyone who didn’t attend but needs resources and tools setup to follow the tutorial. I’m doing this on OS X 10.7.x Lion, so your setup may vary.

  1. Install PyGame stable 1.9 for your machine: http://www.pygame.org/download.shtml.

    I was unable to get the version from PyPI to install, it complained about a missing setup.py file. I used the pre-built version that is designed to work for Apple-supplied Python on Lion. Run the setup .mpkg and test that it installed successfully:

    $ python
    Python 2.7.1 (r271:86832, Jun 25 2011, 05:09:01) 
    [GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pygame
    >>>

    If you don’t get any major complaints then continue with setup. I did notice that movie and scrap modules could not be loaded successfully upon executing import pygame; help(pygame) but haven’t investigated further.

  2. Setup a directory to mess around in:
    $ mkdir ~/gamedev
  3. Grab the sample files from Richard’s BitBucket repo by either downloading them or cloning the repo if you have Mercurial installed (or direct link for OS X 10.7 Installer 2.1.1):
    ~/gamedev$ hg clone https://bitbucket.org/r1chardj0n3s/pygame-tutorial
  4. Test that it’s all working:
    ~/gamedev$ cd pygame-tutorial
    ~/gamedev/pygame-tutorial$ python 01-open-window.py

    If everything is configured correctly, you should see a window flash on the screen momentarily. You should now be ready to follow the tutorial, I’ll update this post if I encounter any issues along the way.

If you have a cool game project in mind, why not sign up for PyWeek? It’s a game development challenge in which participants develop a game in Python over a week by themselves or a team. Registration should be open in a couple of weeks.

Addendum

These are programs that Richard mentions in his presentation.

  • Tiled – Map editor which allows you to design and edit TMX files.
  • sfxr/cfxr – Sound file generator.

Django development server on Debian 6 Stable

Django Webserver Stack Setup on Debian 6.0 “Squeeze”

This guide follows on from the previous post; Lightweight Debian VM on OS X with VirtualBox, but it should work more-or-less fine on a standard Squeeze install.

The webserver stack I’ll be running will be for Django web development. This isn’t for staging or production so I won’t be installing a webserver or front-end such as Apache or nginx, Django’s WSGI development server will suffice.

In case you shut down the instance previously, here’s the startup command:

$ VBoxHeadless -s "Debian Webserver"

I use git, feel free to use whichever (D)CVS you prefer:

local$ ssh devserv
~$ devserv login:
~$ sudo apt-get install git-core

Now add the stable backports repo to your sources.list

sudo vim /etc/apt/sources.list
# squeeze-backports
deb http://backports.debian.org/debian-backports squeeze-backports main >> /etc/apt/sources.list

Installing psycopg2 is as you’d expect, but I’ve chosen to install Django 1.3 (official stable, the current major release in the squeeze backports repo). We’ll need to update the apt cache as we just added a new repo.

~$ sudo apt-get update
~$ sudo apt-get install postgresql postgresql-client python-psycopg2
...
~$ sudo apt-get -t squeeze-backports install python-django

PostgreSQL Database setup

You’ll need to configure postgres to allow local users to authenticate as db users.

$ sudo vim /etc/postgresql/8.4/main/pg_hba.conf

And modify the local line to change the ident value to “trust”.

local   all         postgres                          ident

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
...
# "local" is for Unix domain socket connections only
local   all         all                               trust

Set up a user with privileges on a dev database:

$ sudo adduser django_dbo
...
$ su postgres
$ psql template1
...
template1=# create user django_dbo with password '<password>';
template1=# create database django_dev;
template1=# grant all privileges on database django_dev to django_dbo;
template1=# <Ctrl + D>
$ exit
$ su django_dbo
$ psql django_dev
django_dev=>
django_dev=> <Ctrl + D>

Django setup

If that went smoothly then go ahead and setup a starter Django project:

~$ cd
~$ mkdir django
~$ cd django/
~/django$ django-admin startproject dev
~/django$ ls dev/
~/django$ 
__init__.py  manage.py  settings.py  urls.py

Update your settings.py file’s DATABASES dictionary with the following:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'django_dev',
        'USER': 'django_dbo',
        'PASSWORD': '<password>',
    }
}

Save that and try running syncdb to setup the db (plus a superuser).[1]

$ python manage.py syncdb

If that worked then fire up a dev server:

$ python manage.py runserver 0.0.0.0:8000

Visit your server on your local machine in a browser at: http://devserv:8000

The reason for running it under 0.0.0.0 is so that you can access it on your local machine. It probably won’t be accessible on your LAN, and almost definitely shouldn’t be accessible to the outside world[2].

Annotations

  1. chmod +x your manage.py file so you can execute it like thus:
    $ chmod +x manage.py
    $ ./manage.py runserver ...
  2. You should only run it under 0.0.0.0 if you’re using the VM method from the previous post, otherwise it’ll be publicly accessible.

References

  1. Allow local logins via psql: http://www.cyberciti.biz/faq/postgresql-remote-access-or-connection/.

Incremental volume hotkeys for OS X

In previous versions of OS X you could change the volume with a keyboard shortcut in smaller increments[1]. When you have a good set of monitors[2] you’ll often find that each standard increment is either too soft or too loud. This script allows you to get that Goldilocks zone back again.

TL;DR: I have a GitHub repo setup for this.

What you’ll need:

  • OS X Lion (10.7) [this feature is built-in on previous OSes]
  • AppleScript Editor [built-in to OS X] – the result will be compiled
  • Alfred (or equivalent Global Hotkey for script mapping tool)

You can either copy and paste the scripts below and create the “Up” counterpart, or just download them here.

Incremental Volume

set currentVolume to output volume of (get volume settings)
set volume output volume (currentVolume - 2)

You can also play the “click” sound that normally plays upon volume change:

do shell script "afplay /System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/volume.aiff > /dev/null 2>&1 &"

(Optional) Growl Integration

If you have Growl installed you can get notifications when you execute the script.

tell application "System Events"
	set isRunning to (count of (every process whose bundle identifier is "com.Growl.GrowlHelperApp")) > 0
end tell
 
if isRunning then
	set message to "Dropped the volume by 2 notches. Current volume is " & currentVolume - 2 & "%"
 
	tell application id "com.Growl.GrowlHelperApp"
		-- Make a list of all the notification types 
		-- that this script will ever send:
		set the allNotificationsList to {"Volume Down"}
 
		set the enabledNotificationsList to ¬
			{"Volume Down"}
 
		register as application ¬
			"Incremental Volume Shortcut - Down" all notifications allNotificationsList ¬
			default notifications enabledNotificationsList ¬
 
		notify with name ¬
			"Volume Down" title ¬
			"Volume Down" description ¬
			message application name "Incremental Volume Shortcut - Down"
 
	end tell
end if

Hit Compile and Save it somewhere handy.

Setting up the Keyboard Shortcut

If you have Alfred installed (you may need their plugin pack?) you can assign a global keyboard shortcut to run an AppleScript (or just about any other script really!).

  1. Open Alfred (by default it’s Command + Space)
  2. Click on the cog in the top right to open the apps’ preferences
  3. Open the Hotkeys pane
  4. Drag and drop the script file from Finder
  5. Pick a keyboard shortcut, I used Opt + Shift + Cursor Up/Down

References

  1. For the Growl integration: http://stackoverflow.com/questions/1449543/implementing-keyboard-volume-control-buttons-in-applescript-setting-volume-ins
  2. AppleScript to Growl integration: http://growl.info/documentation/applescript-support.php
  3. AppleScript Reference: https://developer.apple.com/library/mac/#documentation/applescript/conceptual/applescriptlangguide/

Annotations

  1. For the record, this keyboard shortcut (which still works in Snow Leopard) is Opt+Shift+F11/F12.
  2. As in, studio monitors, high-quality headphones or stereo speakers where a small change in sound output from the source could make a significant change in the perceived sound. Gotta be careful with your ears, you only get one set of them!

Lightweight Debian VM on OS X with VirtualBox

Setup guide for running a lightweight headless[1] web server virtual machine guest on an OS X machine host. The VM will be an SSH host, ideal for Python web development. I’ll primarily be developing on Django, and the webserver stack setup will be in a follow-up post.

This guide was built with the following platforms, YMMV.

You’ll need an active internet connection to use the netinst image, VirtualBox provides a pretty solid, generic virtual LAN device[2] so you shouldn’t need any extra drivers.

VirtualBox Setup

If you don’t have VirtualBox already installed, it’s a pretty straightforward setup. Just follow the install wizard after opening the disk image.

  1. Once VirtualBox is installed, run it and select “New” from the VM Manager screen.
  2. Click continue on the first dialog
  3. Give your VM a name, if you label it with Debian the OS and Version should pre-fill for you. Click continue. Screenshot of a VirtualBox VM creation wizard dialog
  4. Select a memory value in MB, I’ve used 1024MB to make the install a breeze but day-to-day usage I think 384MB as recommended will be more than sufficient for a headless install. You can modify this value any time the machine is not running. Click continue. Screenshot of a VirtualBox VM creation wizard dialog
  5. Create a new or use an existing virtual disk. Click continue.Screenshot of a VirtualBox VM creation wizard dialog
  6. Just hit continue on the next screen unless you need interoperability between VM Managers.
  7. Read the info on each disk allocation, but I find dynamic to be suitable for most uses. Click continue.
  8. Select a maximum disk size value, I’ve gone with 4GB which should be sufficient (I’m on an SSD so space is at a premium).Screenshot of a VirtualBox VM creation wizard dialog
  9. If you’re happy with the Summary of the virtual disk then click Create.
  10. Same again for the VM. Click Create if it all checks out. Screenshot of a VirtualBox VM creation wizard dialog

VM Config

Before you start it’s easiest if you load the Debian ISO now. Open the Settings dialog for the VM you just added.

  1. Open the Storage tab
  2. In the Storage Tree pane select the Empty medium underneath the IDE Controller, this is your virtual CD/DVD drive Screenshot of the VirtualBox Storage tab
  3. In the right pane click on the CD icon to the right of the bus selector
  4. Click OK to save the config
  5. Ready to launch! Screenshot of VirtualBox VM Manager ready to launch VM

Debian Install

Fire up the VM and wait for it to load the ISO. The installation process is guided and quite straightforward, however it doesn’t hurt to have the installation documentation handy.

Once you reach the Software Selection step of the installation you may wish to change the defaults. I selected Mail server, SSH server and Standard system utilities only.

System Configuration

The next steps are personal preference, but keep in mind further setup will rely on some of them so it’s worth a scan.

I’ve chosen to install sudo before I proceed with setup.

~$ su -
Password: 
root$ apt-get update
... [ packages will be updated from your apt mirrors]
root$ apt-get install sudo

You’ll either want to add your regular user explicitly to the sudoers with the visudo command or add required users to the sudo group. I like to explicitly add my user to the sudoers

root$ export EDITOR=vi
root$ visudo
... add user to sudoers ...
:wq
root$ exit

Note: If you’re going to be using this VM as an SSH host you’ll note that when executing sudo ifconfig that your eth0 inteerface has a private IP address as it acts as a bypass to your internet connection. You’ll want to add a new virtual ethernet adapter, or, if you don’t need internet access once the VM is configured just update its settings.

  1. ACPI Shutdown the VM (Cmd/$Host + U)
  2. Open the VM Manager Preferences
  3. Switch to the Network tab
  4. Click add (top button on the right of the list)
  5. Save/close the preferences[3]
  6. Open the Settings pane for your VM, open the Network tab
  7. Add a new Network Adapter by clicking on the Adapter 2 pill tab
  8. Make it a host-only adapter, with name set to the vboxnet0 virtual adapter we just added

Fire up the VM again and edit the /etc/network/interfaces file:

~$ sudo vi /etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

# Host-only network interface
auto eth1
iface eth1 inet static
address 192.168.56.2
netmask 255.255.255.0
~$ sudo ifup eth1

You should now be able to ssh to your virtual host from your local machine:

~$ sudo echo 192.168.56.2	devserv >> /etc/hosts
~$ ssh devserv

If everything checks out there, Shutdown the VM (Cmd/$Host + U). Time to run the Virtual Machine headlessly:

~$ VBoxHeadless -s "Debian Webserver"

OR

~$ nohup VBoxHeadless -s "Debian Webserver" > nohup_vm.txt &

You can see in the VM Manager the preview of the running VM so you should be able to tell when it’s at the login prompt, you should be able to connect to the ssh server by that point.

To power off the machine gracefully:

local$ VBoxManage controlvm "Debian Webserver" acpipowerbutton

Annotations

  1. Both because we’re not running an X server, and VirtualBox has a headless mode
  2. To access the host on your own LAN you will need to see the notes on adding a second adapter.
  3. You can change the IP address and other settings, but I encountered issues when doing so. VirtualBox has its own private IP range configured already so it’s probably easiest just to use that.

Keyword shortcut bookmarks in Google Chrome

Firefox has a great feature where you can add a short keyword for a bookmark. It’s not immediately obvious as to how you can do it in Chrome.

Chrome calls them custom search engines, but they can be any URL you like. If you import bookmarks from Firefox they’ll automatically be saved as custom search engines (although the Tags and Description fields will be ignored).

Simple keyword shortcuts for bookmarks

  1. Open the Custom Search Engine preferences by either
    • Navigating to chrome://settings/searchEngines
    • Or, right-clicking in the address field
      Screenshot of GUI shortcut to edit search engines in Chrome

      Right (opt)-click the location bar to view the search engine preferences

  2. Fill in the name, shortcut and URL fields Screenshot of creating a simple keyword shortcut bookmark
  3. Hit Enter/Return and the bookmark is saved
  4. Open a new tab Cmd/Ctrl + T and enter the shortcut you saved Screenshot of keyword shortcut usage

Keyword shortcut for string search

This method allows you to pass an argument to a keyword shortcut, allowing you to use a bookmark as a search engine; this is the intended use of the custom search engine.

  1. Open the CSE preferences.
  2. Fill in the name & shortcut fields.
  3. You’ll need to modify the search URL. For Debian’s online package search

    http://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=python

    modify the keywords GET parameter to “%s” like so:

    http://packages.debian.org/search?suite=default&section=all&arch=any&searchon=names&keywords=%s

    Screenshot of creating a keyword-based custom search engine in Chrome

    Fill in the name, keyword and URL fields (see notes) to create search engine bookmark

  4. Hit Return/Enter and your bookmark is saved
  5. Open a new tab Cmd/Ctrl + T
  6. Enter your keyword—in this case it’s “deb”— followed by your search term, “python”, for example Screenshot of custom keyword search engine usage

WebKit/Chrome Developer Tools Tips & Tricks

WebKit Developer Tools Tips & Tricks

I use Google Chrome for the majority of my daily web development. Its Developer Tools built-in is great, but you probably already use it if you’re reading this. Here’s some handy tips I’ve picked up in part from usage, and also some pointers from a talk given at Google Developer Day 2011, in Sydney.

  1. Shortcuts
  2. Javascript Console
  3. CSS
  4. Configuration

Shortcuts

  • Cmd/Ctrl + Alt/Opt + I Will bring up the Developer Tools window, focused on the Elements panel.
  • Cmd/Ctrl + Shift + C Will bring up the Developer Tools window, focused on the Elements panel, with Inspect mode active. Click on any[1] page element to inspect it.
  • Right-clicking on any[1] element on-page will display a menu, selecting “Inspect Element” will bring up the Developer Tools window, focused on the Elements panel, but also highlight the current element and its DOM hierarchy.

Javascript Console

If you do any DOM/Javascript work, this is your best friend.

  • If you’re in the Elements panel, try hitting Esc. It’ll toggle the Javascript console and allow you to navigate the DOM visually whilst you tinker.
  • Typing in the value of an element’s ID attribute will display that DOM node in the console; the same result as having typed in the usual document.getElementById('identifier'); line.
    Console shortcut to get a document element by its ID attribute value

    Shortcut to get element by ID

  • If you currently have an element highlighted in the Elements pane, then you can reference the node with $0.
    Getting the currently selected node from the Elements pane in Console

    DevTools Console - Get current highlighted node

CSS

Styling your pages in-place and being able to save your (versioned!) changes, tab-completion for style declarations and smart rule creation.

  • Here’s an easy one: toggle your style declarations on and off. It’s not immediately obvious as the checkboxes only show on mouse hover.
    Split screenshot of toggling CSS rules

    Toggling active CSS rules

  • Add a new style rule based on the currently highlighted node in the Elements pane.
    Series of screenshots showing different specificities for creating style rules based on the currently highlighted node

    DevTools CSS - Add new style rules

  • Rewrite stylesheets and save versions of your changes over time. You can use the output to overwrite your source file so you don’t have to keep referring back to the changes you made.
    Split screenshots of saving versioned modifications to CSS

    DevTools CSS - Version snapshots

  • Tab-completion for style rules, declarations and values.
  • Cycle through suggested values for style declarations with cursor keys.

Configuration

A recently-added feature lets you switch your User-Agent string as reported to servers, on-the-fly with a simple selection. Edit: You’ll need to keep the DevTools window open when requesting a page for the UA string to be modified, if you close it the default UA will be sent on each request.

DevTools Configuration - User Agent

Annotations

  1. With the exception of a plugin container, such as a Flash movie or a Java applet. You can, however, inspect the parent block elements to quickly find the OBJECT or EMBED you’re looking for.

PHP logging snippet one-liner

If you need to whip up a quick cron-initialised script for maintenance or a newsletter batch this can come in handy:

file_put_contents('~/logs/'.date('Ymd').'_cron.log', "[".date('Y/m/d H:i:s')."] Log Message"."\n", FILE_APPEND);

Note: updated function to file_put_contents instead of error_log. See end of post for more info.

Things to note:

  • First parameter is the destination file; make sure it’s writeable
  • Assumes your system time (and your php.ini settings aren’t overriding it) is correct
  • Prefixes log files by the current day-based date as a way of making sure you don’t end up with one giant logfile, but you’ll want to tailor this depending on how regularly the script runs/produces output.
  • You’ll want to update the generic log message

Superseded but kept in case you’re looking to log actual errors:

I previously had the following but file_put_contents is more descriptive and uses named constants instead of vague numeric values for setting options.

error_log("[" . date('Y/m/d H:i:s') . "] Log Message" . "\n", 3, '~/out.log');

The 3 value is important; you want to append to the file instead of attempting to overwrite:

3: message is appended to the file destination. A newline is not automatically added to the end of the message string.

From: PHP Manual – error_log() function reference

Script to display current git branch with commits

Here’s a quick bash script to print to command line your current git branch and its commits since HEAD ready to paste in a ticketing system such as Trac. Feel free to customise it to suit your own project/source control system.

bash:

#!/bin/bash
 
git log master..HEAD --pretty=format:" * %s" --date-order --reverse
echo "{{{"
echo -n `pwd` && git branch |grep "* " | sed -e s/[\*]//g
echo "}}}"

To use the snippet for Assembla, for example just change the "{{{", "}}}" tags to “<pre><code>”, “</pre></code>” code snippet delimiters.

Install/Setup

  1. Create a bin folder in your home directory:

    $ mkdir ~/bin

  2. Create the snippet file:

    $ touch ~/bin/git-ticket-summary.sh

  3. Edit and paste in the snippet, save and exit
  4. Make script executable:

    $ chmod +x ~/bin/git-ticket-summary.sh

  5. Run from a directory with a git repository

PROTIP: use a bash alias to make usage a breeze (best added to ~/.bash_aliases — remember to source after you make any changes)

alias gts="~/bin/git-ticket-summary.sh"

Ping user action tracking link from Flash (AS2)

Flash has some pretty strict cross-domain policies, though there are use cases where you may need to hit a tracking link to save a user action, such as the the Play button on a video or completing playback.

What this does

The method below allows you to call a local (i.e. on-page) JavaScript function that then pings an external tracking link with arguments sent from Flash using string concatenation.

Note: If you’re sending a URI as an argument don’t forget to run it through escape() or encodeURI()

The Code

Assuming you’re using a SWF file and jQuery:

ActionScript 2.0:

function playVideo() {
    var ctrack = escape('http://example.com/?action=playback_start&username=foo');
    getURL("javascript:hitClickTracker('" + ctrack + "')");
}

JavaScript:

function hitClickTracker(ctrack) {
    jQuery.get(ctrack);
}

Note: If your Flash file is hosted on a separate domain — such as a CDN — you’ll need to set the allowScriptAccess property. Understand that the new default for allowScriptAccess is now sameDomain for the sake of security. More information is available at Adobe’s Flash docs.

<object>
	<param name="allowScriptAccess" value="always">
</object>

Assuming ctrack is a view that accepts GET parameters you can track various states server-side. Alternatively the link could be a clicktracker from an adserver or a URI tagged with analytics keyvals.

Tracking with DoubleClick click trackers

This is a little more involved. DoubleClick uses redirects in its clicktrackers and can return a 400 Bad Response if simply retrieved with an XmlHttpRequest.

A method I’m piloting at the moment is to use the clicktracker URI as the src attribute of an iframe. Assuming the adurl GET parameter is a tracking pixel, and you’re using the same JavaScript function call from ActionScript as above:

JavaScript:

function hitClickTracker(ctrack) {
	jQuery('<iframe>').attr({
		'src': encodeURI(ctrack),
		'class': 'dc_tracking_pixel'
	}).appendTo('body');
}

Please let me know if this helps you out or if you have any feedback for improvement/bug fixes. This is experimental at the moment.