<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Shiny Blog</title>
	
	<link>http://blog.shinylittlething.com</link>
	<description>Comes with Narwhals and bacon!</description>
	<lastBuildDate>Tue, 18 Aug 2009 13:44:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Moblurorg" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Introducing twitterBatcher.com</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/t5CZaNjiZuc/</link>
		<comments>http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 07:31:31 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[MySelf]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[twitterBatcher]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=290</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/';
var dzone_title = 'Introducing twitterBatcher.com';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/';
reddit_title='Introducing twitterBatcher.com';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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.
So, to solve [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/';
var dzone_title = 'Introducing twitterBatcher.com';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/';
reddit_title='Introducing twitterBatcher.com';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>I&#8217;ve been working on a side project late weeks, let me introduce<strong> <a href="http://twitterBatcher.com">twitterBatcher.com</a>!</strong></p>
<p>I made this app to satisfy a personal need concerning <strong><a href="http://twitter.com">Twitter</a></strong>. I found it was convenient to upload a bunch of text containing twitter IDs (@accounts) rather than add them manually.</p>
<p>It&#8217;s pretty handy on <a href="http://mashable.com/2009/03/06/twitter-followfriday/"><strong>#FollowFriday</strong></a> to follow recommended friends of friends.</p>
<p>So, to solve this simple problem I made a simple app and voilà. twitterBatcher was born.</p>
<p>In a few words like in a few thousand: <a href="http://twitterBatcher.com"><strong>Try twitterBatcher now</strong></a> !</p>
<p>I&#8217;d also love to hear about your feedback ! Please leave comments to help me improve this twitter app!</p>
<p>Update :  I just spawned a  dedicated <a href="http://blog.twitterbatcher.com/introducing-twitterbatcher/">blog for twitterBatcher</a></p>
<!-- AdSense Now! V1.80 -->
<!-- Post[count: 2] -->
<div class="adsense adsense-leadout" style="text-align:center;margin: 12px;"><script type="text/javascript"><!--
google_ad_client = "pub-7261775518325774";
/* 468x60, date de création 07/10/09 */
google_ad_slot = "5180090710";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></div></div><h3  class="related_post_title">Popular Posts</h3><ul class="related_post"><li><a href="http://blog.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">8 Ajax Data Controls and Effects to Work with Tables</a></li><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.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"> Multiple file upload using jQuery and Ruby on Rails Tutorial</a></li><li><a href="http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/" title="Home Web Hosting Best Practices">Home Web Hosting Best Practices</a></li><li><a href="http://blog.shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience">7 jQuery Plugins to Really Enhance Users Experience</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=t5CZaNjiZuc:nWczE1UCV7I:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=t5CZaNjiZuc:nWczE1UCV7I:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=t5CZaNjiZuc:nWczE1UCV7I:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=t5CZaNjiZuc:nWczE1UCV7I:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/08/18/introducing-twitterbatcher-com/</feedburner:origLink></item>
		<item>
		<title>PyGame Tutorials Update</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/7uzE_qIsTUk/</link>
		<comments>http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 08:24:31 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Pygame]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=280</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/';
var dzone_title = 'PyGame Tutorials Update';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/';
reddit_title='PyGame Tutorials Update';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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 :



git clone git://github.com/ncrovatti/Pygame-Tutorials.git


You can also browse the complete sources and ressources from the github repository if you prefer.
Eventually you will be able to see the upcoming tutorials [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/';
var dzone_title = 'PyGame Tutorials Update';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/';
reddit_title='PyGame Tutorials Update';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>So,  I created a dedicated repository on <a href="http://github.com">github</a> to host the source code of my <a href="http://blog.shinylittlething.com/pygame/">PyGame Tutorials Serie </a></p>
<p>You can clone all the tutorials using the following command :</p>
<pre>
<pre class="brush: python">

git clone git://github.com/ncrovatti/Pygame-Tutorials.git
</pre>
</pre>
<p>You can also <a href="http://github.com/ncrovatti/Pygame-Tutorials/tree/master">browse the complete sources and ressources</a> from the github repository if you prefer.</p>
<p>Eventually you will be able to see the upcoming tutorials source code before their release.</p>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &#8211; Parallax Scrolling in 2D games">PyGame &#8211; Parallax Scrolling in 2D games</a></li><li><a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &#8211; Take 2">PyGame and Animated Sprites &#8211; Take 2</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites">PyGame and Animated Sprites</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing">Gama: Pythonic Shiny Thing</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=7uzE_qIsTUk:IvpJB45uNWQ:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=7uzE_qIsTUk:IvpJB45uNWQ:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=7uzE_qIsTUk:IvpJB45uNWQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=7uzE_qIsTUk:IvpJB45uNWQ:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/</feedburner:origLink></item>
		<item>
		<title>PyGame – Event Handling</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/ob4yiCoxF_Q/</link>
		<comments>http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 10:34:54 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Pygame]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[Sprites]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=257</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/';
var dzone_title = 'PyGame &#8211; Event Handling';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/';
reddit_title='PyGame &#8211; Event Handling';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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 is [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/';
var dzone_title = 'PyGame &#8211; Event Handling';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/';
reddit_title='PyGame &#8211; Event Handling';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<h3>Introduction</h3>
<p>To continue further into my <a href="http://www.pygame.org/">PyGame</a> exploration articles and tutorials,  I&#8217;ll try to come up with a complete Shmup game as example. I already covered <strong><a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/">Animated sprites</a> </strong>and <strong><a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/">Parallax Scrolling</a> </strong> in 2D games as a start you can look at the <a href="http://blog.shinylittlething.com/pygame/">PyGame tutorials list</a> page to see them all.</p>
<p>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&#8217;s events management.<br />
<span id="more-257"></span></p>
<h3>Credits</h3>
<p>As usual, I like to deserve credit where it&#8217;s due. I&#8217;d like to thank the following artists for their awesome work :</p>
<blockquote>
<ul>
<li>Clouds Brushes  by  <a href="http://javierzhx.deviantart.com"><strong>~JavierZhX</strong></a></li>
<li>Fighter by <strong><a href="http://prinzeugn.deviantart.com">~PrinzEugn</a></strong></li>
</ul>
</blockquote>
<h3>Class evolution &#8211; The Fighter</h3>
<p>Like <a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/">Parallax class</a> inherited from our base <a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/">AnimatedSprite class</a> in the previous article, we will create a new <strong>Fighter class</strong> (inheriting from AnimatedSprite class) and add specific members to handle it&#8217;s particular behaviors.</p>
<p>Let&#8217;s see some code first, I&#8217;ll go into explaining it just after.</p>
<pre>
<pre class="brush: 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
        &#039;&#039;&#039;
        The higher self.slowing_factor is,
        the longer it takes to stop a movement
        &#039;&#039;&#039;
        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&#039;s slices
    def move(self, direction):
      self.stoping = False
      W,H = RESOLUTION - self.image.get_size()
      x,y = self.location

      if direction == &#039;up&#039;:
        self.image = self._images[0]
        self.destination = Vector2(x, 0)

      elif direction == &#039;down&#039;:
        self.image = self._images[2]
        self.destination = Vector2(x, H)

      elif direction == &#039;left&#039;:
        self.destination = Vector2(0, y)

      elif direction == &#039;right&#039;:
        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)
</pre>
</pre>
<h4>New Members</h4>
<ul>
<blockquote>
<li><strong><em>stoping</em> </strong>(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 <strong>slowing down effect</strong>.</li>
<li><em><strong>slowing_factor</strong></em> (float) determines the ship&#8217;s inertia, the higher inertia is, the longer it takes to stop a movement.</li>
<li><em><strong>default_speed</strong></em> (float) is used to keep track of the original sprite&#8217;s speed and restore it when arrived to destination.</li>
</blockquote>
</ul>
<h4>New Methods</h4>
<p>event_handler method will make calls to appropriate method depending on the PyGame Event it received.</p>
<pre>
<pre class="brush: 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))
</pre>
</pre>
<p>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&#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).</p>
<pre>
<pre class="brush: python">
    def move(self, direction):
      self.stoping = False
      W,H = RESOLUTION - self.image.get_size()
      x,y = self.location

      if direction == &#039;up&#039;:
        self.image = self._images[0]
        self.destination = Vector2(x,0)

      elif direction == &#039;down&#039;:
        self.image = self._images[2]
        self.destination = Vector2(x,H)

      elif direction == &#039;left&#039;:
        self.destination = Vector2(0,y)

      elif direction == &#039;right&#039;:
        self.destination = Vector2(W,y)
</pre>
</pre>
<p>The stop method stops the sprite&#8217;s movement according to keys releases and restore the default sprite image. To avoid the sprite&#8217;s getting off the screen, we need to limit the coordinates to values comprised into  (RESOLUTION &#8211; sprite&#8217;s image size).</p>
<pre>
<pre class="brush: 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)
</pre>
</pre>
<h4>Overriden Methods</h4>
<p>The update method will be used to apply the slow down effect on movement stops.</p>
<pre>
<pre class="brush: 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
</pre>
</pre>
<h3>Instantiating Entities</h3>
<p>Let&#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.</p>
<pre>
<pre class="brush: python">
...
  fghtr  = Fighter(fighter, 60)
  elements.append(fghtr)
...
</pre>
</pre>
<p>Since other objects doesn&#8217;t need to handle Events, we&#8217;ll only add the fighter&#8217;s event handling method call to the events polling loop.</p>
<pre>
<pre class="brush: python">
  for event in pygame.event.get():
    fghtr.event_handler(event)
</pre>
</pre>
<p>This way, our sprite will be able to receive input from player and it&#8217;s location, destination and image will be accordingly updated and rendered.</p>
<h3>Source and Ressources</h3>
<p>The PyGame application is available for download here :</p>
<dl class="wp-caption aligncenter" style="width: 200px;">
<dt class="wp-caption-dt"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/shinyblog-pygame-event-handling.tar.gz"><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" /></a></dt>
<dd class="wp-caption-dd" style="text-align: center;"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/shinyblog-pygame-event-handling.tar.gz">PyGame &#8211; Event Handling Demo</a></dd>
</dl>
<p><em>Dependencies: </em></p>
<ul>
<li><a rel="nofollow" href="http://www.pygame.org/download.shtml">PyGame &gt;= 1.7.1</a></li>
<li><a rel="nofollow" href="http://code.google.com/p/gameobjects/">GameObjects &gt;= 0.0.2</a></li>
</ul>
<h3>Screenshot &amp; Conclusion</h3>
<div id="attachment_275" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/Capture-20.png"><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" /></a><p class="wp-caption-text">Fighter in Action (click for full size)</p></div>
<p>That&#8217;s what&#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&#8217;m still learning ;)</p>
<p>In the next article I&#8217;m planning to cover Fighter&#8217;s firing abilities aka, <em>bullet hell</em>. Stay tuned!</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">class Fighter(AnimatedSprite):<br />
def __init__(self, images, fps = 60):<br />
AnimatedSprite.__init__(self, images, fps)<br />
self.speed                     = 600.<br />
self.default_speed    = self.speed<br />
self.location             = (100, RESOLUTION[1]/2)<br />
self.destination         = self.location<br />
self.stoping                = False<br />
&#8221;&#8217;<br />
The higher self.slowing_factor is,<br />
the longer it takes to stop a movement<br />
&#8221;&#8217;<br />
self.slowing_factor = 10.</p>
<p># Forward movement image &#8211; default<br />
self.image                     = self._images[1]</p>
<p>def event_handler(self, event):<br />
if event.type == KEYUP:<br />
pygame.event.pump()<br />
pressed_keys = pygame.key.get_pressed()<br />
if 1 not in pressed_keys:<br />
self.stop(event.key)</p>
<p>if event.type == KEYDOWN:<br />
self.move(pygame.key.name(event.key))</p>
<p>def update(self, t):<br />
# Slowing effect<br />
if self.stoping is True:<br />
self.speed -= self.speed/self.slowing_factor</p>
<p>if self.stoping is False:<br />
self.speed = self.default_speed</p>
<p>def move(self, direction):<br />
# Overriden to make use differently of the image&#8217;s slices<br />
self.stoping = False<br />
W,H = RESOLUTION &#8211; self.image.get_size()<br />
x,y = self.location</p>
<p>if direction == &#8216;up&#8217;:<br />
self.image = self._images[0]<br />
self.destination = Vector2(x,0)</p>
<p>elif direction == &#8216;down&#8217;:<br />
self.image = self._images[2]<br />
self.destination = Vector2(x,H)</p>
<p>elif direction == &#8216;left&#8217;:<br />
self.destination = Vector2(0,y)</p>
<p>elif direction == &#8216;right&#8217;:<br />
self.destination = Vector2(W,y)</p>
<p>def stop(self, key):<br />
self.stoping = True<br />
W,H                 = RESOLUTION &#8211; self.image.get_size()<br />
x, y                 = self.destination<br />
xa,ya             = self.location<br />
w,h                 =    self.image.get_size()<br />
self.image     = self._images[1]</p>
<p># Stopping Y Axis Movements<br />
if key == K_UP:<br />
self.destination = Vector2(x, max(ya-h*self.slowing_factor, 0))</p>
<p>if key == K_DOWN:<br />
self.destination = Vector2(x, min(ya+h*self.slowing_factor, H))</p>
<p># Stopping X Axis Movements<br />
if key == K_LEFT:<br />
self.destination = Vector2(max(xa-w*self.slowing_factor, 0), y)</p>
<p>if key == K_RIGHT:<br />
self.destination = Vector2(min(xa+w*self.slowing_factor, W), y)</p></div>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &#8211; Take 2">PyGame and Animated Sprites &#8211; Take 2</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites">PyGame and Animated Sprites</a></li><li><a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &#8211; Parallax Scrolling in 2D games">PyGame &#8211; Parallax Scrolling in 2D games</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing">Gama: Pythonic Shiny Thing</a></li><li><a href="http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update">PyGame Tutorials Update</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=ob4yiCoxF_Q:Y0SnXXJ4wrc:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=ob4yiCoxF_Q:Y0SnXXJ4wrc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=ob4yiCoxF_Q:Y0SnXXJ4wrc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=ob4yiCoxF_Q:Y0SnXXJ4wrc:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/</feedburner:origLink></item>
		<item>
		<title>PyGame – Parallax Scrolling in 2D games</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/ZWSCvP-Q6BU/</link>
		<comments>http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 22:59:43 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Pygame]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[parallax]]></category>
		<category><![CDATA[scrolling]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=222</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/';
var dzone_title = 'PyGame &#8211; Parallax Scrolling in 2D games';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/';
reddit_title='PyGame &#8211; Parallax Scrolling in 2D games';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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 2D [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/';
var dzone_title = 'PyGame &#8211; Parallax Scrolling in 2D games';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/';
reddit_title='PyGame &#8211; Parallax Scrolling in 2D games';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>Hi fellow reader, to start this article let me define what Parallax Scrolling is :</p>
<blockquote><p><a title="Wikipedia" href="http://en.wikipedia.org/wiki/Parallax_scrolling"><strong>Parallax scrolling</strong></a> 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 2D video game and adding to the immersion. The technique grew out of the multiplane camera technique used in traditional animation since the 1940s</p></blockquote>
<p>I will reuse and adapt the AnimatedSprite Class from my previous article <a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/">PyGame and Animated Sprites &#8211; Take 2</a> and create a new Class named Parallax that inherits from AnimatedSprite.<br />
<span id="more-222"></span></p>
<pre>
<pre class="brush: 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)
</pre>
</pre>
<p>To handle movements of our <strong>parallax</strong> layers, we need to add some members to the base class. A movement is defined by the following variables :</p>
<p><strong>L</strong><strong>ocation,</strong> that will be continuously updated when in movement. <strong>Destination</strong>, in our case it will always be the same. <strong>Heading</strong> to face the right direction, in our case the direction will never change, finally the movement&#8217;s <strong>Speed</strong> in pixel by second.</p>
<p>To update all these values we need a <strong>process</strong> method that will update each element to it&#8217;s new location according to it&#8217;s speed.</p>
<p>For an analogy I&#8217;d say that a <strong>parallax</strong> is an image loop. To implement this loop we will override the default <strong>render</strong> method in a <strong>Parallax</strong> Class.</p>
<pre>
<pre class="brush: 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)
</pre>
</pre>
<p>Here is a quick schema to illustrate what is happening int the <strong>Parallax.render</strong> method :</p>
<p>Precisely when image A&#8217;s right edge enters screen&#8217;s clipping, blit another A image named A prime at location A.x + A.width.</p>
<div id="attachment_230" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/parallax.png"><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" /></a><p class="wp-caption-text">Image Loop</p></div>
<p>When A&#8217;s right edge is outside the screen clipping, reset it&#8217;s location to initial position. A prime will automatically follow it.</p>
<div id="attachment_232" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/parallax-21.png"><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" /></a><p class="wp-caption-text">Resetting the Loop</p></div>
<p>We are done. A image will repeat itself continuously.</p>
<p>Now to implement a <strong>parallax</strong>, you need at least two layers. So you&#8217;ll add layers with an increased speed setting following this simple rule : <strong> </strong></p>
<blockquote><p><strong>The closer an element is from the point of view, the faster it moves.</strong></p></blockquote>
<p>I bundled a Pygame application for you to download. My implementation is far from being perfect and I&#8217;d be interested in knowing about how you do it.</p>
<p style="text-align: center;">
<dl class="wp-caption aligncenter" style="width: 200px;">
<dt class="wp-caption-dt"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/tutorial-0001.zip"><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" /></a></dt>
<dd class="wp-caption-dd" style="text-align: center;"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/08/tutorial-0001.zip">Pygame Parallax Scrolling Demo</a></dd>
</dl>
<p><em>Dependencies: </em></p>
<ul>
<li><a rel="nofollow" href="http://www.pygame.org/download.shtml">PyGame &gt;= 1.7.1</a></li>
<li><a rel="nofollow" href="http://code.google.com/p/gameobjects/">GameObjects &gt;= 0.0.2</a></li>
</ul>
<p><strong>Demo Preview:</strong><br />
<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"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/Tn7bcWej8tY&amp;hl=fr&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="560" height="340" src="http://www.youtube.com/v/Tn7bcWej8tY&amp;hl=fr&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &#8211; Take 2">PyGame and Animated Sprites &#8211; Take 2</a></li><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites">PyGame and Animated Sprites</a></li><li><a href="http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update">PyGame Tutorials Update</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing">Gama: Pythonic Shiny Thing</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=ZWSCvP-Q6BU:Ueub8Qes5-U:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=ZWSCvP-Q6BU:Ueub8Qes5-U:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=ZWSCvP-Q6BU:Ueub8Qes5-U:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=ZWSCvP-Q6BU:Ueub8Qes5-U:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/</feedburner:origLink></item>
		<item>
		<title>PyGame and Animated Sprites – Take 2</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/enYPqD03UUE/</link>
		<comments>http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 21:48:13 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Pygame]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Sprites]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=210</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/';
var dzone_title = 'PyGame and Animated Sprites &#8211; Take 2';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/';
reddit_title='PyGame and Animated Sprites &#8211; Take 2';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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

Related PostsPyGame &#8211; Event HandlingPyGame &#8211; Parallax Scrolling in 2D gamesPyGame and Animated SpritesPyGame Tutorials UpdateGama: Pythonic Shiny Thing]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/';
var dzone_title = 'PyGame and Animated Sprites &#8211; Take 2';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/';
reddit_title='PyGame and Animated Sprites &#8211; Take 2';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>I made a demo to better illustrate the topic covered in my previous post : <a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/">PyGame and Animated Sprites </a></p>
<p>Here&#8217;s a screenshot of the application :</p>
<div id="attachment_213" class="wp-caption aligncenter" style="width: 309px"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/07/screenshot.png"><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" /></a><p class="wp-caption-text">Animated Explosions Sprites</p></div>
<p style="text-align: center;">
<p style="text-align: left;">Download the Source code of the demo :</p>
<p style="text-align: left;"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/07/explosion-spritetar1.gz">explosion-spritetar.tar.gz</a></p>
<p style="text-align: left;">
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &#8211; Parallax Scrolling in 2D games">PyGame &#8211; Parallax Scrolling in 2D games</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites">PyGame and Animated Sprites</a></li><li><a href="http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update">PyGame Tutorials Update</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing">Gama: Pythonic Shiny Thing</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=enYPqD03UUE:oVca2sCWK78:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=enYPqD03UUE:oVca2sCWK78:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=enYPqD03UUE:oVca2sCWK78:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=enYPqD03UUE:oVca2sCWK78:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/</feedburner:origLink></item>
		<item>
		<title>PyGame and Animated Sprites</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/uA7EPiL3gwE/</link>
		<comments>http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/#comments</comments>
		<pubDate>Tue, 21 Jul 2009 08:27:39 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Pygame]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Sprites]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=192</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/';
var dzone_title = 'PyGame and Animated Sprites';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/';
reddit_title='PyGame and Animated Sprites';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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;
-----------------------------------------
For a  given framerate set [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/';
var dzone_title = 'PyGame and Animated Sprites';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/';
reddit_title='PyGame and Animated Sprites';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>An animated sprite is a serie of the same image slightly modified and displayed at a certain framerate per second.</p>
<div id="attachment_191" class="wp-caption aligncenter" style="width: 150px"><a href="http://lostgarden.com/2007/04/free-game-graphics-tyrian-ships-and.html"><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" /></a><p class="wp-caption-text">Explosion Sprite sampled from Remastered Tyrian Graphics @ Lost Garden</p></div>
<p style="text-align: center;"><a href="http://lostgarden.com/2007/04/free-game-graphics-tyrian-ships-and.html"></a></p>
<p>Sample 5 frames Sprite representation:</p>
<pre>-----------------------------------------
|   1   |   2   |   3   |   4   |   5   |
| 16x16 | 16x16 | 16x16 | 16x16 | 16x16 |
|       |       |       |       |       |
-----------------------------------------</pre>
<p>For a  given framerate set to 30fps :</p>
<ol>
<li>Frame 1 is blited at now()</li>
<li>Frame 2 blitted 1000/30 seconds after Frame 1</li>
<li>Frame 3 blitted 1000/30 seconds after Frame 2</li>
</ol>
<p>and so on.</p>
<p><span id="more-192"></span></p>
<p>This gives the illusion of motion.</p>
<p>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&#8217;s <a href="http://www.pygame.org/docs/ref/surface.html#Surface.subsurface"><strong>Subsurface</strong></a> Method</p>
<p>I made an helper function to load and slice such sprites:</p>
<pre>
<pre class="brush: python">
def load_sliced_sprites(self, w, h, filename):
    &#039;&#039;&#039;
    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 &quot;ressources&quot;
    &#039;&#039;&#039;
    images = []
    master_image = pygame.image.load(os.path.join(&#039;ressources&#039;, 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
</pre>
</pre>
<p>Use it like this :</p>
<pre>
<pre class="brush: python">
&#039;&#039;&#039; Asuming your frames have a 16x16 size &#039;&#039;&#039;
explosion_images = load_sliced_sprites(16, 16, &#039;explosions-sprite.png&#039;)
</pre>
</pre>
<p>explosion_images will then be an iterable list so you can use it with this kind of class courtesy of the excellent <a href="http://www.sacredchao.net/~piman/writing/sprite-tutorial.shtml">piman&#8217;s Sprites Tutorial</a> :</p>
<pre>
<pre class="brush: 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&#039;t work if it&#039;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
</pre>
<p>Happy Learning!</pre>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &#8211; Take 2">PyGame and Animated Sprites &#8211; Take 2</a></li><li><a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &#8211; Parallax Scrolling in 2D games">PyGame &#8211; Parallax Scrolling in 2D games</a></li><li><a href="http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update">PyGame Tutorials Update</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/" title="Gama: Pythonic Shiny Thing">Gama: Pythonic Shiny Thing</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=uA7EPiL3gwE:cFpIxVuCvxs:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=uA7EPiL3gwE:cFpIxVuCvxs:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=uA7EPiL3gwE:cFpIxVuCvxs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=uA7EPiL3gwE:cFpIxVuCvxs:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/</feedburner:origLink></item>
		<item>
		<title>Gama: Pythonic Shiny Thing</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/E9_qmLqoGos/</link>
		<comments>http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/#comments</comments>
		<pubDate>Tue, 21 Jul 2009 07:54:21 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Gama]]></category>
		<category><![CDATA[Pygame]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=185</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/';
var dzone_title = 'Gama: Pythonic Shiny Thing';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/';
reddit_title='Gama: Pythonic Shiny Thing';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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 from It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/';
var dzone_title = 'Gama: Pythonic Shiny Thing';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/';
reddit_title='Gama: Pythonic Shiny Thing';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>Hello dear Shiny reader,</p>
<p>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.</p>
<p>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 from <a href="http://www.willmcgugan.com/blog/tech/">It&#8217;s All Geek to Me</a>, Will McGugan&#8217;s tech blog.</p>
<p>I learned some very interesting concept over here like : <a href="http://www.willmcgugan.com/blog/tech/2007/10/4/free-chapter-of-beginning-game-development-with-python-and-pygame/">A.I. with State Machines</a>, <a href="http://www.willmcgugan.com/blog/tech/2007/4/30/swim-turtle-swim/">Pathfinding</a> (not yet assimilated though) and <a href="http://www.willmcgugan.com/blog/tech/2007/6/15/master-time-with-pygame/">Time Management</a> I even bought Will&#8217;s book <a href="http://www.amazon.fr/gp/product/1590598725?ie=UTF8&amp;tag=moblurorg-21&amp;linkCode=as2&amp;camp=1642&amp;creative=6746&amp;creativeASIN=1590598725">Beginning Game Development With Python and Pygame: From Novice to Professional</a><img style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.fr/e/ir?t=moblurorg-21&amp;l=as2&amp;o=8&amp;a=1590598725" border="0" alt="" width="1" height="1" />.</p>
<p>Most of the game <a href="http://lostgarden.com/2007/04/free-game-graphics-tyrian-ships-and.html">old school graphics</a> come from the talented and  generous <a href="http://lostgarden.com/">Lost Garden </a></p>
<p>You can find the source code and ressources of the simulation on <a href="http://github.com/ncrovatti/Gama/tree/master">github</a> or using this command :</p>
<p><code>git clone git://github.com/ncrovatti/Gama.git </code></p>
<p><strong>Dependencies: </strong></p>
<ul>
<li><a href="http://www.pygame.org/download.shtml">PyGame &gt;= 1.7.1</a><a href="http://code.google.com/p/gameobjects/"></a></li>
<li><a href="http://code.google.com/p/gameobjects/">GameObjects &gt;= 0.0.2</a></li>
</ul>
<p><strong>UPDATE</strong></p>
<p>Here&#8217;s an in-game screenshot</p>
<div id="attachment_206" class="wp-caption aligncenter" style="width: 443px"><a href="http://blog.shinylittlething.com/wp-content/uploads/2009/07/gama-1.png"><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" /></a><p class="wp-caption-text">Gama - In Game Screeshot showing Paths (click for full size)</p></div>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.shinylittlething.com/2009/08/14/pygame-tutorials-update/" title="PyGame Tutorials Update">PyGame Tutorials Update</a></li><li><a href="http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/" title="PyGame &#8211; Parallax Scrolling in 2D games">PyGame &#8211; Parallax Scrolling in 2D games</a></li><li><a href="http://blog.shinylittlething.com/2009/07/22/pygame-and-animated-sprites-take-2/" title="PyGame and Animated Sprites &#8211; Take 2">PyGame and Animated Sprites &#8211; Take 2</a></li><li><a href="http://blog.shinylittlething.com/2009/07/21/pygame-and-animated-sprites/" title="PyGame and Animated Sprites">PyGame and Animated Sprites</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=E9_qmLqoGos:FAvFeau6TY8:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=E9_qmLqoGos:FAvFeau6TY8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=E9_qmLqoGos:FAvFeau6TY8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=E9_qmLqoGos:FAvFeau6TY8:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/07/21/gama-pythonic-shiny-thing/</feedburner:origLink></item>
		<item>
		<title>Multiple file upload using jQuery and Ruby on Rails Tutorial</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/Zy2OzQXRoGQ/</link>
		<comments>http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 07:44:57 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=169</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/';
var dzone_title = 'Multiple file upload using jQuery and Ruby on Rails Tutorial';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/';
reddit_title='Multiple file upload using jQuery and Ruby on Rails Tutorial';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
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 lines shown [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/';
var dzone_title = 'Multiple file upload using jQuery and Ruby on Rails Tutorial';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/';
reddit_title='Multiple file upload using jQuery and Ruby on Rails Tutorial';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<h3>Outline</h3>
<p>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.</p>
<p>Since I don&#8217;t have any Windows or MacOS, the command lines shown in this tutorial<br />
are known working on Debian linux system. I&#8217;m sure you will find your way for your specific OS!</p>
<p>The application will allow users to upload as many image files as they want and return the following information to them :</p>
<ul>
<li>Relative paths to successfully uploaded files</li>
<li>Width and Height for each uploaded file</li>
</ul>
<h3>Prerequisites</h3>
<p>To follow this tutorial you will need to install the Ruby on Rails framework on your system.<br />
You will also need copies of <a href="http://jquery.com/">jQuery</a> and <a href="http://malsup.com/jquery/form/">jQuery Form plugin</a>.</p>
<p><span id="more-169"></span></p>
<h3>Application &amp; Server</h3>
<p>You may want to skip this part if you are enabling multiple file upload for an existing Rails app.</p>
<p>Rails app creation from an empty directory :</p>
<pre class="code" lang="shell">
<pre class="brush: shell">$ ruby rails myApplicationName</pre>
</pre>
<p>Server Spawn :</p>
<pre class="code" lang="shell">
<pre class="brush: shell">$ ruby script/server</pre>
</pre>
<p>Or if you already have an application running here is how to spawn it on a different port :</p>
<pre class="code" lang="shell">
<pre class="brush: shell">$ ruby script/server -p 3001</pre>
</pre>
<h3>Scaffolding</h3>
<p>First things first, model and controller Scaffolding :</p>
<pre class="code" lang="shell">
<pre class="brush: 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</pre>
</pre>
<pre class="code" lang="shell">
<pre class="brush: 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</pre>
</pre>
<p>These simple &#8220;script/generate&#8221; commands generate the stub files for our application.</p>
<h3>Application View</h3>
<p>Let&#8217;s directly edit our view by setting up a simple HTML form and a container for our images in<br />
<code>app/views/upload/uploadfile.html.erb</code> this file is not part of the Scaffolding, just go ahead and create it yourself :</p>
<pre class="code" lang="html">
<pre class="brush: 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=&quot;post&quot; action=&quot;/services/uploadr&quot;
    enctype=&quot;multipart/form-data&quot;
    class=&quot;upload&quot; id=&quot;upload_form&quot;&gt;
        &lt;br/&gt;
        &lt;input type=&quot;button&quot; id=&quot;button&quot; class=&quot;button&quot; value=&quot;Add File&quot; /&gt;
        &lt;input type=&quot;submit&quot; id=&quot;save&quot; class=&quot;save&quot; value=&quot;Upload&quot; /&gt;
&lt;/form&gt;

&lt;h3&gt;Images&lt;/h3&gt;
&lt;div lang=&quot;images_container&quot;&gt;&lt;/div&gt;</pre>
</pre>
<p>The important things in the HTML are the <code>form</code> tag&#8217;s attributes :<br />
the method must be <code>"post"</code> and the encoding type set to <code>"multipart/form-data"</code>.<br />
The &#8220;post&#8221; method allows unlimited size requests (compared to approximately 2000 characters maximum for the &#8220;get&#8221; method).<br />
The <code>multipart/form-data</code> encoding type tells the application that we want to transfer some kind of non-ASCII or binary data.</p>
<p>Note that we could had achieved the very same result using the Rails Form Helper. Here are the required options for the helper :</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby">&lt;% form_for :upload, :html =&gt; { :multipart =&gt; true, :id =&gt; &quot;upload_form&quot; },
            :method =&gt; &#039;post&#039;,
            :url =&gt; { :action =&gt; &quot;upload&quot; } do |f| %&gt;
  &lt;!--  add fields here --&gt;
&lt;% end %&gt;</pre>
</pre>
<p>I am assuming that you know how to include the jQuery library and Forms plugin in your default application javascript file.</p>
<p>Let&#8217;s move on and add the basic jQuery code to allow on-the-fly file fields creation :</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">// public/javascripts/application.js

$(document).ready(function() {
  $(&quot;#button&quot;).bind(&quot;click&quot;, function() {
    /* Generating unique id
    */
    var rand = Math.random().toString().split(&quot;.&quot;)[1];
    var input = &#039;&lt;input type=&quot;file&quot; class=&quot;&#039;+rand+&#039;&quot; /&gt;&#039;
    $(this).before(&#039;&lt;br/&gt;&#039; + input );
  });

  /* Pushing the first input to the DOM
  */
  $(&quot;#button&quot;).trigger(&quot;click&quot;);

});</pre>
</pre>
<p>Since we will be using the DOM selector to bind functions to our user interface&#8217;s inputs,<br />
we need to tell the browser to wait for the elements to be rendered<br />
before executing any code contained in the <code>ready()</code> callback function.<br />
This will avoid any Javascript interpreter complaint about null or non-existent<br />
elements.</p>
<p>We do not want to enable the Forms plugin yet because it will be easier for us<br />
in the developement process.</p>
<p>If you try to access your app now, Rails will complain about an unknown<br />
action, we will have to edit our upload controler to insert a default action:</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># app/controllers/upload_controller.rb

language UploadController &lt; ApplicationController
  protect_from_forgery :only =&gt; [:create, :update, :destroy] 

  def index
     render :file =&gt; &#039;app/views/upload/uploadfile.html.erb&#039;
  end
end</pre>
</pre>
<p><code>protect_from_forgery</code>: Since we are not using the Rails Form Helper, we need to limit the use of the Authenticity Token for our controller.<br />
The default <code>index</code> method displays the HTML file with our<br />
HTML form located at <code>app/views/upload/uploadfile.html.erb</code>.</p>
<p>The <code>index</code><br />
method in Rails acts the same way as the default indexes files on web servers i.e: when<br />
no methods are specified the <code>index</code> method will be executed.</p>
<p>At this point,you should have something very similar to this:</p>
<p><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" /></p>
<p>and you can add as many file fields as you want by clicking the &#8220;Add File&#8221; button.</p>
<p>Let&#8217;s get back to our code; did you spot the problem we will encounter here?</p>
<p>We have no way of knowing the names of the generated inputs thus making it difficult to differentiate them from other parameters<br />
in the Ruby on Rails web service.</p>
<p>In order to recognize them among all the other possible parameters we will wrap them in an array. Simply modify the <code>input</code> variable in the javascript snippet:</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">// public/javascripts/application.js
var rand = Math.random().toString().split(&quot;.&quot;)[1];
var input = &#039;&lt;input type=&quot;file&quot; class=&quot;images[&#039;+rand+&#039;]&quot; /&gt;&#039;</pre>
</pre>
<p>That simple trick will allows us to use the Ruby&#8217;s <code>each()</code> function to loop through uploaded images.</p>
<h3>Application Model</h3>
<p>On to our UploadedFile model :</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># app/models/uploaded_file.rb

require &#039;image_size.rb&#039;

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 + &quot;.&quot; + upload.original_filename.split(&quot;.&quot;).last 

    # target directory to save files
    directory = &quot;public/images/users/&quot;

    # create the file path
    path = File.join(directory, name)

    # write the file
    File.open(path, &quot;wb&quot;) { |f| f.write(upload.read) }

    img = ImageSize.new(open(path))

    return {
      &quot;width&quot;     =&gt; img.get_width,
      &quot;height&quot;    =&gt; img.get_height,
      &quot;filename&quot;  =&gt; name
    }

  end
end</pre>
</pre>
<p>A point to note here. I have included the ImageSize lib. If you don&#8217;t have it installed yet proceed like this as root:</p>
<pre class="code" lang="shell">
<pre class="brush: shell"># apt-get install libimage-size-ruby1.8</pre>
</pre>
<p>*or* my guess for Mac OS X and Windows (I can&#8217;t test these platforms) :</p>
<pre class="code" lang="shell">
<pre class="brush: shell"># gem install imagesize</pre>
</pre>
<p>As you can see it&#8217;s pretty straight forward.</p>
<p>The <code>save</code> method takes only two arguments:</p>
<ul>
<li><code>id</code> which is our unique field name</li>
<li><code>upload</code> which is the uploaded file reference</li>
</ul>
<h3>Application Controller</h3>
<p>Let&#8217;s add the <code>upload</code> method to our UploadController controller.<br />
This method will actually be our web service.</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># app/controllers/upload_controller.rb

language UploadController &lt; ApplicationController
  def index
     render :file =&gt; &#039;app/views/upload/uploadfile.html.erb&#039;
  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</pre>
</pre>
<p>The <code>upload</code> method creates an instance variable<br />
(prefixed by @) <code>@post</code> to store our images data. An instance variable<br />
differs from other variables in that it will be available to work with in our view.</p>
<p>Then, for each item in the <code>params[:images]</code> array (the one we created by<br />
grouping all our images inputs) it will add a new entry to our<br />
<code>@post</code> array.</p>
<p>As you can see, Ruby on Rails code is really easy to read and understand.</p>
<h3>Routes</h3>
<p>In order to access our newly created web service we have to create a named route.<br />
A named route will allow us to give a name that fits our logical organisation<br />
and to set various usage restrictions to our action.</p>
<p>Edit the <code>config/routes.rb</code> file to configure the routes :</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># config/routes.rb

ActionController::Routing::Routes.draw do |map|
map.connect &#039;/services/uploadr&#039;,
  :controller =&gt; &#039;upload&#039;,
  :action =&gt; &#039;upload&#039;,
  :conditions =&gt; {
    :method =&gt; :post
  }

  map.connect &#039;:controller/:action/:id&#039;
  map.connect &#039;:controller/:action/:id.:format&#039;
end</pre>
</pre>
<p>Ok, our <code>upload</code> action will now respond to the path <code>/services/uploadr</code></p>
<p>and only for <code>post</code> requests.</p>
<h3>Webservice&#8217;s View</h3>
<p>Our UploadController will need to use its corresponding view to send back its results to<br />
the browser, just create it and insert the following snippet in it :</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># app/view/upload/upload.html.erb

&lt;% @post.each  do |image|  %&gt;
  &lt;img src=&quot;/images/users/&lt;%= image[&quot;filename&quot;] %&gt;&quot;/&gt;
  &lt;br/&gt;
  &lt;%= image[&quot;width&quot;] %&gt; x &lt;%= image[&quot;height&quot;] %&gt;
  &lt;br/&gt;

&lt;% end %&gt;</pre>
</pre>
<p>This simple erb template renders all the information we planned to send back to the client with some formatting applied.</p>
<p><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" /></p>
<p>You can now test your newly created application using the form located in <code>http://localhost:3000/upload/</code> if you kept the default settings.</p>
<p>Here&#8217;s is a capture of a similar result after the form has been sent :</p>
<p>If images aren&#8217;t showing up you may have a permission problem or a bug in your code.</p>
<p>Verify your <code>RAILS_ROOT/public/images/users/</code> path to see if the<br />
permissions are correct. If this does not resolve your problem please re-read<br />
this tutorial again to ensure you did not miss a step.</p>
<p>The default HTML view for our upload controller is fine to preview our work so far;<br />
but it might be hard to do anything with it with javascript.</p>
<p>We will now add a json format for this view. Json (JavaScript Object Notation )<br />
is the (my) format of choice for client/server communication using XHR.<br />
It is lightweight (lighter than XML), many server side programming and scripting<br />
languages have JSON implementation either natively, using plugins or at least<br />
libraries.</p>
<p>Finally it&#8217;s native javascript language and this is an huge plus.</p>
<h3>JSON communication</h3>
<p>Let&#8217;s implement this new format by editing our upload controller first :</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># app/controllers/upload_controller.rb

language UploadController &lt; ApplicationController
    protect_from_forgery :only =&gt; [:create, :update, :destroy] 

    def index
      render :file =&gt; &#039;app/views/upload/uploadfile.html.erb&#039;
    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</pre>
</pre>
<p>Implementing this new format is easy as 1,2,3 in the Rails framework, just add<br />
this single line in our <code>respond_to</code> block :<br />
<code>format.js  { render :json =&gt; @post }</code>.<br />
Literaly, this line of code will activate the automated json rendering of our <code>@post</code></p>
<p>object and will send back the result with adequate HTTP headers and mime-type<br />
to the client.</p>
<p>We have to modify the routes in order to point to the json format :</p>
<pre class="code" lang="ruby">
<pre class="brush: ruby"># config/routes.rb

ActionController::Routing::Routes.draw do |map|
  map.connect &#039;/services/uploadr&#039;,
  	:controller =&gt; &#039;upload&#039;,
	  :action =&gt; &#039;upload&#039;,
	  :format =&gt; &#039;js&#039;,
	  :conditions =&gt; {
	    :method =&gt; :post
	  }

  map.connect &#039;:controller/:action/:id&#039;
  map.connect &#039;:controller/:action/:id.:format&#039;
end</pre>
</pre>
<p>Basicaly I just added the <code>:format =&gt; 'js'</code> parameter to our<br />
previously created named route <code>/services/uploadr</code>. That&#8217;s it!</p>
<p>You can now test your application again. Here is an example content of the generated file :</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">[
  {
    &quot;filename&quot;: &quot;38396648300918923.png&quot;,
    &quot;height&quot;: 171,
    &quot;width&quot;: 422
  },
  {
    &quot;filename&quot;: &quot;5770189283356341.png&quot;,
    &quot;height&quot;: 165,
    &quot;width&quot;: 549
  }
]</pre>
</pre>
<p>Perfect, now if we add data into the <code>@post</code> object it will be<br />
automagicaly serialized.</p>
<h3>Front End</h3>
<p>Now that our backend webservice is ready let&#8217;s build our frontend in javascript and jQuery.</p>
<p>First we will activate the <code>ajaxForm</code> method from the Forms plugins<br />
in our HTML form and bind a new function to our submit button.</p>
<p>Due to Forms plugins limitations using both files fields and JSON communication,<br />
we will be forced to hack a bit; The JSON data will be returned wraped in <code>&lt;pre&gt;</code><br />
tags. Let&#8217;s get rid of them and evaluate the string containing the JSON to transform<br />
it into a JSON object.</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">// public/javascripts/application.js

$(document).ready(function() {
  $(&quot;#button&quot;).bind(&quot;click&quot;, function() {
    /* Generating unique id
    */
    var rand = Math.random().toString().split(&quot;.&quot;)[1];
    var input = &#039;&lt;input type=&quot;file&quot; id=&quot;upload_field_&#039;+rand+&#039;&quot; class=&quot;images[&#039;+rand+&#039;]&quot; /&gt;&#039;
    $(this).before(input + &#039;&lt;br/&gt;&#039;);
  });

  /* Pushing the first input to the DOM
  */
  $(&quot;#button&quot;).trigger(&quot;click&quot;);

  /* Enabling Ajax form on #upload_form
  */
  $(&quot;#upload_form&quot;).ajaxForm();

  $(&quot;#upload_form&quot;).submit(function() {
    $(this).ajaxSubmit({
      dataType  : &#039;html&#039;,
      iframe 	  : true,
      success	  : function (data) {
        data = eval(data.replace(&quot;&lt;pre&gt;&quot;, &quot;&quot;).replace(&quot;&lt;/pre&gt;&quot;, &quot;&quot;));
      }
    });
    return false;
  });
});</pre>
</pre>
<p>That done our data is ready to be processed on the client side. Let&#8217;s go ahead<br />
and add some functionality.</p>
<h3>JSON data processing</h3>
<p>With our new JSON object we are now able to display uploaded images to our image<br />
container. All the code could be split up into functions or even wraped into an<br />
object; this part depends on your project&#8217;s requirements and/or on your personal coding rules.<br />
I&#8217;ll go for the inline code for this tutorial.</p>
<p>All the following code goes into the <code>success</code> callback function.</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">function (data) {
  files = eval(data.replace(&quot;&lt;pre&gt;&quot;, &quot;&quot;).replace(&quot;&lt;/pre&gt;&quot;, &quot;&quot;));

  for(var i in files) {
    var id      = files[i].filename.split(&quot;.&quot;)[0];
    var img     = new Image();
    img.src     = &quot;/images/users/&quot; + files[i].filename;
    img.height  = files[i].height;
    img.width   = files[i].width;
    img.id      = &quot;img_display_&quot; + id

    $(&quot;.images_container&quot;).append(img);
    var $file = $(&quot;#upload_field_&quot; + id);
    $file.next().remove();
    $file.remove();

  }

  if($(&quot;input[type*=&#039;file&#039;]&quot;).length == 0) {
    $(&quot;#button&quot;).trigger(&quot;click&quot;);
  }
}</pre>
</pre>
<p>What is this function doing ?</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">    var id      = files[i].filename.split(&quot;.&quot;)[0];
    var img     = new Image();
    img.src     = &quot;/images/users/&quot; + files[i].filename;
    img.height  = files[i].height;
    img.width   = files[i].width;
    img.id      = &quot;img_display_&quot; + id</pre>
</pre>
<p>Our data transformed into an object we can loop through it to display<br />
the uploaded images. For each file a new Image object is created and it&#8217;s properties filled with<br />
what our webservice sent back.</p>
<p>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.</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">    $(&quot;.images_container&quot;).append(img);
    var $file = $(&quot;#upload_field_&quot; + id);
    $file.next().remove();
    $file.remove();</pre>
</pre>
<p>We are using the <code>append()</code> jQuery method to add the newly uploaded<br />
file to our im ages container. We have to remove the remaining <code>&lt;br/&gt;</code><br />
tag next to our file field prior to delete the input itself to avoid any unwanted<br />
blank space in our layout.</p>
<p>To prevent sending the same image the next time the user submit the form,<br />
we are removing the file input.</p>
<pre class="code" lang="javascript">
<pre class="brush: javascript">  if($(&quot;input[type*=&#039;file&#039;]&quot;).length == 0) {
    $(&quot;#button&quot;).trigger(&quot;click&quot;);
  }</pre>
</pre>
<p>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 &#8220;Add file&#8221; button.</p>
<h3>Conclusion</h3>
<p>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.</p>
<h3>Credits</h3>
<p>I couldn&#8217;t safely close this tutorial without giving credits where it&#8217;s due! I would like to particulary thank <a href="http://twitter.com/mcaulay">Mark Mcaulay</a> and <a href="http://twitter.com/pet3r">Peter Szinek</a> for their great help, feedback and awesomeness!</p>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/" title="Enabling Dynamic Plugin Support for your JavaScript Application">Enabling Dynamic Plugin Support for your JavaScript Application</a></li><li><a href="http://blog.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">8 Ajax Data Controls and Effects to Work with Tables</a></li><li><a href="http://blog.shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience">7 jQuery Plugins to Really Enhance Users Experience</a></li><li><a href="http://blog.shinylittlething.com/2009/02/20/image-manipulation-jquery-plugins/" title="6 Image Manipulation Plugins for jQuery You Should Know About">6 Image Manipulation Plugins for jQuery You Should Know About</a></li><li><a href="http://blog.shinylittlething.com/2009/02/25/fork-me-im-famous/" title="Fork me, I&#8217;m Famous">Fork me, I&#8217;m Famous</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=Zy2OzQXRoGQ:Va_IDurTkbg:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=Zy2OzQXRoGQ:Va_IDurTkbg:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=Zy2OzQXRoGQ:Va_IDurTkbg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=Zy2OzQXRoGQ:Va_IDurTkbg:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/07/20/multiple-file-upload-using-jquery-and-ruby-on-rails-tutorial/</feedburner:origLink></item>
		<item>
		<title>Home Web Hosting Best Practices</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/xFkRCLhmh2U/</link>
		<comments>http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 07:01:10 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[Server]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[DIY]]></category>
		<category><![CDATA[webhosting]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=34</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/';
var dzone_title = 'Home Web Hosting Best Practices';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/';
reddit_title='Home Web Hosting Best Practices';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
Welcome dear reader. Today I&#8217;m sharing with you my experience on how to be your own web host.
Before you read any further, I&#8217;ll ask you some questions to help you to determine if  you Should.

Do you have any knowledge about how internet is working ? I mean technical stuff like protocols, ports or DNS or,
Do [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/';
var dzone_title = 'Home Web Hosting Best Practices';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/';
reddit_title='Home Web Hosting Best Practices';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>Welcome dear reader. Today I&#8217;m sharing with you my experience on how to be your own web host.</p>
<p>Before you read any further, I&#8217;ll ask you some questions to help you to determine if  you Should.</p>
<ol>
<li>Do you have any knowledge about how internet is working ? I mean technical stuff like protocols, ports or DNS or,</li>
<li>Do you want to learn how it all works ?</li>
<li>Do you have a lot of time ?</li>
<li>Do you take the risk for your site ?</li>
</ol>
<p>If you answered Yes to all these questions then you probably should do host your own website or blog from home, else you can still continue your reading for information or share this post with a friend who expressed this idea.</p>
<p>Note: I will not cover every parts of how to set up your host. It&#8217;s up to you to find the specific informations for your particular hardware, OS, ISP and router combination.</p>
<p>In this post I&#8217;ll try to cover what I learned the hard way,  what I actually found that works better.</p>
<p><span id="more-34"></span></p>
<h3>1. Hardware</h3>
<p><img class="aligncenter size-full wp-image-67" title="step1" src="http://blog.shinylittlething.com/wp-content/uploads/2009/03/step1.jpg" alt="step1" width="550" height="197" /></p>
<p style="padding-left: 30px;"><strong>Rule 1</strong> &#8211; Don&#8217;t go too cheap on hardware.  If you do, you will have to use your backups and that&#8217;s time consuming and coupled with heavy downtimes.</p>
<p style="padding-left: 30px;"><strong>Rule 2</strong> &#8211; Go silent. Nothing is worse than an old, noisy, dusty PC running continuously in your living room. As a personal choice I use a <a href="http://en.wikipedia.org/wiki/Netbook">netbook</a> as my server for hosting this very blog.</p>
<p style="padding-left: 30px;">At the time of this article, Netbooks with SSD storage device are the most silent PC on the market and if applicable, their look and size will please your wife. On top of that, they are wifi enabled out of the box, wich is kind of really awesome if you want to stock your server in a remote place in your house.</p>
<p>If you don&#8217;t mind noise and dust, or if you can&#8217;t affoard anybetter go for an old PC, with the right OS and configuration even an old PC can revive and serve at it&#8217;s best.  For old hardware nothing better than a fresh linux distribution.</p>
<blockquote><p><strong>Tip: </strong>If you go for a netbook or a notebook as webserver, remove the battery pack so it won&#8217;t kill its longevity.</p></blockquote>
<blockquote><p><strong>Tip: </strong>If you go for SSD storage also go for a noatime in your /etc/fstab, this will prevent a write for every read and decrease the  read time and increase longevity.</p></blockquote>
<blockquote><p><strong>Tip:</strong> If you go for old hardware, go linux. Linux scales better, linux runs with low ressources, linux is better at web hosting from home, linux is free, linux is <a href="http://www.ubuntu.com/">here</a>, <a href="http://www.debian.org/">here</a> and <a href="http://www.slackware.com/">here</a>, depending on your level.</p></blockquote>
<h3>2. Software</h3>
<p><img class="aligncenter size-full wp-image-68" title="step2" src="http://blog.shinylittlething.com/wp-content/uploads/2009/03/step2.jpg" alt="step2" width="550" height="165" /></p>
<p>This choice is really up to you and what you want to host; Blog ? Gallery ? Portfolio ? Personal Sandbox ? Everything is now at your reach; Without any limitation except for your will to learn.</p>
<p>Nettuts contains a wide variety of tutorials that I know will grately help you in this task.</p>
<p>Note that, the backend softwares will be often dictated by the frontend software you choose. Be wise in your choices.</p>
<h3>3. Monitoring</h3>
<p><img class="aligncenter size-full wp-image-69" title="step3" src="http://blog.shinylittlething.com/wp-content/uploads/2009/03/step3.jpg" alt="step3" width="550" height="178" /></p>
<p>Every good server is monitored.  There&#8217;s plenty of tools to monitor your server, here&#8217;s a couple that are not hard to setup :</p>
<ul>
<li><a href="http://oss.oetiker.ch/mrtg/">Tobi Oetiker&#8217;s MRTG</a> : Easy install and setup. Enough information to know what going on on about anything from Network traffic to Harddrive temperature.</li>
<li><a href="http://www.snort.org/">Snort</a> : Network Intrusion Detection System (NIDS). This tool will help you to know and prevent supicious activity on your network, remember, you will be directly serving to the internet.</li>
<li>Web stats : You may want to use Google analytics free service to monitor your visitors, but you maybe also want a log parser like Webalizer of Awstats to keep track of bandwidth and untracked files like MP3, images or videos.</li>
</ul>
<h3>4. Backup Strategies</h3>
<p><img class="aligncenter size-full wp-image-70" title="step4" src="http://blog.shinylittlething.com/wp-content/uploads/2009/03/step4.jpg" alt="step4" width="550" height="174" /></p>
<p>The most important thing to do when you are your own webhost is to backup your data, wait, not exactly; the MOST important thing is to be able to actually RESTORE your backuped data. It&#8217;s may sounds funny but, hey, give it a try :)</p>
<p style="padding-left: 30px;"><strong>Rule 1</strong> &#8211; Be organized.</p>
<p style="padding-left: 30px;"><strong>Rule 2</strong> &#8211; Setup cronjobs that never forgets to do their dutty.</p>
<p style="padding-left: 30px;"><strong>Rule 3</strong> &#8211; Never trust hardware. Assume it will fail.</p>
<p>Here an example backup strategy you can use for your own blog :</p>
<p>Make archives of files once a day, if you have many sites, make a single archive for each of them. The filename must be named after the site&#8217;s name + day of the week combination.</p>
<p><strong>Example:</strong> blog.shinylittlething.com-wd4.tar.gz</p>
<p>Make an archive for each databases following the sames rules :</p>
<p><strong>Example:</strong> db-dump-wd4.bz2</p>
<blockquote><p><strong>Tip:</strong> You can find the day of the week in unix systems using the date command :  <code>$ date +"%u"</code></p></blockquote>
<p>Once the backup script is done, make it run once a day when your traffic is very low, possibly at night and upload everything to  a remote host or on a separate Harddrive. I do prefer to send all my data to a trusted host once a day but you might find handy to store everything on a USB pen aswell to allow offline data access.</p>
<p>You will end with a 7 days backups rotation of all your sensitive data.  You may want to have a longer period rotation if you have large storage you may want to use the day of the month.</p>
<h3>5. Bandwidth Issues</h3>
<p><img class="aligncenter size-full wp-image-71" title="step5" src="http://blog.shinylittlething.com/wp-content/uploads/2009/03/step5.jpg" alt="step5" width="550" height="138" /></p>
<p>ADSL. What important here is the &#8220;A&#8221;. That means Asymmetric. In other terms, if something eats up all your bandwidth in any direction, the other direction will be affected. That&#8217;s why you will have to carefully watch your bandwith.</p>
<p style="padding-left: 30px;"><strong>Rule 1</strong> &#8211; Shape your bandwith for certains tasks. <a href="http://en.wikipedia.org/wiki/Traffic_shaping">Traffic shaping</a> will be useful if you are planning to send your backup archives to a remote host. There&#8217;s many tools to achieve this. I personaly use a combination of tools depending on the tasks :</p>
<ul style="padding-left: 60px;">
<li><strong>lftp</strong> command line ftp client allows you to limit your upload rate for ftp transfert.</li>
<li><strong>mod_bandwidth</strong> may be used to control bandwidth on certain virtual hosts, like the one hosting all your rss feeds, per directory, or even per host to control spiders.</li>
</ul>
<p style="padding-left: 30px;"><strong>Rule 2</strong> &#8211; Use a CDN. Here&#8217;s some free Content Delivery Networks :</p>
<ul style="padding-left: 60px;">
<li><a href="http://www.coralcdn.org/">CoralCDN</a> : Entirely free. Easy to setup. Might have slow response times. Use it for videos and content images (not layout images). I setup mine to reduce a light Reddit effect from the last week, my upload bandwitdh is caped at 72kb/s and I was using 50% of it. Here is what happened when I put a simple rewrite rule to redirect all the images requests to the CoralCDN. I put this up at around midnight on saturday the 21th, the upstream traffic drasticaly downed. I even had more visits on monday and was still under the saturday&#8217;s upload rates.</li>
</ul>
<ul style="padding-left: 60px;">
<p style="text-align: center;"><img class="aligncenter size-full wp-image-58" title="february" src="http://blog.shinylittlething.com/wp-content/uploads/2009/02/february.png" alt="february" width="248" height="223" /></p>
</ul>
<ul style="padding-left: 60px;">
<li><a href="http://www.velocix.com/solutions_accelerate.php">Velocix</a> : Add this to your watch list : They have a limited free solution in closed beta, limit is 32MB per file with a 500GB tranfert  hardcap per month. Wich is more than enough for a blog I guess.</li>
<li>If you use a common javascript library I urge you to use the Google&#8217;s<a href="http://code.google.com/apis/ajaxlibs/"> Ajax Library API</a>. This tools will deliverthos heavy files to your clients for you. It will make you and your clients happy because every time they will visit a site that use this technique, they will already have thos files cached on their computer.  As a downside effects, If you use the same templates on your developement servers it will be a pain to work while offline.</li>
</ul>
<p style="padding-left: 30px;"><strong>Rule 3</strong> &#8211; Downsize what can be downsized.</p>
<ul style="padding-left: 60px;">
<li><strong>HTTP Compression </strong>will compress all your compressible content on the fly. That means HTML, scripts, stylesheets and even ajax requests. <strong>mod_deflate</strong> is a good choice for web servers supporting apache modules.</li>
<li><strong>Minify</strong> your javascripts</li>
</ul>
<h3>6. Have fun learning!</h3>
<p>Thanks for reading this article fellow reader. I hope it helped you in some way!</p>
</div></div><h3  class="related_post_title">Popular Posts</h3><ul class="related_post"><li><a href="http://blog.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">8 Ajax Data Controls and Effects to Work with Tables</a></li><li><a href="http://blog.shinylittlething.com/2009/08/11/pygame-event-handling/" title="PyGame &#8211; Event Handling">PyGame &#8211; Event Handling</a></li><li><a href="http://blog.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"> Multiple file upload using jQuery and Ruby on Rails Tutorial</a></li><li><a href="http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/" title="Home Web Hosting Best Practices">Home Web Hosting Best Practices</a></li><li><a href="http://blog.shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience">7 jQuery Plugins to Really Enhance Users Experience</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=xFkRCLhmh2U:hPVO4BFcCmE:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=xFkRCLhmh2U:hPVO4BFcCmE:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=xFkRCLhmh2U:hPVO4BFcCmE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=xFkRCLhmh2U:hPVO4BFcCmE:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/07/20/home-web-hosting-best-practices/</feedburner:origLink></item>
		<item>
		<title>Enabling Dynamic Plugin Support for your JavaScript Application</title>
		<link>http://feedproxy.google.com/~r/Moblurorg/~3/WJ02IgsV4NY/</link>
		<comments>http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 15:38:56 +0000</pubDate>
		<dc:creator>Nicolas Crovatti</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[ja]]></category>

		<guid isPermaLink="false">http://blog.shinylittlething.com/?p=151</guid>
		<description><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/';
var dzone_title = 'Enabling Dynamic Plugin Support for your JavaScript Application';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/';
reddit_title='Enabling Dynamic Plugin Support for your JavaScript Application';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
Hi fellow reader,
I recently came through a problem while working on a javascript framework on top of jQuery.  At one point, having one big javascript file containing all the application objects becomes hard to both naviguate and maintain.
From here you want to ease your developement process by splitting your main class in small, specialized, classes [...]]]></description>
			<content:encoded><![CDATA[<div style="position:relative; width: 100%; padding: 0 0 30px 0;"><div style="position: absolute; bottom: 10px; right:115px; width: 42px;"><script type="text/javascript">
<!--
var dzone_url = 'http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/';
var dzone_title = 'Enabling Dynamic Plugin Support for your JavaScript Application';
var dzone_blurb = '';
var dzone_style = '2';
//-->
</script>
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> 
</div>
<div style="position:relative; width: 100%; padding: 0 0 40px 0;"><div style="position:absolute; bottom: 10px; right:90px; width: 42px;"><script>
<!--
reddit_url='http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/';
reddit_title='Enabling Dynamic Plugin Support for your JavaScript Application';
//-->
</script>
<script type="text/javascript" src="http://www.reddit.com/button.js?t=1"></script>
</div>
<p>Hi fellow reader,</p>
<p>I recently came through a problem while working on a javascript framework on top of jQuery.  At one point, having one big javascript file containing all the application objects becomes hard to both naviguate and maintain.</p>
<p>From here you want to ease your developement process by splitting your main class in small, specialized, classes stored in different files and then includes all these files using &lt;script&gt; tags. This is not convenient, you will have HTTP connections overhead even before your page DOM is loaded and displayed.</p>
<p>You could eventually make use of a server side tool like the PHP library <a href="http://code.google.com/p/minify/">Minify</a> to combine, minify and cache your javascript files. Hovewer I&#8217;ll talk about a system that dynamically and on-demand loads components using <strong>jQuery&#8217;s Ajax implementation</strong>.</p>
<p><span id="more-151"></span></p>
<h2>Simple Javascript Class</h2>
<p>Let&#8217;s start a simple Javascript Class :</p>
<pre>
<pre class="brush: javascript">
var shinyObject = function() {

};
</pre>
</pre>
<p>Extending our classe  with the saySomething() method :</p>
<pre>
<pre class="brush: javascript">
shinyObject.saySomething = function() {
  alert(&quot;Something&quot;);
}
</pre>
</pre>
<p>Ok,  in firebug console we can now type shinyObject.saySomething();  and the revelant code will be executed.</p>
<h2>Plugin support</h2>
<p><strong><strong>Warning, the following code is for concept demonstration pupose only on should not be used in production. Please disregard security concerns, this is not the point.<br />
</strong></strong></p>
<p>Onto creating our <strong>plugin module loader</strong> for our main class. Here is the new method :</p>
<pre>
<pre class="brush: javascript">
shinyObject.loadPlugin = function(options) {
  this.plugin_path = &quot;./&quot;;

  $.ajax(
    {
      type      : &quot;get&quot;,
      url       : shinyObject.plugin_path + options.name + &quot;.js&quot;,
      dataType  : &quot;text&quot;,
      success   : function(code) {
        if(typeof shinyObject[options.name] != &#039;object&#039;) {
          var plugin = eval(code);
          if(typeof plugin == &#039;object&#039;) {
            shinyObject[options.name] = plugin;
          }
          else {
            alert(&quot;Impossible to load &quot; + options.name + &quot; module. Please check your module code syntax.&quot;);
          }
        }
      }
    }
  )
</pre>
</pre>
<p>This snippet is rather easy to understand, the loadPlugin method take a single JSON object as argument, this is convenient because we will want to add more parameters later.  The name of an existing file is passed to the ajax() jQuery method and the results of this HTTP request is passed to a callback function.</p>
<p>If  shinyObject do not already have an instance of this particular plugin in its register table, then we evaluate the code. If the evaluated source code is a valid javascript object, we are affecting  it to a new entry in it&#8217;s register table, otherwise,  warn the developper of possible mistake in the plugin.</p>
<h2>Creating a Plugin</h2>
<p>To create a plugin for our appplication let&#8217;s create a new file in shinyObject.plugin_path  named saySomethingElse.js and put the following snippet inside :</p>
<pre>
<pre class="brush: javascript">
(function () {
  var a_local_variable = &quot;local variable is local&quot;;

  return {
    saySomethingElse = function() {

      alert(&quot;Something Else Matters!&quot;)
      alert(&quot;And you can use local variables because : &quot; + a_local_variable);

    }
  }
})();
</pre>
<p>The important thing here is the self executing function notation :</p>
<pre class="brush: javascript">

(function () {
  /* code */
})();
</pre>
</pre>
<p>This notation is making the difference between a simple library and an autoexecuting piece of code that returns an object.</p>
<h2>Loading a Plugin</h2>
<p>Will are now adding the loadPlugin() call to our the onReady event of the page:</p>
<pre>
<pre class="brush: javascript">

$(document).ready(function() {
  shinyObject.loadPlugin({&#039;name&#039;: &#039;saySomethingElse&#039;});
}); 
</pre>
</pre>
<p>Once the DOM ready for action, our shinyObject will automatically load its dependencies. If the code contained in your plugin do not have to deal with the DOM at all, you can safely make this call directly from the &lt;head&gt; part of your html document. Call me obessional programmer if you want, but I personaly find it more convenient to have everything initialized a the same place.</p>
<h2>Using our Plugin</h2>
<p>Once loaded successfuly, you can access your plugin&#8217;s public methods and properties like this :</p>
<pre>
<pre class="brush: javascript">
/* Simple Method call */
shinyObject.saySomethingElse.saySomethingElse();
/*
Object.ModuleName.Method();
*/
</pre>
<p>As simple as 1, 2, 3.</pre>
<h2>Conclusion</h2>
<p>What we achieved here is rather simple but can be extremely useful in nowadays web applications, even regarding performances. Let&#8217;s say we are building a big application with hundred of plugins that may be optional widgets for our users. The solution described at the begining of this article will generate a great overhead in both bandwith and HTTP requests prior page rendering.</p>
<p><strong>Benefits of our dynamic plugins:</strong></p>
<ul>
<li>Fast Page rendering</li>
<li>Decoupled loading using Asyncronous HTTP</li>
<li>Saves a part of the Bandwidth</li>
<li>Easier library management for developpers</li>
</ul>
<p>What about you dear reader ? What are your solutions for huge javascript libraries management and plugin support ? I&#8217;m really interested to know about it !</p>
</div></div><h3  class="related_post_title">Related Posts</h3><ul class="related_post"><li><a href="http://blog.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"> Multiple file upload using jQuery and Ruby on Rails Tutorial</a></li><li><a href="http://blog.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">8 Ajax Data Controls and Effects to Work with Tables</a></li><li><a href="http://blog.shinylittlething.com/2009/02/24/jquery-plugins-to-enhance-users-experience/" title="7 jQuery Plugins to Really Enhance Users Experience">7 jQuery Plugins to Really Enhance Users Experience</a></li><li><a href="http://blog.shinylittlething.com/2009/02/20/image-manipulation-jquery-plugins/" title="6 Image Manipulation Plugins for jQuery You Should Know About">6 Image Manipulation Plugins for jQuery You Should Know About</a></li><li><a href="http://blog.shinylittlething.com/2009/02/23/essential-web-based-tools-for-javascript-developers/" title="Essential Web-Based tools for JavaScript Developers">Essential Web-Based tools for JavaScript Developers</a></li></ul><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Moblurorg?a=WJ02IgsV4NY:db0ZLkXc4rk:cTv1dNCI_Tc"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=cTv1dNCI_Tc" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=WJ02IgsV4NY:db0ZLkXc4rk:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/Moblurorg?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Moblurorg?a=WJ02IgsV4NY:db0ZLkXc4rk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/Moblurorg?i=WJ02IgsV4NY:db0ZLkXc4rk:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.shinylittlething.com/2009/03/10/enabling-dynamic-plugin-support-for-your-javascript-application/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 1.474 seconds -->
