<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US" xml:base="http://shinylittlething.com/wp-atom.php">
	<title type="text">Shiny Blog</title>
	<subtitle type="text">Comes with Narwhals and bacon!</subtitle>

	<updated>2011-06-06T08:11:36Z</updated>

	<link rel="alternate" type="text/html" href="http://shinylittlething.com" />
	<id>http://shinylittlething.com/feed/atom/</id>
	

	<generator uri="http://wordpress.org/" version="3.4.2">WordPress</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MyShinyWeblog" /><feedburner:info uri="myshinyweblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>MyShinyWeblog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[CSS Minification on the Fly]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/13SNux5qELE/" />
		<id>http://shinylittlething.com/?p=368</id>
		<updated>2010-01-27T08:49:54Z</updated>
		<published>2010-01-20T13:12:33Z</published>
		<category scheme="http://shinylittlething.com" term="CSS" /><category scheme="http://shinylittlething.com" term="PHP" /><category scheme="http://shinylittlething.com" term="Server" /><category scheme="http://shinylittlething.com" term="Wordpress" /><category scheme="http://shinylittlething.com" term="Optimization" /><category scheme="http://shinylittlething.com" term="Performance" />		<summary type="html"><![CDATA[Introduction So, I  recently took the habit to fire Google&#8217;s Page Speed to learn about my websites performances and looking for ways to optimize them for my particular hosting solution and for the benefits of my readership (you). One of the recommendation was to minify CSS. We (web workers) have all encountered JavaScript minification. This [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2010/01/20/css-minification-on-the-fly/">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;So, I  recently took the habit to fire &lt;a href="http://code.google.com/speed/page-speed/"&gt;Google&amp;#8217;s Page Speed&lt;/a&gt; to learn about my websites performances and looking for ways to optimize them for my &lt;a title="particular hosting solution" href="http://shinylittlething.com/2009/07/20/home-web-hosting-best-practices/"&gt;particular hosting solution&lt;/a&gt; and for the benefits of my readership (you).&lt;/p&gt;
&lt;p&gt;One of the recommendation was to minify CSS. We (web workers) have all encountered JavaScript minification. This became a common task to do at the pre launch phase.&lt;/p&gt;
&lt;p&gt;Assets minification is great, it&amp;#8217;s saves bandwidth and reduces latency, however there is a downside, you need to keep copies of the original files if you want to keep any formating.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s where I come with a simple solution to minify on the fly any css embedded in your site. This will involve a little knowledge of PHP and Apache rewrite rules.&lt;/p&gt;
&lt;h2&gt;The PHP minifier&lt;/h2&gt;
&lt;p&gt;Ok, I don&amp;#8217;t like to reinvent the wheel when I know such a wheel exists. So I borrowed and slightly edited the &lt;a href="http://www.lateralcode.com/css-minifer/"&gt;php css minifer&lt;/a&gt; published on lateralcode.com.&lt;/p&gt;
&lt;pre&gt;[sourcecode lang="php"]
header( "Content-type: text/css" );

$file = isset( $_GET[ 'css' ] ) ? $_GET[ 'css' ] : '';

$content = file_get_contents( $_SERVER['DOCUMENT_ROOT'] . $file );
echo minify( $content );

function minify( $css ) {
	$css = preg_replace( '#\s+#', ' ', $css );
	$css = preg_replace( '#/\*.*?\*/#s', '', $css );
	$css = str_replace( '; ', ';', $css );
	$css = str_replace( ': ', ':', $css );
	$css = str_replace( ' {', '{', $css );
	$css = str_replace( '{ ', '{', $css );
	$css = str_replace( ', ', ',', $css );
	$css = str_replace( '} ', '}', $css );
	$css = str_replace( ';}', '}', $css );

	return trim( $css );
}

[/sourcecode]&lt;/pre&gt;
&lt;h2&gt;The Rewrite Rules&lt;/h2&gt;
&lt;p&gt;I saved my minifier PHP script into a directory named /m/ on my site&amp;#8217;s root. All I want know is to minify all my css files without having to edit all the &lt;strong&gt;link&lt;/strong&gt; tags and &lt;strong&gt;@import&lt;/strong&gt; in my code. So I&amp;#8217;ve written this rewrite rule to pass any request to a file ending in .css to my PHP minifier; It&amp;#8217;s not a redirect it&amp;#8217;s just a rewriting so I can keep my paths unmodified.&lt;/p&gt;
&lt;pre&gt;[sourcecode lang="bash"]
	# Avoids infinite loops
	RewriteCond %{REQUEST_URI}	!^/m/$

	# Pass the complete path to any css file to the php minifier
	RewriteRule ^/(.*\.css)$	/m/index.php?css=$1 [NC]
[/sourcecode]&lt;/pre&gt;
&lt;h2&gt;WordPress Tests&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s the results for a request against a typical WordPress installation with a couple plugins installed :&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;div id="attachment_380" class="wp-caption aligncenter" style="width: 310px"&gt;&lt;a href="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/CSS-minified.png"&gt;&lt;img class="size-medium wp-image-380  " title="CSS minified" src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/CSS-minified-300x59.png" alt="" width="300" height="59" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;CSS minified&lt;/p&gt;&lt;/div&gt;
&lt;div id="attachment_381" class="wp-caption aligncenter" style="width: 310px"&gt;&lt;a href="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/CSS-not-minified.png"&gt;&lt;img class="size-medium wp-image-381" title="CSS not minified" src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/CSS-not-minified-300x59.png" alt="" width="300" height="59" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;CSS not minified&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Here is the comparison chart of the gains on a typical request:&lt;/p&gt;
&lt;div class="wp-caption aligncenter" style="width: 610px"&gt;&lt;img title="CSS Minifier Benefits Comparison Chart" src="http://chart.apis.google.com/chart?cht=bhg&amp;amp;chd=t:85,71|15,29&amp;amp;chs=600x125&amp;amp;chm=t+Latency,000000,0,0,13|t+Size,000000,0,1,13|t+Latency+Minified+%2885%+reduction%29,000000,1,0,13|t+Size+Minified+%2829%+reduction%29,000000,1,1,13&amp;amp;chco=D95B43,98402F" alt="" width="600" height="125" /&gt;&lt;p class="wp-caption-text"&gt;CSS Minifier Benefits Comparison Chart&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Latency tests are not extremely accurate since it may varies depending on network connection. I, however, constated significants performances boost and on very few hosts, an unexplained drop in latency performance. My guess is that the latency was introduced by the computations in the PHP minifier script on very busy servers.&lt;/p&gt;
&lt;h2&gt;Enhancements&lt;/h2&gt;
&lt;p&gt;This &amp;#8220;hack&amp;#8221; is not perfect as is. You might want to generate a cache of the minified CSS files to save a significant amount of CPU cycles. Here is the modified PHP CSS minifier vastly inspired by &lt;a href="http://www.snipe.net/2009/03/quick-and-dirty-php-caching/"&gt;Quick and Dirty PHP Caching&lt;/a&gt; article (snipe.net).&lt;/p&gt;
&lt;p&gt;My Apache is configured to send GZIPed content whenever possible so, I dropped the part about compression and merged the different CSS minification functions to get the best out of them.&lt;/p&gt;
&lt;pre&gt;[sourcecode lang="php"]

header("Content-type: text/css");
header("Cache-Control: no-cache, must-revalidate");

$file = isset( $_GET[ 'css' ] ) ? $_GET[ 'css' ] : '';

$cachefile = 'cache/'.basename($file);
$cachetime = 24 *  60 * 60;

if (file_exists($cachefile)
&amp;#038;&amp;#038; (time() - $cachetime &lt; filemtime($cachefile))) {
        header("Expires: " .
			gmdate("D, d M Y H:i:s", filemtime($cachefile) + $cachetime) .
			" GMT", true);
        include($cachefile);
        exit;
}

ob_start(); // start the output buffer

$fp = fopen($cachefile, 'w'); // open the cache file for writing

$content = file_get_contents( $_SERVER['DOCUMENT_ROOT'] . $file );
echo minify($content);
echo "/* Cached ".date('jS F Y H:i', filemtime($cachefile))." */";
// save the contents of output buffer to the file
fwrite($fp, ob_get_contents());
fclose($fp);

ob_end_flush(); // Send the output to the browser

function minify($data) {
    $data = preg_replace( '#/\*.*?\*/#s', '', $data );
    // remove single line comments, like this, from // to \\n
    $data = preg_replace('/(\/\/.*\n)/', '', $data);
    // remove new lines \\n, tabs and \\r
    $data = preg_replace('/(\t|\r|\n)/', '', $data);
    // replace multi spaces with singles
    $data = preg_replace('/(\s+)/', ' ', $data);
    //Remove empty rules
    $data = preg_replace('/[^}{]+{\s?}/', '', $data);
    // Remove whitespace around selectors and braces
    $data = preg_replace('/\s*{\s*/', '{', $data);
    // Remove whitespace at end of rule
    $data = preg_replace('/\s*}\s*/', '}', $data);
    // Just for clarity, make every rules 1 line tall
    $data = preg_replace('/}/', "}\n", $data);
    $data = str_replace( ';}', '}', $data );
    $data = str_replace( ', ', ',', $data );
    $data = str_replace( '; ', ';', $data );
    $data = str_replace( ': ', ':', $data );
    $data = preg_replace( '#\s+#', ' ', $data );

    return $data;
}
[/sourcecode]&lt;/pre&gt;
&lt;h2&gt;More Enhancements&lt;/h2&gt;
&lt;p&gt;Well, we are now saving all minified css files into our cache so we can read from these cached files for all the next requests for 24 hours thus completly anihilating the latency problem on busy servers. That done I restored the Browser Caching leverage by adding an Expires header related to each files generation time + the cache lifetime.&lt;/p&gt;
&lt;h2&gt;But Wait, There is more! Cache Control&lt;/h2&gt;
&lt;p&gt;Addionaly, as web developers we will need something to deactivate this caching behavior. Deactivating it completly is just as easy as removing the Apache rewrite rules. But what we might find very handy is to regenerate the cache if  the master CSS file has been modified.&lt;/p&gt;
&lt;p&gt;The PHP CSS Minifier script becomes then:&lt;/p&gt;
&lt;pre&gt;[sourcecode lang="php"]
$time_start = microtime_float();

header("Content-type: text/css");
header("X-Powered-by: CSS Minifier v0.1", true);
header("Cache-Control: no-cache, must-revalidate");

$file = isset( $_GET[ 'css' ] ) ? $_GET[ 'css' ] : '';

$cachefile = 'cache/'.basename($file);
$cachetime = 24 *  60 * 60;

$age = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);

header("X-Original-Generated-At: " . nicetime($age));

if (file_exists($cachefile)
&amp;#038;&amp;#038; (time() - $cachetime &lt; filemtime($cachefile))) {
        header("Expires: " .
			gmdate("D, d M Y H:i:s", filemtime($cachefile) + $cachetime) .
			" GMT", true);
 $time_end = microtime_float();
 $time = $time_end - $time_start;
 header("Cache-Status: cached");
 header("X-Runtime: ". $time . "sec");

 include($cachefile);
 exit;
}

header("Cache-Status: regenerated");
ob_start(); // start the output buffer
$fp = fopen($cachefile, 'w'); // open the cache file for writing

$content = file_get_contents( $_SERVER['DOCUMENT_ROOT'] . $file );
echo minify($content);
echo "/* Cached ".date('jS F Y H:i', filemtime($cachefile))." */";
fwrite($fp, ob_get_contents()); // save the contents of output buffer to the file
fclose($fp); // close the file

$time_end = microtime_float();
$time = $time_end - $time_start;
header( "X-Runtime: ". $time . "sec" );

ob_end_flush(); // Send the output to the browser

function minify($data) {
 $data = preg_replace( '#/\*.*?\*/#s', '', $data );
 // remove single line comments, like this, from // to \\n
 $data = preg_replace('/(\/\/.*\n)/', '', $data);
 // remove new lines \\n, tabs and \\r
 $data = preg_replace('/(\t|\r|\n)/', '', $data);
 // replace multi spaces with singles
 $data = preg_replace('/(\s+)/', ' ', $data);
 //Remove empty rules
 $data = preg_replace('/[^}{]+{\s?}/', '', $data);
 // Remove whitespace around selectors and braces
 $data = preg_replace('/\s*{\s*/', '{', $data);
 // Remove whitespace at end of rule
 $data = preg_replace('/\s*}\s*/', '}', $data);
 // Just for clarity, make every rules 1 line tall
 $data = preg_replace('/}/', "}\n", $data);
 $data = str_replace( ';}', '}', $data );
 $data = str_replace( ', ', ',', $data );
 $data = str_replace( '; ', ';', $data );
 $data = str_replace( ': ', ':', $data );
 $data = preg_replace( '#\s+#', ' ', $data );

 return $data;
}

function microtime_float() {
 list($usec, $sec) = explode(" ", microtime());
 return ((float)$usec + (float)$sec);
}

function nicetime($date)
{
 if(empty($date)) {
 return "No date provided";
 }

 $periods         = array(
							"second", "minute", "hour",
							"day", "week", "month", "year", "decade"
					);
 $lengths         = array(
							"60","60","24","7",
							"4.35","12","10"
					);

 $now             = time();
 $unix_date         = $date;

 // check validity of date
 if(empty($unix_date)) {
 return "Bad date";
 }

 // is it future date or past date
 if($now &gt; $unix_date) {
 $difference     = $now - $unix_date;
 $tense         = "ago";

 } else {
 $difference     = $unix_date - $now;
 $tense         = "from now";
 }

 for($j = 0; $difference &gt;= $lengths[$j]
		&amp;#038;&amp;#038; $j &lt; count($lengths)-1; $j++) {
 	$difference /= $lengths[$j];
 }

 $difference = round($difference);

 if($difference != 1) {
 $periods[$j].= "s";
 }

 return "$difference $periods[$j] {$tense}";
}

[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Note the additional HTTP headers to keep track of cache statuses. Here's how to test the whole functionalities:&lt;/p&gt;
&lt;p&gt;1 . No cache available&lt;/p&gt;
&lt;div id="attachment_395" class="wp-caption aligncenter" style="width: 310px"&gt;&lt;a href="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-minifier-no-cache.png"&gt;&lt;img class="size-medium wp-image-395" title="CSS Minifier No Cache" src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-minifier-no-cache-300x127.png" alt="" width="300" height="127" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;CSS Minifier No Cache&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;2 . File is already cache:&lt;/p&gt;
&lt;div id="attachment_393" class="wp-caption aligncenter" style="width: 310px"&gt;&lt;a href="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-minifier-cached.png"&gt;&lt;img class="size-medium wp-image-393" title="CSS Minifier Cached File " src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-minifier-cached-300x124.png" alt="" width="300" height="124" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;CSS Minifier Cached File &lt;/p&gt;&lt;/div&gt;
&lt;p&gt;3 . Master CSS file has been modified:&lt;/p&gt;
&lt;div id="attachment_394" class="wp-caption aligncenter" style="width: 310px"&gt;&lt;a href="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-minifier-file-modified.png"&gt;&lt;img class="size-medium wp-image-394" title="CSS Master Modified" src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-minifier-file-modified-300x128.png" alt="" width="300" height="128" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;CSS Master Modified&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;As you can see, the different HTTP headers : &lt;strong&gt;Cache-Status&lt;/strong&gt;, &lt;strong&gt;X-Original-Generated-At&lt;/strong&gt; and &lt;strong&gt;X-Runtime&lt;/strong&gt; helps to determine if the cache is functioning properly. When statisfied, it's safe to remove those lines in production code.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;These ~100 lines of php will saves you a lot a bits.&lt;/p&gt;
&lt;h3&gt;Update&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/defaultlogo.png"&gt;&lt;img class="alignleft size-full wp-image-407" title="Google Code Logo" src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/defaultlogo.png" alt="Google Code Logo" width="48" height="48" /&gt;&lt;/a&gt;I created a new project on google code to host the code of my PHP CSS minifier. Along with a complete rewrite in OO PHP, you will be able to download the latest sources from &lt;a href="http://code.google.com/p/cssshrink/"&gt;the CSS Shrink project&lt;/a&gt;.&lt;/p&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F&amp;amp;title=CSS%20Minification%20on%20the%20Fly&amp;amp;notes=Introduction%0D%0ASo%2C%20I%C2%A0%20recently%20took%20the%20habit%20to%20fire%20Google%27s%20Page%20Speed%20to%20learn%20about%20my%20websites%20performances%20and%20looking%20for%20ways%20to%20optimize%20them%20for%20my%20particular%20hosting%20solution%20and%20for%20the%20benefits%20of%20my%20readership%20%28you%29.%0D%0A%0D%0AOne%20of%20the%20reco" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F&amp;amp;title=CSS%20Minification%20on%20the%20Fly" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F&amp;amp;title=CSS%20Minification%20on%20the%20Fly" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=CSS%20Minification%20on%20the%20Fly%20-%20http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F&amp;amp;title=CSS%20Minification%20on%20the%20Fly" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F&amp;amp;t=CSS%20Minification%20on%20the%20Fly" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=CSS%20Minification%20on%20the%20Fly&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F20%2Fcss-minification-on-the-fly%2F&amp;amp;t=CSS%20Minification%20on%20the%20Fly" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2010/01/16/psd-template-to-wordpress-theme-from-scratch/" title="PSD template to Wordpress Theme from Scratch"&gt;PSD template to Wordpress Theme from Scratch&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=13SNux5qELE:TDwM4KmUoxI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/13SNux5qELE" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2010/01/20/css-minification-on-the-fly/#comments" thr:count="19" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2010/01/20/css-minification-on-the-fly/feed/atom/" thr:count="19" />
		<thr:total>19</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2010/01/20/css-minification-on-the-fly/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[PSD template to WordPress Theme from Scratch]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/FHSc5XI1-aU/" />
		<id>http://blog.shinylittlething.com/?p=307</id>
		<updated>2010-01-25T09:16:48Z</updated>
		<published>2010-01-16T12:44:03Z</published>
		<category scheme="http://shinylittlething.com" term="Wordpress" /><category scheme="http://shinylittlething.com" term="CSS" /><category scheme="http://shinylittlething.com" term="JavaScript" /><category scheme="http://shinylittlething.com" term="Photoshop" /><category scheme="http://shinylittlething.com" term="PHP" /><category scheme="http://shinylittlething.com" term="Template" /><category scheme="http://shinylittlething.com" term="Theme" />		<summary type="html"><![CDATA[Clean &#38; Detailed PSD template to WordPress Theme from Scratch In this tutorial I&#8217;ll guide you in the process to transform a PhotoshopTM PSD template to a complete XHTML and CSS site build. In the process you will learn how to slice the PSD, how to reproduce some photoshop layer styles using CSS3 and how [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2010/01/16/psd-template-to-wordpress-theme-from-scratch/">&lt;h2&gt;Clean &amp;amp; Detailed PSD template to WordPress Theme from Scratch&lt;/h2&gt;
&lt;p style="text-align: justify;"&gt;In this tutorial I&amp;#8217;ll guide you in the process to transform a Photoshop&lt;sup&gt;&lt;small&gt;TM&lt;/small&gt;&lt;/sup&gt; PSD template to a complete XHTML and CSS site build. In the process you will learn how to slice the PSD, how to reproduce some photoshop layer styles using CSS3 and how to easily implement CSS sprites. You will not find any cross browser hacks or tricks because, this topic would require a complete tutorial by itself and this is not the purpose of this tutorial.&lt;/p&gt;
&lt;h2&gt;Final image result&lt;/h2&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/final-result.jpg" alt="Final Image Result" /&gt;&lt;/p&gt;
&lt;h2&gt;WordPress Setup&lt;/h2&gt;
&lt;p&gt;In order to have a complete preview of what can go into a WordPress blog I use a resource from wpcandy.com:&lt;a href="http://wpcandy.com/articles/easier-theme-development-with-the-sample-post-collection.html"&gt; Easier Theme Development with Sample WordPress Content&lt;/a&gt; this archive contains a complete dummy content like blockquotes, lists, and floating images that are common to blogs and that need to be supported in every theme you release.&lt;/p&gt;
&lt;p&gt;Simply download and extract the archive then go to the WordPress Dashboard and Tools &amp;gt; Import choose «Wordpress» and upload the extracted «posts.xml» file.&lt;/p&gt;
&lt;p&gt;We now have a solid content base that will prevent us to omit something in our CSS/XHTML design process so we can now focus on slicing and theming our new WordPress blog!&lt;/p&gt;
&lt;h2&gt;Starting from default WordPress theme&lt;/h2&gt;
&lt;p&gt;A common usage if you do not already made a subsequent amount of WordPress themes is to start from the default one, Kubrick. First thing to do is to clear the style.css and insert the well known&lt;a href="http://meyerweb.com/eric/tools/css/reset/index.html"&gt; CSS reset by Eric Meyer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You should obtain something very similar to this as a result:&lt;br /&gt;
&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-reset.jpg" alt="CSS Reset" /&gt;&lt;/p&gt;
&lt;p&gt;Do you notice the background image still visible in our reseted layout ? The Kubrick theme inserts this CSS at runtime after a sidebar detection. Let&amp;#8217;s remove it. Open the file «/wordpress/wp-content/themes/default/header.php» and remove the inline style block mentioning the &lt;code&gt;#page&lt;/code&gt; id.&lt;br /&gt;
It should looks like this :&lt;br /&gt;
[sourcecode language='php']&lt;/p&gt;
&lt;style type="text/css" media="screen"&gt;
&lt;p&gt;&lt;?php
// Checks to see whether it needs a sidebar or not
if ( empty($withcomments) &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; !is_single() ) {
?&gt;
#page { background: url("&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/kubrickbg-&lt;?php bloginfo('text_direction'); ?&gt;.jpg") repeat-y top; border: none; }
&lt;?php } else { // No sidebar ?&gt;
#page { background: url("&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/kubrickbgwide.jpg") repeat-y top; border: none; }
&lt;?php } ?&gt;&lt;/p&gt;
&lt;/style&gt;
&lt;p&gt;[/sourcecode]&lt;br /&gt;
Remove this block and as well as the «rtl.css» and «screenshot.png» files and everything in «images/», I will not cover the Right To Left implementation in this tutorial and we will replace the screenshot at the very end.&lt;/p&gt;
&lt;h2&gt;Main zones analysis&lt;/h2&gt;
&lt;p&gt;Here are the top level zones identified in our Photoshop template :&lt;br /&gt;
&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/step-1.jpg" alt="Identified zones" /&gt;&lt;/p&gt;
&lt;p&gt;To build a theme we need to first define the zones we will implement, starting by large containers, slowly focusing on smaller elements. Here are the first elements I identified.&lt;/p&gt;
&lt;p&gt;Our theme features by default the following top level elements: &lt;code&gt;#header, #content, #sidebar and #footer&lt;/code&gt; all contained in the main wrapper: &lt;code&gt;#page&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s almost complete, but our layout features a navigation bar. We will have to add a CSS hook for this one, open up «/wordpress/wp-content/themes/default/header.php» in your favorite editor if you closed it and add the following code a the end of file.&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div id="wrapper"&gt;
&lt;div id="navigation"&gt;
&lt;ul class="left"&gt;
&lt;li&lt;?php if(is_home() &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; !is_paged()) echo ' class="current_item"'; ?&gt;&gt;&lt;br /&gt;
&lt;a href="&lt;?php bloginfo('url'); ?&gt;&amp;#8220;&gt;&lt;?php _e('Home'); ?&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;p&gt;&lt;?php wp_list_pages('title_li=&amp;amp;amp;amp;amp;amp;amp;depth=2'); ?&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Then in «/wordpress/wp-content/themes/default/footer.php», just after the &lt;code&gt;hr&lt;/code&gt; tag, close the wrapper div:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;?php&lt;br /&gt;
/**&lt;br /&gt;
* @package WordPress&lt;br /&gt;
* @subpackage Default_Theme&lt;br /&gt;
*/&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Basically, we added the list of the top level pages in an unordered list and wrapped our everything except the header and footer in a div.&lt;/p&gt;
&lt;p&gt;The first conditional block just displays a «Home» link and optionally apply it a class if we are on the frontpage or in a paged navigation.&lt;br /&gt;
Our WordPress template should now looks like this in a browser:&lt;br /&gt;
&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/navigation.jpg" alt="Adding Navigation Hook" /&gt;&lt;/p&gt;
&lt;h2&gt;PSD Slicing&lt;/h2&gt;
&lt;p&gt;Start by isolating the top header background image.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/header-background-slicing.jpg" alt="Header Background Isolation" /&gt;&lt;/p&gt;
&lt;p&gt;Save the slice for web &amp;amp; device as «/wordpress/wp-content/themes/default/images/header-bg.png»&lt;br /&gt;
using png-24 (lesser size in this case) then start &lt;a href="http://getfirebug.com"&gt;Firebug&lt;/a&gt; (F12).&lt;br /&gt;
Using the &lt;abbr title="Document Object Model"&gt;DOM&lt;/abbr&gt; Inspector tool (&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/firebug-dom-inspect.gif" alt="Firebug DOM Inspector tool" /&gt;),&lt;br /&gt;
select the header zone (&lt;code&gt;id=header&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/firebug-header-selection.png" alt="Header Selection" /&gt;&lt;/p&gt;
&lt;p&gt;Once the node selected, right click (ctrl+click on Macintosh) in the «Style» tab on the right&lt;br /&gt;
firebug panel and choose «Edit Element Style &amp;#8230;».&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/firebug-header-edition.png" alt="Header Edition" /&gt;&lt;/p&gt;
&lt;p&gt;You can now preview all CSS changes you make in live.&lt;/p&gt;
&lt;p&gt;Enter the following directives :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
background: transparent url(images/header-bg.png) repeat-x scroll 0 0;&lt;br /&gt;
height:116px;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Once done and satisfied with the result, save the generated CSS into our theme main stylesheets document: «/wordpress/wp-content/themes/default/style.css»&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#header {&lt;br /&gt;
background: transparent url(images/header-bg.png) repeat-x scroll 0 0;&lt;br /&gt;
height:116px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Back to Photoshop, hide all groups except for the background and create a new horizontal guide at 116px&lt;br /&gt;
(if not already exists) and grab a selection from this guide to just under the background gradient&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/photoshop-background-selection.jpg" alt="Background Selection" /&gt;&lt;/p&gt;
&lt;p&gt;Enter the following directives in your «style.css» file:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
body {&lt;br /&gt;
background: #663300 url(images/bg.jpg) no-repeat scroll center 116px;&lt;br /&gt;
font-family:&amp;#8221;Myriad Pro&amp;#8221;, helvetica, arial, sans-serif;&lt;br /&gt;
line-height:1.7em;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Then build the footer like you did for the header :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/footer-background-slicing.jpg" alt="Footer Selection" /&gt;&lt;/p&gt;
&lt;p&gt;Then, style it :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#footer {&lt;br /&gt;
background: transparent url(images/footer-bg.png) repeat-x scroll 0 0;&lt;br /&gt;
height:295px;&lt;br /&gt;
clear:both;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;And style the wrapper div and the common elements while you&amp;#8217;re at it:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#wrapper {&lt;br /&gt;
margin: 0 auto;&lt;br /&gt;
width:970px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;a {&lt;br /&gt;
color:#FFFFFF;&lt;br /&gt;
text-decoration:none;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;h2&gt;Navigation&lt;/h2&gt;
&lt;p&gt;The default WordPress content we used to seed our favorite blogging engine features hierarchized pages. This is an unique occasion for us to style and add some fancy drop down menu with jQuery.&lt;/p&gt;
&lt;p&gt;For a start the styling is not rocket science :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;/p&gt;
&lt;p&gt;/* Prevents blocks to hang side by side */&lt;br /&gt;
#content {&lt;br /&gt;
clear:both;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#navigation li&lt;br /&gt;
{&lt;br /&gt;
display:block;&lt;br /&gt;
float:left;&lt;br /&gt;
line-height:35px;&lt;br /&gt;
min-width:100px;&lt;br /&gt;
text-align:center;&lt;br /&gt;
position:relative;&lt;br /&gt;
padding-left:5px;&lt;br /&gt;
padding-right:5px;&lt;br /&gt;
height:33px;&lt;br /&gt;
background:transparent url(images/navigation-separator.png) no-repeat scroll 0 0;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;/* Hiding sub menu items */&lt;br /&gt;
#navigation li ul {&lt;br /&gt;
display:none;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;To slice our navigation background images we must, hide all groups except for Navigation one. Start with the left part of the navigation bar:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/navigation-background-slicing-1.png" alt="Navigation Slicing" /&gt;&lt;/p&gt;
&lt;p&gt;Once saved, transform the selection in order to make a narrow selection, that will be the main navigation background.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/navigation-background-slicing-2.png" alt="Navigation Slicing" /&gt;&lt;/p&gt;
&lt;p&gt;That done you can now slice the tab separator then style the navigation elements:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#navigation {&lt;br /&gt;
background: transparent url(images/nav-left.png) no-repeat scroll 0 0;&lt;br /&gt;
padding-left:11px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#navigation ul {&lt;br /&gt;
background: transparent url(images/nav-middle.png) repeat-x scroll 0 0;&lt;br /&gt;
height:44px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#navigation li:hover, #navigation li ul li:hover {&lt;br /&gt;
background:transparent url(images/navigation-hover.png) no-repeat scroll 0 0;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;You may need to adjust your padding and height if necessary, it only depends on your sliced images sizes.&lt;/p&gt;
&lt;p&gt;For example, I added a left padding of 11 pixels to my navigation div because I don&amp;#8217;t want the background of the element inside it to hide it&amp;#8217;s content.&lt;/p&gt;
&lt;p&gt;Take a look at the difference:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-padding-difference.png" alt="CSS Padding Difference" /&gt;&lt;/p&gt;
&lt;p&gt;It speaks by itself.&lt;/p&gt;
&lt;p&gt;Well, you may have noticed that I included a rule to handle the CSS &lt;code&gt;:hover&lt;/code&gt; pseudo-class.&lt;/p&gt;
&lt;p&gt;The code is not relevant, it just displays another image as the background of the tab. If there&amp;#8217;s something you must pay attention to, is the hover image size. It must be at least longer than you longer tab, itself being conditioned by the longest title of your pages.&lt;/p&gt;
&lt;p&gt;Here is a quick preview of what you will face if the hover image is too short:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/css-sliding-doors-behaviors.png" alt="Too short hover image" /&gt;&lt;/p&gt;
&lt;p&gt;This is one if not the only the counter part of using CSS sliding doors.&lt;/p&gt;
&lt;h2&gt;Displaying submenus using jQuery&lt;/h2&gt;
&lt;p&gt;First create a new folder named «/wordpress/wp-content/themes/default/js/» and install a fresh copy of jQuery inside along with a new file named «shiny-theme.js».&lt;br /&gt;
Open «/wordpress/wp-content/themes/default/footer.php» and just before the closing&lt;code&gt; body&lt;/code&gt; tag, add the references to jQuery and shiny-theme.js:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;script src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/js/jquery-1.3.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;
&lt;script src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/js/shiny-theme.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;You might want to take advantage of Google&amp;#8217;s Ajax CDN to save bandwidth. In this case replace the jQuery reference by this one :&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"&gt;&lt;/script&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;«Why in the footer?» You might ask. The answer is based on the assumption that any javascript that affects the &lt;abbr title="Document Object Model"&gt;DOM&lt;/abbr&gt; won&amp;#8217;t be triggered until the DOM is fully parsed by the browser, generating errors otherwise. More important, having the javascripts in the footer avoid browsers stalling while rendering a page. Because it doesn&amp;#8217;t have to download and parse huge files prior DOM rendering.&lt;/p&gt;
&lt;p&gt;Styling submenus:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#navigation li ul {&lt;br /&gt;
display:none;&lt;br /&gt;
left:0;&lt;br /&gt;
position:absolute;&lt;br /&gt;
top:33px;&lt;br /&gt;
height:auto;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#navigation li ul li {&lt;br /&gt;
background:transparent url(images/navigation-hover.png) repeat scroll 0 0;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Open «/wordpress/wp-content/themes/default/js/shiny-theme.js» and paste the following snippet:&lt;/p&gt;
&lt;p&gt;[sourcecode language='javascript']&lt;br /&gt;
$(document).ready(function(){&lt;/p&gt;
&lt;p&gt;$(&amp;#8216;#navigation li&amp;#8217;).hover(&lt;br /&gt;
function() {$(this).find(&amp;#8216;ul:first&amp;#8217;).show();},&lt;br /&gt;
function() {$(this).find(&amp;#8216;ul:first&amp;#8217;).hide();}&lt;br /&gt;
);&lt;/p&gt;
&lt;p&gt;})&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Refresh your page and take a look at the result :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/jquery-menu.png" alt="jQuery Menu" /&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s nice, but it could be nicer using some CSS3 rules.&lt;/p&gt;
&lt;p&gt;In the previous screenshot the &lt;code&gt;li&lt;/code&gt; are not clearly diferenciated from the post content. It&amp;#8217;s too flat, there&amp;#8217;s no deepness. Let&amp;#8217;s add some deepness using a couple CSS3 rules edit the &lt;code&gt;ul&lt;/code&gt; selector to add two new browser specific rules :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#navigation li ul {&lt;br /&gt;
display:none;&lt;br /&gt;
left:0;&lt;br /&gt;
position:absolute;&lt;br /&gt;
top:33px;&lt;br /&gt;
height:auto;&lt;br /&gt;
&lt;strong&gt;&lt;br /&gt;
-moz-box-shadow:0 2px 5px #000000;&lt;br /&gt;
-webkit-box-shadow:0 2px 5px #000000;&lt;br /&gt;
&lt;/strong&gt;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Then take a look at the result:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/jquery-menu-shaded.png" alt="jQuery Menu Shaded" /&gt;&lt;/p&gt;
&lt;p&gt;Voilà! Our design just took another dimension. With just only those two lines you are covering Firefox 3.1+, Safari 3+ and Chrome browsers. I don&amp;#8217;t know about you but on my sites it&amp;#8217;s a more than significant part of my audience.&lt;/p&gt;
&lt;h2&gt;The content and sidebar areas&lt;/h2&gt;
&lt;p&gt;Kubrick does not shows the sidebar while on a post or page and it displays the navigations links above the content element. Let&amp;#8217;s change these behaviors by adding the following code just before the &lt;code&gt;get_footer()&lt;/code&gt; call in «/wordpress/wp-content/themes/default/single.php»:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;?php get_sidebar(); ?&gt;&lt;br /&gt;
&lt;?php get_footer(); ?&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;&amp;#8230; And by removing the navigation snippet.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s quickly lay some CSS rules to style our main content and sidebar.&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
/*&lt;br /&gt;
The left margin of the #content element must be the same&lt;br /&gt;
as the #navigation left padding&lt;br /&gt;
*/&lt;br /&gt;
#content {&lt;br /&gt;
clear:both;&lt;br /&gt;
float:left;&lt;br /&gt;
margin:0 0 0 11px;&lt;br /&gt;
width:625px;&lt;br /&gt;
background-color:#ccc;&lt;br /&gt;
border: 1px solid #fff;&lt;br /&gt;
margin-bottom:20px;&lt;br /&gt;
padding:10px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#content a {&lt;br /&gt;
color:#663300;&lt;br /&gt;
text-decoration:underline;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#sidebar  {&lt;br /&gt;
background-color:#ccc;&lt;br /&gt;
border: 1px solid #fff;&lt;br /&gt;
margin-bottom:20px;&lt;br /&gt;
padding:10px;&lt;br /&gt;
float:left;&lt;br /&gt;
width:270px;&lt;br /&gt;
color:#666;&lt;br /&gt;
font-size:0.9em;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post {&lt;br /&gt;
margin-bottom:20px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;You should now have something very similar to the following screenshot when you browse a specific post:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/content-and-sidebar-areas.jpg" alt="Content and Sidebar Areas" /&gt;&lt;/p&gt;
&lt;p&gt;Once formated properly, we should add the basic typography and formating rules.&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
.post h2, .post h3, .post h4, .post h5, .post h6 {&lt;br /&gt;
color:#333333;&lt;br /&gt;
font-family:Georgia, &amp;#8220;Times New Roman&amp;#8221; ,serif;&lt;br /&gt;
font-style:italic;&lt;br /&gt;
margin-bottom:10px;&lt;br /&gt;
height:32px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;h2 {font-size:28px;}&lt;br /&gt;
h3 {font-size:24px;}&lt;br /&gt;
h4 {font-size:20px;}&lt;br /&gt;
h5 {font-size:16px;}&lt;br /&gt;
h6 {font-size:12px;}&lt;/p&gt;
&lt;p&gt;.post {&lt;br /&gt;
margin-bottom:20px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post img {&lt;br /&gt;
background-color:#CCCCCC;&lt;br /&gt;
border:3px solid #AAAAAA;&lt;br /&gt;
margin-bottom:10px;&lt;br /&gt;
margin-top:10px;&lt;br /&gt;
padding:4px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.alignright {&lt;br /&gt;
margin-left:10px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.alignleft {&lt;br /&gt;
margin-right:10px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.entry p {&lt;br /&gt;
text-align:justify;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post blockquote {&lt;br /&gt;
border-bottom:3px solid #663300;&lt;br /&gt;
border-top:3px solid #663300;&lt;br /&gt;
font-style:oblique;&lt;br /&gt;
margin:1em;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post ul, .post ol {&lt;br /&gt;
list-style-type:disc;&lt;br /&gt;
margin-left:1em;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post ol {&lt;br /&gt;
list-style-type:decimal;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post cite {&lt;br /&gt;
margin-left:1em;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;textarea {&lt;br /&gt;
width:100%;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;You must now have something more readable:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/basic-post-styling.jpg" alt="Basic Post Formating" /&gt;&lt;/p&gt;
&lt;h2&gt;Meta data&lt;/h2&gt;
&lt;p&gt;To stick to our PSD layout, we must move and edit the meta data informations, mainly the publication date and categories, to the top of the post area, just below the post title.&lt;/p&gt;
&lt;p&gt;Open «/wordpress/wp-content/themes/default/single.php» and add the following code just after&lt;code&gt; the_title()&lt;/code&gt; call&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;h2&gt;&lt;?php the_title(); ?&gt;&lt;/h2&gt;
&lt;div class="post-meta"&gt;
Posted in&lt;br /&gt;
&lt;span&gt;&lt;?php the_category(', ') ?&gt;&lt;/span&gt; on&lt;br /&gt;
&lt;span&gt;&lt;?php the_time('l, F jS, Y') ?&gt;&lt;/span&gt; at&lt;br /&gt;
&lt;span&gt;&lt;?php the_time() ?&gt;&lt;/span&gt; by&lt;br /&gt;
&lt;span&gt;&lt;?php the_author_link(); ?&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Also remove the similar content in the &lt;code&gt;.postmetadata&lt;/code&gt; block then style the newly created publication information in «/wordpress/wp-content/themes/default/style.css».&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;/p&gt;
&lt;p&gt;.post-meta {&lt;br /&gt;
font-family:Georgia, &amp;#8220;Times New Roman&amp;#8221; ,serif;&lt;br /&gt;
font-style:italic;&lt;br /&gt;
font-size:14px;&lt;br /&gt;
margin-bottom:2em;&lt;br /&gt;
color: #888;&lt;br /&gt;
font-weight:bold;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post-meta span {&lt;br /&gt;
font-style:normal;&lt;br /&gt;
font-weight:normal;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s refresh our browser to see our style publication informations:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/publication-information-formating.jpg" alt="Publication information Formating" /&gt;&lt;/p&gt;
&lt;h2&gt;Comments Bubble&lt;/h2&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/comments-bubble-preview.png" alt="Comments Bubble Preview" /&gt;&lt;/p&gt;
&lt;p&gt;The comment bubble will be as easy to slice and code, hide everything that is not the bubble itself then make a tight selection around it and make a merged copy (shift+ctrl+c) of it.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/comments-bubble-selection.png" alt="Comments Bubble Selection" /&gt;&lt;/p&gt;
&lt;p&gt;Create a new Photoshop document (ctrl+N) (it should be at the good size) then paste the bubble and Save for the web &amp;amp; devices.&lt;/p&gt;
&lt;p&gt;Open «/wordpress/wp-content/themes/default/single.php» and add the following code just after our previous edition:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;h2&gt;&lt;?php the_title(); ?&gt;&lt;/h2&gt;
&lt;div class="post-meta"&gt;
Posted in&lt;br /&gt;
&lt;span&gt;&lt;?php the_category(', ') ?&gt;&lt;/span&gt; on&lt;br /&gt;
&lt;span&gt;&lt;?php the_time('l, F jS, Y') ?&gt;&lt;/span&gt; at&lt;br /&gt;
&lt;span&gt;&lt;?php the_time() ?&gt;&lt;/span&gt; by&lt;br /&gt;
&lt;span&gt;&lt;?php the_author_link(); ?&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&amp;lt;div class=&amp;#8221;comments-count&amp;#8221;&amp;gt;&lt;br /&gt;
&amp;lt;?php comments_number(&amp;#8216;No Comments&amp;#8217;, &amp;#8216;One Comment&amp;#8217;, &amp;#8216;% Comments&amp;#8217; );?&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Finally apply relevant CSS rules to this new &lt;code&gt;div.comments-count&lt;/code&gt; element :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;/p&gt;
&lt;p&gt;.entry {&lt;br /&gt;
position: relative;&lt;/p&gt;
&lt;p&gt;}&lt;br /&gt;
.entry .comments-count {&lt;br /&gt;
background:transparent url(images/comments-bubble.png) no-repeat scroll 0 0;&lt;br /&gt;
color:#FFFFFF;&lt;br /&gt;
height:37px;&lt;br /&gt;
position:absolute;&lt;br /&gt;
right:0;&lt;br /&gt;
font-size:12px;&lt;br /&gt;
text-align:center;&lt;br /&gt;
top:-32px;&lt;br /&gt;
width:110px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;h2&gt;Post image&lt;/h2&gt;
&lt;p&gt;To finish the content area, we need to add two elements, the post image and the attached ribbon graphical element. To do so we will make use of WordPress custom fields. Slice the illustrative image from the PSD layout and save it in «/wordpress/wp-content/themes/default/default-post-image.jpg». Needless to say that making use of such feature generate a little bit more work when writing new posts.&lt;/p&gt;
&lt;p&gt;Edit the post you are currently using as master then add the following informations in the Custom Fields area and update the post, or whatever is relevant to your installation path.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/custom-field.jpg" alt="Custom fields settings" /&gt;&lt;/p&gt;
&lt;p&gt;To get benefit from this new information, we will make use of the &lt;code&gt;get_post_meta()&lt;/code&gt; function. Slice &amp;amp; save the illustrative image&amp;#8217;s ribbon and shadow then open «/wordpress/wp-content/themes/default/single.php».&lt;/p&gt;
&lt;p&gt;Add the following snippet just above &lt;code&gt;the_content()&lt;/code&gt; call:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;?php if (get_post_meta(get_the_ID(), 'post_image', true) != '') {?&gt;&lt;/p&gt;
&lt;p class="post-image"&gt;
&lt;span class="ribbon"&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;img src="&lt;?php echo get_post_meta(get_the_ID(), 'post_image', true); ?&gt;&amp;#8221; alt=&amp;#8221;&lt;?php the_title(); ?&gt;&amp;#8221; width=&amp;#8221;630&amp;#8243; /&gt;&lt;/p&gt;
&lt;div class="post-image-shadow"&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;?php } ?&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;This is some additional markup conditioned by the presence of a &lt;code&gt;post_image&lt;/code&gt; custom field in the post currently displayed. Basically, if there is no image associated with the post then do not display this part.&lt;em&gt; As an exercise, you could also try an implement a default image to display in place of the &lt;code&gt;post_image&lt;/code&gt; custom field.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Add the corresponding CSS formating and positioning in the stylesheets file :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;/p&gt;
&lt;p&gt;.post-image {&lt;br /&gt;
position: relative;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post-image img {&lt;br /&gt;
border:1px solid #FFFFFF;&lt;br /&gt;
padding:0;&lt;br /&gt;
margin-bottom:0;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.ribbon {&lt;br /&gt;
background:transparent url(images/vertical-ribbon.png) no-repeat scroll center center;&lt;br /&gt;
height:100%;&lt;br /&gt;
left:-28px;&lt;br /&gt;
position:absolute;&lt;br /&gt;
width:44px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.post-image-shadow {&lt;br /&gt;
background:transparent url(images/post-image-shadow.png) no-repeat scroll center top;&lt;br /&gt;
height:44px;&lt;br /&gt;
width:100%;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;The completed post design should now looks like this in your browser:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/completed-post-design.jpg" alt="Completed post design" /&gt;&lt;/p&gt;
&lt;h2&gt;Author box&lt;/h2&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/author-box.jpg" alt="Author box" /&gt;&lt;/p&gt;
&lt;p&gt;Open «/wordpress/wp-content/themes/default/single.php» in your favorite editor and place your cursor just before the &lt;code&gt;comments_template()&lt;/code&gt; call. Paste the following code:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div class="hr"&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;/div&gt;
&lt;div id="author-bio-container"&gt;
&lt;h3&gt;&lt;?php _e('About the Author');?&gt;&lt;/h3&gt;
&lt;div class="author vcard"&gt;
&lt;div class="user-avatar"&gt;&lt;?php&lt;br /&gt;
echo get_avatar(get_the_author_meta('ID'), $size='64', $default = get_option('home') . 'http://static.moblur.org/shinylittlething.com//wp-content/themes/default/images/avatar.png'); ?&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p id="author-bio"&gt;
&lt;?php&lt;br /&gt;
the_author_meta('description');&lt;br /&gt;
?&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="clear"&gt;&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;This is straight forward, display an horizontal line, display the header then display the author&amp;#8217;s avatar and description. Edit the existing headers rule :&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
.post h2, .post h3, .post h4, .post h5, .post h6,&lt;br /&gt;
h3#comments, #comments-description, #respond h3,&lt;br /&gt;
&lt;strong&gt;#author-bio, #author-bio-container h3&lt;/strong&gt; {&lt;br /&gt;
color:#333333;&lt;br /&gt;
font-family:Georgia, &amp;#8220;Times New Roman&amp;#8221; ,serif;&lt;br /&gt;
font-style:italic;&lt;br /&gt;
margin-bottom:10px;&lt;br /&gt;
height:32px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Then add the following rules to format the newly created markup:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
.author {&lt;br /&gt;
float:left;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.author .user-avatar {&lt;br /&gt;
margin-right:42px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#author-bio {&lt;br /&gt;
font-size:12px;&lt;br /&gt;
font-style:italic;&lt;br /&gt;
line-height:1.5em;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;And we are done for this simple element.&lt;/p&gt;
&lt;h2&gt;Comments area&lt;/h2&gt;
&lt;p&gt;The slicing and coding will become a little it heavier in this step, we will adapt the existing «/wordpress/wp-content/themes/default/comments.php» to fit our needs.&lt;/p&gt;
&lt;p&gt;Add a couple new selectors to the HTML Headers rules:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
.post h2, .post h3, .post h4, .post h5, .post h6, &lt;strong&gt;h3#comments, #comments-description&lt;/strong&gt; {&lt;br /&gt;
color:#333333;&lt;br /&gt;
font-family:Georgia, &amp;#8220;Times New Roman&amp;#8221; ,serif;&lt;br /&gt;
font-style:italic;&lt;br /&gt;
margin-bottom:10px;&lt;br /&gt;
height:32px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Edit the text to fit the PSD layout by replacing the following code&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;h3 id="comments"&gt;&lt;?php comments_number('No Responses', 'One Response', '% Responses' );?&gt; to “&lt;?php the_title(); ?&gt;”&lt;/h3&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;by&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;h3 id="comments"&gt;Comments (&lt;?php comments_number('0', '1', '%' );?&gt;) &lt;span&gt;&lt;a href="#respond"&gt;Participate!&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Then add the description line&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;span id="comments-description"&gt;Take a look at the responses we&amp;#8217;ve had to this article.&lt;/span&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Apply some CSS rules to the newly introduced elements.&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;/p&gt;
&lt;p&gt;#comments-description {&lt;br /&gt;
font-weight:bold;&lt;br /&gt;
color:#666;&lt;br /&gt;
font-size:14px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;h3#comments {&lt;br /&gt;
margin-bottom:0;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;h3#comments span {&lt;br /&gt;
float:right;&lt;br /&gt;
font-size:14px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;h2&gt;Comments boxes&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s analyze our comment box, there&amp;#8217;s a custom default avatar that is larger (64 x 64px) than the WordPress default one and the user name and comment are framed in a comic like bubble. Nothing to be scared of.&lt;/p&gt;
&lt;p&gt;At this point you should know how to slice a PSD layout, I&amp;#8217;ll not explain further how to slice the parts (default avatar, left arrow and horizontal line) we will need in this step, let&amp;#8217;s instead focus on code. Open «/wordpress/wp-content/themes/default/functions.php» and delete everything under the&lt;code&gt; register_sidebar&lt;/code&gt; conditional test and add the following function :&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
function shinytheme_comment($comment, $args, $depth) {&lt;br /&gt;
$GLOBALS['comment'] = $comment;&lt;br /&gt;
$urlHome = get_option(&amp;#8216;home&amp;#8217;) . &amp;#8216;/wp-content/themes/default/images/&amp;#8217;;&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;li &lt;?php comment_class(); ?&gt; id=&amp;#8221;li-comment-&lt;?php comment_ID() ?&gt;&amp;#8220;&gt;
&lt;div id="comment-&lt;?php comment_ID(); ?&gt;&amp;#8220;&gt;&lt;/p&gt;
&lt;div class="comment-author vcard"&gt;
&lt;div class="user-avatar"&gt;&lt;?php echo get_avatar($comment, $size='64', $default = $urlHome . 'avatar.png'); ?&gt;&lt;/div&gt;
&lt;div class="reply"&gt;
&lt;?php comment_reply_link(array_merge( $args, array('depth' =&gt; $depth, &amp;#8216;max_depth&amp;#8217; =&gt; $args['max_depth']))) ?&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="comment-text"&gt;
&lt;div class="left-arrow"&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;/div&gt;
&lt;div class="comment-meta commentmetadata"&gt;
&lt;?php comment_author_link() ?&gt;&lt;?php _e('&amp;amp;amp;amp;amp;amp;amp;nbsp;said:&amp;amp;amp;amp;amp;amp;amp;nbsp;');?&gt;
&lt;/div&gt;
&lt;p&gt;&lt;?php comment_text() ?&gt;&lt;br /&gt;
&lt;span&gt;&lt;?php comment_date(__('l, F jS, Y')) ?&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;?php comment_time(__('H:i')) ?&gt;&lt;/span&gt;&lt;br /&gt;
&lt;?php if ($comment-&gt;comment_approved == &amp;#8217;0&amp;#8242;) : ?&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;?php _e('Your comment is awaiting approval.'); ?&gt;&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;?php endif; ?&gt;
&lt;/div&gt;
&lt;div class="clear"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;?php }&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;This function will be used as a replacement of the WordPress default comment display handling. Let's register it. Open «/wordpress/wp-content/themes/default/comments.php» then replace the &lt;code&gt;wp_list_comments&lt;/code&gt; call by this one :&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;ol class="commentlist"&gt;
&lt;?php&lt;br /&gt;
wp_list_comments('type=all&amp;amp;amp;amp;amp;amp;amp;callback=shinytheme_comment');&lt;br /&gt;
?&gt;
&lt;/ol&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;This instruction simply overrides the default WordPress comments display by a custom callback function.&lt;/p&gt;
&lt;p&gt;All what is left concerning the comment boxes is the CSS. In «/wordpress/wp-content/themes/default/style.css», add the following rules:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
.comment-author {&lt;br /&gt;
float:left;&lt;br /&gt;
margin-right:10px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.comment-text {&lt;br /&gt;
background-color:#E9E9E9;&lt;br /&gt;
border:1px solid #FFFFFF;&lt;br /&gt;
margin-bottom:30px;&lt;br /&gt;
margin-left:100px;&lt;br /&gt;
padding:10px;&lt;br /&gt;
position:relative;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.comment-text span {&lt;br /&gt;
font-size:12px;&lt;br /&gt;
color: #666;&lt;/p&gt;
&lt;p&gt;}&lt;br /&gt;
.clear {&lt;br /&gt;
clear:both;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.left-arrow {&lt;br /&gt;
background:transparent url(images/left-arrow.png) no-repeat scroll center top;&lt;br /&gt;
height:26px;&lt;br /&gt;
left:-15px;&lt;br /&gt;
position:absolute;&lt;br /&gt;
top:3px;&lt;br /&gt;
width:19px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.user-avatar {&lt;br /&gt;
border: 1px solid #aaa;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.hr {&lt;br /&gt;
background:transparent url(images/hr.png) no-repeat scroll center top;&lt;br /&gt;
height:2px;&lt;br /&gt;
margin:20px;&lt;br /&gt;
width:100%;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;And we are done, let's take a quick look at the result:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/finished-comment-boxes.jpg" alt="Finished Comment Boxes" /&gt;&lt;/p&gt;
&lt;h2&gt;Comment form&lt;/h2&gt;
&lt;p&gt;We will now style the comment form to match as closely as possible our PSD layout.&lt;/p&gt;
&lt;p&gt;Open «/wordpress/wp-content/themes/default/style.css» and move the textarea line above the&lt;code&gt; is_user_logged_in()&lt;/code&gt; call:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;p&gt;&lt;textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"&gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;p&gt;&lt;?php if ( is_user_logged_in() ) : ?&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Add the user (or default if not logged) avatar just inside the &lt;code&gt;form#commentform&lt;/code&gt; element:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div class="comment-author vcard"&gt;
&lt;div class="user-avatar"&gt;&lt;?php&lt;br /&gt;
global $current_user;&lt;br /&gt;
get_currentuserinfo();&lt;br /&gt;
echo get_avatar($current_user-&gt;ID, $size='64', $default = get_option('home') . 'http://static.moblur.org/shinylittlething.com//wp-content/themes/default/images/avatar.png'); ?&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Wrap the rest in a &lt;code&gt;div#comment-fields&lt;/code&gt; element:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div id="comment-fields"&gt;
&lt;p&gt;
&lt;span class="left-arrow-white"&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;textarea name="comment" id="comment" rows="10" tabindex="4"&gt;&lt;/textarea&gt;
&lt;/p&gt;
&lt;p&gt;&lt;?php if ( is_user_logged_in() ) : ?&gt;&lt;/p&gt;
&lt;p&gt;Logged in as &lt;a href="&lt;?php echo get_option('siteurl'); ?&gt;/wp-admin/profile.php"&gt;&lt;?php echo $user_identity; ?&gt;&lt;/a&gt;. &lt;a href="&lt;?php echo wp_logout_url(get_permalink()); ?&gt;" title="Log out of this account"&gt;Log out &amp;amp;amp;amp;amp;amp;amp;raquo;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;?php else : ?&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="text" name="author" id="author" value="&lt;?php echo esc_attr($comment_author); ?&gt;" size="22" tabindex="1" &lt;?php if ($req) echo "aria-required='true'"; ?&gt; /&gt;&lt;br /&gt;
&lt;label for="author"&gt;&lt;small&gt;Name &lt;?php if ($req) echo "(required)"; ?&gt;&lt;/small&gt;&lt;/label&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="text" name="email" id="email" value="&lt;?php echo esc_attr($comment_author_email); ?&gt;" size="22" tabindex="2" &lt;?php if ($req) echo "aria-required='true'"; ?&gt; /&gt;&lt;br /&gt;
&lt;label for="email"&gt;&lt;small&gt;Mail (will not be published) &lt;?php if ($req) echo "(required)"; ?&gt;&lt;/small&gt;&lt;/label&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="text" name="url" id="url" value="&lt;?php echo esc_attr($comment_author_url); ?&gt;" size="22" tabindex="3" /&gt;&lt;br /&gt;
&lt;label for="url"&gt;&lt;small&gt;Website&lt;/small&gt;&lt;/label&gt;&lt;/p&gt;
&lt;p&gt;&lt;?php endif; ?&gt;&lt;/p&gt;
&lt;p id="submit-container"&gt;&lt;input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" /&gt;&lt;br /&gt;
&lt;?php comment_id_fields(); ?&gt;
&lt;/p&gt;
&lt;p&gt;&lt;?php do_action('comment_form', $post-&gt;ID); ?&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;And format the elements using CSS:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#comment-fields {&lt;br /&gt;
float:left;&lt;br /&gt;
margin-left:22px;&lt;br /&gt;
width:522px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#comment-fields p {&lt;br /&gt;
position:relative;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#comment, #author, #email, #url{&lt;br /&gt;
border:1px solid #999999;&lt;br /&gt;
margin-bottom:20px;&lt;br /&gt;
width:505px;&lt;br /&gt;
padding:10px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.left-arrow-white {&lt;br /&gt;
background:transparent url(images/left-arrow-white.png) no-repeat scroll center top;&lt;br /&gt;
height:26px;&lt;br /&gt;
left:-14px;&lt;br /&gt;
position:absolute;&lt;br /&gt;
top:6px;&lt;br /&gt;
width:19px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;You should get something very similar to the following screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/comments-form-early-formating.jpg" alt="Comments Form Early Formating" /&gt;&lt;/p&gt;
&lt;p&gt;Some work's left in this area. Labels should appear inside the inputs and the submit button needs a background image.&lt;/p&gt;
&lt;p&gt;Here is the content of the &lt;code&gt;div#comments-fields&lt;/code&gt; element after a bit editing and Javascript magic:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div id="comment-fields"&gt;
&lt;p&gt;
&lt;span class="left-arrow-white"&gt;&amp;amp;amp;amp;amp;amp;amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;textarea name="comment" id="comment" rows="10" tabindex="4"&lt;br /&gt;
onfocus="javascript:if(this.value == 'What\\'s on your mind ?'){this.value=''};"&lt;br /&gt;
onblur="javascript:if(this.value==''){this.value='What\\'s on your mind ?'}"&lt;br /&gt;
&gt;What's on your mind ?&lt;/textarea&gt;
&lt;/p&gt;
&lt;p&gt;&lt;?php if ( is_user_logged_in() ) : ?&gt;&lt;/p&gt;
&lt;p&gt;Logged in as &lt;a href="&lt;?php echo get_option('siteurl'); ?&gt;/wp-admin/profile.php"&gt;&lt;?php echo $user_identity; ?&gt;&lt;/a&gt;. &lt;a href="&lt;?php echo wp_logout_url(get_permalink()); ?&gt;" title="Log out of this account"&gt;Log out &amp;amp;amp;amp;amp;amp;amp;raquo;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;?php else : ?&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="text" name="author" id="author"&lt;br /&gt;
onfocus="javascript:if(this.value == 'Your name &lt;?php if ($req) echo "(required)"; ?&gt;'){this.value=''};"&lt;br /&gt;
onblur="javascript:if(this.value==''){this.value='Your name &lt;?php if ($req) echo "(required)"; ?&gt;'}"&lt;br /&gt;
value="&lt;?php echo (esc_attr($comment_author))==''?'Your name ' . (($req)?"(required)":""):esc_attr($comment_author); ?&gt;"&lt;br /&gt;
size="22" tabindex="1" &lt;?php if ($req) echo "aria-required='true'"; ?&gt; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;input type="text" name="email" id="email"&lt;br /&gt;
onfocus="javascript:if(this.value == 'Mail (will not be published) &lt;?php if ($req) echo "(required)"; ?&gt;'){this.value=''};"&lt;br /&gt;
onblur="javascript:if(this.value==''){this.value='Mail (will not be published) &lt;?php if ($req) echo "(required)"; ?&gt;'}"&lt;br /&gt;
value="&lt;?php echo (esc_attr($comment_author_email))==''?'Mail (will not be published) ' .(($req)?"(required)":""):esc_attr($comment_author_email); ?&gt;"&lt;br /&gt;
size="22" tabindex="2" &lt;?php if ($req) echo "aria-required='true'"; ?&gt; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;input type="text" name="url" id="url"&lt;br /&gt;
onfocus="javascript:if(this.value == 'Website'){this.value=''};"&lt;br /&gt;
onblur="javascript:if(this.value==''){this.value='Website'}"&lt;br /&gt;
value="&lt;?php echo (esc_attr($comment_author_url))==''?'Website':esc_attr($comment_author_url); ?&gt;"&lt;br /&gt;
size="22" tabindex="3" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;?php endif; ?&gt;&lt;/p&gt;
&lt;p id="submit-container"&gt;&lt;input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" /&gt;&lt;br /&gt;
&lt;?php comment_id_fields(); ?&gt;
&lt;/p&gt;
&lt;p&gt;&lt;?php do_action('comment_form', $post-&gt;ID); ?&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Nothing especially hard to understand here, labels strings have been moved into inputs values and two javascript events have been added, let me explain this a bit further. &lt;code&gt;onFocus&lt;/code&gt; &amp;amp;&lt;code&gt; onBlur&lt;/code&gt; events are triggered when a user respectively enters or leaves an html field. The actions are rather simple too, it reads like this in pseudo code:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
onFocus, we clear the field so the user don't have to:&lt;/p&gt;
&lt;p&gt;IF my.value == 'something' THEN&lt;br /&gt;
clear my.value&lt;br /&gt;
FI&lt;/p&gt;
&lt;p&gt;onBlur, we reset the field to a known state so the onFocus event could be triggered again&lt;/p&gt;
&lt;p&gt;IF my.value is empty THEN&lt;br /&gt;
my.value = 'something'&lt;br /&gt;
FI&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;That's all for javascript, we could have go for some jQuery event binding too. I love jQuery, but I couldn't find any good argument for this particular usage apart from being unobtrusive. Anyway here the unobtrusive equivalent to our snippets:&lt;/p&gt;
&lt;p&gt;[sourcecode language='javascript']&lt;br /&gt;
$(document).ready(function(){&lt;br /&gt;
$("#author").&lt;br /&gt;
bind('focus', function(){&lt;br /&gt;
if($(this).val() == "Your name") {&lt;br /&gt;
$(this).val('');&lt;br /&gt;
}&lt;br /&gt;
}).&lt;br /&gt;
bind('blur', function(){&lt;br /&gt;
if($(this).val() == "") {&lt;br /&gt;
$(this).val('Your name');&lt;br /&gt;
}&lt;br /&gt;
});&lt;/p&gt;
&lt;p&gt;/* Rinse, repeat for other fields. */&lt;br /&gt;
});&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;The only tricky part resides in fact, in the values filled using PHP. It might be confusing to beginners because it makes use in some cases of 2 ternary operations. Let's decompose this:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
echo (esc_attr($comment_author))==''?'Your name ' . (($req)?"(required)":""):esc_attr($comment_author);&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Is equivalent to :&lt;/p&gt;
&lt;p&gt;[sourcecode language='javascript']&lt;br /&gt;
if (esc_attr($comment_author) == '') {&lt;br /&gt;
echo 'Your name ';&lt;br /&gt;
if($req != '') {&lt;br /&gt;
echo '(required)';&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
else {&lt;br /&gt;
echo esc_attr($comment_author)&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Ternary operators are bottled awesomeness when it comes to one liners.&lt;/p&gt;
&lt;p&gt;Onto the submit button. You have two choices, going for a full alpha channel PNG24 version of it or a matted version in PNG8.&lt;/p&gt;
&lt;p&gt;Each solution have it's own downside I'll explain them both and you'll have to choose by yourself what's better for your particular situation.&lt;/p&gt;
&lt;p&gt;PNG24 is more flexible, let's say you want to change the background of your main content area, your button will follow the flow and you will not have to slice it again until you completely change your layout. This has a cost, in terms of bytes this button will be about 10kbytes. Which is kind of huge a en element of this size.&lt;/p&gt;
&lt;p&gt;PNG8 on the other hand, will produce a smaller image, around 3kbytes, but you'll have to embed the background color information (Matte option in Photoshop Save for web &amp;amp; devices) thus limiting the uses for this graphical element and forcing you to re-export it each time you change it's background.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/alpha-channel-cost.jpg" alt="PNG24 vs. PNG8" /&gt;&lt;/p&gt;
&lt;p&gt;My choice will go to PNG24 and flexibility. So slice and export your button and style the &lt;code&gt;input#submit&lt;/code&gt; element:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#submit-container{&lt;br /&gt;
text-align:right;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#submit {&lt;br /&gt;
background:transparent url(images/add-comment.png) no-repeat scroll center top;&lt;br /&gt;
border:none;&lt;br /&gt;
height:68px;&lt;br /&gt;
text-indent:-100000px;&lt;br /&gt;
width:273px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;To finish this area off we yet have to change to form title which reads  «Leave a reply» to  «Participate!»&lt;br /&gt;
Once done, your are finished with the comments area and you should have something very similar to the&lt;br /&gt;
following screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/comments-final-formating.jpg" alt="Comments Final Formating" /&gt;&lt;/p&gt;
&lt;p&gt;And for logged in users :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/comments-final-formating-loggedin-users.jpg" alt="Comments Final Formating for Logged In Users " /&gt;&lt;/p&gt;
&lt;h2&gt;Header and Subscriptions&lt;/h2&gt;
&lt;p&gt;An important part if not the most, of every web design is the header. In our case it's composed of a logo with a tagline and the common subscriptions options you find on about every blog. We will edit the default header markup to fit our need. But first slice the PSD and save the following parts as files in «/wordpress/wp-content/themes/default/images/»:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Logo + tagline as 323 x 70px «logo.png»&lt;/li&gt;
&lt;li&gt;Header Background gradient as 1 x 115px  «inner-orange.png»&lt;/li&gt;
&lt;li&gt;Separator as 2 x 78px  «header-separator.png»&lt;/li&gt;
&lt;li&gt;Twitter Subscription as 48 x 60px «twitter-sub.png»&lt;/li&gt;
&lt;li&gt;eMail Subscription as 90 x 60px «email-sub.png»&lt;/li&gt;
&lt;li&gt;Twitter Subscription as 57 x 60px «rss-sub.png»&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Open «/wordpress/wp-content/themes/default/header.php» and replace the&lt;code&gt; div#header&lt;/code&gt; element by the following code :&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div id="header" role="banner"&gt;
&lt;div id="headerimg"&gt;
&lt;h1&gt;&lt;a href="&lt;?php echo get_option('home'); ?&gt;/"&gt;&lt;img height="70" width="321" src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/logo.png" alt="&lt;?php bloginfo('name'); ?&gt;" title="&lt;?php bloginfo('name'); ?&gt;"&lt;/a&gt;&lt;/h1&gt;
&lt;div id="subscriptions"&gt;
&lt;a href="http://twitter.com/ncrovatti"&gt;&lt;img src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/twitter-sub.png" alt="Subscribe via Twitter"/&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void();"&gt;&lt;img src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/email-sub.png" alt="Subscribe via Email"/&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="&lt;?php bloginfo('rss2_url'); ?&gt;"&gt;&lt;img src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/rss-sub.png" alt="Subscribe via RSS"/&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Nothing exceptional about the markup, try to keep a clean and as smaller as possible markup is my only advice. All elements layed out we need to style them, the logo must float on the left side of the header and the subscriptions at the exact opposite.&lt;/p&gt;
&lt;p&gt;You might have noticed the link for email subscription is a "do_nothing" Javascription function. We will get back to this later in this chapter.&lt;/p&gt;
&lt;p&gt;Be sure to check your the dimensions of your sliced images, depending on how you do it, you might not obtain the same size, thus involving a bit CSS editing. Anyway here the CSS for my slices of the headers elements:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#headerimg {&lt;br /&gt;
background:transparent url(images/inner-orange.png) repeat-x scroll center center;&lt;br /&gt;
height:115px;&lt;br /&gt;
margin:0 auto;&lt;br /&gt;
width:952px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#headerimg h1 {&lt;br /&gt;
float:left;&lt;br /&gt;
padding-top:20px;&lt;br /&gt;
padding-left:10px;&lt;br /&gt;
width:335px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#subscriptions {&lt;br /&gt;
background:transparent url(images/header-separator.png) no-repeat scroll center left;&lt;br /&gt;
float:right;&lt;br /&gt;
margin-top:26px;&lt;br /&gt;
text-align:right;&lt;br /&gt;
width:600px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Only three elements, &lt;code&gt;#headerimg&lt;/code&gt; is our container, it must be centered.&lt;br /&gt;
&lt;code&gt;#headerimg h1&lt;/code&gt; is the logo, it belong to the left side of &lt;code&gt;#headerimg&lt;/code&gt; and must have a width setup in order to avoid overlapping over the &lt;code&gt;#subscriptions&lt;/code&gt; elements, finally, the &lt;code&gt;#subscriptions&lt;/code&gt; element belonging to the right of the header section.&lt;/p&gt;
&lt;p&gt;All finished you should have a header section very similar to the following screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/header-formating.jpg" alt="Header Formating" /&gt;&lt;/p&gt;
&lt;h2&gt;ShinyTheme Options Page&lt;/h2&gt;
&lt;p&gt;Having a subscription for your twitter feed is great, it's a no brainer on any blog. But you do not want the people using your theme have to hack into the code just to add their Twitter account.&lt;/p&gt;
&lt;p&gt;We will now build the options page for our theme. The explained process will help you produce a clean, WordPress look &amp;amp; feel settings page for your theme. The only field I will explain is how to customize the blog's Twitter account for the corresponding subscription option.&lt;/p&gt;
&lt;p&gt;Everything starts in «/wordpress/wp-content/themes/default/function.php», at the top of the file, before the sidebar registering, add the following php code :&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
$themename = "ShinyTheme";&lt;br /&gt;
$shortname = "wpst";&lt;br /&gt;
$options = array (&lt;/p&gt;
&lt;p&gt;array(&lt;br /&gt;
"name" =&gt; "Subscription Settings",&lt;br /&gt;
"type" =&gt; "title"&lt;br /&gt;
),&lt;/p&gt;
&lt;p&gt;array(&lt;br /&gt;
"type" =&gt; "open"&lt;br /&gt;
),&lt;/p&gt;
&lt;p&gt;array(&lt;br /&gt;
"name" =&gt; "Twitter account",&lt;br /&gt;
"desc" =&gt; "Enter the twitter account related to your blog.",&lt;br /&gt;
"id"   =&gt; $shortname."_twitter_account",&lt;br /&gt;
"std"  =&gt; "",&lt;br /&gt;
"type" =&gt; "text"&lt;br /&gt;
),&lt;/p&gt;
&lt;p&gt;array(&lt;br /&gt;
"type" =&gt; "close"&lt;br /&gt;
)&lt;/p&gt;
&lt;p&gt;);&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$themename&lt;/code&gt; variable is the display name of our theme accross the whole WordPress installation.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$shortname&lt;/code&gt; is the prefix for all our custom options fields.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$options&lt;/code&gt; The options array's arrays can be read as template blocks
&lt;ul&gt;
&lt;li&gt;Index 0: The Title of the option page&lt;/li&gt;
&lt;li&gt;Index 1: The options opening. In our case it will correspond to a &lt;code&gt;table&lt;/code&gt; tag opening.&lt;/li&gt;
&lt;li&gt;Index 2: An (or more) option field.&lt;/li&gt;
&lt;li&gt;Index 3: The options closing. This is where we will close the &lt;code&gt;table&lt;/code&gt; tag opened&lt;br /&gt;
at opening stage.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Add the generic options handling function :&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;p&gt;function shinytheme_add_admin() {&lt;br /&gt;
global&lt;br /&gt;
$themename,&lt;br /&gt;
$shortname,&lt;br /&gt;
$options;&lt;/p&gt;
&lt;p&gt;if ($_GET['page'] == basename(__FILE__)) {&lt;br /&gt;
if ('save' == $_REQUEST['action']) {&lt;br /&gt;
foreach ($options as $value) {&lt;br /&gt;
update_option($value['id'], $_REQUEST[ $value['id']]);&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;foreach ($options as $value) {&lt;br /&gt;
if(isset($_REQUEST[$value['id']])) {&lt;br /&gt;
update_option($value['id'], $_REQUEST[ $value['id']]);&lt;br /&gt;
}&lt;br /&gt;
else {&lt;br /&gt;
delete_option($value['id']);&lt;br /&gt;
}&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;header("Location: themes.php?page=functions.php&amp;amp;amp;amp;amp;amp;amp;saved=true");&lt;br /&gt;
die();&lt;/p&gt;
&lt;p&gt;}&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;add_theme_page($themename." Settings", "".$themename." Settings", 'edit_themes', basename(__FILE__), 'shinytheme_admin');&lt;/p&gt;
&lt;p&gt;}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;This function saves the parameters filled in the options form of our theme settings admin page. If you want to add different action handling it's the function you have to hack into.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Here comes the Beast&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If there's a thing I dislike concerning WordPress admin pages, it's how the markup is handled. I mean, if I learned one thing in more than ten years of web working, it's to separate content from logic.&lt;br /&gt;
This is clearly not the case when you glance at the following admin settings function:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
function shinytheme_admin() {&lt;br /&gt;
global&lt;br /&gt;
$themename,&lt;br /&gt;
$shortname,&lt;br /&gt;
$options;&lt;/p&gt;
&lt;p&gt;if ($_REQUEST['saved']) {&lt;br /&gt;
echo '
&lt;div id="message" class="updated fade"&gt;
&lt;p&gt;&lt;strong&gt;'.$themename.' settings saved.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;';&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;?&gt;&lt;/p&gt;
&lt;div class="wrap"&gt;
&lt;div class="icon32" id="icon-options-general"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;h2&gt;&lt;?php echo $themename; ?&gt; settings&lt;/h2&gt;
&lt;form method="post"&gt;
&lt;p&gt;&lt;?php foreach ($options as $value) {&lt;/p&gt;
&lt;p&gt;switch ( $value['type'] ) {&lt;br /&gt;
case "open":&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;table class="form-table"&gt;
&lt;p&gt;&lt;?php&lt;br /&gt;
break;&lt;br /&gt;
case "close":&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;?php&lt;br /&gt;
break;&lt;br /&gt;
case "title":&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;h3&gt;&lt;?php echo $value['name']; ?&gt;&lt;/h3&gt;
&lt;p&gt;&lt;?php&lt;br /&gt;
break;&lt;br /&gt;
case 'text':&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;label for="&lt;?php echo $value['id']; ?&gt;"&gt;&lt;?php echo $value['name']; ?&gt;&lt;/label&gt;
&lt;/th&gt;
&lt;td&gt;
&lt;input class="regular-text" name="&lt;?php echo $value['id']; ?&gt;" id="&lt;?php echo $value['id']; ?&gt;" type="&lt;?php echo $value['type']; ?&gt;" value="&lt;?php if ( get_settings( $value['id'] ) != "") { echo get_settings( $value['id'] ); } else { echo $value['std']; } ?&gt;" /&gt;&lt;br /&gt;
&lt;span class="description"&gt;&lt;?php echo $value['desc']; ?&gt;&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;p&gt;&lt;?php&lt;br /&gt;
break;&lt;/p&gt;
&lt;p&gt;}&lt;br /&gt;
}&lt;br /&gt;
?&gt;&lt;/p&gt;
&lt;p class="submit"&gt;
&lt;input type="submit" value="Save Changes" class="button-primary" name="Submit"/&gt;&lt;br /&gt;
&lt;input type="hidden" name="action" value="save" /&gt;
&lt;/p&gt;
&lt;/form&gt;
&lt;p&gt;&lt;?php&lt;/p&gt;
&lt;p&gt;}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Anyway, it's how WordPress does things. As a side note, I've been greatly inspired from&lt;a href="http://blog.themeforest.net/Wordpress/create-an-options-page-for-your-Wordpress-theme/"&gt; this blog post&lt;/a&gt; concerning the whole theme admin page building, I just simplified the code, stripped out the inline CSS and applied the core WordPress stylesheets in order to keep unity accross the administration panels.&lt;/p&gt;
&lt;p&gt;One last thing to do is to actually register the admin function with WordPress itself:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
add_action('admin_menu', 'shinytheme_add_admin');&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;And we are (almost) done! The appearance box should now displays the link to our settings page:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/appearance-box.png" alt="Appearance Box" /&gt;&lt;/p&gt;
&lt;p&gt;The settings page itself:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/settings-page.png" alt="Settings Page" /&gt;&lt;/p&gt;
&lt;p&gt;It's clean, it blends nicely with the whole WordPress administration panels and it's simple. Yet we only have one option but I'm sure you got the picture.&lt;/p&gt;
&lt;p&gt;Now the time as come to make use of these specific informations in the ShinyTheme. Open «/wordpress/wp-content/themes/default/header.php» and add the following php code snippet just below the &lt;code&gt;wp_head()&lt;/code&gt; call:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
&lt;?&lt;br /&gt;
// Making options available in the current function&lt;br /&gt;
global $options;&lt;/p&gt;
&lt;p&gt;foreach ($options as $value) {&lt;br /&gt;
/*&lt;br /&gt;
Stores the result of get_settings() into a variable&lt;br /&gt;
to avoid multiple calls to the function&lt;br /&gt;
*/&lt;br /&gt;
$current_option = get_settings($value['id']);&lt;/p&gt;
&lt;p&gt;$$value['id'] = ($current_option === false) ? $value['std'] : $current_option;&lt;br /&gt;
}&lt;br /&gt;
?&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;The last line worth a little bit more explanation. It creates a new variable named after &lt;code&gt;$value['id']&lt;/code&gt; content (See &lt;a href="http://www.php.net/manual/en/language.variables.variable.php"&gt;Variable variables&lt;/a&gt; in PHP documentation). e.g: if &lt;code&gt;$value['id']&lt;/code&gt; value is «hello», this will create a new variable named $hello with either &lt;code&gt;$current_option&lt;/code&gt; or &lt;code&gt;$value['std']&lt;/code&gt; as value. Providing by this mean, a convenient way to handle default values by setting «std» in the &lt;code&gt;$options&lt;/code&gt; array.&lt;/p&gt;
&lt;p&gt;With that in mind it's not difficult to guess what variable will be assigned: &lt;code&gt;$wpst_twitter_account&lt;/code&gt; wich is the id parameter of the &lt;code&gt;$options&lt;/code&gt; array: &lt;code&gt;'id' =&amp;gt; $shortname."_twitter_account"&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;All you have to do now is to add a conditional verification to display or not the Twitter subscription image and link. Open «/wordpress/wp-content/themes/default/header.php» and edit the &lt;code&gt;div#header&lt;/code&gt; block:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div id="header" role="banner"&gt;
&lt;div id="headerimg"&gt;
&lt;h1&gt;&lt;a href="&lt;?php echo get_option('home'); ?&gt;/"&gt;&lt;img height="70" width="321" src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/logo.png" alt="&lt;?php bloginfo('name'); ?&gt;" title="&lt;?php bloginfo('name'); ?&gt;"&lt;/a&gt;&lt;/h1&gt;
&lt;div id="subscriptions"&gt;
&lt;?php if ($wpst_twitter_account != "") { ?&gt;&lt;br /&gt;
&lt;a href="http://twitter.com/&lt;?php echo $wpst_twitter_account;?&gt;"&gt;&lt;img src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/twitter-sub.png" alt="Subscribe via Twitter"/&gt;&lt;/a&gt;&lt;br /&gt;
&lt;?php }?&gt;&lt;br /&gt;
&lt;a href="javascript:void;"&gt;&lt;img src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/email-sub.png" alt="Subscribe via Email"/&gt;&lt;/a&gt;&lt;br /&gt;
&lt;a href="&lt;?php bloginfo('rss2_url'); ?&gt;"&gt;&lt;img src="&lt;?php bloginfo('stylesheet_directory'); ?&gt;/images/rss-sub.png" alt="Subscribe via RSS"/&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;And we are done for the theme options part. Let's look at the result:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/account-set-vs-unset.png" alt="Twitter Account: Set vs Unset" /&gt;&lt;/p&gt;
&lt;h2&gt;The Sidebar&lt;/h2&gt;
&lt;p&gt;Here is the preview of what we are going to build in this section:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/sidebar-headings-preview.png" alt="Sidebar headings preview" /&gt;&lt;/p&gt;
&lt;p&gt;But first, we need to setup our widgetizable sidebar accordingly to the PSD layout:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/sidebar-widgets-and-options.png" alt="Sidebar widgets and options" /&gt;&lt;/p&gt;
&lt;p&gt;To achieve the dotted effect on the sidebar headings we will not slice and export each heading separatly, nor we won't use any text replacement technique. Instead, we will use a pattern overlay applied over the headings, using CSS.&lt;/p&gt;
&lt;p&gt;Created a new Photoshop document 2 x 2px transparent background and using the background color of the sidebar, reproduce the following pattern :&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/pattern-overlay.png" alt="Pattern overlay" /&gt;&lt;/p&gt;
&lt;p&gt;And save it for the web as «pattern.png».&lt;/p&gt;
&lt;p&gt;Edit the &lt;code&gt;register_sidebar()&lt;/code&gt; function in «/wordpress/wp-content/themes/default/functions.php» to add a bit of markup (bolded in the following snippet) to the headings wrappers so we can hook in CSS.&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
register_sidebar(array(&lt;br /&gt;
'before_widget' =&gt; '
&lt;li id="%1$s" class="widget %2$s"&gt;',&lt;br /&gt;
'after_widget' =&gt; '&lt;/li&gt;
&lt;p&gt;',&lt;br /&gt;
'before_title' =&gt; '&lt;br /&gt;
&lt;h2 class="widgettitle"&gt;',&lt;br /&gt;
'after_title' =&gt; '&lt;strong&gt;&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;',&lt;br /&gt;
));&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;CSS formating and positioning&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
.widget {&lt;br /&gt;
margin-bottom:20px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.widgettitle {&lt;br /&gt;
background:transparent url(images/sidebar-separator.png) no-repeat scroll center bottom;&lt;br /&gt;
color:#333;&lt;br /&gt;
margin-bottom:10px;&lt;br /&gt;
padding-bottom:5px;&lt;br /&gt;
position:relative;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.overlay {&lt;br /&gt;
background:transparent url(images/pattern.png) repeat scroll 0 0;&lt;br /&gt;
position:absolute;&lt;br /&gt;
height:1em;&lt;br /&gt;
left:0;&lt;br /&gt;
top:0;&lt;br /&gt;
width:100%;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Here we are giving some breath to the widgets, and setting the newly created &lt;code&gt;span&lt;/code&gt; elements on&lt;br /&gt;
top of the heading text. The effect is complete. You might want to try different patterns and colors in your&lt;br /&gt;
own designs.&lt;/p&gt;
&lt;p&gt;Here are some examples:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/pattern-experiment.png" alt="Pattern experiment" /&gt;&lt;/p&gt;
&lt;p&gt;Ok, nothing tricky anymore, let's style the rest of the sidebar:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#s {&lt;br /&gt;
border:1px solid #999;&lt;br /&gt;
padding:10px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#searchsubmit {&lt;br /&gt;
display:none;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#sidebar a {&lt;br /&gt;
color: #630;&lt;br /&gt;
text-decoration: underline;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;#sidebar ul li ul li	{&lt;br /&gt;
list-style-image:url(images/bullet.png);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;#sidebar ul li ul	{&lt;br /&gt;
margin-left: 20px;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Let's keep the CSS at minimal styling. Here's the result:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/sidebar-final-preview.png" alt="Sidebar final preview" /&gt;&lt;/p&gt;
&lt;h2&gt;The Footer&lt;/h2&gt;
&lt;p&gt;As is, wordpress comes with a default footer. Our PSD layout features rich content in this area. Let's completly rewrite the markup. Open «/wordpress/wp-content/themes/default/footer.php» and replace everything in &lt;code&gt;div#footer&lt;/code&gt; element by the following HTML markup:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div id="footer_container"&gt;
&lt;div class="footer_block separator"&gt;
&lt;h3&gt;About&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="footer_block separator"&gt;
&lt;h3&gt;Last Tweet&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="footer_block"&gt;
&lt;h3&gt;Elsewhere&lt;span class="overlay"&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;[/sourcecode]&lt;/p&gt;
&lt;p&gt;Apply the basic CSS for formating and positioning the floating boxes:&lt;/p&gt;
&lt;p&gt;[sourcecode language='css']&lt;br /&gt;
#footer_container {&lt;br /&gt;
width:960px;&lt;br /&gt;
margin: 0 auto;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.footer_block {&lt;br /&gt;
float:left;&lt;br /&gt;
margin-top:10px;&lt;br /&gt;
min-height:230px;&lt;br /&gt;
width:320px;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.footer_block.separator {&lt;br /&gt;
background:transparent url(images/footer-separator.png) no-repeat scroll right top;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;.footer_block h3 {&lt;br /&gt;
font-size:32px;&lt;br /&gt;
margin:10px;&lt;br /&gt;
padding:2px;&lt;br /&gt;
position:relative;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Glance at the result:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://static.moblur.org/shinylittlething.com//wp-content/uploads/2010/01/footer-preview.jpg" alt="Footer preview" /&gt;&lt;/p&gt;
&lt;p&gt;See this Last Tweet box ? We will make use of a third party library provided by Twitter itself to display our lastest Twitter activity, however, we will need to get the Twitter Account setting from ou theme in order to query Twitter.&lt;/p&gt;
&lt;p&gt;Due to variable scope, the newly created variables in the header won't be available in the footer, because it's two diferent functions and localy instancied variables stays local.&lt;/p&gt;
&lt;p&gt;To resolve this issue, I could have copy/pasted the corresponding snippet from the header to the footer, thus repeating a complete portion of the code, and almost doubling it's maintenance time. Needless to says that this is a very bad pratice. Instead we have the option to either register those variables in the global namespace or to register them in the wrapping php object.&lt;/p&gt;
&lt;p&gt;The cleaner way is always to not polute the global namespace. In our case we will add those variables in the &lt;code&gt;$wp&lt;/code&gt; object, wich is the WordPress main object. Yet this is polution of WordPress object, but, it's a small price to pay compared to the time saved.&lt;/p&gt;
&lt;p&gt;On to the code, open «/wordpress/wp-content/themes/default/header.php» and change the code that gets the custom options to this one:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
// Making options available in the current function&lt;br /&gt;
global $options;&lt;/p&gt;
&lt;p&gt;foreach ($options as $value) {&lt;br /&gt;
if($value['id'] == '') {continue;}&lt;br /&gt;
/*&lt;br /&gt;
Stores the result of get_settings() into a variable&lt;br /&gt;
to avoid multiple calls to the function&lt;br /&gt;
*/&lt;br /&gt;
$current_option = get_settings($value['id']);&lt;br /&gt;
/* Save it in the Worpress oject to have this&lt;br /&gt;
information later in the script */&lt;br /&gt;
$wp-&gt;shinytheme[$value['id']] = ($current_option === false) ? $value['std'] : $current_option;&lt;br /&gt;
}&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;We must also change the manner we display this information to reflect the changes:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;br /&gt;
$wpst_twitter_account becomes : $wp-&gt;shinytheme['wpst_twitter_account']&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Back to the footer, add the following code in the "Last Tweet" column:&lt;/p&gt;
&lt;p&gt;[sourcecode language='php']&lt;/p&gt;
&lt;div class="author vcard"&gt;
&lt;a href="http://twitter.com/&lt;?php echo $wp-&gt;shinytheme[\'wpst_twitter_account\']; ?&gt;"&gt;&lt;img alt="Subscribe via Twitter" src="http://localhost:83/wp-content/themes/default/images/twitter-sub.png"/&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div id="tweet-box"&gt;
&lt;div id="twitter_update_list" &gt;
&lt;li&gt;&lt;em&gt;And all is quiet ...&lt;/em&gt;&lt;/li&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"&gt;&lt;/script&gt;&lt;br /&gt;
&lt;script type="text/javascript" src="http://twitter.com/statuses/user_timeline/&lt;?php echo $wpst_twitter_account; ?&gt;.json?callback=twitterCallback2&amp;amp;amp;amp;amp;amp;count=1"&gt;&lt;/script&gt;&lt;br /&gt;
&lt;?php }?&gt;&lt;br /&gt;
[/sourcecode]&lt;/p&gt;
&lt;p&gt;Everything is now setup. The Last Tweet box will display a small informative text in case of failwhale  or it will make a call to Twitter's server and display your last tweet.&lt;/p&gt;
&lt;h2&gt;Afterword&lt;/h2&gt;
&lt;p&gt;Worpress is such a great tool that I could go on talking about it for days. So I'll bring a consious ending to this tutorial. All I hope is that it helped you in some way. You may notice some mistakes I could have made. IF this is the case please contact me at nicolas dot crovatti at gmail dot com.&lt;/p&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F&amp;amp;title=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch&amp;amp;notes=Clean%20%26amp%3B%20Detailed%20PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch%0D%0AIn%20this%20tutorial%20I%27ll%20guide%20you%20in%20the%20process%20to%20transform%20a%20PhotoshopTM%20PSD%20template%20to%20a%20complete%20XHTML%20and%20CSS%20site%20build.%20In%20the%20process%20you%20will%20learn%20how%20to%20slice%20the%20PSD%2C%20how%20" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F&amp;amp;title=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F&amp;amp;title=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch%20-%20http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F&amp;amp;title=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F&amp;amp;t=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2010%2F01%2F16%2Fpsd-template-to-wordpress-theme-from-scratch%2F&amp;amp;t=PSD%20template%20to%20Wordpress%20Theme%20from%20Scratch" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2010/01/20/css-minification-on-the-fly/" title="CSS Minification on the Fly"&gt;CSS Minification on the Fly&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/" title=" Multiple file upload using jQuery and Ruby on Rails Tutorial"&gt; Multiple file upload using jQuery and Ruby on Rails Tutorial&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/" title="Enabling Dynamic Plugin Support for your JavaScript Application"&gt;Enabling Dynamic Plugin Support for your JavaScript Application&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience"&gt;7 jQuery Plugins to Really Enhance Users Experience&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/02/23/essential-web-based-tools-for-javascript-developers/" title="Essential Web-Based tools for JavaScript Developers"&gt;Essential Web-Based tools for JavaScript Developers&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=FHSc5XI1-aU:rBIsXqLbnA4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/FHSc5XI1-aU" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2010/01/16/psd-template-to-wordpress-theme-from-scratch/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2010/01/16/psd-template-to-wordpress-theme-from-scratch/feed/atom/" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2010/01/16/psd-template-to-wordpress-theme-from-scratch/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[Introducing twitterBatcher.com]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/kLXDf2tdbes/" />
		<id>http://blog.shinylittlething.com/?p=290</id>
		<updated>2009-08-18T13:44:02Z</updated>
		<published>2009-08-18T07:31:31Z</published>
		<category scheme="http://shinylittlething.com" term="MySelf" /><category scheme="http://shinylittlething.com" term="twitter" /><category scheme="http://shinylittlething.com" term="twitterBatcher" />		<summary type="html"><![CDATA[I&#8217;ve been working on a side project late weeks, let me introduce twitterBatcher.com! I made this app to satisfy a personal need concerning Twitter. I found it was convenient to upload a bunch of text containing twitter IDs (@accounts) rather than add them manually. It&#8217;s pretty handy on #FollowFriday to follow recommended friends of friends. [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/">&lt;p&gt;I&amp;#8217;ve been working on a side project late weeks, let me introduce&lt;strong&gt; &lt;a href="http://twitterBatcher.com"&gt;twitterBatcher.com&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I made this app to satisfy a personal need concerning &lt;strong&gt;&lt;a href="http://twitter.com"&gt;Twitter&lt;/a&gt;&lt;/strong&gt;. I found it was convenient to upload a bunch of text containing twitter IDs (@accounts) rather than add them manually.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s pretty handy on &lt;a href="http://mashable.com/2009/03/06/twitter-followfriday/"&gt;&lt;strong&gt;#FollowFriday&lt;/strong&gt;&lt;/a&gt; to follow recommended friends of friends.&lt;/p&gt;
&lt;p&gt;So, to solve this simple problem I made a simple app and voilà. twitterBatcher was born.&lt;/p&gt;
&lt;p&gt;In a few words like in a few thousand: &lt;a href="http://twitterBatcher.com"&gt;&lt;strong&gt;Try twitterBatcher now&lt;/strong&gt;&lt;/a&gt; !&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d also love to hear about your feedback ! Please leave comments to help me improve this twitter app!&lt;/p&gt;
&lt;p&gt;Update :  I just spawned a  dedicated &lt;a href="http://blog.twitterbatcher.com/introducing-twitterbatcher/"&gt;blog for twitterBatcher&lt;/a&gt;&lt;/p&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F&amp;amp;title=Introducing%20twitterBatcher.com&amp;amp;notes=I%27ve%20been%20working%20on%20a%20side%20project%20late%20weeks%2C%20let%20me%20introduce%20twitterBatcher.com%21%0D%0A%0D%0AI%20made%20this%20app%20to%20satisfy%20a%20personal%20need%20concerning%20Twitter.%20I%20found%20it%20was%20convenient%20to%20upload%20a%20bunch%20of%20text%20containing%20twitter%20IDs%20%28%40accounts%29%20rather%20than%20" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F&amp;amp;title=Introducing%20twitterBatcher.com" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F&amp;amp;title=Introducing%20twitterBatcher.com" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=Introducing%20twitterBatcher.com%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F&amp;amp;title=Introducing%20twitterBatcher.com" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F&amp;amp;t=Introducing%20twitterBatcher.com" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=Introducing%20twitterBatcher.com&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F18%2Fintroducing-twitterbatcher-com%2F&amp;amp;t=Introducing%20twitterBatcher.com" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Popular Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2010/01/20/css-minification-on-the-fly/" title="CSS Minification on the Fly"&gt;CSS Minification on the Fly&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/03/04/8-ajax-data-controls-and-effects-to-work-with-tables/" title="8 Ajax Data Controls and Effects to Work with Tables"&gt;8 Ajax Data Controls and Effects to Work with Tables&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience"&gt;7 jQuery Plugins to Really Enhance Users Experience&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/" title="Enabling Dynamic Plugin Support for your JavaScript Application"&gt;Enabling Dynamic Plugin Support for your JavaScript Application&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/" title=" Multiple file upload using jQuery and Ruby on Rails Tutorial"&gt; Multiple file upload using jQuery and Ruby on Rails Tutorial&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=kLXDf2tdbes:nWczE1UCV7I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/kLXDf2tdbes" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[PyGame Tutorials Update]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/KtxCDOZByos/" />
		<id>http://blog.shinylittlething.com/?p=280</id>
		<updated>2009-08-14T08:24:31Z</updated>
		<published>2009-08-14T08:24:31Z</published>
		<category scheme="http://shinylittlething.com" term="Pygame" /><category scheme="http://shinylittlething.com" term="Python" /><category scheme="http://shinylittlething.com" term="Tutorials" />		<summary type="html"><![CDATA[So,  I created a dedicated repository on github to host the source code of my PyGame Tutorials Serie You can clone all the tutorials using the following command : [sourcecode language='python'] git clone git://github.com/ncrovatti/Pygame-Tutorials.git [/sourcecode] You can also browse the complete sources and ressources from the github repository if you prefer. Eventually you will be [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/">&lt;p&gt;So,  I created a dedicated repository on &lt;a href="http://github.com"&gt;github&lt;/a&gt; to host the source code of my &lt;a href="http://blog.shinylittlething.com/pygame/"&gt;PyGame Tutorials Serie &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can clone all the tutorials using the following command :&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']

git clone git://github.com/ncrovatti/Pygame-Tutorials.git

[/sourcecode]&lt;/pre&gt;
&lt;p&gt;You can also &lt;a href="http://github.com/ncrovatti/Pygame-Tutorials/tree/master"&gt;browse the complete sources and ressources&lt;/a&gt; from the github repository if you prefer.&lt;/p&gt;
&lt;p&gt;Eventually you will be able to see the upcoming tutorials source code before their release.&lt;/p&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F&amp;amp;title=PyGame%20Tutorials%20Update&amp;amp;notes=So%2C%C2%A0%20I%20created%20a%20dedicated%20repository%20on%20github%20to%20host%20the%20source%20code%20of%20my%20PyGame%20Tutorials%20Serie%20%0D%0A%0D%0AYou%20can%20clone%20all%20the%20tutorials%20using%20the%20following%20command%20%3A%0D%0A%5Bsourcecode%20language%3D%27python%27%5D%0D%0A%0D%0Agit%20clone%20git%3A%2F%2Fgithub.com%2Fncrovatti%2FPygame-Tut" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F&amp;amp;title=PyGame%20Tutorials%20Update" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F&amp;amp;title=PyGame%20Tutorials%20Update" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=PyGame%20Tutorials%20Update%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F&amp;amp;title=PyGame%20Tutorials%20Update" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F&amp;amp;t=PyGame%20Tutorials%20Update" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=PyGame%20Tutorials%20Update&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F14%2Fpygame-tutorials-update%2F&amp;amp;t=PyGame%20Tutorials%20Update" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &amp;#8211; Event Handling"&gt;PyGame &amp;#8211; Event Handling&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &amp;#8211; Parallax Scrolling in 2D games"&gt;PyGame &amp;#8211; Parallax Scrolling in 2D games&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &amp;#8211; Take 2"&gt;PyGame and Animated Sprites &amp;#8211; Take 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites"&gt;PyGame and Animated Sprites&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing"&gt;Gama: Pythonic Shiny Thing&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=KtxCDOZByos:IvpJB45uNWQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/KtxCDOZByos" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/08/14/pygame-tutorials-update/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[PyGame &#8211; Event Handling]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/0R8F33V7qSc/" />
		<id>http://blog.shinylittlething.com/?p=257</id>
		<updated>2009-08-11T10:34:54Z</updated>
		<published>2009-08-11T10:34:54Z</published>
		<category scheme="http://shinylittlething.com" term="Programming" /><category scheme="http://shinylittlething.com" term="Pygame" /><category scheme="http://shinylittlething.com" term="Python" /><category scheme="http://shinylittlething.com" term="Animation" /><category scheme="http://shinylittlething.com" term="Events" /><category scheme="http://shinylittlething.com" term="Sprites" />		<summary type="html"><![CDATA[Introduction To continue further into my PyGame exploration articles and tutorials,  I&#8217;ll try to come up with a complete Shmup game as example. I already covered Animated sprites and Parallax Scrolling in 2D games as a start you can look at the PyGame tutorials list page to see them all. The goal of this article [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/08/11/pygame-event-handling/">&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;To continue further into my &lt;a href="http://www.pygame.org/"&gt;PyGame&lt;/a&gt; exploration articles and tutorials,  I&amp;#8217;ll try to come up with a complete Shmup game as example. I already covered &lt;strong&gt;&lt;a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/"&gt;Animated sprites&lt;/a&gt; &lt;/strong&gt;and &lt;strong&gt;&lt;a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/"&gt;Parallax Scrolling&lt;/a&gt; &lt;/strong&gt; in 2D games as a start you can look at the &lt;a href="http://blog.shinylittlething.com/pygame/"&gt;PyGame tutorials list&lt;/a&gt; page to see them all.&lt;/p&gt;
&lt;p&gt;The goal of this article is to combine what we have already learned into a single piece and add a new feature.  For instance, this application will be featuring parallax background, animated sprites and we will add  user inputs handling using PyGame&amp;#8217;s events management.&lt;br /&gt;
&lt;span id="more-257"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Credits&lt;/h3&gt;
&lt;p&gt;As usual, I like to deserve credit where it&amp;#8217;s due. I&amp;#8217;d like to thank the following artists for their awesome work :&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Clouds Brushes  by  &lt;a href="http://javierzhx.deviantart.com"&gt;&lt;strong&gt;~JavierZhX&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fighter by &lt;strong&gt;&lt;a href="http://prinzeugn.deviantart.com"&gt;~PrinzEugn&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Class evolution &amp;#8211; The Fighter&lt;/h3&gt;
&lt;p&gt;Like &lt;a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/"&gt;Parallax class&lt;/a&gt; inherited from our base &lt;a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/"&gt;AnimatedSprite class&lt;/a&gt; in the previous article, we will create a new &lt;strong&gt;Fighter class&lt;/strong&gt; (inheriting from AnimatedSprite class) and add specific members to handle it&amp;#8217;s particular behaviors.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s see some code first, I&amp;#8217;ll go into explaining it just after.&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
class Fighter(AnimatedSprite):
    def __init__(self, images, fps = 60):
        AnimatedSprite.__init__(self, images, fps)
        self.speed          = 600.
        self.default_speed  = self.speed
        self.location       = (100, RESOLUTION[1]/2)
        self.destination    = self.location
        self.stoping        = False
        '''
        The higher self.slowing_factor is,
        the longer it takes to stop a movement
        '''
        self.slowing_factor = 10.

        # Forward movement image - default
        self.image          = self._images[1]

    def event_handler(self, event):
      if event.type == KEYUP:
        self.stop(event.key)

      if event.type == KEYDOWN:
        self.move(pygame.key.name(event.key))  

    def update(self, t):
      # Slowing effect
      if self.stoping is True:
        self.speed -= self.speed/self.slowing_factor

      if self.stoping is False:
        self.speed = self.default_speed

    # Overriden to make use differently of the image's slices
    def move(self, direction):
      self.stoping = False
      W,H = RESOLUTION - self.image.get_size()
      x,y = self.location

      if direction == 'up':
        self.image = self._images[0]
        self.destination = Vector2(x, 0)

      elif direction == 'down':
        self.image = self._images[2]
        self.destination = Vector2(x, H)

      elif direction == 'left':
        self.destination = Vector2(0, y)

      elif direction == 'right':
        self.destination = Vector2(W, y)

    def stop(self, key):
      self.stoping = True
      W , H        = RESOLUTION - self.image.get_size()
      x , y        = self.destination
      xa, ya       = self.location
      w , h        = self.image.get_size()
      self.image   = self._images[1]

      # Stopping Y Axis Movements
      if key == K_UP:
        self.destination = Vector2(x, max(ya-h*self.slowing_factor, 0))

      if key == K_DOWN:
        self.destination = Vector2(x, min(ya+h*self.slowing_factor, H))

      # Stopping X Axis Movements
      if key == K_LEFT:
        self.destination = Vector2(max(xa-w*self.slowing_factor, 0), y)

      if key == K_RIGHT:
        self.destination = Vector2(min(xa+w*self.slowing_factor, W), y)

[/sourcecode]&lt;/pre&gt;
&lt;h4&gt;New Members&lt;/h4&gt;
&lt;ul&gt;
&lt;blockquote&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;stoping&lt;/em&gt; &lt;/strong&gt;(boolean) is used to know at update time if we are, err,  in the process of stoping our movement, wee need to be aware of this information to trigger a &lt;strong&gt;slowing down effect&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;slowing_factor&lt;/strong&gt;&lt;/em&gt; (float) determines the ship&amp;#8217;s inertia, the higher inertia is, the longer it takes to stop a movement.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;default_speed&lt;/strong&gt;&lt;/em&gt; (float) is used to keep track of the original sprite&amp;#8217;s speed and restore it when arrived to destination.&lt;/li&gt;
&lt;/blockquote&gt;
&lt;/ul&gt;
&lt;h4&gt;New Methods&lt;/h4&gt;
&lt;p&gt;event_handler method will make calls to appropriate method depending on the PyGame Event it received.&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
    def event_handler(self, event):
      if event.type == KEYUP:
        self.stop(event.key)

      if event.type == KEYDOWN:
        self.move(pygame.key.name(event.key))
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;The move method simply changes the destination of our fighter sprite according to the keyboards keys inputs it receives. Eventually, it also changes the fighter&amp;#8217;s image to an inclined version of it when moving lateraly (since we are running from left to right in this game, the lateral moves are Up and Down arrows).&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
    def move(self, direction):
      self.stoping = False
      W,H = RESOLUTION - self.image.get_size()
      x,y = self.location

      if direction == 'up':
        self.image = self._images[0]
        self.destination = Vector2(x,0)

      elif direction == 'down':
        self.image = self._images[2]
        self.destination = Vector2(x,H)

      elif direction == 'left':
        self.destination = Vector2(0,y)

      elif direction == 'right':
        self.destination = Vector2(W,y)
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;The stop method stops the sprite&amp;#8217;s movement according to keys releases and restore the default sprite image. To avoid the sprite&amp;#8217;s getting off the screen, we need to limit the coordinates to values comprised into  (RESOLUTION &amp;#8211; sprite&amp;#8217;s image size).&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
    def stop(self, key):
      self.stoping = True
      W , H        = RESOLUTION - self.image.get_size()
      x , y        = self.destination
      xa, ya       = self.location
      w , h        = self.image.get_size()
      self.image   = self._images[1]

      # Stopping Y Axis Movements
      if key == K_UP:
        self.destination = Vector2(x, max(ya-h*self.slowing_factor, 0))

      if key == K_DOWN:
        self.destination = Vector2(x, min(ya+h*self.slowing_factor, H))

      # Stopping X Axis Movements
      if key == K_LEFT:
        self.destination = Vector2(max(xa-w*self.slowing_factor, 0), y)

      if key == K_RIGHT:
        self.destination = Vector2(min(xa+w*self.slowing_factor, W), y)
[/sourcecode]&lt;/pre&gt;
&lt;h4&gt;Overriden Methods&lt;/h4&gt;
&lt;p&gt;The update method will be used to apply the slow down effect on movement stops.&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
    def update(self, t):
      # Slowing effect
      if self.stoping is True:
        self.speed -= self.speed/self.slowing_factor

      if self.stoping is False:
        self.speed = self.default_speed
[/sourcecode]&lt;/pre&gt;
&lt;h3&gt;Instantiating Entities&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s append a new instance of the Fighter class to the main loop to have it being updated, processed and rendered with other entities.&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
...
  fghtr  = Fighter(fighter, 60)
  elements.append(fghtr)
...
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Since other objects doesn&amp;#8217;t need to handle Events, we&amp;#8217;ll only add the fighter&amp;#8217;s event handling method call to the events polling loop.&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
  for event in pygame.event.get():
    fghtr.event_handler(event)
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;This way, our sprite will be able to receive input from player and it&amp;#8217;s location, destination and image will be accordingly updated and rendered.&lt;/p&gt;
&lt;h3&gt;Source and Ressources&lt;/h3&gt;
&lt;p&gt;The PyGame application is available for download here :&lt;/p&gt;
&lt;dl class="wp-caption aligncenter" style="width: 200px;"&gt;
&lt;dt class="wp-caption-dt"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/shinyblog-pygame-event-handling.tar.gz"&gt;&lt;img class="    " title="PyGame - Event Handling Demo" src="http://blog.shinylittlething.com/wp-includes/images/crystal/archive.png" alt="PyGame - Event Handling Demo" width="46" height="60" /&gt;&lt;/a&gt;&lt;/dt&gt;
&lt;dd class="wp-caption-dd" style="text-align: center;"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/shinyblog-pygame-event-handling.tar.gz"&gt;PyGame &amp;#8211; Event Handling Demo&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Dependencies: &lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel="nofollow" href="http://www.pygame.org/download.shtml"&gt;PyGame &amp;gt;= 1.7.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" href="http://code.google.com/p/gameobjects/"&gt;GameObjects &amp;gt;= 0.0.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Screenshot &amp;amp; Conclusion&lt;/h3&gt;
&lt;div id="attachment_275" class="wp-caption aligncenter" style="width: 310px"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/Capture-20.png"&gt;&lt;img class="size-medium wp-image-275" title="Capture-20" src="http://blog.shinylittlething.com/wp-content/uploads/2009/08/Capture-20-300x225.png" alt="Fighter in Action (click for full size)" width="300" height="225" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;Fighter in Action (click for full size)&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s what&amp;#8217;s closes this article. I hope it has been helpful in anyway to you. Provided code is not perfect at all and not optimized because like you eventually, I&amp;#8217;m still learning ;)&lt;/p&gt;
&lt;p&gt;In the next article I&amp;#8217;m planning to cover Fighter&amp;#8217;s firing abilities aka, &lt;em&gt;bullet hell&lt;/em&gt;. Stay tuned!&lt;/p&gt;
&lt;div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;"&gt;class Fighter(AnimatedSprite):&lt;br /&gt;
def __init__(self, images, fps = 60):&lt;br /&gt;
AnimatedSprite.__init__(self, images, fps)&lt;br /&gt;
self.speed                     = 600.&lt;br /&gt;
self.default_speed    = self.speed&lt;br /&gt;
self.location             = (100, RESOLUTION[1]/2)&lt;br /&gt;
self.destination         = self.location&lt;br /&gt;
self.stoping                = False&lt;br /&gt;
&amp;#8221;&amp;#8217;&lt;br /&gt;
The higher self.slowing_factor is,&lt;br /&gt;
the longer it takes to stop a movement&lt;br /&gt;
&amp;#8221;&amp;#8217;&lt;br /&gt;
self.slowing_factor = 10.&lt;/p&gt;
&lt;p&gt;# Forward movement image &amp;#8211; default&lt;br /&gt;
self.image                     = self._images[1]&lt;/p&gt;
&lt;p&gt;def event_handler(self, event):&lt;br /&gt;
if event.type == KEYUP:&lt;br /&gt;
pygame.event.pump()&lt;br /&gt;
pressed_keys = pygame.key.get_pressed()&lt;br /&gt;
if 1 not in pressed_keys:&lt;br /&gt;
self.stop(event.key)&lt;/p&gt;
&lt;p&gt;if event.type == KEYDOWN:&lt;br /&gt;
self.move(pygame.key.name(event.key))&lt;/p&gt;
&lt;p&gt;def update(self, t):&lt;br /&gt;
# Slowing effect&lt;br /&gt;
if self.stoping is True:&lt;br /&gt;
self.speed -= self.speed/self.slowing_factor&lt;/p&gt;
&lt;p&gt;if self.stoping is False:&lt;br /&gt;
self.speed = self.default_speed&lt;/p&gt;
&lt;p&gt;def move(self, direction):&lt;br /&gt;
# Overriden to make use differently of the image&amp;#8217;s slices&lt;br /&gt;
self.stoping = False&lt;br /&gt;
W,H = RESOLUTION &amp;#8211; self.image.get_size()&lt;br /&gt;
x,y = self.location&lt;/p&gt;
&lt;p&gt;if direction == &amp;#8216;up&amp;#8217;:&lt;br /&gt;
self.image = self._images[0]&lt;br /&gt;
self.destination = Vector2(x,0)&lt;/p&gt;
&lt;p&gt;elif direction == &amp;#8216;down&amp;#8217;:&lt;br /&gt;
self.image = self._images[2]&lt;br /&gt;
self.destination = Vector2(x,H)&lt;/p&gt;
&lt;p&gt;elif direction == &amp;#8216;left&amp;#8217;:&lt;br /&gt;
self.destination = Vector2(0,y)&lt;/p&gt;
&lt;p&gt;elif direction == &amp;#8216;right&amp;#8217;:&lt;br /&gt;
self.destination = Vector2(W,y)&lt;/p&gt;
&lt;p&gt;def stop(self, key):&lt;br /&gt;
self.stoping = True&lt;br /&gt;
W,H                 = RESOLUTION &amp;#8211; self.image.get_size()&lt;br /&gt;
x, y                 = self.destination&lt;br /&gt;
xa,ya             = self.location&lt;br /&gt;
w,h                 =    self.image.get_size()&lt;br /&gt;
self.image     = self._images[1]&lt;/p&gt;
&lt;p&gt;# Stopping Y Axis Movements&lt;br /&gt;
if key == K_UP:&lt;br /&gt;
self.destination = Vector2(x, max(ya-h*self.slowing_factor, 0))&lt;/p&gt;
&lt;p&gt;if key == K_DOWN:&lt;br /&gt;
self.destination = Vector2(x, min(ya+h*self.slowing_factor, H))&lt;/p&gt;
&lt;p&gt;# Stopping X Axis Movements&lt;br /&gt;
if key == K_LEFT:&lt;br /&gt;
self.destination = Vector2(max(xa-w*self.slowing_factor, 0), y)&lt;/p&gt;
&lt;p&gt;if key == K_RIGHT:&lt;br /&gt;
self.destination = Vector2(min(xa+w*self.slowing_factor, W), y)&lt;/p&gt;&lt;/div&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F&amp;amp;title=PyGame%20-%20Event%20Handling&amp;amp;notes=Introduction%0D%0ATo%20continue%20further%20into%20my%20PyGame%20exploration%20articles%20and%20tutorials%2C%C2%A0%20I%27ll%20try%20to%20come%20up%20with%20a%20complete%20Shmup%20game%20as%20example.%20I%20already%20covered%20Animated%20sprites%20and%20Parallax%20Scrolling%20%20in%202D%20games%20as%20a%20start%20you%20can%20look%20at%20the%20Py" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F&amp;amp;title=PyGame%20-%20Event%20Handling" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F&amp;amp;title=PyGame%20-%20Event%20Handling" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=PyGame%20-%20Event%20Handling%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F&amp;amp;title=PyGame%20-%20Event%20Handling" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F&amp;amp;t=PyGame%20-%20Event%20Handling" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=PyGame%20-%20Event%20Handling&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F11%2Fpygame-event-handling%2F&amp;amp;t=PyGame%20-%20Event%20Handling" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &amp;#8211; Take 2"&gt;PyGame and Animated Sprites &amp;#8211; Take 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites"&gt;PyGame and Animated Sprites&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &amp;#8211; Parallax Scrolling in 2D games"&gt;PyGame &amp;#8211; Parallax Scrolling in 2D games&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing"&gt;Gama: Pythonic Shiny Thing&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update"&gt;PyGame Tutorials Update&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=0R8F33V7qSc:Y0SnXXJ4wrc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/0R8F33V7qSc" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/08/11/pygame-event-handling/#comments" thr:count="23" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/08/11/pygame-event-handling/feed/atom/" thr:count="23" />
		<thr:total>23</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/08/11/pygame-event-handling/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[PyGame &#8211; Parallax Scrolling in 2D games]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/h0KZfnZdYa4/" />
		<id>http://blog.shinylittlething.com/?p=222</id>
		<updated>2009-08-10T14:23:40Z</updated>
		<published>2009-08-08T22:59:43Z</published>
		<category scheme="http://shinylittlething.com" term="Pygame" /><category scheme="http://shinylittlething.com" term="2D" /><category scheme="http://shinylittlething.com" term="Animation" /><category scheme="http://shinylittlething.com" term="parallax" /><category scheme="http://shinylittlething.com" term="scrolling" />		<summary type="html"><![CDATA[Hi fellow reader, to start this article let me define what Parallax Scrolling is : Parallax scrolling is a special scrolling technique in computer graphics, seen first in the 1982 arcade game Moon Patrol. In this pseudo-3D technique, background images move by the &#8220;camera&#8221; slower than foreground images, creating an illusion of depth in a [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/">&lt;p&gt;Hi fellow reader, to start this article let me define what Parallax Scrolling is :&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;a title="Wikipedia" href="http://en.wikipedia.org/wiki/Parallax_scrolling"&gt;&lt;strong&gt;Parallax scrolling&lt;/strong&gt;&lt;/a&gt; is a special scrolling technique in computer graphics, seen first in the 1982 arcade game Moon Patrol. In this pseudo-3D technique, background images move by the &amp;#8220;camera&amp;#8221; slower than foreground images, creating an illusion of depth in a 2D video game and adding to the immersion. The technique grew out of the multiplane camera technique used in traditional animation since the 1940s&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I will reuse and adapt the AnimatedSprite Class from my previous article &lt;a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/"&gt;PyGame and Animated Sprites &amp;#8211; Take 2&lt;/a&gt; and create a new Class named Parallax that inherits from AnimatedSprite.&lt;br /&gt;
&lt;span id="more-222"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
class AnimatedSprite(pygame.sprite.Sprite):
    def __init__(self, images, fps = 10):
      pygame.sprite.Sprite.__init__(self)

      # Animation
      self._start       = pygame.time.get_ticks()
      self._delay       = 1000 / fps
      self._last_update = 0
      self._frame       = 0
      self._images      = images

      self.image        = self._images[self._frame]

      # Movement
      self.location     = (0,0)
      self.destination  = (0,0)
      self.heading      = None
      self.speed        = 0.

    def process(self, t):
      if self.speed &gt; 0. and self.location != self.destination:
          destination              = self.destination - self.location
          distance                 = destination.get_length()
          self.heading             = destination.get_normalized()
          most_accurate_distance   = min(distance, t * self.speed)
          self.location           += most_accurate_distance * self.heading

    def update(self, t):
      if t - self._last_update &gt; self._delay:
        self._frame += 1
        if self._frame &gt;= len(self._images):
          self._frame = 0

        self.image = self._images[self._frame]
        self._last_update = t

    def render(self, screen):
      screen.blit(self.image, self.location)
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;To handle movements of our &lt;strong&gt;parallax&lt;/strong&gt; layers, we need to add some members to the base class. A movement is defined by the following variables :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;L&lt;/strong&gt;&lt;strong&gt;ocation,&lt;/strong&gt; that will be continuously updated when in movement. &lt;strong&gt;Destination&lt;/strong&gt;, in our case it will always be the same. &lt;strong&gt;Heading&lt;/strong&gt; to face the right direction, in our case the direction will never change, finally the movement&amp;#8217;s &lt;strong&gt;Speed&lt;/strong&gt; in pixel by second.&lt;/p&gt;
&lt;p&gt;To update all these values we need a &lt;strong&gt;process&lt;/strong&gt; method that will update each element to it&amp;#8217;s new location according to it&amp;#8217;s speed.&lt;/p&gt;
&lt;p&gt;For an analogy I&amp;#8217;d say that a &lt;strong&gt;parallax&lt;/strong&gt; is an image loop. To implement this loop we will override the default &lt;strong&gt;render&lt;/strong&gt; method in a &lt;strong&gt;Parallax&lt;/strong&gt; Class.&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
class Parallax(AnimatedSprite):
    def __init__(self, images, fps = 30):
        AnimatedSprite.__init__(self, images, fps)

    # Overridding the default render method
    def render(self, screen):
      w,h = self.image.get_size()
      x,y = self.location
      W,H = RESOLUTION

      # Reseting original image location
      if abs(x) == w:
          self.location = Vector2(0, y)
          x = 0

      # Blitting the image loop
      if x - w &lt; W:
        location = Vector2(x+w, y)
        screen.blit(self.image, location)

      screen.blit(self.image, self.location)
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Here is a quick schema to illustrate what is happening int the &lt;strong&gt;Parallax.render&lt;/strong&gt; method :&lt;/p&gt;
&lt;p&gt;Precisely when image A's right edge enters screen's clipping, blit another A image named A prime at location A.x + A.width.&lt;/p&gt;
&lt;div id="attachment_230" class="wp-caption aligncenter" style="width: 510px"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/parallax.png"&gt;&lt;img class="size-full wp-image-230" title="parallax" src="http://blog.shinylittlething.com/wp-content/uploads/2009/08/parallax.png" alt="Image Loop" width="500" height="296" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;Image Loop&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;When A's right edge is outside the screen clipping, reset it's location to initial position. A prime will automatically follow it.&lt;/p&gt;
&lt;div id="attachment_232" class="wp-caption aligncenter" style="width: 510px"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/parallax-21.png"&gt;&lt;img class="size-full wp-image-232" title="parallax-21" src="http://blog.shinylittlething.com/wp-content/uploads/2009/08/parallax-21.png" alt="Resetting the Loop" width="500" height="296" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;Resetting the Loop&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;We are done. A image will repeat itself continuously.&lt;/p&gt;
&lt;p&gt;Now to implement a &lt;strong&gt;parallax&lt;/strong&gt;, you need at least two layers. So you'll add layers with an increased speed setting following this simple rule : &lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;The closer an element is from the point of view, the faster it moves.&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I bundled a Pygame application for you to download. My implementation is far from being perfect and I'd be interested in knowing about how you do it.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;dl class="wp-caption aligncenter" style="width: 200px;"&gt;
&lt;dt class="wp-caption-dt"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/tutorial-0001.zip"&gt;&lt;img class="    " title="Pygame Parallax Scrolling Demo" src="http://blog.shinylittlething.com/wp-includes/images/crystal/archive.png" alt="Pygame Parallax Scrolling Demo" width="46" height="60" /&gt;&lt;/a&gt;&lt;/dt&gt;
&lt;dd class="wp-caption-dd" style="text-align: center;"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/tutorial-0001.zip"&gt;Pygame Parallax Scrolling Demo&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Dependencies: &lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel="nofollow" href="http://www.pygame.org/download.shtml"&gt;PyGame &amp;gt;= 1.7.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" href="http://code.google.com/p/gameobjects/"&gt;GameObjects &amp;gt;= 0.0.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Demo Preview:&lt;/strong&gt;&lt;br /&gt;
&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="560" height="340" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://www.youtube.com/v/Tn7bcWej8tY&amp;amp;hl=fr&amp;amp;fs=1&amp;amp;" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;embed type="application/x-shockwave-flash" width="560" height="340" src="http://www.youtube.com/v/Tn7bcWej8tY&amp;amp;hl=fr&amp;amp;fs=1&amp;amp;" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F&amp;amp;title=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games&amp;amp;notes=Hi%20fellow%20reader%2C%20to%20start%20this%20article%20let%20me%20define%20what%20Parallax%20Scrolling%20is%20%3A%0D%0AParallax%20scrolling%20is%20a%20special%20scrolling%20technique%20in%20computer%20graphics%2C%20seen%20first%20in%20the%201982%20arcade%20game%20Moon%20Patrol.%20In%20this%20pseudo-3D%20technique%2C%20background%20imag" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F&amp;amp;title=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F&amp;amp;title=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F&amp;amp;title=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F&amp;amp;t=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F08%2F08%2Fpygame-parallax-scrolling-in-2d-games%2F&amp;amp;t=PyGame%20-%20Parallax%20Scrolling%20in%202D%20games" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &amp;#8211; Take 2"&gt;PyGame and Animated Sprites &amp;#8211; Take 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &amp;#8211; Event Handling"&gt;PyGame &amp;#8211; Event Handling&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites"&gt;PyGame and Animated Sprites&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update"&gt;PyGame Tutorials Update&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing"&gt;Gama: Pythonic Shiny Thing&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=h0KZfnZdYa4:Ueub8Qes5-U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/h0KZfnZdYa4" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/feed/atom/" thr:count="5" />
		<thr:total>5</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[PyGame and Animated Sprites &#8211; Take 2]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/BC4r7pWFZUo/" />
		<id>http://blog.shinylittlething.com/?p=210</id>
		<updated>2009-07-23T07:06:46Z</updated>
		<published>2009-07-22T21:48:13Z</published>
		<category scheme="http://shinylittlething.com" term="Pygame" /><category scheme="http://shinylittlething.com" term="2D" /><category scheme="http://shinylittlething.com" term="Animation" /><category scheme="http://shinylittlething.com" term="Sprites" />		<summary type="html"><![CDATA[I made a demo to better illustrate the topic covered in my previous post : PyGame and Animated Sprites Here&#8217;s a screenshot of the application : Download the Source code of the demo : explosion-spritetar.tar.gz Spread the word: Related PostsPyGame &#8211; Event HandlingPyGame &#8211; Parallax Scrolling in 2D gamesPyGame and Animated SpritesPyGame Tutorials UpdateGama: Pythonic [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/">&lt;p&gt;I made a demo to better illustrate the topic covered in my previous post : &lt;a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/"&gt;PyGame and Animated Sprites &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a screenshot of the application :&lt;/p&gt;
&lt;div id="attachment_213" class="wp-caption aligncenter" style="width: 309px"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/07/screenshot.png"&gt;&lt;img class="size-full wp-image-213" title="screenshot" src="http://blog.shinylittlething.com/wp-content/uploads/2009/07/screenshot.png" alt="screenshot" width="299" height="321" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;Animated Explosions Sprites&lt;/p&gt;&lt;/div&gt;
&lt;p style="text-align: center;"&gt;
&lt;p style="text-align: left;"&gt;Download the Source code of the demo :&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/07/explosion-spritetar1.gz"&gt;explosion-spritetar.tar.gz&lt;/a&gt;&lt;/p&gt;
&lt;p style="text-align: left;"&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites%20-%20Take%202&amp;amp;notes=I%20made%20a%20demo%20to%20better%20illustrate%20the%20topic%20covered%20in%20my%20previous%20post%20%3A%20PyGame%20and%20Animated%20Sprites%20%0D%0A%0D%0AHere%27s%20a%20screenshot%20of%20the%20application%20%3A%0D%0A%0D%0A%0D%0A%0D%0ADownload%20the%20Source%20code%20of%20the%20demo%20%3A%0D%0Aexplosion-spritetar.tar.gz%0D%0A" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites%20-%20Take%202" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites%20-%20Take%202" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=PyGame%20and%20Animated%20Sprites%20-%20Take%202%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites%20-%20Take%202" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F&amp;amp;t=PyGame%20and%20Animated%20Sprites%20-%20Take%202" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=PyGame%20and%20Animated%20Sprites%20-%20Take%202&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F22%2Fpygame-and-animated-sprites-take-2%2F&amp;amp;t=PyGame%20and%20Animated%20Sprites%20-%20Take%202" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &amp;#8211; Event Handling"&gt;PyGame &amp;#8211; Event Handling&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &amp;#8211; Parallax Scrolling in 2D games"&gt;PyGame &amp;#8211; Parallax Scrolling in 2D games&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites"&gt;PyGame and Animated Sprites&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update"&gt;PyGame Tutorials Update&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing"&gt;Gama: Pythonic Shiny Thing&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=BC4r7pWFZUo:oVca2sCWK78:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/BC4r7pWFZUo" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/feed/atom/" thr:count="5" />
		<thr:total>5</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[PyGame and Animated Sprites]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/sMhRakFCwew/" />
		<id>http://blog.shinylittlething.com/?p=192</id>
		<updated>2009-08-10T08:39:48Z</updated>
		<published>2009-07-21T08:27:39Z</published>
		<category scheme="http://shinylittlething.com" term="Pygame" /><category scheme="http://shinylittlething.com" term="Animation" /><category scheme="http://shinylittlething.com" term="Sprites" />		<summary type="html"><![CDATA[An animated sprite is a serie of the same image slightly modified and displayed at a certain framerate per second. Sample 5 frames Sprite representation: ----------------------------------------- &#124;   1   &#124;   2   &#124;   3   &#124;   4   &#124;   5  &#124; &#124; 16x16 &#124; 16x16 &#124; 16x16 &#124; 16x16 &#124; 16x16 &#124; &#124;       &#124;       &#124;       &#124;       &#124;      &#124; ----------------------------------------- [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/">&lt;p&gt;An animated sprite is a serie of the same image slightly modified and displayed at a certain framerate per second.&lt;/p&gt;
&lt;div id="attachment_191" class="wp-caption aligncenter" style="width: 150px"&gt;&lt;a href="http://lostgarden.com/2007/04/free-game-graphics-tyrian-ships-and.html"&gt;&lt;img class="size-full wp-image-191" title="explosed-sprite" src="http://blog.shinylittlething.com/wp-content/uploads/2009/07/explosed-sprite.png" alt="explosed-sprite" width="140" height="20" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;Explosion Sprite sampled from Remastered Tyrian Graphics @ Lost Garden&lt;/p&gt;&lt;/div&gt;
&lt;p style="text-align: center;"&gt;&lt;a href="http://lostgarden.com/2007/04/free-game-graphics-tyrian-ships-and.html"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sample 5 frames Sprite representation:&lt;/p&gt;
&lt;pre&gt;-----------------------------------------
|   1   |   2   |   3   |   4   |   5   |
| 16x16 | 16x16 | 16x16 | 16x16 | 16x16 |
|       |       |       |       |       |
-----------------------------------------&lt;/pre&gt;
&lt;p&gt;For a  given framerate set to 30fps :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Frame 1 is blited at now()&lt;/li&gt;
&lt;li&gt;Frame 2 blitted 1000/30 seconds after Frame 1&lt;/li&gt;
&lt;li&gt;Frame 3 blitted 1000/30 seconds after Frame 2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;and so on.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-192"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This gives the illusion of motion.&lt;/p&gt;
&lt;p&gt;With PyGame you can load a set of images to an Animated Sprite Class or you can load a single image containing all your frames and slice it using PyGame&amp;#8217;s &lt;a href="http://www.pygame.org/docs/ref/surface.html#Surface.subsurface"&gt;&lt;strong&gt;Subsurface&lt;/strong&gt;&lt;/a&gt; Method&lt;/p&gt;
&lt;p&gt;I made an helper function to load and slice such sprites:&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
def load_sliced_sprites(self, w, h, filename):
    '''
    Specs :
    	Master can be any height.
    	Sprites frames width must be the same width
    	Master width must be len(frames)*frame.width
    Assuming you ressources directory is named "ressources"
    '''
    images = []
    master_image = pygame.image.load(os.path.join('ressources', filename)).convert_alpha()

    master_width, master_height = master_image.get_size()
    for i in xrange(int(master_width/w)):
    	images.append(master_image.subsurface((i*w,0,w,h)))
    return images

[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Use it like this :&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
''' Asuming your frames have a 16x16 size '''
explosion_images = load_sliced_sprites(16, 16, 'explosions-sprite.png')
[/sourcecode]&lt;/pre&gt;
&lt;p&gt;explosion_images will then be an iterable list so you can use it with this kind of class courtesy of the excellent &lt;a href="http://www.sacredchao.net/~piman/writing/sprite-tutorial.shtml"&gt;piman&amp;#8217;s Sprites Tutorial&lt;/a&gt; :&lt;/p&gt;
&lt;pre&gt;[sourcecode language='python']
import pygame

class AnimatedSprite(pygame.sprite.Sprite):
    def __init__(self, images, fps = 10):
        pygame.sprite.Sprite.__init__(self)
        self._images = images

        # Track the time we started, and the time between updates.
        # Then we can figure out when we have to switch the image.
        self._start = pygame.time.get_ticks()
        self._delay = 1000 / fps
        self._last_update = 0
        self._frame = 0

        # Call update to set our first image.
        self.update(pygame.time.get_ticks())

    def update(self, t):
        # Note that this doesn't work if it's been more that self._delay
        # time between calls to update(); we only update the image once
        # then, but it really should be updated twice.

        if t - self._last_update &gt; self._delay:
            self._frame += 1
            if self._frame &gt;= len(self._images): self._frame = 0
            self.image = self._images[self._frame]
            self._last_update = t

[/sourcecode]

Happy Learning!&lt;/pre&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites&amp;amp;notes=An%20animated%20sprite%20is%20a%20serie%20of%20the%20same%20image%20slightly%20modified%20and%20displayed%20at%20a%20certain%20framerate%20per%20second.%0D%0A%0D%0A%0D%0A%0D%0A%0D%0ASample%205%20frames%20Sprite%20representation%3A%0D%0A-----------------------------------------%0D%0A%7C%C2%A0%C2%A0%201%C2%A0%C2%A0%20%7C%C2%A0%C2%A0%202%C2%A0%C2%A0%20%7C%C2%A0%C2%A0%203%C2%A0%C2%A0%20%7C%C2%A0%C2%A0%204" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=PyGame%20and%20Animated%20Sprites%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F&amp;amp;title=PyGame%20and%20Animated%20Sprites" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F&amp;amp;t=PyGame%20and%20Animated%20Sprites" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=PyGame%20and%20Animated%20Sprites&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fpygame-and-animated-sprites%2F&amp;amp;t=PyGame%20and%20Animated%20Sprites" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &amp;#8211; Event Handling"&gt;PyGame &amp;#8211; Event Handling&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &amp;#8211; Take 2"&gt;PyGame and Animated Sprites &amp;#8211; Take 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &amp;#8211; Parallax Scrolling in 2D games"&gt;PyGame &amp;#8211; Parallax Scrolling in 2D games&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update"&gt;PyGame Tutorials Update&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing"&gt;Gama: Pythonic Shiny Thing&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=sMhRakFCwew:cFpIxVuCvxs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/sMhRakFCwew" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/feed/atom/" thr:count="2" />
		<thr:total>2</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[Gama: Pythonic Shiny Thing]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/dETKFd0IVR4/" />
		<id>http://blog.shinylittlething.com/?p=185</id>
		<updated>2009-07-21T13:09:23Z</updated>
		<published>2009-07-21T07:54:21Z</published>
		<category scheme="http://shinylittlething.com" term="Python" /><category scheme="http://shinylittlething.com" term="Gama" /><category scheme="http://shinylittlething.com" term="Pygame" />		<summary type="html"><![CDATA[Hello dear Shiny reader, I just started learning Python a couple weeks ago. Well, I&#8217;m amazed. Pyhton&#8217;s Oriented Object Model is really flawless from my point of view. Multi-Heritance is like bottled awesomeness. As a start project, I&#8217;m currently building a 2D RTS game/simulation named Gama using PyGame and GameObjects while following extremely good tutorials [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/">&lt;p&gt;Hello dear Shiny reader,&lt;/p&gt;
&lt;p&gt;I just started learning Python a couple weeks ago. Well, I&amp;#8217;m amazed. Pyhton&amp;#8217;s Oriented Object Model is really flawless from my point of view. Multi-Heritance is like bottled awesomeness.&lt;/p&gt;
&lt;p&gt;As a start project, I&amp;#8217;m currently building a 2D RTS game/simulation named Gama using PyGame and GameObjects while following extremely good tutorials from &lt;a href="http://www.willmcgugan.com/blog/tech/"&gt;It&amp;#8217;s All Geek to Me&lt;/a&gt;, Will McGugan&amp;#8217;s tech blog.&lt;/p&gt;
&lt;p&gt;I learned some very interesting concept over here like : &lt;a href="http://www.willmcgugan.com/blog/tech/2007/10/4/free-chapter-of-beginning-game-development-with-python-and-pygame/"&gt;A.I. with State Machines&lt;/a&gt;, &lt;a href="http://www.willmcgugan.com/blog/tech/2007/4/30/swim-turtle-swim/"&gt;Pathfinding&lt;/a&gt; (not yet assimilated though) and &lt;a href="http://www.willmcgugan.com/blog/tech/2007/6/15/master-time-with-pygame/"&gt;Time Management&lt;/a&gt; I even bought Will&amp;#8217;s book &lt;a href="http://www.amazon.fr/gp/product/1590598725?ie=UTF8&amp;amp;tag=moblurorg-21&amp;amp;linkCode=as2&amp;amp;camp=1642&amp;amp;creative=6746&amp;amp;creativeASIN=1590598725"&gt;Beginning Game Development With Python and Pygame: From Novice to Professional&lt;/a&gt;&lt;img style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.fr/e/ir?t=moblurorg-21&amp;amp;l=as2&amp;amp;o=8&amp;amp;a=1590598725" border="0" alt="" width="1" height="1" /&gt;.&lt;/p&gt;
&lt;p&gt;Most of the game &lt;a href="http://lostgarden.com/2007/04/free-game-graphics-tyrian-ships-and.html"&gt;old school graphics&lt;/a&gt; come from the talented and  generous &lt;a href="http://lostgarden.com/"&gt;Lost Garden &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can find the source code and ressources of the simulation on &lt;a href="http://github.com/ncrovatti/Gama/tree/master"&gt;github&lt;/a&gt; or using this command :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git clone git://github.com/ncrovatti/Gama.git &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dependencies: &lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.pygame.org/download.shtml"&gt;PyGame &amp;gt;= 1.7.1&lt;/a&gt;&lt;a href="http://code.google.com/p/gameobjects/"&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/gameobjects/"&gt;GameObjects &amp;gt;= 0.0.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s an in-game screenshot&lt;/p&gt;
&lt;div id="attachment_206" class="wp-caption aligncenter" style="width: 443px"&gt;&lt;a href="http://blog.shinylittlething.com/wp-content/uploads/2009/07/gama-1.png"&gt;&lt;img class="size-medium wp-image-206" title="gama-1" src="http://blog.shinylittlething.com/wp-content/uploads/2009/07/gama-1-300x213.png" alt="Gama - In Game Screeshot showing Paths (click for full size)" width="433" height="307" /&gt;&lt;/a&gt;&lt;p class="wp-caption-text"&gt;Gama - In Game Screeshot showing Paths (click for full size)&lt;/p&gt;&lt;/div&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F&amp;amp;title=Gama%3A%20Pythonic%20Shiny%20Thing&amp;amp;notes=Hello%20dear%20Shiny%20reader%2C%0D%0A%0D%0AI%20just%20started%20learning%20Python%20a%20couple%20weeks%20ago.%20Well%2C%20I%27m%20amazed.%20Pyhton%27s%20Oriented%20Object%20Model%20is%20really%20flawless%20from%20my%20point%20of%20view.%20Multi-Heritance%20is%20like%20bottled%20awesomeness.%0D%0A%0D%0AAs%20a%20start%20project%2C%20I%27m%20currentl" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F&amp;amp;title=Gama%3A%20Pythonic%20Shiny%20Thing" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F&amp;amp;title=Gama%3A%20Pythonic%20Shiny%20Thing" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=Gama%3A%20Pythonic%20Shiny%20Thing%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F&amp;amp;title=Gama%3A%20Pythonic%20Shiny%20Thing" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F&amp;amp;t=Gama%3A%20Pythonic%20Shiny%20Thing" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=Gama%3A%20Pythonic%20Shiny%20Thing&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F21%2Fgama-pythonic-shiny-thing%2F&amp;amp;t=Gama%3A%20Pythonic%20Shiny%20Thing" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &amp;#8211; Event Handling"&gt;PyGame &amp;#8211; Event Handling&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update"&gt;PyGame Tutorials Update&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &amp;#8211; Parallax Scrolling in 2D games"&gt;PyGame &amp;#8211; Parallax Scrolling in 2D games&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &amp;#8211; Take 2"&gt;PyGame and Animated Sprites &amp;#8211; Take 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites"&gt;PyGame and Animated Sprites&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=dETKFd0IVR4:FAvFeau6TY8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/dETKFd0IVR4" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/feed/atom/" thr:count="2" />
		<thr:total>2</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Nicolas Crovatti</name>
						<uri>http://blog.shinylittlething.com</uri>
					</author>
		<title type="html"><![CDATA[Multiple file upload using jQuery and Ruby on Rails Tutorial]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MyShinyWeblog/~3/r0z0rDEVqnQ/" />
		<id>http://blog.shinylittlething.com/?p=169</id>
		<updated>2009-08-10T08:40:37Z</updated>
		<published>2009-07-20T07:44:57Z</published>
		<category scheme="http://shinylittlething.com" term="jQuery" /><category scheme="http://shinylittlething.com" term="Ruby" /><category scheme="http://shinylittlething.com" term="Ruby On Rails" /><category scheme="http://shinylittlething.com" term="ajax" /><category scheme="http://shinylittlething.com" term="JavaScript" />		<summary type="html"><![CDATA[Outline Today I&#8217;ll share with you how to solve problems relating to uploading multiple files and how to effectively use Ruby on Rails in combination with jQuery Form plugins to allow your users to upload a single file or multiple files without refreshing the page. Since I don&#8217;t have any Windows or MacOS, the command [...]]]></summary>
		<content type="html" xml:base="http://shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/">&lt;h3&gt;Outline&lt;/h3&gt;
&lt;p&gt;Today I&amp;#8217;ll share with you how to solve problems relating to uploading multiple files and how to effectively use Ruby on Rails in combination with jQuery Form plugins to allow your users to upload a single file or multiple files without refreshing the page.&lt;/p&gt;
&lt;p&gt;Since I don&amp;#8217;t have any Windows or MacOS, the command lines shown in this tutorial&lt;br /&gt;
are known working on Debian linux system. I&amp;#8217;m sure you will find your way for your specific OS!&lt;/p&gt;
&lt;p&gt;The application will allow users to upload as many image files as they want and return the following information to them :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Relative paths to successfully uploaded files&lt;/li&gt;
&lt;li&gt;Width and Height for each uploaded file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;To follow this tutorial you will need to install the Ruby on Rails framework on your system.&lt;br /&gt;
You will also need copies of &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; and &lt;a href="http://malsup.com/jquery/form/"&gt;jQuery Form plugin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-169"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Application &amp;amp; Server&lt;/h3&gt;
&lt;p&gt;You may want to skip this part if you are enabling multiple file upload for an existing Rails app.&lt;/p&gt;
&lt;p&gt;Rails app creation from an empty directory :&lt;/p&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']$ ruby rails myApplicationName[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Server Spawn :&lt;/p&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']$ ruby script/server[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Or if you already have an application running here is how to spawn it on a different port :&lt;/p&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']$ ruby script/server -p 3001[/sourcecode]&lt;/pre&gt;
&lt;h3&gt;Scaffolding&lt;/h3&gt;
&lt;p&gt;First things first, model and controller Scaffolding :&lt;/p&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']$ script/generate model UploadedFile
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/uploaded_file.rb
      create  test/unit/uploaded_file_test.rb
      create  test/fixtures/uploaded_files.yml
      create  db/migrate
      create  db/migrate/20090217221029_create_uploaded_files.rb[/sourcecode]&lt;/pre&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']$ script/generate controller Upload
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/upload
      exists  test/functional/
      create  app/controllers/upload_controller.rb
      create  test/functional/upload_controller_test.rb
      create  app/helpers/upload_helper.rb[/sourcecode]&lt;/pre&gt;
&lt;p&gt;These simple &amp;#8220;script/generate&amp;#8221; commands generate the stub files for our application.&lt;/p&gt;
&lt;h3&gt;Application View&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s directly edit our view by setting up a simple HTML form and a container for our images in&lt;br /&gt;
&lt;code&gt;app/views/upload/uploadfile.html.erb&lt;/code&gt; this file is not part of the Scaffolding, just go ahead and create it yourself :&lt;/p&gt;
&lt;pre class="code" lang="html"&gt;[sourcecode language='html']&lt;!- app/views/upload/uploadfile.html.erb --&gt;

&lt;h1&gt;Multiple Files Upload Using Rails and jQuery&lt;/h1&gt;

&lt;h3&gt;Files&lt;/h3&gt;
&lt;form method="post" action="/services/uploadr"
    enctype="multipart/form-data"
    class="upload" id="upload_form"&gt;
        &lt;br/&gt;
        &lt;input type="button" id="button" class="button" value="Add File" /&gt;
        &lt;input type="submit" id="save" class="save" value="Upload" /&gt;
&lt;/form&gt;

&lt;h3&gt;Images&lt;/h3&gt;
&lt;div lang="images_container"&gt;&lt;/div&gt;[/sourcecode]&lt;/pre&gt;
&lt;p&gt;The important things in the HTML are the &lt;code&gt;form&lt;/code&gt; tag&amp;#8217;s attributes :&lt;br /&gt;
the method must be &lt;code&gt;"post"&lt;/code&gt; and the encoding type set to &lt;code&gt;"multipart/form-data"&lt;/code&gt;.&lt;br /&gt;
The &amp;#8220;post&amp;#8221; method allows unlimited size requests (compared to approximately 2000 characters maximum for the &amp;#8220;get&amp;#8221; method).&lt;br /&gt;
The &lt;code&gt;multipart/form-data&lt;/code&gt; encoding type tells the application that we want to transfer some kind of non-ASCII or binary data.&lt;/p&gt;
&lt;p&gt;Note that we could had achieved the very same result using the Rails Form Helper. Here are the required options for the helper :&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']&lt;% form_for :upload, :html =&gt; { :multipart =&gt; true, :id =&gt; "upload_form" },
            :method =&gt; 'post',
            :url =&gt; { :action =&gt; "upload" } do |f| %&gt;
  &lt;!--  add fields here --&gt;
&lt;% end %&gt;[/sourcecode]&lt;/pre&gt;
&lt;p&gt;I am assuming that you know how to include the jQuery library and Forms plugin in your default application javascript file.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s move on and add the basic jQuery code to allow on-the-fly file fields creation :&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']// public/javascripts/application.js

$(document).ready(function() {
  $("#button").bind("click", function() {
    /* Generating unique id
    */
    var rand = Math.random().toString().split(".")[1];
    var input = '&lt;input type="file" class="'+rand+'" /&gt;'
    $(this).before('&lt;br/&gt;' + input );
  });

  /* Pushing the first input to the DOM
  */
  $("#button").trigger("click");

});[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Since we will be using the DOM selector to bind functions to our user interface&amp;#8217;s inputs,&lt;br /&gt;
we need to tell the browser to wait for the elements to be rendered&lt;br /&gt;
before executing any code contained in the &lt;code&gt;ready()&lt;/code&gt; callback function.&lt;br /&gt;
This will avoid any Javascript interpreter complaint about null or non-existent&lt;br /&gt;
elements.&lt;/p&gt;
&lt;p&gt;We do not want to enable the Forms plugin yet because it will be easier for us&lt;br /&gt;
in the developement process.&lt;/p&gt;
&lt;p&gt;If you try to access your app now, Rails will complain about an unknown&lt;br /&gt;
action, we will have to edit our upload controler to insert a default action:&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# app/controllers/upload_controller.rb

language UploadController &lt; ApplicationController
  protect_from_forgery :only =&gt; [:create, :update, :destroy] 

  def index
     render :file =&gt; 'app/views/upload/uploadfile.html.erb'
  end
end[/sourcecode]&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;protect_from_forgery&lt;/code&gt;: Since we are not using the Rails Form Helper, we need to limit the use of the Authenticity Token for our controller.&lt;br /&gt;
The default &lt;code&gt;index&lt;/code&gt; method displays the HTML file with our&lt;br /&gt;
HTML form located at &lt;code&gt;app/views/upload/uploadfile.html.erb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;index&lt;/code&gt;&lt;br /&gt;
method in Rails acts the same way as the default indexes files on web servers i.e: when&lt;br /&gt;
no methods are specified the &lt;code&gt;index&lt;/code&gt; method will be executed.&lt;/p&gt;
&lt;p&gt;At this point,you should have something very similar to this:&lt;/p&gt;
&lt;p&gt;&lt;img class="aligncenter size-full wp-image-173" title="sc-1" src="http://blog.shinylittlething.com/wp-content/uploads/2009/07/sc-1.png" alt="sc-1" width="304" height="249" /&gt;&lt;/p&gt;
&lt;p&gt;and you can add as many file fields as you want by clicking the &amp;#8220;Add File&amp;#8221; button.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s get back to our code; did you spot the problem we will encounter here?&lt;/p&gt;
&lt;p&gt;We have no way of knowing the names of the generated inputs thus making it difficult to differentiate them from other parameters&lt;br /&gt;
in the Ruby on Rails web service.&lt;/p&gt;
&lt;p&gt;In order to recognize them among all the other possible parameters we will wrap them in an array. Simply modify the &lt;code&gt;input&lt;/code&gt; variable in the javascript snippet:&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']// public/javascripts/application.js
var rand = Math.random().toString().split(".")[1];
var input = '&lt;input type="file" class="images['+rand+']" /&gt;'[/sourcecode]&lt;/pre&gt;
&lt;p&gt;That simple trick will allows us to use the Ruby&amp;#8217;s &lt;code&gt;each()&lt;/code&gt; function to loop through uploaded images.&lt;/p&gt;
&lt;h3&gt;Application Model&lt;/h3&gt;
&lt;p&gt;On to our UploadedFile model :&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# app/models/uploaded_file.rb

require 'image_size.rb'

language UploadedFile &lt; ActiveRecord::Base
  def self.save(id, upload)

    # skipping empty fields
    return false unless upload.blank?

    # The saved file name is composed of the unique id and original extension
    name =  id + "." + upload.original_filename.split(".").last 

    # target directory to save files
    directory = "public/images/users/"

    # create the file path
    path = File.join(directory, name)

    # write the file
    File.open(path, "wb") { |f| f.write(upload.read) }

    img = ImageSize.new(open(path))

    return {
      "width"     =&gt; img.get_width,
      "height"    =&gt; img.get_height,
      "filename"  =&gt; name
    }

  end
end[/sourcecode]&lt;/pre&gt;
&lt;p&gt;A point to note here. I have included the ImageSize lib. If you don&amp;#8217;t have it installed yet proceed like this as root:&lt;/p&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']# apt-get install libimage-size-ruby1.8[/sourcecode]&lt;/pre&gt;
&lt;p&gt;*or* my guess for Mac OS X and Windows (I can&amp;#8217;t test these platforms) :&lt;/p&gt;
&lt;pre class="code" lang="shell"&gt;[sourcecode language='shell']# gem install imagesize[/sourcecode]&lt;/pre&gt;
&lt;p&gt;As you can see it&amp;#8217;s pretty straight forward.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;save&lt;/code&gt; method takes only two arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt; which is our unique field name&lt;/li&gt;
&lt;li&gt;&lt;code&gt;upload&lt;/code&gt; which is the uploaded file reference&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Application Controller&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s add the &lt;code&gt;upload&lt;/code&gt; method to our UploadController controller.&lt;br /&gt;
This method will actually be our web service.&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# app/controllers/upload_controller.rb

language UploadController &lt; ApplicationController
  def index
     render :file =&gt; 'app/views/upload/uploadfile.html.erb'
  end

  def upload
      @post = [];

      params[:images].each { | id, image |
        result = UploadedFile.save(id, image);
        @post &lt;&lt; result if result
      }

      respond_to do |format|
        format.html
      end
  end
end[/sourcecode]&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;upload&lt;/code&gt; method creates an instance variable&lt;br /&gt;
(prefixed by @) &lt;code&gt;@post&lt;/code&gt; to store our images data. An instance variable&lt;br /&gt;
differs from other variables in that it will be available to work with in our view.&lt;/p&gt;
&lt;p&gt;Then, for each item in the &lt;code&gt;params[:images]&lt;/code&gt; array (the one we created by&lt;br /&gt;
grouping all our images inputs) it will add a new entry to our&lt;br /&gt;
&lt;code&gt;@post&lt;/code&gt; array.&lt;/p&gt;
&lt;p&gt;As you can see, Ruby on Rails code is really easy to read and understand.&lt;/p&gt;
&lt;h3&gt;Routes&lt;/h3&gt;
&lt;p&gt;In order to access our newly created web service we have to create a named route.&lt;br /&gt;
A named route will allow us to give a name that fits our logical organisation&lt;br /&gt;
and to set various usage restrictions to our action.&lt;/p&gt;
&lt;p&gt;Edit the &lt;code&gt;config/routes.rb&lt;/code&gt; file to configure the routes :&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# config/routes.rb

ActionController::Routing::Routes.draw do |map|
map.connect '/services/uploadr',
  :controller =&gt; 'upload',
  :action =&gt; 'upload',
  :conditions =&gt; {
    :method =&gt; :post
  }

  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
end[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Ok, our &lt;code&gt;upload&lt;/code&gt; action will now respond to the path &lt;code&gt;/services/uploadr&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;and only for &lt;code&gt;post&lt;/code&gt; requests.&lt;/p&gt;
&lt;h3&gt;Webservice's View&lt;/h3&gt;
&lt;p&gt;Our UploadController will need to use its corresponding view to send back its results to&lt;br /&gt;
the browser, just create it and insert the following snippet in it :&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# app/view/upload/upload.html.erb

&lt;% @post.each  do |image|  %&gt;
  &lt;img src="/images/users/&lt;%= image["filename"] %&gt;"/&gt;
  &lt;br/&gt;
  &lt;%= image["width"] %&gt; x &lt;%= image["height"] %&gt;
  &lt;br/&gt;

&lt;% end %&gt;[/sourcecode]&lt;/pre&gt;
&lt;p&gt;This simple erb template renders all the information we planned to send back to the client with some formatting applied.&lt;/p&gt;
&lt;p&gt;&lt;img class="aligncenter size-full wp-image-176" title="sc-2" src="http://blog.shinylittlething.com/wp-content/uploads/2009/07/sc-2.png" alt="sc-2" width="422" height="171" /&gt;&lt;/p&gt;
&lt;p&gt;You can now test your newly created application using the form located in &lt;code&gt;http://localhost:3000/upload/&lt;/code&gt; if you kept the default settings.&lt;/p&gt;
&lt;p&gt;Here's is a capture of a similar result after the form has been sent :&lt;/p&gt;
&lt;p&gt;If images aren't showing up you may have a permission problem or a bug in your code.&lt;/p&gt;
&lt;p&gt;Verify your &lt;code&gt;RAILS_ROOT/public/images/users/&lt;/code&gt; path to see if the&lt;br /&gt;
permissions are correct. If this does not resolve your problem please re-read&lt;br /&gt;
this tutorial again to ensure you did not miss a step.&lt;/p&gt;
&lt;p&gt;The default HTML view for our upload controller is fine to preview our work so far;&lt;br /&gt;
but it might be hard to do anything with it with javascript.&lt;/p&gt;
&lt;p&gt;We will now add a json format for this view. Json (JavaScript Object Notation )&lt;br /&gt;
is the (my) format of choice for client/server communication using XHR.&lt;br /&gt;
It is lightweight (lighter than XML), many server side programming and scripting&lt;br /&gt;
languages have JSON implementation either natively, using plugins or at least&lt;br /&gt;
libraries.&lt;/p&gt;
&lt;p&gt;Finally it's native javascript language and this is an huge plus.&lt;/p&gt;
&lt;h3&gt;JSON communication&lt;/h3&gt;
&lt;p&gt;Let's implement this new format by editing our upload controller first :&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# app/controllers/upload_controller.rb

language UploadController &lt; ApplicationController
    protect_from_forgery :only =&gt; [:create, :update, :destroy] 

    def index
      render :file =&gt; 'app/views/upload/uploadfile.html.erb'
    end

    def upload
      @post = [];

      params[:images].each { | id, image |
        result = UploadedFile.save(id, image);
        @post &lt;&lt; result if result
      }

      respond_to do |format|
        format.html
        format.js  { render :json =&gt; @post }
      end
    end

end[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Implementing this new format is easy as 1,2,3 in the Rails framework, just add&lt;br /&gt;
this single line in our &lt;code&gt;respond_to&lt;/code&gt; block :&lt;br /&gt;
&lt;code&gt;format.js  { render :json =&amp;gt; @post }&lt;/code&gt;.&lt;br /&gt;
Literaly, this line of code will activate the automated json rendering of our &lt;code&gt;@post&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;object and will send back the result with adequate HTTP headers and mime-type&lt;br /&gt;
to the client.&lt;/p&gt;
&lt;p&gt;We have to modify the routes in order to point to the json format :&lt;/p&gt;
&lt;pre class="code" lang="ruby"&gt;[sourcecode language='ruby']# config/routes.rb

ActionController::Routing::Routes.draw do |map|
  map.connect '/services/uploadr',
  	:controller =&gt; 'upload',
	  :action =&gt; 'upload',
	  :format =&gt; 'js',
	  :conditions =&gt; {
	    :method =&gt; :post
	  }

  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
end[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Basicaly I just added the &lt;code&gt;:format =&amp;gt; 'js'&lt;/code&gt; parameter to our&lt;br /&gt;
previously created named route &lt;code&gt;/services/uploadr&lt;/code&gt;. That's it!&lt;/p&gt;
&lt;p&gt;You can now test your application again. Here is an example content of the generated file :&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript'][
  {
    "filename": "38396648300918923.png",
    "height": 171,
    "width": 422
  },
  {
    "filename": "5770189283356341.png",
    "height": 165,
    "width": 549
  }
][/sourcecode]&lt;/pre&gt;
&lt;p&gt;Perfect, now if we add data into the &lt;code&gt;@post&lt;/code&gt; object it will be&lt;br /&gt;
automagicaly serialized.&lt;/p&gt;
&lt;h3&gt;Front End&lt;/h3&gt;
&lt;p&gt;Now that our backend webservice is ready let's build our frontend in javascript and jQuery.&lt;/p&gt;
&lt;p&gt;First we will activate the &lt;code&gt;ajaxForm&lt;/code&gt; method from the Forms plugins&lt;br /&gt;
in our HTML form and bind a new function to our submit button.&lt;/p&gt;
&lt;p&gt;Due to Forms plugins limitations using both files fields and JSON communication,&lt;br /&gt;
we will be forced to hack a bit; The JSON data will be returned wraped in &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;&lt;br /&gt;
tags. Let's get rid of them and evaluate the string containing the JSON to transform&lt;br /&gt;
it into a JSON object.&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']// public/javascripts/application.js

$(document).ready(function() {
  $("#button").bind("click", function() {
    /* Generating unique id
    */
    var rand = Math.random().toString().split(".")[1];
    var input = '&lt;input type="file" id="upload_field_'+rand+'" class="images['+rand+']" /&gt;'
    $(this).before(input + '&lt;br/&gt;');
  });

  /* Pushing the first input to the DOM
  */
  $("#button").trigger("click");

  /* Enabling Ajax form on #upload_form
  */
  $("#upload_form").ajaxForm();

  $("#upload_form").submit(function() {
    $(this).ajaxSubmit({
      dataType  : 'html',
      iframe 	  : true,
      success	  : function (data) {
        data = eval(data.replace("&lt;pre&gt;", "").replace("&lt;/pre&gt;
&lt;p&gt;", ""));&lt;br /&gt;
      }&lt;br /&gt;
    });&lt;br /&gt;
    return false;&lt;br /&gt;
  });&lt;br /&gt;
});[/sourcecode]&lt;br /&gt;
That done our data is ready to be processed on the client side. Let's go ahead&lt;br /&gt;
and add some functionality.&lt;/p&gt;
&lt;h3&gt;JSON data processing&lt;/h3&gt;
&lt;p&gt;With our new JSON object we are now able to display uploaded images to our image&lt;br /&gt;
container. All the code could be split up into functions or even wraped into an&lt;br /&gt;
object; this part depends on your project's requirements and/or on your personal coding rules.&lt;br /&gt;
I'll go for the inline code for this tutorial.&lt;/p&gt;
&lt;p&gt;All the following code goes into the &lt;code&gt;success&lt;/code&gt; callback function.&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']function (data) {
  files = eval(data.replace("&lt;pre&gt;", "").replace("&lt;/pre&gt;
&lt;p&gt;", ""));&lt;/p&gt;
&lt;p&gt;  for(var i in files) {&lt;br /&gt;
    var id      = files[i].filename.split(".")[0];&lt;br /&gt;
    var img     = new Image();&lt;br /&gt;
    img.src     = "/images/users/" + files[i].filename;&lt;br /&gt;
    img.height  = files[i].height;&lt;br /&gt;
    img.width   = files[i].width;&lt;br /&gt;
    img.id      = "img_display_" + id&lt;/p&gt;
&lt;p&gt;    $(".images_container").append(img);&lt;br /&gt;
    var $file = $("#upload_field_" + id);&lt;br /&gt;
    $file.next().remove();&lt;br /&gt;
    $file.remove();&lt;/p&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  if($("input[type*='file']").length == 0) {&lt;br /&gt;
    $("#button").trigger("click");&lt;br /&gt;
  }&lt;br /&gt;
}[/sourcecode]&lt;br /&gt;
What is this function doing ?&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']    var id      = files[i].filename.split(".")[0];
    var img     = new Image();
    img.src     = "/images/users/" + files[i].filename;
    img.height  = files[i].height;
    img.width   = files[i].width;
    img.id      = "img_display_" + id[/sourcecode]&lt;/pre&gt;
&lt;p&gt;Our data transformed into an object we can loop through it to display&lt;br /&gt;
the uploaded images. For each file a new Image object is created and it's properties filled with&lt;br /&gt;
what our webservice sent back.&lt;/p&gt;
&lt;p&gt;We already know the path where we uploaded the images to, so we can complete the src attribute with the filename. Setting width and height and an id to later ease our manipulation on each image precisely.&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']    $(".images_container").append(img);
    var $file = $("#upload_field_" + id);
    $file.next().remove();
    $file.remove();[/sourcecode]&lt;/pre&gt;
&lt;p&gt;We are using the &lt;code&gt;append()&lt;/code&gt; jQuery method to add the newly uploaded&lt;br /&gt;
file to our im ages container. We have to remove the remaining &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt;&lt;br /&gt;
tag next to our file field prior to delete the input itself to avoid any unwanted&lt;br /&gt;
blank space in our layout.&lt;/p&gt;
&lt;p&gt;To prevent sending the same image the next time the user submit the form,&lt;br /&gt;
we are removing the file input.&lt;/p&gt;
&lt;pre class="code" lang="javascript"&gt;[sourcecode language='javascript']  if($("input[type*='file']").length == 0) {
    $("#button").trigger("click");
  }[/sourcecode]&lt;/pre&gt;
&lt;p&gt;In order to keep our interface clean and usable, we are checking for remaining file fields; if none are found then we create one by triggering a simulated click on our "Add file" button.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;This tutorial has explained how to upload multiple files using jQuery and a web service written in Ruby on rails. This application may ever be a start point for or a new component for an existing app. On top of that, the backend part could effectively be in whatever language you are comfortable with.&lt;/p&gt;
&lt;h3&gt;Credits&lt;/h3&gt;
&lt;p&gt;I couldn't safely close this tutorial without giving credits where it's due! I would like to particulary thank &lt;a href="http://twitter.com/mcaulay"&gt;Mark Mcaulay&lt;/a&gt; and &lt;a href="http://twitter.com/pet3r"&gt;Peter Szinek&lt;/a&gt; for their great help, feedback and awesomeness!&lt;/p&gt;



Spread the word:


	&lt;a rel="nofollow"  href="http://delicious.com/post?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F&amp;amp;title=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial&amp;amp;notes=Outline%0D%0AToday%20I%27ll%20share%20with%20you%20how%20to%20solve%20problems%20relating%20to%20uploading%20multiple%20files%20and%20how%20to%20effectively%20use%20Ruby%20on%20Rails%20in%20combination%20with%20jQuery%20Form%20plugins%20to%20allow%20your%20users%20to%20upload%20a%20single%20file%20or%20multiple%20files%20without%20refre" title="del.icio.us"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://reddit.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F&amp;amp;title=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial" title="Reddit"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F&amp;amp;title=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial" title="StumbleUpon"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://technorati.com/faves?add=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F" title="Technorati"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/technorati.png" title="Technorati" alt="Technorati" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://twitter.com/home?status=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial%20-%20http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F" title="Twitter"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.dzone.com/links/add.html?url=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F&amp;amp;title=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial" title="DZone"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/dzone.png" title="DZone" alt="DZone" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.facebook.com/share.php?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F&amp;amp;t=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial" title="Facebook"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://www.friendfeed.com/share?title=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial&amp;amp;link=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F" title="FriendFeed"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" /&gt;&lt;/a&gt;
	&lt;a rel="nofollow"  href="http://news.ycombinator.com/submitlink?u=http%3A%2F%2Fshinylittlething.com%2F2009%2F07%2F20%2Fmultiple-file-upload-using-jquery-and-ruby-on-rails-tutorial%2F&amp;amp;t=%20Multiple%20file%20upload%20using%20jQuery%20and%20Ruby%20on%20Rails%20Tutorial" title="HackerNews"&gt;&lt;img src="http://shinylittlething.com/wp-content/plugins/sociable/images/hackernews.png" title="HackerNews" alt="HackerNews" /&gt;&lt;/a&gt;


&lt;br/&gt;&lt;br/&gt;&lt;h3  class="related_post_title"&gt;Related Posts&lt;/h3&gt;&lt;ul class="related_post"&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/" title="Enabling Dynamic Plugin Support for your JavaScript Application"&gt;Enabling Dynamic Plugin Support for your JavaScript Application&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/03/04/8-ajax-data-controls-and-effects-to-work-with-tables/" title="8 Ajax Data Controls and Effects to Work with Tables"&gt;8 Ajax Data Controls and Effects to Work with Tables&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience"&gt;7 jQuery Plugins to Really Enhance Users Experience&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2009/02/20/image-manipulation-jquery-plugins/" title="6 Image Manipulation Plugins for jQuery You Should Know About"&gt;6 Image Manipulation Plugins for jQuery You Should Know About&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://shinylittlething.com/2010/01/16/psd-template-to-wordpress-theme-from-scratch/" title="PSD template to Wordpress Theme from Scratch"&gt;PSD template to Wordpress Theme from Scratch&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/MyShinyWeblog?a=r0z0rDEVqnQ:Va_IDurTkbg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/MyShinyWeblog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MyShinyWeblog/~4/r0z0rDEVqnQ" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/#comments" thr:count="21" />
		<link rel="replies" type="application/atom+xml" href="http://shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/feed/atom/" thr:count="21" />
		<thr:total>21</thr:total>
	<feedburner:origLink>http://shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/</feedburner:origLink></entry>
	</feed><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic (Feed is rejected)
Page Caching using memcached
Database Caching 31/92 queries in 0.186 seconds using memcached
Content Delivery Network via static.moblur.org/shinylittlething.com/

Served from: shinylittlething.com @ 2013-05-22 12:40:28 -->
