<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="lyceum/1.0.2" -->
<!-- This is 512 bytes of nonsense, since the Firefox 2 developers, in one of the strangest decisions ever, decidedthey would obsolete XML styles by overriding them without permission.  Furthermore, the developers appear to be disinterested in fixing this.  Therefore, we use the unofficial workaround, which includes fillingup the first 512 bytes of a document so that the sniffer doesn't encounter the RSS tag.  I really enjoyusing Firefox, but this particular behavior really annoys me! Anyway, since I'm almost at 512 characters, I'mgoing to ramble on for another minute in this comment, and then, without further adue, present you with avalid XML feed. -->
<rss version="2.0" 
	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/"
	>

<channel>
	<title>Red Hat Magazine</title>
	<link>http://www.redhatmagazine.com</link>
	<description></description>
	<pubDate>Wed, 23 Jul 2008 22:12:52 +0000</pubDate>
	<generator>http://lyceum.ibiblio.org/?v=1.0.2</generator>
	<language>en</language>
			<item>
		<title>Friday round-up</title>
		<link>http://www.redhatmagazine.com/2008/03/07/friday-round-up-2/</link>
		<comments>http://www.redhatmagazine.com/2008/03/07/friday-round-up-2/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 21:36:06 +0000</pubDate>
		<dc:creator>the editorial team</dc:creator>
		
		<category>from the editors</category>

		<category>culture</category>

		<category>education</category>

		<category>events</category>

		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2008/03/07/friday-round-up-2/</guid>
		<description><![CDATA[It&#8217;s been a while since we posted a good round-up, and there&#8217;s so much we&#8217;ve come across lately that we really wanted to tell you about.  In no particular order, here&#8217;s a list of things that have piqued our interest in the last few weeks:

Thomas Chung&#8217;s photo essay from SCALE 6X.
Here is another SCALE [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since we posted a good round-up, and there&#8217;s <em>so much</em> we&#8217;ve come across lately that we really wanted to tell you about.  In no particular order, here&#8217;s a list of things that have piqued our interest in the last few weeks:</p>
<ul>
<li>Thomas Chung&#8217;s <a href="http://tchung.fedorapeople.org/scale6x/">photo essay</a> from SCALE 6X.</li>
<li>Here is another <a href="http://spot.livejournal.com/288447.html">SCALE 6X trip report</a> from Fedora Engineering Manager Tom &#8220;Spot&#8221; Callaway</li>
<li>Mary Lou Jepsen&#8217;s (the former CTO of the One Laptop per Child project) keynote at the Greener Gadgets conference:  <a href="http://www.inhabitat.com/2008/02/20/mary-lou-jepsen-at-greener-gadgets/">How green is the XO?</a></li>
<li><a href="http://www.pctipsbox.com/top-10-linux-distributions-for-audio-production/">Top 10 Linux distributions for audio</a></li>
<li>Check out <a href="http://lewk.org/blog/gobby.html">Gobby on fedoraproject.org</a>. For those not in the know, Gobby is &#8220;a free collaborative editor supporting multiple documents in one session and a multi-user chat. It runs on Microsoft Windows, Mac OS X, Linux, and other Unix-like platforms.&#8221;</li>
<li>More One Laptop in the news:  A comparison of <a href="http://www.virtualhosting.com/blog/2008/top-5-sub-300-laptops-compared/">sub-$300 laptops</a></li>
<li><a href="http://www.tedprize.org/?page_id=7">Dave Eggers</a>, winner of a 2008 <a href="http://www.tedprize.org/?page_id=15">TED prize</a>, wants 1,000 people to engage with their local public schools through <a href="http://onceuponaschool.org">onceuponaschool.org</a>. They need domain hosting, developers, and non-technical people. A perfect opportunity to combine open source&#8217;s benefits with education&#8230;</li>
<li><a href="http://www.quelsolaar.com/">Love</a>. As in the love of game development. Check out <a href="http://www.rockpapershotgun.com/?p=1164">the amazing graphics</a> in this multiplayer first-person shooter game that was created entirely by one person.</li>
<li>You&#8217;re going to have to pull yourself away from the screen sooner or later. When you&#8217;re looking for something to eat this weekend, may we recommend <a href="http://www.notmartha.org/archives/2008/02/27/bacon-cups/">bacon cups</a>? (Because here at Red Hat Magazine?  We like bacon.)</li>
<li><a href="http://journal.neilgaiman.com/2008/03/more-on-free-and-suchlike.html">Neil Gaiman&#8217;s giving away books</a> and name-checking Cory Doctorow.  Trent Reznor&#8217;s up to much of the same with NIN&#8217;s new album, <a href="http://ghosts.nin.com/main/home">Ghosts</a>.  Yay for major artists getting on the sharing bandwagon.</li>
<li>And speaking of Cory Doctorow, check out this list of <a href="http://io9.com/361597/the-twenty-science-fiction-novels-that-will-change-your-life">20 science fiction novels that will change your life</a>.  <em>Down and Out in the Magic Kingdom</em> is a particular favorite and shouldn&#8217;t be missed.  But what&#8217;s your favorite that didn&#8217;t make the cut?     For us?  Madeline L&#8217;Engle&#8217;s transformative series about the Wallace family, starting with <em>A Wrinkle in Time</em>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2008/03/07/friday-round-up-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>OLPC: Give One Get One, right now</title>
		<link>http://www.redhatmagazine.com/2007/11/15/olpc-give-one-get-one-right-now/</link>
		<comments>http://www.redhatmagazine.com/2007/11/15/olpc-give-one-get-one-right-now/#comments</comments>
		<pubDate>Thu, 15 Nov 2007 18:54:46 +0000</pubDate>
		<dc:creator>Greg DeKoenigsberg</dc:creator>
		
		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/11/15/olpc-give-one-get-one-right-now/</guid>
		<description><![CDATA[I&#8217;ve been demoing this little green laptop for months.  Everywhere I go, it&#8217;s a star, and everyone who sees it always asks me the same question: when can I get one?  Finally, I have an answer: right now.  But you&#8217;d better hurry, because they are only available for another 12 days.  [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been demoing this little green laptop for months.  Everywhere I go, it&#8217;s a star, and everyone who sees it always asks me the same question: when can I get one?  Finally, I have an answer: <a href="http://laptopgiving.org">right now</a>.  But you&#8217;d better hurry, because they are only available for another 12 days.  And here&#8217;s a little secret: it&#8217;s a <em>really good deal</em>.</p>
<p><a id="more-562"></a></p>
<p>The mission of One Laptop Per Child (OLPC) is ambitious: to empower the children of developing countries to learn by providing one connected laptop to every school-age child.  To accomplish this ambitious goal, the project needs supporters who believe in this goal. Until November 26, OLPC is sponsoring the <a href="http://laptopgiving.org">Give One Get One</a> program in the United States and Canada. During this time, you can donate the revolutionary XO laptop to a child in a developing nation, and also receive one for the child in your life in recognition of your contribution.</p>
<p>Beyond idealism, there&#8217;s one great pragmatic reasons for doing it: it&#8217;s a great value.  The purchase price is $399 plus shipping and handling, but $200 of that is a tax write-off.  Also, everyone who gets an OLPC will also receive <a href="http://www.laptopgiving.org/en/free-wi-fi.php">free wifi service from T-Mobile</a> for one year.</p>
<p>Do the math: for a little over $400, you get a revolutionary laptop (value: $200), free wifi service for a year (value: $350), a tax write-off (value: a few bucks, maybe more depending on your financial situation), and the knowledge that a child in the developing world has a chance that he or she would never have had otherwise (value: priceless).</p>
<p>It&#8217;s the best Christmas deal out there.  Go take advantage of it. <a href="http://www.laptopgiving.org/en/give-one-get-one.php">Right now.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/11/15/olpc-give-one-get-one-right-now/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Open source and Blog Action Day</title>
		<link>http://www.redhatmagazine.com/2007/10/15/open-source-and-blog-action-day/</link>
		<comments>http://www.redhatmagazine.com/2007/10/15/open-source-and-blog-action-day/#comments</comments>
		<pubDate>Mon, 15 Oct 2007 16:04:31 +0000</pubDate>
		<dc:creator>Ruth Suehle</dc:creator>
		
		<category>culture</category>

		<category>events</category>

		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/10/15/open-source-and-blog-action-day/</guid>
		<description><![CDATA[Today more than 15,000 bloggers are participating in Blog Action Day, an initiative that asks bloggers to post on one topic en masse on the same day each year. The 2007 topic is the environment, and open source bloggers are joining in. 
Pure Distortion suggests consolidating some of your hardware to reduce your environmental impact. [...]]]></description>
			<content:encoded><![CDATA[<p>Today more than 15,000 bloggers are participating in <a href="http://www.blogactionday.com">Blog Action Day</a>, an initiative that asks bloggers to post on one topic en masse on the same day each year. The 2007 topic is the environment, and open source bloggers are joining in. <a id="more-502"></a></p>
<p><a href="http://puredistortion.blogspot.com/2007/10/blog-action-day-ways-to-save-energy-and.html">Pure Distortion</a> suggests consolidating some of your hardware to reduce your environmental impact. </p>
<blockquote><p>Running all of my servers on one large piece of hardware is seeing my household have a 10% saving on the amount of electricity that we use and that could be potentially more depending on how mch hardware you are running at home.</p></blockquote>
<p>For <a href="http://distributedinformation.com/blog/2007/10/15/simple-things-you-can-do-to-save-the-planet/">simple things you can do to save the planet</a>, Distributed Information suggests:</p>
<blockquote><p>&#8230;work on or support the use of open source software.</p>
<p>Closed source is based on restricting access to software, which inevitably leads to pointless, non-innovative duplication of efforts. I’m not talking about the duplication of competitive features, or key differentiators that make your business a success either. There are a myriad of tiny internal tools written in every company or project, to just get stuff done, which if shared could improve your bottom line, just by sharing the code amongst all the other companies in the world that do a similar thing.</p></blockquote>
<p>ComputerWorld UK discusses the idea of <a href="http://www.computerworlduk.com/green-computing/blogs/index.cfm?entryid=98&#038;blogid=8">a green API</a> with four examples, including:</p>
<blockquote><p>2. Connecting people to other people and useful services. For example, there&#8217;s now a Facebook Carpool app which &#8220;makes sharing a ride safer and easier by using Facebook to find people going in the same direction.&#8221; Boston-based GoLoco is pursuing the same ends with a stand-alone web service. Both are perfect examples of leveraging the web to connect people towards a greater environmental good. </p></blockquote>
<p>Finally, here&#8217;s a post on <a href="http://jmbuser.livejournal.com/6764.html">OLPC and the environment</a>.</p>
<p>Did you post for Blog Action Day? See a great open source/truth-related Blog Action Day post? Let us know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/10/15/open-source-and-blog-action-day/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Book review: The End of Poverty</title>
		<link>http://www.redhatmagazine.com/2007/07/30/book-review-the-end-of-poverty/</link>
		<comments>http://www.redhatmagazine.com/2007/07/30/book-review-the-end-of-poverty/#comments</comments>
		<pubDate>Mon, 30 Jul 2007 15:20:19 +0000</pubDate>
		<dc:creator>Julie Bryce</dc:creator>
		
		<category>culture</category>

		<category>review</category>

		<category>education</category>

		<category>design</category>

		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/07/30/book-review-the-end-of-poverty/</guid>
		<description><![CDATA[
Author: Jeffrey D.Sachs  Publisher: Penguin PressPublication date: October 1, 2006http://www.earthinstitute.columbia.edu/endofpoverty/

Last weekend I finished reading this book and watched Al Gore&#8217;s Inconvenient Truth, all in the span of 24 hours. Thoughts of global warming, the threat of a permanently altered planet, and extreme poverty killing thousands every day were swimming in my mind. While I [...]]]></description>
			<content:encoded><![CDATA[<div class="alignLeft"><a href="http://www.amazon.com/gp/product/0143036580/103-8536270-5901408?ie=UTF8&amp;tag=wwwredhatcom-20&amp;linkCode=xm2&amp;camp=1789&amp;creativeASIN=0143036580"><img src="http://farm1.static.flickr.com/177/396509202_8707a4fbba.jpg?v=0" alt="The End of Poverty" /></a></div>
<p><strong>Author:</strong> Jeffrey D.Sachs </strong> <br /><strong>Publisher:</strong> Penguin Press<br /><strong>Publication date:</strong> October 1, 2006<br /></strong><a href="http://www.earthinstitute.columbia.edu/endofpoverty/">http://www.earthinstitute.columbia.edu/endofpoverty/</a></p>
<p>
Last weekend I finished reading this book and watched Al Gore&#8217;s <em>Inconvenient Truth</em>, all in the span of 24 hours. Thoughts of global warming, the threat of a permanently altered planet, and extreme poverty killing thousands every day were swimming in my mind. While I felt a sense of urgency, I also felt conflicted. Because it&#8217;s hard to feel urgent about both. In fact, history shows it&#8217;s hard for the US government to give urgent attention to more than one crisis at a time. So what to do in the face of such cultural monsters?</p>
<p><a id="more-302"></a>
<p>Interestingly, and perhaps the deeper cause of turmoil, author Jeff Sachs lauds the industry that the film Inconvenient Truth condemns for polluting our planet. And I fear they&#8217;re both right. Industrialization and widespread globalization are contributing to global warming, especially as previously agrarian laborers move to cities and create more epicenters of activity. Working in more skilled jobs (industries that are often culprits of polluting), these laborers eventually purchase cars and add to the carbon dioxide the human race collectively emits. And yet, this is a success story. A human being has climbed out of extreme poverty and, as their children grow, and their grandchildren are born, the generations that follow him will enter the world on a higher rung of the the socioeconomic ladder. Further removed from the extreme poverty that afflicted their ancestors.</p>
<p>In fact, a ladder is the analogy Sachs uses most to describe extreme poverty and its escape. He explains that people living in extreme poverty can&#8217;t grasp even the bottom rung of the  ladder. They don&#8217;t have the basic necessities to sustain life: food, clean water, shelter. Without basic sustenance, it&#8217;s impossible to pursue education or consider means of income beyond than subsistence agriculture.</p>
<p>Sachs cites Malawi as an example of the &#8220;the perfect storm&#8221; of extreme poverty. All of these characteristics culminate, compounded by AIDS and Malaria epidemics, into a &#8220;horrific maelstrom.&#8221; And unfortunately, &#8220;the world community has so far displayed a fair bit of hand-wringing and even some high-minded rhetoric, but precious little help.&#8221;</p>
<p>&#8220;Currently, more than eight million people around the world die each year because they are too poor to stay alive.&#8221; Sachs gives us the newspaper headline that we will probably never see: <em>More than 20,000 people died yesterday because they couldn&#8217;t afford the basic necessities required for human life.</em></p>
<p>The situation Sachs addresses in The End of Poverty is a tragedy that&#8217;s occurring as I write this review. It was a crisis when I got up this morning. And as you poured your coffee in whatever corner of the world you&#8217;re reading this, people were dying of hunger, thirst, and disease. By the thousands, every day. This is not an impending crisis; we&#8217;re in the climax. Though a grave problem and one of great consequence, global warming is still mounting. Nature is showing the effects, and scientists are predicting the consequences that will be felt by the human race in as little as ten years. This is not a trivial matter or one to be minimized. But if the United States is to mount an immediate offense against one crisis or the other, I think millions dying senseless deaths takes precedent.</p>
<p>Is there hope? Sure. If Macroeconomics 101 put you to sleep in college, give Sachs a second chance to teach you some basic economics. Does the name <a href="”http://en.wikipedia.org/wiki/John_Maynard_Keynes”">John Maynard Keynes</a> ring a bell? Keynes wrote around the time of the Great Depression and fathered Keynesian theory, which asserts that both the state and private enterprise play important roles in developing a healthy economy fit for long-term growth. Important for Sachs is Keynes&#8217; emphasis on scientific and technological innovation as a means to long-term economics growth. He predicted this kind of growth even in the throws of the Great Depression in America. His predictions came true. Technological and scientific innovation has for the most part eradicated extreme poverty in America and the rest of the developed world. We&#8217;re not talking about computers or the Internet, either. Scientific and technological advancements as basic as paved roads, which allow goods and services to be traded freely and with ease, are impediments to economic stability and growth in underdeveloped nations in Asia and in Sub-Saharan Africa.</p>
<p>The remedy? Unfortunately there&#8217;s no one-size-fits-most panacea. Sachs emphasizes the importance of grassroots programs and small-scale initiatives tailored to specific needs and demographics. The rest of the world often imagines Africans as one ethnicity, facing similar challenges. When the truth is, more than a dozen countries make up Sub-Saharan Africa, an area widely-regarded as one of the most needy. It&#8217;s no surprise that small-scale operations aimed at specific countries, even specific towns or subsets of towns, are most effective.</p>
<p>And this is where open source comes in. Specialized aid efforts, targeted at specific regions, using the expertise and know-how of those involved. Now imagine all these how-tos and that information gathered by aid organizations is documented publicly, available for mass distribution. Even mass reproduction.</p>
<p>When knowledge is shared, and intricate mistakes and successes are made public, the world can take real steps toward the end of poverty.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/07/30/book-review-the-end-of-poverty/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Inside One Laptop per Child: Episode 04</title>
		<link>http://www.redhatmagazine.com/2007/07/25/inside-one-laptop-per-child-episode-04/</link>
		<comments>http://www.redhatmagazine.com/2007/07/25/inside-one-laptop-per-child-episode-04/#comments</comments>
		<pubDate>Wed, 25 Jul 2007 18:34:09 +0000</pubDate>
		<dc:creator>Julie Bryce</dc:creator>
		
		<category>culture</category>

		<category>education</category>

		<category>design</category>

		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/07/25/inside-one-laptop-per-child-episode-04/</guid>
		<description><![CDATA[
Download this video: [Ogg Theora]Video by Simple Coat. Produced by Julie Bryce, Kristin Hondros, Kim Jokisch, and Tim Kiernan.

&#160;&#160;Episode 04 takes us on location in Porto Alegre, Brazil. Where the first batches of XOs have been delivered and deployed. Meet the teachers using the laptops in the classroom. Where besides doing daily assignments on the [...]]]></description>
			<content:encoded><![CDATA[<div class="alignLeft"><embed src="http://www.redhat.com/v/swf/flvplayer.swf?file=http://www.redhat.com/v/magazine/swf/olpcEp04.flv&#038;autoStart=false&#038;image=http://www.redhat.com/g/magazine/video_stills/still_olpcEp4.jpg" width="320" height="260" quality="high" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
<div class="caption" style="width: 320px;">Download this video: [<a href="http://www.redhat.com/v/magazine/ogg/olpcEp04.ogg">Ogg Theora</a>]<br />Video by <a href="http://www.simplecoat.tv">Simple Coat</a>. Produced by Julie Bryce, Kristin Hondros, Kim Jokisch, and Tim Kiernan.</div>
<p><!-- caption --></div>
<p><!-- alignLeft --><img src="http://www.redhat.com/g/magazine/icon_video_white.gif" alt="(video)" />&nbsp;&nbsp;Episode 04 takes us on location in Porto Alegre, Brazil. Where the first batches of XOs have been delivered and deployed. Meet the teachers using the laptops in the classroom. Where besides doing daily assignments on the machines, some students have already learned programing. Local culture has permeated the project, and as a veteran school principal explains, an improved education is set to equip a new generation of Brazilian citizens. <a href="http://www.redhatmagazine.com/category/one-laptop-per-child/">Watch past episodes.</a><br clear="both" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/07/25/inside-one-laptop-per-child-episode-04/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Inside One Laptop per Child: Episode 03</title>
		<link>http://www.redhatmagazine.com/2007/06/08/inside-one-laptop-per-child-episode-03/</link>
		<comments>http://www.redhatmagazine.com/2007/06/08/inside-one-laptop-per-child-episode-03/#comments</comments>
		<pubDate>Fri, 08 Jun 2007 21:37:55 +0000</pubDate>
		<dc:creator>Julie Bryce</dc:creator>
		
		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/06/08/inside-one-laptop-per-child-episode-03/</guid>
		<description><![CDATA[

Download this video: [Ogg Theora]

Video by Simple Coat.Produced by Julie Bryce and Kristin Hondros.




Since piloting this video series, we&#8217;ve received lots of questions about the XO&#8217;s mesh network. How can these laptops &#8220;talk&#8221; to each other even without widespread internet access? How is the network they create different from the network at your home or [...]]]></description>
			<content:encoded><![CDATA[<div class="alignLeft">
<embed src="http://www.redhat.com/v/swf/flvplayer.swf?file=http://www.redhat.com/v/magazine/swf/olpcEp03.flv&#038;autoStart=false&#038;image=http://www.redhat.com/v/magazine/swf/070321_olpc.png" width="320" height="260" quality="high" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed></p>
<div class="caption" >Download this video: [<a href="http://www.redhat.com/v/magazine/ogg/olpcEp03.ogg">Ogg Theora</a>]<br />
<br />
Video by <a href="http://www.simplecoat.tv">Simple Coat</a>.<br />Produced by Julie Bryce and Kristin Hondros.
</div>
<p><!-- caption -->
</div>
<p><!-- alignLeft --></p>
<p>Since piloting this video series, we&#8217;ve received lots of questions about the XO&#8217;s mesh network. How can these laptops &#8220;talk&#8221; to each other even without widespread internet access? How is the network they create different from the network at your home or office? Episode 03 explains it all.<br />
<br clear="both" />
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/06/08/inside-one-laptop-per-child-episode-03/feed/</wfw:commentRss>
		</item>
		<item>
		<title>One Laptop per Child on 60 Minutes, Sunday May 20</title>
		<link>http://www.redhatmagazine.com/2007/05/18/one-laptop-per-child-on-60-minutes-sunday-may-20/</link>
		<comments>http://www.redhatmagazine.com/2007/05/18/one-laptop-per-child-on-60-minutes-sunday-may-20/#comments</comments>
		<pubDate>Fri, 18 May 2007 20:04:08 +0000</pubDate>
		<dc:creator>the editorial team</dc:creator>
		
		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/05/18/one-laptop-per-child-on-60-minutes-sunday-may-20/</guid>
		<description><![CDATA[

Episode 1.  Filmed and edited by Simple Coat Productions.Download this video: [ogg]

Episode 2. Filmed and edited by Simple Coat Productions.Download this video: [ogg]


&#160;&#160;Little green men often make the front pages of supermarket tabloids.  Little green laptops?  Not so much.
But this Sunday, the XO (which we&#8217;ve been talking about for months) will get [...]]]></description>
			<content:encoded><![CDATA[<div class="alignLeft">
<embed src="http://www.redhat.com/v/swf/flvplayer.swf?file=/v/magazine/swf/070321_olpc.flv&#038;autoStart=false&#038;image=http://www.redhat.com/v/magazine/swf/070321_olpc.png" width="320" height="260" quality="high" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed></p>
<div class="caption" ><strong>Episode 1.</strong>  Filmed and edited by <a href="http://www.simplecoat.tv/">Simple Coat Productions.<br />Download this video: [<a href="http://www.redhat.com/v/magazine/ogg/070321_olpc.ogg">ogg</a>]</div>
<p><embed src="http://www.redhat.com/v/swf/flvplayer.swf?file=http://www.redhat.com/v/swf/olpc02Final.flv&#038;autoStart=false&#038;image=http://www.redhat.com/v/swf/olpc_episode2.png" width="320" height="260" quality="high" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed></p>
<div class="caption" ><strong>Episode 2.</strong> Filmed and edited by <a href="http://www.simplecoat.tv/">Simple Coat Productions.<br />Download this video: [<a href="http://www.redhat.com/v/ogg/olpc02Final.ogg">ogg</a>]</div>
</div>
<p><!-- alignLeft --></p>
<p><img src="http://www.redhat.com/g/magazine/icon_video_white.gif" alt="(video)">&nbsp;&nbsp;Little green men often make the front pages of supermarket tabloids.  Little green laptops?  Not so much.</p>
<p>But this Sunday, the XO (which we&#8217;ve been talking about for months) will get its mainstream news debut on CBS&#8217;s highly regarded program, <a href="http://www.cbsnews.com/sections/60minutes/main3415.shtml">60 Minutes</a>. (A far cry from the <a href="http://www.nationalenquirer.com/">National Enquirer</a>.)  </p>
<p><a href="http://www.redhatmagazine.com/2007/02/20/up-close-with-the-one-laptop-per-child-xo/">Faces familiar to our readers</a> have helped make <a href="http://en.wikipedia.org/wiki/Nicholas_Negroponte">Nicholas Negroponte&#8217;s</a> dream a reality.  From the earliest concept (remember the hand crank?) to its current working build which has been deployed in several nations for beta testing, this laptop has come a long way.  And it would not have been possible without the hard work of folks like <a href="http://www.0xdeadbeef.com/weblog/?cat=12">Chris Blizzard</a>, Dan Williams, <a href="http://www.advogato.org/person/dwmw2/">David Woodhouse</a>, Marcelo Tosatti, and <a href="http://www.j5live.com/?cat=15">John &#8220;J5&#8243; Palmieri</a>.</p>
<p>Just as our developers were inspired by Nicolas Negroponte and <a href="http://en.wikipedia.org/wiki/Walter_Bender">Walter Bender&#8217;s</a> concepts, we hope the millions watching Sunday night&#8217;s newscast will see in the project the promise for a worldwide solution to poverty.  In a word: education.</p>
<p>And more than that, we hope they&#8217;ll <a href="http://laptopfoundation.org/en/index.shtml">get involved</a>, whether it&#8217;s donating money, developing code, or simply spreading the good word.  </p>
<p>Congratulations to everyone working on the project.  We wish you continued good luck and prosperity.  And good press.  </p>
<p>XOXO</p>
<p><br clear="both" />
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/05/18/one-laptop-per-child-on-60-minutes-sunday-may-20/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Building the XO: Porting a PyGTK game to Sugar, part two</title>
		<link>http://www.redhatmagazine.com/2007/04/26/building-the-xo-porting-a-pygtk-game-to-sugar-part-two/</link>
		<comments>http://www.redhatmagazine.com/2007/04/26/building-the-xo-porting-a-pygtk-game-to-sugar-part-two/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 09:52:18 +0000</pubDate>
		<dc:creator>John (J5) Palmieri</dc:creator>
		
		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/04/26/building-the-xo-porting-a-pygtk-game-to-sugar-part-two/</guid>
		<description><![CDATA[In the last lesson we learned about what made Block Party tick.  In this lesson, we will turn the same PyGtk codebase into a Sugar activity with only minimal modification of the core code.  As always, the code for this lesson can be found at: 
http://dev.laptop.org/~j5/BlockParty_tutorial/block_party_lesson_2.tar.gz

For this lesson you will need a computer [...]]]></description>
			<content:encoded><![CDATA[<p>In the last lesson we learned about what made Block Party tick.  In this lesson, we will turn the same PyGtk codebase into a Sugar activity with only minimal modification of the core code.  As always, the code for this lesson can be found at: </p>
<p><a href="http://dev.laptop.org/~j5/BlockParty_tutorial/block_party_lesson_2.tar.gz">http://dev.laptop.org/~j5/BlockParty_tutorial/block_party_lesson_2.tar.gz</a><br />
<a id="more-105"></a></p>
<p>For this lesson you will need a computer with the latest version of the Sugar environment running on it.  This can either be from <a href="http://wiki.laptop.org/go/Sugar_with_sugar-jhbuild">sugar-jhbuild</a> or any build after or including <a href="http://olpc.download.redhat.com/olpc/streams/development/"> build 303</a> running in an emulated environment like qemu, from the LiveCD or on the laptop itself.  </p>
<h2>Entry points</h2>
<p>The first thing we need to clean up in the Block Party source is the entry point.  When running standalone, we call init() from the main() function.  This creates a window, sets up all the signal handlers, and then goes into the mainloop.  </p>
<p>When being run by Sugar, however, the main loop and toplevel window are all taken care of by the Activity class.  In fact, the Activity class is just a subclass of GtkWindow.  Because of this we will define init() as the common entry point and shift the window creation code from init() to main(). </p>
<pre>
def main():
&nbsp;&nbsp;&nbsp;&nbsp;toplevel_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
&nbsp;&nbsp;&nbsp;&nbsp;init(toplevel_window)
&nbsp;&nbsp;&nbsp;&nbsp;gtk.main()
&nbsp;&nbsp;&nbsp;&nbsp;return 0
</pre>
<p>In the init() function we now take a GtkWindow as a parameter and use that, instead of creating the window ourselves.</p>
<pre>
def init(toplevel_window):
&nbsp;&nbsp;&nbsp;&nbsp;global window
&nbsp;&nbsp;&nbsp;&nbsp;window = toplevel_window
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;# remove any children of the window that Sugar may have added
&nbsp;&nbsp;&nbsp;&nbsp;for widget in window.get_children():
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.remove(widget)
</pre>
<p>You will also notice we remove the window of any child widgets.  This is because Sugar comes stacked with a HippoCanvas widget, which is usually what the main UI layer activities are built on.  At some point it may be nice to port Block Party to use the canvas &#8212; but for right now we are dealing with direct drawing layers, so we need to discard the canvas.</p>
<div class="alignLeft">
<img width="240px" height="180px" src="http://farm1.static.flickr.com/181/455791520_aae5a53e8c_m.jpg" /></p>
<div class="caption" style="width: 240px;">A child plays Block Party on his laptop in Porto Alegre, Brazil.</div>
</div>
<p><!-- alignLeft --></p>
<p>That&#8217;s all that needs to be touched in the current code.  Now that we have our entry points, we can still run and debug the program without Sugar by simply running the command python BlockParty.py, but now we also have the API call necessary to hook into Sugar.</p>
<h2>The activity class</h2>
<p>These next parts require Block Party to be run in a Sugar environment.  The Activity class is the central API for hooking into Sugar and the entry point when Sugar launches an activity.  In order to create a Block Party activity, we simply inherit from the Activity class, hook up to a couple of signals, and run the entry point for Block Party. We will do this all in the BlockPartyActivity.py file.</p>
<pre>
import BlockParty
&nbsp;&nbsp;&nbsp;&nbsp;
from sugar.activity import activity
&nbsp;&nbsp;&nbsp;&nbsp;
class BlockPartyActivity(activity.Activity):
&nbsp;&nbsp;&nbsp;&nbsp;def __init__(self, handle):
&nbsp;&nbsp;&nbsp;&nbsp;activity.Activity.__init__(self, handle)
&nbsp;&nbsp;&nbsp;&nbsp;self.connect('destroy', self._cleanup_cb)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;self.gamename = 'blockparty'
&nbsp;&nbsp;&nbsp;&nbsp;self.set_title("BlockParty")
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# connect to the in/out events
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.connect('focus_in_event', self._focus_in)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.connect('focus_out_event', self._focus_out)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BlockParty.init(self)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;def _cleanup_cb(self, data=None):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;def _focus_in(self, event, data=None):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;def _focus_out(self, event, data=None):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return
</pre>
<p>As you see, we import BlockParty which loads the BlockParty.py file and then imports the activity module from sugar.activity.  We then have the BlockPartyActivity class inherit from activity.Activity which takes a handle argument for its constructor.  The handle is the id given to the instance of the activity when it is launched.</p>
<p>Notice we attach to the focus_in_event and focus_out_event.  Right now we don&#8217;t do anything in those handlers, but we could use them to conserve power by having the activity stop processing when it is in the background.  In the case of Block Party, we could simply pause the game.</p>
<p>At the end of the constructor, we call the Block Party entry point.  We pass self to init because, if you remember, the Activity class is itself the toplevel window we wish to draw on.</p>
<p>That&#8217;s it.  That&#8217;s all the code needed to sugarize a PyGtk application.  </p>
<p>Now let&#8217;s look at some of the support files that go into making this activity into a bundle.</p>
<h2>Bundles</h2>
<p>An activity bundle is a self contained set of files which make up a Sugar activity.  They are usually zipped up into a file ending with the .xo extension.  This allows activities to be run simply by placing the bundle in the correct place in the file system.  Now that we have created the activity, we need to create the support files.</p>
<p>The first support file is the setup.py file. This file makes it easy to manage building and distributing the activity. In most cases we are dealing with python so the setup.py will look the same, but in the future it will be easy to extend setup.py to support other types of projects.</p>
<pre>
#!/usr/bin/env python
from sugar.activity import bundlebuilder
bundlebuilder.start()
</pre>
<p>As you can see, it is very simple script which handles most of what you will need to do without further coding.  </p>
<p>The setup.py script still needs a couple of other files in order to function.  The MANIFEST file is a simple list of source files that should be added to the bundle for distribution.  Sometimes there are files which are needed for the version of the bundle in version control repositories but make little sense inside the actual shipping bundle.  These files can be left out of the MANIFEST and will not be bundled up.  Let&#8217;s take a look at our MANIFEST file.</p>
<pre>
BlockParty.py
BlockPartyActivity.py
</pre>
<p>Notice we only list the source files and not the files in the activity directory or the setup.py file.  These files are automatically added to the bundle and should not be in the MANIFEST file.</p>
<p>The activity.info file in the Activity directory is another of the support files.  This tells Sugar about the activity and how to launch it.  Let&#8217;s take a look at it.</p>
<pre>
[Activity]
name = BlockParty
service_name = org.laptop.BlockPartyActivity
class = BlockPartyActivity.BlockPartyActivity
icon = activity-blockparty
activity_version = 1
show_launcher = yes
</pre>
<p>The activity.info file is a simple .ini formatted configuration file.  We start with the [Activity] block header and then give a name, the D-Bus service name, the module and class we are launching, an icon, version and if the icon should show up on the launcher panel.  </p>
<p>The D-Bus service name usually looks like a reverse URL with the organizations namespace followed by the activity name.  In our case we namespace with org.laptop.  </p>
<p>The class also includes the module namespace. Here we find the BlockPartyActivity class in the BlockPartyActivity.py file so we prepend the class name with the BlockPartyActivity module name.  </p>
<p>The icon field specifies the svg icon which should reside in the activity folder alongside the info file.</p>
<p>Versioning for bundles is handled by the activity_vesion key and is a straight integer.  Right now this is used by the setup.py script to take on the version number at the end of the bundle name (i.e. BlockParty-1.xo).  In the future this will be used to determine when to upgrade the bundle if another user has a newer version.</p>
<p>Some activities are special activities which are managed by Sugar or other activities.  In those cases it doesn&#8217;t make sense to show them to the user so show_launcher can be set to &#8220;no&#8221;.</p>
<p>The final file we need to deal with is the svg icon file in the activity directory.  We use a special formatted svg for our icons.</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
&nbsp;&nbsp;&lt;!ENTITY fill_color "#FFFFFF"&gt;
&nbsp;&nbsp;&lt;!ENTITY stroke_color "#000000"&gt;
]&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
&nbsp;&nbsp;&lt;rect x="6" y="19" width="10" height="10" style="fill:&#038;fill_color;;stroke:&#038;stroke_color;;stroke-width:2"/&gt;
&nbsp;&nbsp;&lt;rect x="21" y="5" width="10" height="10" style="fill:&#038;fill_color;;stroke:&#038;stroke_color;;stroke-width:2"/&gt;
&nbsp;&nbsp;&lt;rect x="21" y="19" width="10" height="10" style="fill:&#038;fill_color;;stroke:&#038;stroke_color;;stroke-width:2"/&gt;
&nbsp;&nbsp;&lt;rect x="36" y="19" width="10" height="10" style="fill:&#038;fill_color;;stroke:&#038;stroke_color;;stroke-width:2"/&gt;
&nbsp;
&lt;/svg&gt;
</pre>
<p>Notice the two entities at the top of the file: fill_color and stroke_color.  Sugar icons must be two-toned, and we use the two entities in order to fit in with the look and feel of Sugar.  Sugar will take those entities and fill them in with the user&#8217;s personal colors.</p>
<h2>Producing a shippable bundle</h2>
<p>After all the files are created and modification done we are ready to build a bundle to be shipped and run in Sugar.  All one has to do is run &#8216;python setup.py dist&#8217; in a Sugar environment and it will produce a bundle which looks like BlockParty-1.xo.</p>
<p>To install the bundle, simply run &#8217;sugar-install-bundle BlockParty-1.xo&#8217; as the olpc user.  You should see the Block Party icon pop up on the launcher.  Click on the icon to run.</p>
<h2>Conclusion</h2>
<p>As we now see, sugarizing a PyGtk application takes little time or effort.  This is only the tip of the iceberg, though; deep integration will take a bit more effort for other applications.  In the next lesson, we will explore more of the python side of things and look into cleaning up the code to use classes in preparation for moving to the cairo drawing layer. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/04/26/building-the-xo-porting-a-pygtk-game-to-sugar-part-two/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Inside One Laptop per Child: Episode 02</title>
		<link>http://www.redhatmagazine.com/2007/04/25/inside-one-laptop-per-child-episode-02/</link>
		<comments>http://www.redhatmagazine.com/2007/04/25/inside-one-laptop-per-child-episode-02/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 16:38:07 +0000</pubDate>
		<dc:creator>Julie Bryce</dc:creator>
		
		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/04/25/inside-one-laptop-per-child-episode-02/</guid>
		<description><![CDATA[ Filmed and edited by Simple Coat Productions.
Episode 02 of this series documenting the One Laptop per Child project focuses on the activities built for the laptop. Activities, not applications, since the machine is designed for children and applications is a decidedly adult word.

Also in this episode, meet more of the faces behind the project [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.redhat.com/g/magazine/icon_video_white.gif" alt="(video)"> <em>Filmed and edited by <a href="http://www.simplecoat.tv/">Simple Coat Productions.</a></em><br />
Episode 02 of this series documenting the One Laptop per Child project focuses on the activities built for the laptop. Activities, not applications, since the machine is designed for children and applications is a decidedly adult word.<br />
<a id="more-111"></a><br />
Also in this episode, meet more of the faces behind the project and hear more from CTO <a href="http://en.wikipedia.org/wiki/Mary_Lou_Jepsen"> Mary Lou Jepsen</a> and Red Hat team lead <a Ohref="http://www.0xdeadbeef.com/weblog/?cat=12">Chris Blizzard. </a></p>
<p>Have questions you&#8217;d like answered about the project? Or an idea for a future episode? Leave us a comment&#8211;let us know what you want to see.</p>
<div class="alignLeft">
<embed src="http://www.redhat.com/v/swf/flvplayer.swf?file=http://www.redhat.com/v/swf/olpc02Final.flv&#038;autoStart=false&#038;image=http://www.redhat.com/v/swf/olpc_episode2.png" width="320" height="260" quality="high" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed></p>
<div class="caption" >Download this video: [<a href="http://www.redhat.com/v/ogg/olpc02Final.ogg">ogg</a>]</div>
</div>
<p>Other related videos: <a href="http://www.redhatmagazine.com/2007/03/23/inside-one-laptop-per-child-episode-one/">Inside One Laptop per Child, episode 01. </a>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/04/25/inside-one-laptop-per-child-episode-02/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Building the XO: Porting a PyGTK game to Sugar, part one</title>
		<link>http://www.redhatmagazine.com/2007/04/05/building-the-xo-porting-a-pygtk-game-to-sugar-part-one/</link>
		<comments>http://www.redhatmagazine.com/2007/04/05/building-the-xo-porting-a-pygtk-game-to-sugar-part-one/#comments</comments>
		<pubDate>Thu, 05 Apr 2007 09:23:31 +0000</pubDate>
		<dc:creator>John (J5) Palmieri</dc:creator>
		
		<category>One Laptop per Child</category>

		<guid isPermaLink="false">http://www.redhatmagazine.com/2007/04/05/building-the-xo-porting-a-pygtk-game-to-sugar-part-one/</guid>
		<description><![CDATA[Welcome to this tutorial series on porting a PyGTK game to the OLPC&#8217;s Sugar environment.  While we will be concentrating on a game called Block Party, the lessons taught here can be used as a guide to create or port any number of applications.  Games are just more fun to learn with.  [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to this tutorial series on porting a PyGTK game to the OLPC&#8217;s Sugar environment.  While we will be concentrating on a game called Block Party, the lessons taught here can be used as a guide to create or port any number of applications.  Games are just more fun to learn with.  On top of learning a bit about the Sugar environment, one will also learn about graphics and input handling in PyGTK as well as a few object oriented concepts.  All code in this tutorial should run as standalone PyGTK apps as well as inside of the Sugar environment.</p>
<p><a id="more-90"></a></p>
<p><strong>What is Sugar?</strong></p>
<p>Sugar is the desktop environment which runs on the laptops being developed at OLPC.  It provides a number of interfaces which can be used by applications to integrate into the Sugar environment.  These include interfaces for registering with Sugar and using the mesh networking capabilities of the laptop, among other features.  When an application is integrated into Sugar it is said to be a Sugar activity.</p>
<p><strong>What is Block Party?</strong></p>
<p>Block Party is a Tetris clone written in PyGTK by <a href="http://vadim.oversigma.com/">Vadim Gerasimov</a> and modified by <a href="http://j5live.com">John (J5) Palmieri</a> for this tutorial.  Vadim is one of the original authors of Tetris which he helped create in 1985 when he was 16 years old.  It has been ported to many platforms and clones of it with various modifications are too numerous to count.  Because of this and its relative simplicity it is the perfect program to start playing around with on the OLPC laptop.</p>
<p><img src="http://farm1.static.flickr.com/201/447214858_f71bc01409.jpg?v=0" /></p>
<p><strong>What you will need for this tutorial?</strong></p>
<p>You will need a computer with the latest version of the Sugar environment running on it.  This can either be from sugar-jhbuild, which was covered in <a href="http://www.redhatmagazine.com/2007/02/23/building-the-xo-introducing-sugar/">a previous Red Hat Magazine article</a>, or any build after or including <a href="http://olpc.download.redhat.com/olpc/streams/development/">build 303</a> running in an emulated environment like qemu, from the LiveCD or on the laptop itself. The builds have vim and pico editors installed in them but you may want to use an editor you are more familiar with and copy over the files to test them.</p>
<p>You will also need to <a href="http://dev.laptop.org/~j5/BlockParty_tutorial/">download the source files</a> for the lessons. There is a separate package for each lesson.</p>
<p>It is also assumed the reader knows a bit about the concepts of gtk+ programming and in particular gtk+ programming in python.</p>
<p><strong>Lesson 1: An Overview of the Block Party Source Code</strong></p>
<p>The first step to porting an application is understanding the application you are porting.  To get the source code please download and untar the first lesson&#8217;s source bundle which can be found at <a href="http://dev.laptop.org/~j5/BlockParty_tutorial/block_party_lesson_1.tar.gz">http://dev.laptop.org/~j5/BlockParty_tutorial/block_party_lesson_1.tar.gz</a>.  You should end up with a directory structure looking like this:</p>
<p><code><br />
block_party_lesson_1/<br />
&nbsp;&nbsp;&nbsp;&nbsp;BlockParty.py<br />
</code></p>
<p>To run the program simple change into the lesson directory and run BlockParty.py using python.</p>
<p><code><br />
$ cd block_party_lesson_1<br />
$ python BlockParty.py<br />
</code></p>
<p><strong>The anatomy of a game</strong></p>
<p>Games for the most part follow a similar structure consisting of a couple of high level elements.  There is the main loop and timing element which makes sure events are triggered according to a relatively strict time line. Along with that goes the logic phase which determines positioning and interactions between elements in the game world.  There is also input which needs to be processed and can affect game state.  Finally there is the output which typically happens on the computer monitor.</p>
<p><strong>Mainloops and Timing</strong></p>
<p>Most games have a tight custom mainloop which they use to squeeze every last bit of performance out of their platform.  Games can do this because for the most part they are dedicated applications which interact little with the environment outside their own codebase.  Gtk+ games and in particular Sugar games are a bit different and will often access code not specifically written for the game itself (for instance Sugar&#8217;s networking facilities which will be discussed in a later lesson).  Because of this we need to use a more generic mainloop and do some tricks to get as tight a timing as possible to grantee our game runs smoothly.  For this we use the ever popular glib mainloop.</p>
<p>The glib mainloop allows programs to attach sources to it in order to execute application code on specific events, whether it be networking events, keyboard interrupts or timers.  Of particular interest to us right now is the timer sources.  Timer sources are added using the gobject.timeout_add method.</p>
<p><code><br />
import gobject<br />
&nbsp;<br />
main_loop = gobject.MainLoop()<br />
&nbsp;<br />
# call the timeout_cb function every second<br />
timeout_id = gobject.timeout_add(1000, timeout_cb)<br />
main_loop.run()<br />
</code></p>
<p>This can be seen in the BlockParty.py source at line 480 in the init() method.</p>
<p><code><br />
gobject.timeout_add(20, timer)<br />
</code></p>
<p>Here we call the method timer() every 1/50th of a second.  It is interesting to play with the timeout value to find the optimal timeout period to call.  Calling more times per second doesn&#8217;t necessarily speed up the game and can in fact slow it down as well as drain power from devices which run on battery.  This is because you are running more instructions per second, mostly just checking to see if it is time to trigger an event.  Most of the game&#8217;s time is spent waiting around for events to happen; letting the gtk+ mainloop determine this for you means more efficient use of resources.  However, the gtk+ mainloop is not guaranteed to call the timer() function at exactly every 1/50th of a second; it only tries to make its best effort to do so and may be preempted by higher priority sources.  Let&#8217;s look at the timer() function to see how we can tighten up our timing to make our game run smoothly.</p>
<p><code><br />
# time_step = 100<br />
&nbsp;<br />
def timer():<br />
&nbsp;&nbsp;&nbsp;&nbsp;global game_mode<br />
&nbsp;&nbsp;&nbsp;&nbsp;global next_tick, time_step<br />
&nbsp;&nbsp;&nbsp;&nbsp;while game_mode == PLAY and time.time() >= next_tick:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next_tick += time_step<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tick()<br />
&nbsp;&nbsp;&nbsp;&nbsp;if game_mode != PLAY:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next_tick = time.time()+100<br />
&nbsp;&nbsp;&nbsp;&nbsp;return True<br />
</code></p>
<p>What&#8217;s happening here?  We are getting the current time from the system clock and checking if it is 100 milliseconds after the last &#8216;tick&#8217;.  If we are in PLAY mode and it&#8217;s time for a new tick, we update the next tick to happen 100 milliseconds from now and call the tick() function where we perform all of our game logic.  Returning True at the end of the timer function tells the mainloop to call this function again at the prescribed timeout period.  One always wants to set timeouts to be more granular than the actual frame rate needed for the game.  This is why we call timer() every 1/50th of a second when we only need to update every 1/10th of a second.  I leave it up to the reader to figure out how many frames per second that is.  Hint: Block Party doesn&#8217;t need to run all that fast to be playable.</p>
<p><code>Input</code></p>
<p>Again in most game mainloops one of the steps in the loop is to check for input.  Luckily with the glib mainloop we just get notified when interesting input happens.  This is separate from the timeout source, so we don&#8217;t have to wait for the timeout to be called or the tick to be run to process an input event.  This allows input to feel responsive even if we only update the game logic every 1/10th of a second.  </p>
<p>For Block Party we are mainly interested in the keyboard keys for input, but other games may use the mouse, or even a web cam if the developer possesses some ingenuity.  To get key press events we attach to the key_press_event and key_release_event signals on the main application window in the init() function in BlockParty.py at line 457.</p>
<p><code><br />
window.connect("key_press_event", keypress_cb)<br />
window.connect("key_release_event", keyrelease_cb)<br />
</code></p>
<p>In reality we only care about the key_press_event so the keypress_cb() function is where we do all of our work.</p>
<p><code><br />
def keypress_cb(widget, event):<br />
&nbsp;&nbsp;&nbsp;&nbsp;key_action(gtk.gdk.keyval_name(event.keyval))<br />
&nbsp;&nbsp;&nbsp;&nbsp;return True<br />
</code></p>
<p>Notice that the keypress_cb takes a widget and event object.  The widget in this case is the main GtkWindow we connected the signal handler to.  The event itself contains the key we pressed.  Here we get the key value from the event, translate it to a string and pass it into key_action.  It should be noted that translating the key value to its string representation is a step used to make the code more readable when debugging or looking at other parts of the code.  It does require more processing power to compare the strings and should perhaps be refactored in the future to use just the integer key values.  </p>
<p>The key_action() function does most of the heavy lifting, so let&#8217;s take a look there now.</p>
<p><code><br />
left_key  = ['Left', 'KP_Left']<br />
right_key  = ['Right', 'KP_Right']<br />
drop_key  = ['space', 'KP_Down']<br />
rotate_key = ['Up', 'KP_Up']<br />
exit_key = ['Escape']<br />
sound_toggle_key = ['s', 'S']<br />
enter_key  = ['Return']<br />
&nbsp;<br />
def key_action(key):<br />
&nbsp;&nbsp;&nbsp;&nbsp;global figure,px,py,tickcnt<br />
&nbsp;&nbsp;&nbsp;&nbsp;global glass_update<br />
&nbsp;&nbsp;&nbsp;&nbsp;global game_mode<br />
&nbsp;&nbsp;&nbsp;&nbsp;global soundon<br />
&nbsp;&nbsp;&nbsp;&nbsp;global level<br />
&nbsp;&nbsp;&nbsp;&nbsp;global next_tick, time_step<br />
&nbsp;&nbsp;&nbsp;&nbsp;if key in exit_key: quit_game()<br />
&nbsp;&nbsp;&nbsp;&nbsp;if key in sound_toggle_key: soundon = not soundon<br />
&nbsp;&nbsp;&nbsp;&nbsp;if game_mode == SELECT_LEVEL:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if key in left_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_level(level-1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;glass_update = True<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if key in right_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_level(level+1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;glass_update = True<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: # if key in enter_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;complete_update = True<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next_tick = time.time()+time_step<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;game_mode = PLAY<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_picture()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br />
&nbsp;&nbsp;&nbsp;&nbsp;if game_mode == IDLE:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br />
&nbsp;&nbsp;&nbsp;&nbsp;if game_mode == GAME_OVER:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init_game()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br />
&nbsp;&nbsp;&nbsp;&nbsp;changed = False<br />
&nbsp;&nbsp;&nbsp;&nbsp;if key in left_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;px-=1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not figure_fits(): px+=1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: changed=True<br />
&nbsp;&nbsp;&nbsp;&nbsp;if key in right_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;px+=1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not figure_fits(): px-=1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else: changed=True<br />
&nbsp;&nbsp;&nbsp;&nbsp;if key in drop_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changed = drop_figure()<br />
&nbsp;&nbsp;&nbsp;&nbsp;if key in rotate_key:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changed = rotate_figure_ccw(True)<br />
&nbsp;&nbsp;&nbsp;&nbsp;if changed:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;glass_update = True<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_picture()<br />
</code></p>
<p>If you look closely at the key definitions, you see that we define a list for each key.  This makes use of the python &#8216;in&#8217; operator which allows us to check against multiple key values with one statement.  For instance the statement &#8216;Left&#8217; in left_key will return True where as &#8216;Right&#8217; in left_key will return False.</p>
<p>Really, key_action() is a small state machine that responds to user input based on what state it is in.  For instance, in the SELECT_LEVEL state the right and left arrow keys will cause the level to go up and down, but in the PLAY state (it is not listed in an if statement because it is the default state) it updates the px variable which is what the drawing code uses to figure out what column to draw the falling block in (py defines which row).</p>
<p>If the input has changed the positioning of a block, the display now needs to be updated outside of the timing loop.  If we were to wait until the tick decided to draw input would seem sluggish to the user.  Go ahead and comment out the update_picture() call to see what I mean.  Later on we will talk about the gdk graphics layer we use to draw to the screen and in a later lesson we will show how to refactor the drawing code to use the more modern cairo drawing layer.</p>
<p>While we are on the subject it should be noted that the way drawing is done in lesson 1&#8217;s code is not completely correct since it actually draws to the graphics layer outside the expose event.  All drawing should be done in the expose event to avoid bugs and work with features like double buffering.  The reasons will become clearer in the Cairo lesson.</p>
<p><strong>Logic</strong></p>
<p>A game is no fun without logic.  This is where the rules of the game are enforced and what makes the game fun, challenging and engaging.  If you thought the graphics were the cool part, that is just the end result of the game logic.  No amount of amazing graphics can make up for lack in game logic.  This is why with Block Party&#8217;s decidedly dull graphics it is still a fun game to play.  Later on we may spice them up a bit but that is just icing on the cake.</p>
<p>While some of the game logic resides in the input handlers the bulk of the logic happens from the timing loop when tick() is called every 1/10th of a second.  Every tick the current block is dropped a row and then checked against the game board to see if it created a line or ran into obstacles.  If so the score is updated, a new block is dropped from the top and the next block is computed.  If not the current block waits for another tick or input to do it all over again.  Let&#8217;s examine some of the code.</p>
<p><code><br />
def tick():<br />
&nbsp;&nbsp;&nbsp;&nbsp;global figure, px, py, tickcnt, bh<br />
&nbsp;&nbsp;&nbsp;&nbsp;global figure_score<br />
&nbsp;&nbsp;&nbsp;&nbsp;global complete_update, glass_update<br />
&nbsp;&nbsp;&nbsp;&nbsp;global level, linecount<br />
&nbsp;&nbsp;&nbsp;&nbsp;global game_mode<br />
&nbsp;&nbsp;&nbsp;&nbsp;glass_update = True<br />
&nbsp;&nbsp;&nbsp;&nbsp;py-=1<br />
&nbsp;&nbsp;&nbsp;&nbsp;if figure_score > 0: figure_score -= 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;if not figure_fits():<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;py+=1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;put_figure()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;make_sound('heart.wav')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_figure()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not figure_fits():<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i = random.randint(0, 2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i is 0: make_sound('ouch.wav')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i is 1: make_sound('wah.au'),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i is 2: make_sound('lost.wav')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print 'GAME OVER: score ' + str(score)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;game_mode = GAME_OVER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;complete_update = True<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_picture()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br />
&nbsp;&nbsp;&nbsp;&nbsp;chk_glass()<br />
&nbsp;&nbsp;&nbsp;&nbsp;new_level = int(linecount/5)<br />
&nbsp;&nbsp;&nbsp;&nbsp;if new_level > level: set_level(new_level)<br />
&nbsp;&nbsp;&nbsp;&nbsp;tickcnt += 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;update_picture()<br />
</code></p>
<p>In the tick() function one of the first things we do is drop the block by 1 row.</p>
<p><code><br />
py-=py<br />
</code></p>
<p>We then check to see if the figure is off the screen in the figure_fits() function.  If so the game is over and we set the game into the GAME_OVER state.</p>
<p><code><br />
game_mode = GAME_OVER<br />
</code></p>
<p>If the figure still fits on the game board we then call the chk_glass() function.  In Block Party the glass is how we refer to the game board where the blocks are dropped.  The chk_glass() function goes over the game grid and compares each piece of the block to already filled in parts of the grid.  If there is a collision the glass is checked for full lines and those lines are removed.  Since the game logic from this point can get quite complex it is left as an exercise to the reader to follow the code and see how this is all done.</p>
<p><strong>Drawing</strong></p>
<p>At the end of the logic sequence the board is redrawn via the update_picture() function.  This is also called at the end of input processing.  Block Party uses the Gdk graphics layer to draw into an X window and the Pango API a layer above Gdk for drawing text.  If you look in the init() function you cane see code similar to this.</p>
<p><code><br />
window = gtk.Window(gtk.WINDOW_TOPLEVEL)<br />
window.connect("expose_event", expose_cb)<br />
area = window.window<br />
gc = area.new_gc()<br />
</code></p>
<p>What we are doing is creating a toplevel window, connecting it to the expose event which will tell the window when something has caused it to need a redraw.  We then get the GdkWindow and create a GdkGC.  The GdkGC is used to tell the Gdk graphics layer how to draw its primitives.  Later we will use it to set the colors of the object we wish to draw.</p>
<p><code><br />
def update_picture():<br />
&nbsp;&nbsp;&nbsp;&nbsp;global complete_update, glass_update<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if complete_update:<br />
&nbsp;&nbsp;&nbsp;&nbsp;draw_background()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw_score()<br />
&nbsp;&nbsp;&nbsp;&nbsp;if complete_update or glass_update:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw_glass()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw_next()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if game_mode is GAME_OVER: draw_game_end_poster()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if game_mode is SELECT_LEVEL: draw_select_level_poster()<br />
&nbsp;&nbsp;&nbsp;&nbsp;complete_update = False<br />
&nbsp;&nbsp;&nbsp;&nbsp;glass_update = False<br />
</code></p>
<p>Looking at the update_picture() function we see a couple of draw function which are used to draw the various parts of the game board.  We will be looking at the draw_score() and draw_next() functions to show how both text and graphics are handled in BlockParty.</p>
<p><img src="http://farm1.static.flickr.com/207/447214890_68e51e4c4d.jpg?v=0" /><br />
<code><br />
def draw_score():<br />
&nbsp;&nbsp;&nbsp;&nbsp;global gc, area<br />
&nbsp;&nbsp;&nbsp;&nbsp;global linecount, score, level, scorefont<br />
&nbsp;&nbsp;&nbsp;&nbsp;global scorex, scorey<br />
&nbsp;&nbsp;&nbsp;&nbsp;global color_score<br />
&nbsp;&nbsp;&nbsp;&nbsp;displaystr = 'Score: ' + str(score)<br />
&nbsp;&nbsp;&nbsp;&nbsp;displaystr += '\nLevel: ' + str(level)<br />
&nbsp;&nbsp;&nbsp;&nbsp;displaystr += '\nLines: ' + str(linecount)<br />
&nbsp;&nbsp;&nbsp;&nbsp;pl = window.create_pango_layout(displaystr)<br />
&nbsp;&nbsp;&nbsp;&nbsp;pl.set_font_description(scorefont)<br />
&nbsp;&nbsp;&nbsp;&nbsp;gc.set_foreground(color_score)<br />
&nbsp;&nbsp;&nbsp;&nbsp;area.draw_layout(gc, scorex, scorey, pl)<br />
</code></p>
<p>In draw_score we create a string called displaystr of the text we wish to draw.  We then create a pango layout and pass the string to it.  A font description is then set which was created earlier in the init() function with these commands.</p>
<p><code><br />
scorefont = pango.FontDescription('Sans')<br />
scorefont.set_size(window_w*16*pango.SCALE/1024)<br />
</code></p>
<p>After setting the font we set the foreground color and use the draw_layout method on the GdkWindow to display the pango layout.  </p>
<p>That is all there is to it.  Now let&#8217;s look at the draw_next() function.</p>
<p><img src="http://farm1.static.flickr.com/229/447214888_48a487f9db.jpg?v=0" /><br />
<code><br />
def draw_next():<br />
&nbsp;&nbsp;&nbsp;&nbsp;global gc, area, window, next_figure<br />
&nbsp;&nbsp;&nbsp;&nbsp;global bw, bh, bwpx, bhpx, xshift, yshift<br />
&nbsp;&nbsp;&nbsp;&nbsp;gc.set_foreground(color_score)<br />
&nbsp;&nbsp;&nbsp;&nbsp;draw_centered_string('NEXT', xnext+bwpx*2.5, ynext)<br />
&nbsp;&nbsp;&nbsp;&nbsp;gc.set_foreground(colors[0])<br />
&nbsp;&nbsp;&nbsp;&nbsp;area.draw_rectangle(gc, True, xnext, ynext+50, bwpx*5, bhpx*5)<br />
&nbsp;&nbsp;&nbsp;&nbsp;gc.set_foreground(color_score)<br />
&nbsp;&nbsp;&nbsp;&nbsp;for i in range(4):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for j in range(4):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if next_figure[i][j] is not 0:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gc.set_foreground(colors[next_figure[i][j]])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;area.draw_rectangle(gc, True, xnext+j*bwpx+bwpx/2, ynext+50+(3-i)*bhpx+bhpx/2, bwpx, bhpx)<br />
</code></p>
<p>The draw_next() function draws the box which displays the next block which will fall after the current block has been placed.  Here we set the foreground color and use our draw_center_string() function to basically do the same thing we did in draw_score().  After we are done drawing the text label &#8216;NEXT&#8217;, we set the foreground color to the first value of the colors array which is black.  The colors array is setup earlier in the code and contains a set of predefined colors we use throughout the game. Next we draw a black rectangle with the draw_rectangle() method.  This will become the box where we will draw the block in.</p>
<p>Each block in Block Party is defined in a 4 by 4 array.  A square block may look something like this:</p>
<table cellpadding="10">
<tr>
<td>
0000<br />
0110<br />
0110<br />
0000
</td>
<td>
<img src="http://farm1.static.flickr.com/232/447214882_121cba5d23.jpg?v=0" /></p>
<td>
</tr>
</table>
<p>Or a T block may look something like this:</p>
<table cellpadding="10">
<tr>
<td>
0100<br />
0110<br />
0100<br />
0000
</td>
<td>
<img src="http://farm1.static.flickr.com/194/447214894_8307351eda.jpg?v=0" /></p>
<td>
</tr>
</table>
<p>The 0s represent no colors and the 1s actually represent a color value in the array.  When the code loops over this array and sees a color value, a rectangle is drawn at the offset with the color specified by the color value.  An interesting challenge for the reader would be to replace the color value with a picture, and change the drawing code to draw the picture instead of just plain colored squares.</p>
<p>The rest of the drawing code does similar tasks of drawing text and rectangles.  The draw_glass() function is the most interesting of the drawing code, as it needs to keep track of the game grid and erase previous draws or falling blocks would simply paint the screen by leaving trails of itself every time it moved.  We will get rid of some of this complexity when we move to cairo and will end up having to repaint the entire screen on expose events.  That might seem like it would inefficient but with effective use of dirty regions it will actually clean up the code quite a bit without loss of performance.</p>
<p><strong>Conclusion</strong></p>
<p>Now that we have a decent understanding of how Block Party works, we can start to delve deeper and evolve the codebase.  The next lesson will show how to take the code we have been working with and, with little modification, turn it into a Sugar activity bundle.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.redhatmagazine.com/2007/04/05/building-the-xo-porting-a-pygtk-game-to-sugar-part-one/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
