<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Ranger Sheck's Blog - Home</title>
  <id>tag:rangersheck.com,2010:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  <link href="http://rangersheck.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://rangersheck.com/" rel="alternate" type="text/html"/>
  <updated>2010-05-10T13:59:48Z</updated>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2010-05-08:308</id>
    <published>2010-05-08T17:05:00Z</published>
    <updated>2010-05-10T13:59:48Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="dungeons"/>
    <category term="javascript"/>
    <category term="nethack"/>
    <category term="procedural generation"/>
    <category term="rogue"/>
    <category term="roguelike"/>
    <category term="rpg"/>
    <category term="RPG"/>
    <link href="http://rangersheck.com/2010/5/8/procedural-dungeon-generation" rel="alternate" type="text/html"/>
    <title>Procedural Dungeon Generation</title>
<content type="html">
            &amp;lt;style&gt;
pre { color: #852; }
td { background: #EEE; padding: 2px; }
&amp;lt;/style&gt;
&lt;p&gt;There are a lot of good resources out there for Procedural Content Generation. The &lt;a href=&quot;http://pcg.wikidot.com/pcg-algorithm:dungeon-generation&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PCG&lt;/span&gt; wiki&lt;/a&gt; lists a ton, and if you&#8217;re looking to read up on the subject, it&#8217;s a great place to start.&lt;/p&gt;
&lt;p&gt;A lot of these ideas are derived from the original Nethack game (and predecessors like Rogue and Angband). As the &lt;span class=&quot;caps&quot;&gt;PCG&lt;/span&gt; wiki says, there are two basic methods to dungeon generation: you either start with a bunch of rooms and then connect them, or you start with solid rock and carve out a maze.&lt;/p&gt;
&lt;p&gt;As you might expect, implementations of the first method are more widely used. I&#8217;ve been playing Chocobo&#8217;s Dungeon off and on for a while now (over a year, I guess), and whenever I play it I start thinking about procedural generation. It&#8217;s quite obvious that the dungeons in Chocobo&#8217;s are a bunch of standard room shapes randomly scattered about a floor and then connected via corridors.&lt;/p&gt;
&lt;p&gt;There is a &lt;strong&gt;code sample&lt;/strong&gt; and &lt;strong&gt;live demo&lt;/strong&gt; (in javascript) linked toward the end of this article, but if you&#8217;re impatient and you want to see what the heck I&#8217;m talking about, &lt;strong&gt;&lt;a href=&quot;http://examples.rangersheck.com/proc_dung_gen/&quot;&gt;here is the demo&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;
&lt;h3&gt;Starting with the Rooms&lt;/h3&gt;
&lt;p&gt;In some cases, the shapes of rooms might themselves be randomly derived. I noticed that in Chocobo&#8217;s, there were some definite pre-created room shapes. I decided to try it that way myself. I created a couple of text files to store each room-shape&#8217;s data. I used a simple, arbitrary code for &#8220;drawing&#8221; the rooms with characters:&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;character&lt;/th&gt;
		&lt;th&gt;stands for&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;W&lt;/td&gt;
		&lt;td&gt;walls&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;f&lt;/td&gt;
		&lt;td&gt;floors&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;+&lt;/td&gt;
		&lt;td&gt;possible connection points&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;(space)&lt;/td&gt;
		&lt;td&gt;empty space&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;An example room:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;W+WWWWW
Wfffff+
WfffffW
WfffWWW
WfffW
+fffW
WW+WW&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Toss some Rooms together, one Row at a Time&lt;/h3&gt;
&lt;p&gt;At first it&#8217;s tempting to be really random when throwing rooms together. Most of the time, however, we want our rooms to collectively fit into a nice neat square or rectangle. Personally, I don&#8217;t want my rooms too spread out either. Which lead me to the next temptation &#8211; just create a grid and put one room in each cell of a grid. I think you can already guess how boring that might look. It&#8217;d be like someone built a dungeon on a tic-tac-toe board.&lt;/p&gt;
&lt;p&gt;So I&#8217;m going for a compromise. First, I start with an arbitrary size limit &#8211; like: 30&#215;40. Then I take things one &#8220;row&#8221; at a time &#8211; and by &#8220;row&#8221;, I mean a row of rooms. I pick a room at random, stick that into a list. I keep track of how much x-space (width) this room is taking up out of my maximum. I pick another random room (narrowing my list down to only rooms that will fit in the space remaining &#8211; adding 3 units to account for corridors in between), add it to the list, add up the total used space, and so on.&lt;/p&gt;
&lt;p&gt;What I end up with is a handful of room shapes. I randomize the order of my list and start placing them in a row &#8211; as if I&#8217;m sticking objects side by side into a box &#8211; taking care to pad the breaks in between with 3 units to make sure there is minimum room for a corridor. Then I figure out the leftover horizontal space on the end of the box. I redistribute that space randomly throughout the whole &#8220;room row&#8221;, causing rooms to space out from each other a little if there is extra room.&lt;/p&gt;
&lt;p&gt;At this point, the room-row is as tall as the tallest room. I can now shuffle the shorter rooms up and down randomly. Here&#8217;s a sample room-row:&lt;/p&gt;
&lt;pre&gt;W+WWWWW              WWW+W
Wfffff+   WWW+WWW    WfffW
WfffffW   Wfffff+    WfffW
WfffWWW   WfffffW    +fffW
WfffW     +fffffW    WfffWWWWW
+fffW     WWW+WWW    Wfffffff+
WW+WW                WfffffffW
                     W+WWWWWWW&lt;/pre&gt;
&lt;p&gt;Then we move on to another row of rooms, and another, as long as we have space to accommodate them. The key to keeping this as un-grid-like as possible is variations on room shapes &#8211; particularly, variations on widths and heights. Try making rooms that are large, small, long, tall, L shapes (pointing in various directions) and other interesting shapes.&lt;/p&gt;
&lt;h3&gt;Connecting Rooms with Corridors&lt;/h3&gt;
&lt;p&gt;There are a few different ways to go about generating corridors. You can specifically try creating them room by room, ensuring that every room is connected to at least one other room; the benefit of this method is that you never have to worry about having a map split into two segments, unreachable from each other.&lt;/p&gt;
&lt;p&gt;I decided to go another direction though: almost totally random connections. The side effects of method are: a) you are not guaranteed that all rooms will be connected &#8211; you have to do some kind of test (like a flood fill) at the end and discard your dungeon if not all floor tiles are reachable; and b) you get some interesting results where rooms might connect to themselves by an external corridor across one side. I liked this second side effect, since it adds just a little less predictability to the process, so that&#8217;s why I&#8217;m doing it this way.&lt;/p&gt;
&lt;p&gt;First, I find what I call the &#8220;nubs&#8221; of every room. These are the points out in space, just off the connector points that I used a &#8216;+&#8217; to designate. I find each &#8216;+&#8217;, then ask &#8220;where is the blank space from here&#8221;? In other words, from the (x,y) of the &#8216;+&#8217;, I try N, S, E, W until I find the coordinates that have just a space (rather than a &#8216;f&#8217; or a &#8216;W&#8217;). Then I take a random ordering of the &#8220;nubs&#8221; and for each one of those, I try connecting it randomly to every other. I check to see if a corridor could be drawn by first checking to see if a rectangle could be drawn, with each nub as a corner. If I can draw a rectangle without crossing any other filled coordinates, then we go ahead and make a corridor.&lt;/p&gt;
&lt;h3&gt;Drawing a Corridor&lt;/h3&gt;
&lt;p&gt;Making a corridor is pretty easy, really. You have a start point and end point. First, you have to determine which x-direction and which y-direction you need to go. For example: if your start is 2,3 and your end is 6,7, then you need to go positive in both x and y. If your start is 2,7 and your end is 6,3, then you need to go positive in x but negative in y. Then we randomly decide &#8211; either step in the x direction or step in the y direction. Each step we take, we make sure not to go over the ending x or y. For example, if we reach the x destination, then we stop picking x or y randomly and instead just step in y direction the rest of the way.&lt;/p&gt;
&lt;pre&gt;W+WWWWW          
Wffffffff WWW+WWW
WfffffW f Wfffff+
WfffWWW ffWfffffW
WfffW    fffffffW
+fffW     WWW+WWW
WW+WW           &lt;/pre&gt;
&lt;p&gt;&lt;em&gt;an example of a randomly drawn corridor&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Notice that we didn&#8217;t bother with the walls &#8211; we&#8217;ve only mapped out the floor tiles between the start and the end points. After the floor is drawn, we can add walls by cycling through every floor tile and checking N, S, E, and W of each one. If there is a blank tile next to a floor tile, turn that blank into a &#8216;W&#8217;. Finally, we replace any unused &#8216;+&#8217; tiles with a &#8216;W&#8217; as well.&lt;/p&gt;
&lt;h3&gt;Code Sample and Live Demo&lt;/h3&gt;
&lt;p&gt;I wrote this code originally in Ruby, since it&#8217;s going to become part of the code-base for &lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&lt;/a&gt; (no, you won&#8217;t see these kinds of dungeons in Aethora, but you will see a spin-off: a more &#8220;dungeon crawler &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;&#8221; type of game, less &#8220;tactics/strategy&#8221; type of game). I&#8217;ve taken the time to rewrite the algorithms as javascript so that I can demonstrate it easily on a web page and that more people will be able to dig into it and read it (admitting that more people are familiar with js than ruby).&lt;/p&gt;
&lt;p&gt;Requirements for this code: I used &lt;a href=&quot;http://jquery.com&quot;&gt;jquery&lt;/a&gt; this time, so you&#8217;ll need that I&#8217;m using 1.4.2). I&#8217;m also using the small but awesome &lt;a href=&quot;http://wiki.github.com/danwrong/low-pro/&quot; title=&quot;for jquery&quot;&gt;lowpro&lt;/a&gt; library, which allows for an object-oriented style way of writing behaviors for events on elements. This library was extremely useful when used with prototype, since prototype lacks the handy &#8220;attach&#8221; functions that jquery has, but I still find it nice for jquery because it allows me to organize event handling in a clean way.&lt;/p&gt;
&lt;p&gt;If you view the source on the page (that I&#8217;m about to link to) you&#8217;ll notice a couple of other js files that I&#8217;ve created:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://examples.rangersheck.com/proc_dung_gen/javascripts/array.js&quot;&gt;array.js&lt;/a&gt; &#8211; just a few helper methods for bastardizing the Array prototype to include sum, max, and min&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://examples.rangersheck.com/proc_dung_gen/javascripts/room_template.js&quot;&gt;room_template.js&lt;/a&gt; &#8211; a simple object class for encapsulating those &lt;strong&gt;room shapes&lt;/strong&gt; that we set up in the beginning&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://examples.rangersheck.com/proc_dung_gen/javascripts/mapper.js&quot;&gt;mapper.js&lt;/a&gt; &#8211; an object class used to encapsulate the map generation functions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&#8217;ll also see a small block of js in the source of the index file where RoomGenerator is defined &#8211; that&#8217;s the lowpro behavior. We just attach it to the &#8220;generate&#8221; form.&lt;/p&gt;
&lt;p&gt;The room shapes are in textareas, so go ahead and tweak them if you want. Also you can play with the dimensions &#8211; I&#8217;ve given you a starting size of 30&#215;30, but put in whatever you want. Use at your own risk!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://examples.rangersheck.com/proc_dung_gen/&quot;&gt;Procedural Dungeon Generation Demo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One more note &#8211; notice that in this demo, we&#8217;re not checking to make sure all the rooms are connected. In my real code, what I do is: first generate a dungeon. Second, make a copy of the dungeon. Grab a floor tile of the copy and replace it with an &#8216;X&#8217;, and flood-fill out from there, replacing all f&#8217;s with X&#8217;s. Then I loop through the copy and make sure there are no f&#8217;s left. If there are, then I know those floor tiles were unreachable by flood-fill, and therefore unconnected. I toss out the dungeon and generate a new one (no, it doesn&#8217;t really take long to randomly generate these dungeons; a few milliseconds is all). Another option would be to somehow look for a way to force a connection between any disconnected rooms, by just finding any ol&#8217; space where a corridor might fit.&lt;/p&gt;
&lt;h3&gt;Bonus Round: Converting &#8216;f&#8217;, &#8216;W&#8217; into images&lt;/h3&gt;
&lt;p&gt;We&#8217;ve covered the generation of the rooms and corridors. If you&#8217;re making a text-based game, then just using &#8216;W&#8217; to designate a wall works just fine. But if you want to convert those walls into image tiles, you&#8217;ll want to figure out how to place corners, horizontal walls, vertical walls, connecting walls, and so on.&lt;/p&gt;
&lt;p&gt;To simplify this task, I decided to name my walls based on the directions a wall tile connects to other walls. Some examples:&lt;/p&gt;
&lt;pre&gt;WW
W&lt;/pre&gt;
&lt;p&gt;The first tile is a corner wall. It connects to a wall to the &lt;strong&gt;South&lt;/strong&gt; and a wall to the &lt;strong&gt;East&lt;/strong&gt;. It&#8217;s image name is &lt;strong&gt;wall_s_e&lt;/strong&gt;.&lt;br /&gt;
The second tile connects only to the &lt;strong&gt;West&lt;/strong&gt;: &lt;strong&gt;wall_w&lt;/strong&gt;&lt;br /&gt;
The bottom tile connects only to the &lt;strong&gt;North&lt;/strong&gt;: &lt;strong&gt;wall_n&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;WWW&lt;/pre&gt;
&lt;p&gt;The first tile only connects to the &lt;strong&gt;East&lt;/strong&gt;: &lt;strong&gt;wall_e&lt;/strong&gt;&lt;br /&gt;
The middle wall tile connects to the &lt;strong&gt;East&lt;/strong&gt; and to the &lt;strong&gt;West&lt;/strong&gt;: &lt;strong&gt;wall_e_w&lt;/strong&gt;.&lt;br /&gt;
The last tile connects to the &lt;strong&gt;West&lt;/strong&gt;: &lt;strong&gt;wall_w&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It may seem a little backwards at first &#8211; because you think a wall is sticking out to the South, but it&#8217;s &lt;em&gt;connecting&lt;/em&gt; to the North, so we call it wall_n instead of wall_s. There is a reason for doing it this way &#8211; it&#8217;s much easier to write code to detect which directions walls connect in than which directions they &#8220;stick out in&#8221;.&lt;/p&gt;
&lt;p&gt;So anyway, it&#8217;s just a matter of looping through all the wall tiles and then checking: do I have a wall to the North? do I have one to the South? East? West? Okay, on to the next wall tile.&lt;/p&gt;
&lt;p&gt;Before you know it, you&#8217;ve turned your W&#8217;s and f&#8217;s into tiles:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://rangersheck.com/assets/2010/5/8/example_dungeon.png&quot;&gt;&lt;img title=&quot;click for larger version&quot; src=&quot;/assets/2010/5/8/example_dungeon-sm.png&quot; alt=&quot;click for larger version&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;em&gt;click the image for a larger version&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, that&#8217;s all for today. If you have any questions, don&#8217;t hesitate to ask. I&#8217;m too lazy to put a license in the js code itself, but you can consider it licensed under &lt;span class=&quot;caps&quot;&gt;MIT&lt;/span&gt; (so do whatever you want with it; credit would be nice, but not required). If anyone has the time to port this code to &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt;, Python, perl, .&lt;span class=&quot;caps&quot;&gt;NET&lt;/span&gt;, or whatever, please let me know. I can provide a ruby version on request, but if you&#8217;re patient, I do plan on releasing a whole giant chunk of the Aethora code base (which is Ruby on Rails) as open source.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2010-03-14:303</id>
    <published>2010-03-14T21:44:00Z</published>
    <updated>2010-03-14T21:45:26Z</updated>
    <category term="Game Design"/>
    <category term="Reviews and Reflections"/>
    <category term="crpg"/>
    <category term="reflections"/>
    <category term="reviews"/>
    <category term="role playing games"/>
    <category term="rpg"/>
    <category term="RPG"/>
    <category term="rpg reviews"/>
    <link href="http://rangersheck.com/2010/3/14/rpg-reflections-eschalon-book-i" rel="alternate" type="text/html"/>
    <title>RPG Reflections - Eschalon Book I</title>
<content type="html">
            &lt;p&gt;Hey, everyone. I have been very lax on making posts to this blog lately, but I&#8217;m going to try to be more active. I&#8217;m a player as much as a developer, so I&#8217;ve decided to gather some of my thoughts about a few different CRPGs that I&#8217;ve played in the past year or so. These games will probably seem random to some people, but that&#8217;s me &#8211; I like to sample a little of everything.&lt;/p&gt;


	&lt;p&gt;Rather than write reviews, however, it&#8217;s my intention to reflect on the designs of games. There are things that I like and things that I don&#8217;t like, and I&#8217;d like to talk about why, and how the elements of these games affect my own game designs.&lt;/p&gt;


	&lt;h3&gt;&lt;a href=&quot;http://basiliskgames.com/eschalon-book-i&quot;&gt;Eschalon: Book I&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;&lt;em&gt;Basilisk Games &#8211; Linux, Mac, Windows &#8211; $19.95, downloadable (price as of 3/2010)&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;I&#8217;ve played Eschalon Book I off and on for the last couple of years. I finally completed a game of it sometime last year. It&#8217;s a somewhat retro-style single player &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;. Combat and movement is &lt;strong&gt;turn-based&lt;/strong&gt; and the isometric graphics are laid out on an invisible grid. You get one character (no parties, pets, or henchmen) and there are a bunch of equipment slots. The game features a typical exp-based level system with skill points and character attributes. Be forewarned &#8211; it takes a lot of time to level up in this game. If you&#8217;re used to the ridiculous leveling pace of your average &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt;, you may find yourself going through &lt;strong&gt;ding-withdrawal&lt;/strong&gt;.&lt;/p&gt;


&lt;div&gt;&lt;a href=&quot;/assets/2010/3/14/book1_shot1.jpg&quot;&gt;&lt;img src=&quot;/assets/2010/3/14/book1_shot1-sm.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;em&gt;Eschalon: Book I &#8211; in the mood for a classic &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;?&lt;/em&gt;
&lt;/div&gt;

	&lt;p&gt;There are a couple of things I really love about EB-I. First off, it&#8217;s &lt;strong&gt;cross-platform&lt;/strong&gt;, so it already gets an extra look from me. I do all my day to day work in a Linux environment, and any game that runs natively in Linux is a game I am more inclined to try out to break up my workday. It&#8217;s developed by an &lt;strong&gt;indie&lt;/strong&gt; game company, and I know when I spend $20 on the download, the money is going right to the developers. Oh, and there&#8217;s a playable &lt;strong&gt;demo&lt;/strong&gt;, so you can try it before you buy it.&lt;/p&gt;


	&lt;p&gt;But enough of that &#8211; let&#8217;s talk game mechanics. I&#8217;m a big fan of the turn-based play; you take a step, all your enemies take a step, that kind of thing. It&#8217;s not much for &#8220;realism&#8221;, but it&#8217;s great for casual RPGs because you can stop and think about what you want to do &#8211; and if you have to stop in the middle of combat and answer email or something, there&#8217;s no pressure &#8211; you can always come back to the game and pick up wherever you left off. EB-I does turn based action very well. Tight hallways and small rooms indoors and in dungeons provide a nice contrast to wide open spaces in the wilderness, resulting in benefits and weaknesses to different fighting styles depending on the situation.&lt;/p&gt;


	&lt;p&gt;EB-I also features an interesting &lt;strong&gt;day and night&lt;/strong&gt; system. The transition doesn&#8217;t happen all at once, but rather, you get various degrees of visibility as the sun goes down and it slowly gets darker. The &lt;strong&gt;map system&lt;/strong&gt; is unique in that it requires a &#8220;cartography&#8221; skill. As you walk around the world, the area you can see gets drawn in on your map. The more points you spend on cartography, the more clearly and colorfully your map gets drawn.&lt;/p&gt;


&lt;div&gt;&lt;a href=&quot;/assets/2010/3/14/book1_shot2.jpg&quot;&gt;&lt;img src=&quot;/assets/2010/3/14/book1_shot2-sm.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;em&gt;Oh, how I love that mapping system&lt;/em&gt;
&lt;/div&gt;

	&lt;p&gt;The storyline of EB-I is pretty decent. As a rule, I&#8217;m never blown away by &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt; storylines, but I can say I actually read most of the dialog in EB-I as opposed to mashing the skip button as fast as I can (as with some other games that tend to drone on and on about prophecies and gods I&#8217;m expected to know about). The game has a quest system that allows you to pursue the main storyline as well as several side-quests at any given time. The quests are pretty much linear &#8211; you either do what you&#8217;re told to or you don&#8217;t finish the quest.&lt;/p&gt;


	&lt;p&gt;There are a few interesting puzzles in the game. However, there are also a few faux-puzzles &#8211; those annoying times when you have to run all the way from one end of a dungeon to the other to hit a switch that opens a door back at the beginning. These kinds of annoyances seemed to be more frequent in the early areas of the game (which had the unfortunate side-effect of making me get bored quit playing it for a while). Later on, the exploration of new areas gets much more interesting.&lt;/p&gt;


	&lt;p&gt;In EB-I, all the enemies you&#8217;ll face are specifically placed throughout the world. For example, let&#8217;s say you walk into a forest clearing and encounter three lizards. If you were to start a new game with a new character and go to that same clearing, you&#8217;ll see the same three lizards. There is &lt;strong&gt;no respawning of enemies&lt;/strong&gt;, either, so once you kill those three lizards you can revisit that clearing and you&#8217;ll never see any enemies there.&lt;/p&gt;


	&lt;p&gt;I&#8217;m not sure how I feel about this little quirk. On the one hand, it&#8217;s nice to be able to travel through an area already &#8220;cleared&#8221; without having to fight through more of the same monsters. But on the other hand, there are a finite number of enemies, and thus a finite amount of experience points (and thus, levels) you can get. If you find yourself getting stuck somewhere because you&#8217;re just not strong enough, you don&#8217;t have a way to go back and re-fight easier enemies to level up. It keeps the game challenging, I suppose, but depending on the class you pick, it can be a little too challenging to be fun. There is one way to &#8220;spawn&#8221; enemies, and that is to pick a spot outside and rest for hours and hours (in game, not real time) and get ambushed by traveling gangs of enemies; but that just feels&#8230; clumsy.&lt;/p&gt;


	&lt;h4&gt;My take-away from &lt;em&gt;Eschalon: Book I&lt;/em&gt; as a game designer and developer&lt;/h4&gt;


	&lt;p&gt;This game is several years old, but they still sell it, and probably make new sales all the time. Honestly, due to it&#8217;s retro design, it&#8217;s protected from going out of style. Sometime this year they expect to release Book II (finally), and will sell it for $25. Anyone who has played through the first one will almost certainly spring for the second one (I certainly will). Some thoughts:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Having no easy way to fight randomly-spawned enemies is a small hang-up, but in terms of my personal preferences in game design, I would choose to include some system that would allow for it. Spawned enemies give a player a chance to practice different combat styles and tactics, try out equipment, and see how spells, potions, and special abilities work. It allows them to do a little &#8220;field testing&#8221; before heading off to fight tougher enemies.&lt;/li&gt;
		&lt;li&gt;The game has a pretty easy-to-master interface and despite it&#8217;s limited resolution, pretty decent graphics for an indie game.&lt;/li&gt;
		&lt;li&gt;I like the skill point system and the fact that some skills are not necessarily combat-based, but still worth spending skill points in (I love the cartography and mapping system, and also the alchemy skill and system is well done). There is a quick travel feature that allows you to jump back to a few select points once you&#8217;ve visited them &#8211; that&#8217;s a great feature for casual gamers like me.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;That&#8217;s all for today. I don&#8217;t know about you all, but I&#8217;m suffering from &lt;em&gt;daylight-savings jet lag&lt;/em&gt; &#8211; which makes this a perfect Sunday for veging-out with some video games. Have a good week, and keep on playing!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2009-07-24:297</id>
    <published>2009-07-24T15:06:00Z</published>
    <updated>2009-07-24T15:11:51Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="ajaj"/>
    <category term="ajax"/>
    <category term="browser game"/>
    <category term="game design"/>
    <category term="game development"/>
    <category term="javascript"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="web design"/>
    <link href="http://rangersheck.com/2009/7/24/rewriting-aethora-s-battle-interface" rel="alternate" type="text/html"/>
    <title>Rewriting Aethora's Battle Interface - Part 1</title>
<content type="html">
            &lt;p&gt;Over the last several months, I worked out a whole new interface for &lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&#8217;s&lt;/a&gt; battle screen. I&#8217;ve learned a lot about javascript in the last couple of years since the original design, and I felt that it was about time to scrap the whole thing and rewrite it from scratch. I&#8217;m breaking this article into two parts. The first part here will touch on what was wrong with the old interface a little, and then focus on  performance improvements. The second part will focus on &#8220;point and click&#8221; interface improvements.&lt;/p&gt;


	&lt;h3&gt;Beef with the original&lt;/h3&gt;


	&lt;p&gt;The original design drew the battle map by actually drawing a huge table and putting a map tile in each cell. At the end of every turn, any NPCs that needed to take their turn would do so while the player sat and watched a big &#8220;Loading&#8230;&#8221; box, then the whole page got redrawn, the server globbing a huge amount of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; back to the browser. The only evidence that any NPCs took their turns was in the battle log.&lt;/p&gt;


	&lt;p&gt;When you wanted to take an action, you had to first highlight a target. It was like a &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt; &#8211; target first, then act. When you targeted someone, you&#8217;d get a list of valid actions depending on whether they were friendly or not, how close you were, and how many Action Points you had left. Some players reported that they often moved PCs one tile at a time, inching their way closer to see when they would be just in range for certain attacks. Many players complained that area-based attacks could not be placed in the center of a group of targets unless one of the targets happened to be standing dead center.&lt;/p&gt;


&lt;div&gt;&lt;img src=&quot;/assets/2009/7/24/old_tabs_sm.jpg&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;em&gt;old UI: tabby&lt;/em&gt;&lt;/div&gt;

	&lt;p&gt;The old interface also featured a bunch of tabbed components to the right of the map. They held, individually, information about the character who&#8217;s turn it was, the help screen, the chat screen, the battle log, and the &#8220;turn order&#8221; screen (which showed all the PCs and NPCs in the order in which they get their turns, each with health and defense bars). Tabs are a great way to group UI elements when you are dealing with multiple pages of configuration, but when they hide elements that players want to see constantly, then they just become a nuisance.  In particular, not being able to see the battle log and the full list of PCs/NPCs with their current status was a common player lament.&lt;/p&gt;


	&lt;h3&gt;Setting the bar&lt;/h3&gt;


&lt;div&gt;&lt;img src=&quot;/assets/2009/7/24/mountains_sm.jpg&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;em&gt;new UI: everything is visible&lt;/em&gt;
&lt;/div&gt;

I had a couple of goals for the rewrite:
	&lt;ul&gt;
	&lt;li&gt;no full screen page refreshing&lt;/li&gt;
		&lt;li&gt;show the player what the &lt;span class=&quot;caps&quot;&gt;NPC&lt;/span&gt; are doing during their turns&lt;/li&gt;
		&lt;li&gt;minimize the amount of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; needed&lt;/li&gt;
		&lt;li&gt;separate the javascript from the server-side code in a way so that either could be used without the other (having the mindset of an open &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;)&lt;/li&gt;
		&lt;li&gt;fit all the elements onto one compact screen with no tabs hiding information&lt;/li&gt;
		&lt;li&gt;improve the user interaction (moving characters and taking actions)&lt;/li&gt;
		&lt;li&gt;keep everything as generic as possible to lay the groundwork for PvP/Co-op in the future&lt;/li&gt;
	&lt;/ul&gt;


&lt;div&gt;
&lt;em&gt;&lt;strong&gt;So what about PvP/Co-op? Does this mean it&#8217;s not far off for Aethora?&lt;/strong&gt;&lt;/em&gt;
&lt;br /&gt;&lt;br /&gt;
Well, code-wise, there&#8217;s not a whole lot to do. The server-side code has to be tweaked a bit to allow multiple parties to participate in a battle. Some game design decisions have to be made:

	&lt;ul&gt;
	&lt;li&gt;Where will PvP be allowed? &lt;/li&gt;
		&lt;li&gt;What are the consequences? &lt;/li&gt;
		&lt;li&gt;How long will a player have to wait for another player to act before the game passes on their turn&#8230;&lt;/li&gt;
		&lt;li&gt;...or should it act for them rather than pass? &lt;/li&gt;
		&lt;li&gt;And how many turns are passed before someone forfeits? &lt;/li&gt;
		&lt;li&gt;What if it&#8217;s co-op? &lt;/li&gt;
		&lt;li&gt;Is the battle lost if someone times out? Or is it a &#8220;draw&#8221;?&lt;/li&gt;
	&lt;/ul&gt;


A lot of questions still to answer before we go down that road, I&#8217;m afraid.
&lt;/div&gt;

	&lt;p&gt;The first couple of goals kind of go together. What they amount to is a whole lot of javascript. I took advantage of the object-oriented aspects of javascript and roughly mapped some of my server side objects to javascript objects. When the battle window first opens, some &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; sets up the framing of the layout, and then a couple different ajax calls are made: the map tiles, the &#8220;mobs&#8221;  (short for &#8220;mobiles&#8221;: in other words, PCs and NPCs), the chat log, the battle log, and the actions that are available for the PC with the &#8220;current turn&#8221;. Each of these calls fills in a different part of the screen (and actually, the actions-load doesn&#8217;t trigger until after the mobs are loaded in).&lt;/p&gt;


	&lt;p&gt;From this point, I can update any individual components as they are needed. When someone moves their character, the only thing that needs to be reloaded is that mob&#8217;s stats: to reflect the deduction of movement points and to set their x,y location on the map. If they take an action against another mob, then both of those mobs need to be updated. In both these cases, the battle log also needs to be updated.&lt;/p&gt;


	&lt;h3&gt;Smaller bites of &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; &#8211; or as the kids say these days&#8230; &lt;span class=&quot;caps&quot;&gt;AJAJ&lt;/span&gt;?&lt;/h3&gt;


	&lt;p&gt;All of these updates are &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; calls, although as many people have started to point out, &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; is not always Asynchronous Javascript and &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt;. In this case, I, like many others, have set aside &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; and opted for the much leaner and easier to read &lt;a href=&quot;http://www.json.org/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;&lt;/a&gt; data format. So a request is made to the server, the server does some database lookups and some processing, then sends back a pure data response in &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; form. The javascript then takes the data and decides what to do with it. Since the calls are &#8220;asynchronous&#8221;, the javascript doesn&#8217;t have to wait for all the calls to come back to deal with the data; it can start updating the battle log when that data comes in and if the mob data gets in at the same time, it can process that too, more or less simultaneously.&lt;/p&gt;


	&lt;p&gt;The bonus of this strategy is that calls to the server are extremely short. The server only looks up a small amount of data and slaps it into &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; format on each call. The side effect is that there are more calls to the server. Would you rather have multiple short requests, or single, large requests on your server? If you&#8217;re concerned about &lt;em&gt;connections&lt;/em&gt;, you might feel as though single large requests would be a better option. However the advantage to many short requests comes in during optimization.&lt;/p&gt;


	&lt;h3&gt;Bastardizing the server-side code&lt;/h3&gt;


	&lt;p&gt;I haven&#8217;t mentioned it to this point, but the server side code I am using is Ruby on Rails. I love Rails for the flexibility it gives me in developing database-backed web applications (insert your own favorite &lt;a href=&quot;http://en.wikipedia.org/wiki/Object-relational_mapping&quot;&gt;&lt;span class=&quot;caps&quot;&gt;ORM&lt;/span&gt;&lt;/a&gt; / &lt;a href=&quot;http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;&gt;&lt;span class=&quot;caps&quot;&gt;MVC&lt;/span&gt;&lt;/a&gt; web framework here &#8211; I&#8217;m not biased against any, I just happen to like Ruby a great deal). Where Ruby and Rails fall behind is on performance. A Rails server uses up huge chunks of memory, and this limits the number of requests it can take at one time.&lt;/p&gt;


	&lt;p&gt;When Rails runs in development mode, you can watch the log files and take careful note of the database calls that are being made. This feature allows me to look at each of the requests being made one by one and determine that &#8211; if somewhere in all those layers that a web app might have &#8211; unnecessary hits to the DB are being made. It also allows me to grab those DB queries and throw them into an &lt;a href=&quot;http://www.devshed.com/c/a/MySQL/Analyzing-Queries-for-Speed-with-EXPLAIN/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;EXPLAIN&lt;/span&gt; statement&lt;/a&gt; so I can determine if indexes are being used. Then I can simplify my Rails code and optimize my DB queries as necessary, to maximize the speed of each of those individual &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; calls.&lt;/p&gt;


&lt;div&gt;
&lt;em&gt;&lt;strong&gt;Why not use more caching? It&#8217;s a great way to speed up a web app!&lt;/strong&gt;&lt;/em&gt;

	&lt;p&gt;Caching is great, and Aethora takes advantage of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; caching as well as &lt;a href=&quot;http://www.danga.com/memcached/&quot;&gt;memcached&lt;/a&gt; for caching database-backed objects in memory. However, during a battle, many of the stuff is just changing too fast to bother caching. The battle log is just written as row after row of minimal data, and calls only need to grab the last few rows at any given time. The stats on mobiles are constantly changing during a battle.&lt;/p&gt;


	&lt;p&gt;The battle log is an example of where the &lt;span class=&quot;caps&quot;&gt;ORM&lt;/span&gt; model gets in the way a little. Well, I should say &#8211; it gets in the way when it comes to &lt;em&gt;reading&lt;/em&gt; the battle log table&#8217;s rows &#8211; it&#8217;s very handy for making table &lt;em&gt;writes&lt;/em&gt; easier to code. When reading the battle log, it&#8217;s just as easy to go from database row to json as it is to go from object to json.&lt;/p&gt;


&lt;em&gt;Items&lt;/em&gt;, &lt;em&gt;skills&lt;/em&gt;, and &lt;em&gt;actions&lt;/em&gt;, however, are all stored in the database as objects, and are more complex to work with. They are great examples of where using class-based objects really makes the code so much cleaner. Since they are fairly static, they get cached with memcache. That not only saves us the extra database call, it also saves the extra processing time it takes the Rails server to transform a database row into an object (because the memcached server in this case is storing a marshaled Ruby object).
&lt;/div&gt;

	&lt;p&gt;And finally, as a major bonus &#8211; I was actually able to take some of those simplified queries and plug them into a few lines of &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt;. Yeah, that&#8217;s right &#8211; I can run both Rails and &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; on the same web server &#8211; there&#8217;s no law against it! So, for example, the &lt;strong&gt;battle log&lt;/strong&gt; &#8211; these requests are made constantly while an &lt;span class=&quot;caps&quot;&gt;NPC&lt;/span&gt; is taking their turn, so the player gets the impression that they are watching the turn unfold in real time. There is nothing secret in a battle log &#8211; no user information or anything. It really is just about grabbing a couple rows of log data and a couple fields of mob data. Using &lt;a href=&quot;http://httpd.apache.org/docs/2.2/programs/ab.html&quot;&gt;ApacheBench&lt;/a&gt; to do a quick speed test, the &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; calls are a little faster than the Rails calls to get the same data. Punch up the number of concurrent connections, and you really start to see a difference: with 5 concurrent connections, the &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; script time was about 2/3rds that of the Rails time. The number of simultaneous Rails processes is limited by memory usage, whereas Apache can fire off &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; scripts by the gobs.&lt;/p&gt;


	&lt;p&gt;One important thing to note if you&#8217;re going to run multiple server-side engines to respond to &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; calls: be careful not to violate &lt;a href=&quot;http://en.wikipedia.org/wiki/Same_origin_policy&quot;&gt;same origin&lt;/a&gt; &lt;a href=&quot;https://developer.mozilla.org/En/Same_origin_policy_for_JavaScript&quot;&gt;policy&lt;/a&gt;. If you need to run different server-side code under different subdomains, make sure to set document.domain (as described in those articles). I&#8217;m using the wonderful &lt;a href=&quot;http://modrails.org/&quot;&gt;passenger&lt;/a&gt; module, which allows me to run Rails straight out of Apache. In this setup, Apache can bypass Rails to get anything out of the public directory (for images, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, javascript, etc). If it finds a php file in the public directory, well then, it&#8217;s business as usual. That way I can have: http://mydomain.tld/something/from/rails and http://mydomain.tld/minicall.php &#8211; same domain, different server side processing!&lt;/p&gt;


	&lt;p&gt;That&#8217;s it for the performance improvements &#8211; I&#8217;ll come back and give you another article that focuses on the point-and-click interface improvements.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2009-03-27:295</id>
    <published>2009-03-27T16:12:00Z</published>
    <updated>2009-03-27T16:13:24Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="aethora"/>
    <category term="game design"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="rpg"/>
    <category term="RPG"/>
    <link href="http://rangersheck.com/2009/3/27/running-an-event" rel="alternate" type="text/html"/>
    <title>Running an Event</title>
<content type="html">
            &lt;p&gt;Been a while since I&#8217;ve posted, so I thought I&#8217;d at least mention what&#8217;s happening in &lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&lt;/a&gt; right now.&lt;/p&gt;


	&lt;p&gt;We&#8217;re currently running an event called &#8220;Pioneers Week&#8221;. Here&#8217;s the short description:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Pioneers Week is the time when people all over Hopilus celebrate the anniversary of the discovery and colonization of their continent. They honor the struggle and the achievements of their forefathers, and due to this great attention to the past and its protagonists, the flow of ather itself shifts, temporarily, creating echoes of those who have lived and worked that walk around in places where they worked and acted.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;You can find these echoes &#8211; ghosts, as some call them &#8211; although you have been told they are rather weak echoes, and that there are more powerful, permanent and natural ones all over Hopilus. All towns have some old town square or town hall where the first colonists of that town appear, and on the roads you may be challenged by others, who are remembered for traveling, and like a challenge or who have failed, and are resentful for it.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;img src=&quot;http://rangersheck.com/assets/2009/3/27/PW-battle-sm.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;The event lasts one &#8220;week&#8221;, which really means two weeks. This is the second event we&#8217;ve done in Aethora, and I think it&#8217;s going &#8230; well, it&#8217;s going ok. One goal we have with events is to make them challenging. The skill system in Aethora gives us the chance to introduce new &lt;span class=&quot;caps&quot;&gt;NPC&lt;/span&gt;-only skills just for an event, which really levels the playing field and even the most maxed-out players will find it challenging. Unfortunately, we are finding that we may have made the event a little too challenging. Some players are getting frustrated. The dedicated players know that if they stick with it, and start with the lower level areas and work their way up to the harder stuff, they will enjoy it. However, I think more casual players are turned off by the scenario. If they have played enough to be high level, they tend to start playing the event in the high level areas and then are quickly lambasted by the event NPCs.&lt;/p&gt;


	&lt;h3&gt;So what have we learned from this experience?&lt;/h3&gt;


	&lt;p&gt;Well, for one thing, we&#8217;re not going to add event-only &#8220;roamers&#8221; to the world next time. They can be a real pain in the neck for players &#8211; those players that logged out in a high level area, come to the event, and then want to travel back to the low level areas to train up have a chance of being jumped by roaming event NPCs surrounding those high level areas. As you can imagine, players find this a little irritating, because these NPCs are extremely tough. And, as my lead designer put it &#8211; &lt;strong&gt;not everyone likes being forced into an event.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Secondly, we&#8217;re thinking the event should be more focused &#8211; in other words, it should have a clearer goal. Perhaps centered around a certain mission or something. We like for certain aspects of the event to be repeatable, so the hardcore players can enjoy it fully, but I think &lt;strong&gt;casual players might appreciate achieving a sense of accomplishment&lt;/strong&gt; by finishing the main &#8220;mission&#8221; of the event. In our current event, there are two &#8220;mini-missions&#8221;, but they are really just set-ups for single encounters with rewards for their completion.&lt;/p&gt;


	&lt;p&gt;Lastly, while an event is great fun and gives us a chance to flex our creative muscles, perhaps even introduce some humor and temporary silliness to the game, we know that &#8220;real&#8221; updates to the game would probably be more attractive to our player base at this point. Initially, we had hoped that doing a few events would be an easy way to crank out some temporary content to keep players interested in Aethora. Unfortunately, the work behind an event actually takes a lot more time than you might think.&lt;/p&gt;


	&lt;p&gt;The good news is that we&#8217;ll be able to re-use the work that we&#8217;ve done and bring two events back each year, with some improvements. In the meantime, it&#8217;s time to get back to work on more permanent content and code updates!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2008-07-24:221</id>
    <published>2008-07-24T00:40:00Z</published>
    <updated>2008-07-24T00:44:38Z</updated>
    <category term="PBBG"/>
    <category term="gadget"/>
    <category term="game development"/>
    <category term="igoogle"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="pbbg development"/>
    <category term="pbbgdev"/>
    <link href="http://rangersheck.com/2008/7/24/an-igoogle-gadget-for-your-game" rel="alternate" type="text/html"/>
    <title>An iGoogle Gadget for your Game</title>
<summary type="html">&lt;p&gt;If you’ve ever personalized a Google home page, you’ve seen the various gadgets that can be added. These gadgets can also be placed into other web pages, blogs, and so forth pretty easily, and they share a very similar framework with &#8220;gadgets&#8221; in other sites, such as MySpace&#8217;s new &lt;em&gt;MySpace Apps&lt;/em&gt;. In this article, I&#8217;ll show you how to make a simple gadget that pulls dynamic data from your game and displays it in a nice little box.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;If you’ve ever personalized a Google home page, you’ve seen the various gadgets that can be added. These gadgets can also be placed into other web pages, blogs, and so forth pretty easily, and they share a very similar framework with &#8220;gadgets&#8221; in other sites, such as MySpace&#8217;s new &lt;em&gt;MySpace Apps&lt;/em&gt;. In this article, I&#8217;ll show you how to make a simple gadget that pulls dynamic data from your game and displays it in a nice little box.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;

	&lt;p&gt;Here&#8217;s a basic gadget I created for &lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&lt;/a&gt; that shows a player&#8217;s list of characters and each character&#8217;s skill levels. It also displays the Health of each character, which is nice &#8211; if you&#8217;ve ever played Aethora, you know that inactive characters heal up as time passes. This gadget is handy for seeing at a glance which characters are ready to get back into action. A little minor JavaScript makes it interactive, allowing you to click on the skills link and expand each character&#8217;s skill list.&lt;/p&gt;


	&lt;p&gt;Rather than go into detail about how I created this gadget specifically, I&#8217;m going to make up a generic game called Fake &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; and explain how to build a gadget for it.&lt;/p&gt;


	&lt;h2&gt;0. What you need&lt;/h2&gt;


	&lt;p&gt;Before we get started, let&#8217;s run down a short list of requirements.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;A game to pull data from&lt;/li&gt;
		&lt;li&gt;Some knowledge of JavaScript&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://getfirebug.com&quot;&gt;Firebug&lt;/a&gt; is highly recommended&lt;/li&gt;
		&lt;li&gt;A design in mind: a gadget is not like a full web page, so give it a little thought. I did my Aethora gadget at 320&#215;300, but for this example, I started with a design that fits into 300&#215;200 pixels.&lt;/li&gt;
		&lt;li&gt;Reference: &lt;a href=&quot;http://code.google.com/apis/gadgets/docs/legacy/dev_guide.html&quot;&gt;Legacy Gadgets &lt;span class=&quot;caps&quot;&gt;API &lt;/span&gt;Developer&#8217;s Guide&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;1. Prepping the Data&lt;/h2&gt;


	&lt;p&gt;First we&#8217;ll need to create a page that will serve up our player&#8217;s data. We&#8217;ve got a couple of options when it comes to displaying data. We can use plain old text, perhaps &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt;-style, but it&#8217;s probably best if we use &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;. XML is typically good for generating well-formatted blocks of data intended to be used for a very broad range of applications. Parsing &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; data in JavaScript is not real fun; thankfully, we have &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;, which is much easier to work with. In this example, I&#8217;ll be using &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; for that reason.&lt;/p&gt;


	&lt;p&gt;Most languages provide simple methods for getting &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;-formatted data. In Ruby on Rails, there is a handy &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Serialization.html#M001014&quot;&gt;to_json method&lt;/a&gt; that can be called on any ActiveRecord object, and allows for options such as restricting which attributes get displayed, including method calls as attributes, and including associated objects. &lt;span class=&quot;caps&quot;&gt;PHP &lt;/span&gt;(5.2.0 and up) provides a &lt;a href=&quot;http://php.net/manual/en/function.json-encode.php&quot;&gt;json-encode function&lt;/a&gt; that translates any variable (be it array, string, or any other type) into a &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; string.&lt;/p&gt;


	&lt;p&gt;Let&#8217;s do this example with a simple &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; file. Since this is &lt;em&gt;Fake &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;&lt;/em&gt;, we&#8217;ll pretend each player in the game has four player characters (PCs) and each PC has some attributes. I&#8217;m going to fake the data as if I pulled it from a database, but really it&#8217;s just a bunch of arrays.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;&lt;span class=&quot;i&quot;&gt;?p&lt;/span&gt;hp&lt;tt&gt;
&lt;/tt&gt;function make_up_stats() {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; array(&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Strength&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;rand(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Wisdom&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;rand(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Dexterity&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;rand(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;),&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Luck&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;rand(&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;20&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  );&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt; pretend we loaded some data from a database&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$pc1&lt;/span&gt; = array(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Jack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;100&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;make_up_stats() );&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$pc2&lt;/span&gt; = array(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Jannus&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;6&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;25&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;make_up_stats() );&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$pc3&lt;/span&gt; = array(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Samathia&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;65&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;make_up_stats() );&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$pc4&lt;/span&gt; = array(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Keleton&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;6&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;stats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt;make_up_stats() );&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$pcs&lt;/span&gt; = array( &lt;span class=&quot;gv&quot;&gt;$pc1&lt;/span&gt;, &lt;span class=&quot;gv&quot;&gt;$pc2&lt;/span&gt;, &lt;span class=&quot;gv&quot;&gt;$pc3&lt;/span&gt;, &lt;span class=&quot;gv&quot;&gt;$pc4&lt;/span&gt; );&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$player&lt;/span&gt; = array ( &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt; &lt;span class=&quot;gv&quot;&gt;$_GET&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;user_login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;], &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pcs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;=&amp;gt; &lt;span class=&quot;gv&quot;&gt;$pcs&lt;/span&gt; );&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt; output as &lt;span class=&quot;co&quot;&gt;JSON&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;echo json_encode(&lt;span class=&quot;gv&quot;&gt;$player&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;i&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Notice our flimsy little &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; script looks for a &#8216;user_login&#8217; parameter in the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; to determine the player&#8217;s username. Normally, we&#8217;d use this parameter to actually look up the player&#8217;s data and whatnot, but this tutorial is about iGoogle gadgets, so we&#8217;re faking it. If we were doing this for real, we might consider using &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; authentication or something like that. Aethora&#8217;s gadget does not require authentication, because the player and character stats that are being displayed are public anyway. The only real &#8220;danger&#8221;, so to speak, is that someone could display another player&#8217;s stats on their own web page using one of these gadgets (of course, they say imitation is the highest form of flattery, so I don&#8217;t consider that scenario much of a security breach).&lt;/p&gt;


	&lt;p&gt;Now we test our &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; script by pointing our browser to it. You can try this by going to my example at: &lt;a href=&quot;http://examples.rangersheck.com/fake_game_json.php?user_login=Ranger+Sheck&quot;&gt;http://examples.rangersheck.com/fake_game_json.php?user_login=Ranger+Sheck&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Notice the string of data blocked out with {}&#8217;s and []&#8217;s; that&#8217;s &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;, baby, and it translates to pure JavaScript!&lt;/p&gt;


	&lt;h2&gt;2. Creating a Gadget: the &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; definition file&lt;/h2&gt;


	&lt;p&gt;All iGoogle gadgets require a single &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file to start with. Google prefers that you host this &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file on your own server, but if you need to, you can use their &lt;a href=&quot;http://code.google.com/apis/gadgets/docs/legacy/gs.html#Scratchpad&quot;&gt;Google Gadgets Editor&lt;/a&gt; to host your &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file. Since I want to break out my JavaScript and &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; for the sake of cleanliness, I&#8217;m going to host my &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; file on my own server.&lt;/p&gt;


	&lt;p&gt;The entire &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; block should be wrapped in a Module element. We start with a Module Prefs section. This is where we can set up the configuration for our little gadget as well as provide some miscellaneous data such as screenshots.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;pp&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; ?&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;Module&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;ModulePrefs&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;title&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Fake RPG Character Sheets&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;scrolling&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;height&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;width&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;an&quot;&gt;description&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;This is an example of what you might do with a web-based game and igoogle gadgets.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;an&quot;&gt;author&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Ranger Sheck&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;author_email&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rangersheck@skipintrodevelopment.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;an&quot;&gt;title_url&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://rangersheck.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;an&quot;&gt;screenshot&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://examples.rangersheck.com/gadget/screenshot.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;an&quot;&gt;thumbnail&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://examples.rangersheck.com/gadget/screenshot-tn.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;/ModulePrefs&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;Next, we add as many UserPref elements as we need. Each of these UserPrefs can be set by the user when they install the gadget. In this case, we only need to know the login name they use for our game, and we're going to make it a required attribute.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;UserPref&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;player_login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;display_name&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Fake RPG Login name (username):&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;required&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;Here we can start displaying some HTML. When an iGoogle gadget is displayed on a page, it's actually being displayed inside an iframe. That makes it easy for us to set up whatever we want in terms of HTML, JavaScript, CSS. Notice here, I reference a .css file, a couple .js files. Then I stick in some real basic HTML that will make a nice little two-column layout. At the end, I use a couple of Google's _IG_... methods to grab the UserPref variables and to make a call to a function once the page is done loading.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;Content&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;er&quot;&gt;&amp;lt;&lt;/span&gt;![CDATA[&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://examples.rangersheck.com/gadget/fake-rpg-stats.css&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;            &lt;span class=&quot;an&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;stylesheet&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;text/css&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;ta&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://examples.rangersheck.com/gadget/utils.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://examples.rangersheck.com/gadget/json2-min.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://examples.rangersheck.com/gadget/fake-rpg-stats.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;content_div&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;style&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;width:300px; background-color: #EEE; margin:0 auto;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;char_wrap&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;     &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;details_block&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;ta&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Fake RPG&lt;span class=&quot;ta&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;ta&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;login_name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;ta&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;em&amp;gt;&lt;/span&gt;mouse over each character for details&lt;span class=&quot;ta&quot;&gt;&amp;lt;/em&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;     &lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;style&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;display:none;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;style&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;clear:both&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;text/javascript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      // Get userprefs&lt;tt&gt;
&lt;/tt&gt;      var prefs = new _IG_Prefs();&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;      // make JSON request once page loads&lt;tt&gt;
&lt;/tt&gt;      _IG_RegisterOnloadHandler(makeJSONRequest);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;ta&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  ]]&lt;span class=&quot;er&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;/Content&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/Module&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;3. Parsing the JSON and generating HTML&lt;/h2&gt;

&lt;p&gt;At the very end of the XML file, we are triggering a call to a function called makeJSONRequest. This is just a function I created myself in the file &lt;a href=&quot;http://examples.rangersheck.com/gadget/fake-rpg-stats.js&quot;&gt;fake-rpg-stats.js&lt;/a&gt;. Let's take a look at that file:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt; makeJSONRequest() {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// This URL returns a JSON-encoded string that represents a JavaScript object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; url = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://yourdomain.com/fake_game_json.php?user_login=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; url += &lt;span class=&quot;fu&quot;&gt;escape&lt;/span&gt;(prefs.getString(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;player_login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;));&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// here we call the iGoogle method that grabs the text from the url and passes &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// it off to our responseHandler function&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// let's set the refreshInterval to tell it to grab the content every 10 minutes&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  _IG_FetchContent(url, responseHandler, { refreshInterval: (60 * 10) });&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt; responseHandler(response) {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// display error if we got bad response&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (response == &lt;span class=&quot;pc&quot;&gt;null&lt;/span&gt; || typeof(response) != &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) {&lt;tt&gt;
&lt;/tt&gt;    msg = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;i&amp;gt;Invalid data. Response: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + response + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + typeof(response) + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&amp;lt;/i&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;content_div&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).innerHTML = msg;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// parse the response string as JSON - note that the parser resides in the json2-min.js file&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; player = JSON.&lt;span class=&quot;fu&quot;&gt;parse&lt;/span&gt;(response);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// we're creating two chunks of HTML - one for the left side and one for the right&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// on the left side, we stack up the character names in boxes&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// on the right side are blocks containin each of the PCs details - they all start out hidden&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; pc_html = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; hidden_pc_html = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// loop through player characters&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; p = 0; p &amp;lt; player.pcs.length ; p++) {&lt;tt&gt;
&lt;/tt&gt;    pc = player.pcs[p]&lt;tt&gt;
&lt;/tt&gt;    pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;div class=&amp;quot;char&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.name + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Level &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.level + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;   &lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;div style=&amp;quot;display:none&amp;quot; id=&amp;quot;pc_detail_&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + p + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.name + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Health: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + colored_number(pc.health) + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Strength: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.stats.Strength +&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Wisdom: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.stats.Wisdom +&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Dexterity: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.stats.Dexterity +&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    hidden_pc_html += &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Luck: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; + pc.stats.Luck +&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  } &lt;span class=&quot;c&quot;&gt;// end player characters for loop&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// set login name header to our player's name&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;login_name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).innerHTML = player.name;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// fill in the left side&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;char_wrap&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).innerHTML = pc_html;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// fill in the hidden blocks on the right side&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).innerHTML = hidden_pc_html;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// now that the new HTML is generated, we can add some onmouseover functionality&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  setupRollovers();&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;A couple of things to note here. I've created some &quot;utility&quot; functions that you can find in the &lt;a href=&quot;http://examples.rangersheck.com/gadget/utils.js&quot;&gt;utils.js&lt;/a&gt; file. These are basically just some prototype-like shortcuts for grabbing HTML elements and showing or hiding them. Also, since we want to safely parse the JSON, I grabbed the &lt;a href=&quot;http://www.json.org/js.html&quot;&gt;parser from json.org&lt;/a&gt; and &lt;a href=&quot;http://examples.rangersheck.com/gadget/json2-min.js&quot;&gt;minified it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you've never worked with JSON before, go back and take a look at the code from 'fake-rpg-stats.js'. Notice how we assigned the whole block of data (after parsing it) to the player variable. This variable is a javascript object, or associative array. That means all of it's children can be accessed using an object-oriented notation or an array notation. I find OO-style more readable, so when I want the player's name, I use:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;player.name&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;but you could also use:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;player[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;Notice how player.pcs is an array containing the PCs, and each of those elements contains a few attributes like 'name' and 'level' as well as another array of 'stats'. It's pretty basic JavaScript to loop through our array of PCs, grab the attributes from each, and plug that data into a block of simple HTML.&lt;/p&gt;

&lt;h2&gt;4. DHTML Magic&lt;/h2&gt;

&lt;p&gt;You'll notice the HTML in both the XML file and the stuff generated by our JavaScript is pretty bare. I've kept all the styling in &lt;a href=&quot;http://examples.rangersheck.com/gadget/fake-rpg-stats.css&quot;&gt;fake-rpg-stats.css&lt;/a&gt;, and that's where you'll find the oh-so-fancy background images, text colorations, and block decoration. When you mouse-over each of the names in the left side of the widget, the &quot;stats&quot; for that character should appear on the right. The &quot;setupRollovers()&quot; function we call at the very end of our responseHandler can be found in that 'utils.js' file. This function &lt;a href=&quot;http://en.wikipedia.org/wiki/Unobtrusive_JavaScript&quot;&gt;unobtrusively&lt;/a&gt; grafts an &quot;onmouseover&quot; attribute onto each of the divs with the PC names in them on the left side. When the mouse goes over one of those divs, we want to hide all other player-detail divs and show only the one we moused over.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt; setupRollovers() {&lt;tt&gt;
&lt;/tt&gt;  pc_name_divs = &lt;span class=&quot;pt&quot;&gt;document&lt;/span&gt;.getElementById(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;char_wrap&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).getElementsByTagName(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; i = 0; i &amp;lt; pc_name_divs.length ; i++) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// need a way to reference the index of this PC, so set a pc_id attribute&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    pc_name_divs[i].pc_id = i;&lt;tt&gt;
&lt;/tt&gt;    pc_name_divs[i].onmouseover = &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() { switch_to_pc(&lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.pc_id); };&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;// display this PC's stats and hide others&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;function&lt;/span&gt; switch_to_pc(p) {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// 'details' is hidden by default so we don't get the border with nothing inside&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  show(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;  pc_divs = &lt;span class=&quot;pt&quot;&gt;document&lt;/span&gt;.getElementById(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).getElementsByTagName(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; i = 0; i &amp;lt; pc_divs.length ; i++) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; (i == p) {&lt;tt&gt;
&lt;/tt&gt;      show(pc_divs[i].id);&lt;tt&gt;
&lt;/tt&gt;    } &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt; {&lt;tt&gt;
&lt;/tt&gt;      hide(pc_divs[i].id);&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;h2&gt;5. Testing the code in iGoogle&lt;/h2&gt;

&lt;div&gt;&lt;em&gt;the finished gadget&lt;/em&gt;&lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Assuming you have an iGoogle account, and you're logged in, testing your gadget out is pretty easy. I like to have a separate &quot;tab&quot; for testing purposes. If you've never added a tab to iGoogle, notice that there is a Home tab just below the search form. Next to that, there should be an &quot;Add tab&quot; link - just click that to add another tab and name it Testing. Once you're in a Testing tab, you can add the &quot;My Gadgets&quot; developer gadget. Go to &lt;a href=&quot;http://www.google.com/ig/directory?url=www.google.com/ig/modules/developer.xml&quot;&gt;this page&lt;/a&gt; and click the &quot;Add it now&quot; button.&lt;/p&gt;

&lt;p&gt;With this utility gadget, you can paste the URL of your base XML file into the &quot;Add a gadget&quot; form and your gadget will automatically show up under your Testing tab. Under normal circumstances, Google will cache your XML file, refreshing it only after an hour or so. During testing, this behavior can be quite the pain in the neck, but the &quot;My Gadgets&quot; gadget allows you to disable caching for your gadget just by unchecking a box. Note that this only bypasses the cached file for you. If this is a live gadget, any other users who are using will still only get an updated version of the XML file every hour or so. There is no way to tell Google to manually purge their cache of your gadget's XML file. If you make a change, your users will just have to wait until the cached version expires.&lt;/p&gt;

&lt;p&gt;Notice that when you add your gadget to iGoogle, it prompts you for the &quot;login name&quot; for &quot;Fake RPG&quot;. - That prompt comes from the UserPref requirement we set in the very beginning. Since I wrote the fake PHP script to take any username you give it, you can just type anything into this field and click Save. After that, your gadget should load. Note that a user can go back and change the value they entered for username by clicking the little down-arrow at the top right corner of the gadget, and then clicking &quot;Edit settings&quot;.&lt;/p&gt;

&lt;h2&gt;6. End Notes&lt;/h2&gt;

&lt;p&gt;The iGoogle _IG_... functions come from an API that is currently being re-written by Google to conform more to the OpenSocial API. Changing over this example code to the new API is extremely easy. You'll only have to replace the three functions that start with _IG_. Most of them are just renamed using a gadgets.* namespace. The _IG_Fetch* functions are replaced by a more generic gadgets.io.makeRequest function that takes a parameter that specifies the type of content you're expecting to grab. In the new API, you can specify JSON as a content type, which means that you'll be able to drop the JSON parser library and skip the parsing step because Google's API will handle that stuff automatically.&lt;/p&gt;

&lt;p&gt;At this time (July, 2008), the Google's implementation of the OpenSocial API is not public. You can register to try it out in some kind of iGoogle &quot;Sandbox mode&quot;, but the gadgets.* stuff won't work for your general end-users at this time. It's worth checking out, however, because other sites that implement the OpenSocial API use the same gadgets.* format. I experimented a little with MySpace's implementation of &quot;gadgets&quot; (they call them Apps), but unfortunately, MySpace Apps don't use the UserPref setting (most likely as a security precaution - it's a minor miracle they are allowing any kind of javascript back into MySpace at all). So there's no way to prompt the user for their username on another, non-MySpace system. I haven't had time to experiment with the actual inter-linking of OpenSocial data, but I expect there's a way to use OpenSocial to get a MySpace App to act just like your iGoogle gadget. From what I can tell, MySpace uses a &lt;a href=&quot;http://developer.myspace.com/community/myspace/myopenspace.aspx#MyOpenSpace.MySpaceContainer.makeRequest&quot;&gt;makeRequest&lt;/a&gt; function which can be used to fetch XML or JSON data, very similarly to the Google implementation.&lt;/p&gt;

&lt;p&gt;That's all for now. Here's all the code I showed you in one archive: &lt;a href=&quot;http://examples.rangersheck.com/fake-rpg-gadget.zip&quot;&gt;fake-rpg-gadget.zip&lt;/a&gt;. Now get started on some gadgets of your own!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2008-06-28:217</id>
    <published>2008-06-28T00:54:00Z</published>
    <updated>2008-06-28T00:55:46Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="game design"/>
    <category term="game development"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="web game"/>
    <link href="http://rangersheck.com/2008/6/28/game-design-principles-part-2" rel="alternate" type="text/html"/>
    <title>Game Design Principles - Part 2</title>
<content type="html">
            &lt;p&gt;Continuing from &lt;a href=&quot;/2008/6/28/game-design-principles&quot;&gt;Game Design Principles &#8211; Part 1&lt;/a&gt;.&lt;/p&gt;


	&lt;h2&gt;Game Design Principles behind &lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&lt;/a&gt; (5 through 9 of 9)&lt;/h2&gt;


	&lt;h3&gt;5. Good strategy should mean combining lots of different skills. The appearance of a successful strategy that utilizes only one or two skills is an indicator of imbalance.&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/dunechaser/518821732/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/lego-army.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Everyone who&#8217;s ever played a &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt; knows that balance is always an ongoing issue. The developers are always making adjustments to classes, abilities, equipment, and so forth. The sheer quantity and variety of factors that are involved make the concept of total balance something that&#8217;s impossible to achieve during the design phase. You can get pretty close, but one thing a designer has to remember &#8211; you design aspects of the game with certain intended uses, and the balancing you provide is based on those intended uses. When players get ahold of the game and start using things in ways you didn&#8217;t intend or anticipate, you&#8217;re going to discover new imbalances. It&#8217;s a fact, Jack.&lt;/p&gt;


	&lt;p&gt;So one easy rule of thumb that I&#8217;m using here, somewhat specific to Aethora, but in general I think a good strategy: If I notice that a player is gearing up all their characters with the same gear, then I can guess that they think they have found an attack or two that is far superior to other attacks. Sometimes, this strategy is a bad one. Other times, the player could be onto something &#8211; there may be an attack that makes a battle much easier to win and other attacks are inferior by comparison.&lt;/p&gt;


	&lt;p&gt;The overall point is, at least for Aethora, the game is party-based. A good party in any &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; should have some variety. Characters tend to fill different roles, such as melee, magic-user, healer, and so forth; or in common &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt;-speak: Tanks, DPSers (damage-dealers), Buffers, Healers, Crowd-Controllers, and various other &#8220;Support&#8221; roles. So, in Aethora, I want to see the good players using a broad mixture of skills in combat.&lt;/p&gt;


	&lt;h3&gt;6. Victory in combat on average should be decided by factors in this pecking order: Good strategy &amp;gt; Higher Skill Levels &amp;gt; Better Equipment&lt;/h3&gt;


	&lt;p&gt;Aethora is a tactical, or strategy &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;. Party-based combat on a map is the core of combat, so I try to spend some time thinking about what makes map-based combat fun and challenging. I like to think of a tactical &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; almost as a game of chess; but instead of simply different move-patterns, the pieces have different offensive and defensive abilities. Since the game at it&#8217;s core is still a role-playing game, the whole point is to advance character development; so character skill levels should, of course, make a difference when it comes to combat. The secondary method of character development in an &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; has to do with acquiring better equipment, and clearly a well crafted longsword should outperform a rusty fire poker.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/peterjr1961/2190264036/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/armor.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;So the goal of this principle is this: good equipment is no substitute for adequate skill levels, and skill levels are no substitute for good strategy. In other words, a player should still have a chance to win a fight in which they are outclassed in terms of equipment and skills, to a certain degree, as long as they employ good strategy. Likewise, if a player has a poor strategy going into a fight, expensive equipment will not save them.&lt;/p&gt;


	&lt;p&gt;To achieve the &#8220;Higher Skill Levels &amp;gt; Better Equipment&#8221; part of this principle, there is some real basic math going on. The combat formula uses some weighting to give advantage or disadvantage between attacker and defender skill levels, and then a lesser weighting when comparing attacker&#8217;s weapon strength with defender&#8217;s armor strength. Making &#8220;Good Strategy&#8221; the most important factor in combat is a little trickier, and it relies pretty heavily on principle #5.&lt;/p&gt;


	&lt;h3&gt;7. No &#8220;punishment&#8221; paths in missions (quests). Any path that &#8220;burns a bridge&#8221; should be roughly equal in benefits to any other path.&lt;/h3&gt;


	&lt;p&gt;Mission-writing has been a primary goal of our development team in the last few months, so I felt it necessary to lay down this particular ground rule. It&#8217;s very tempting to create a branching point where a player can chose to do the &#8220;right thing&#8221; or the &#8220;wrong thing&#8221;; after all, decision making is part of the challenge of doing quests or missions. So if a player chooses the &#8220;right thing&#8221;, maybe they get a little more gold in the end, or even a better piece of equipment as a reward; and that makes sense. However, it makes me a little uncomfortable to see a situation in which a player might do the &#8220;right thing&#8221; and gain access to another mission later on, where the player who picks the &#8220;wrong thing&#8221; ends up at a dead-end.&lt;/p&gt;


	&lt;p&gt;Mainly this principle has to do with Aethora being somewhat of a &#8220;casual&#8221; &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;. I&#8217;d hate for a player to become frustrated and quit because they missed out on something when they took the wrong path &#8211; especially when the decision was tricky (and often these things are not obvious). Since this is an online game, and not a single-player game, there is no previous saved game to reload when you make a mistake.&lt;/p&gt;


	&lt;p&gt;So I devised a simple formula for &#8220;factors of mission outcome equality&#8221;: 
Chance for another mission = 100; unique piece of equipment = 10; monetary reward = 1&lt;/p&gt;


	&lt;p&gt;In other words, two branching mission paths that both offer another mission are roughly equal (100 vs 100). Two branching paths in which one offers gold but the other offers equipment are close enough to equal (10 vs 1). Branching paths in which one offers a new mission but the other offers only one piece of equipment are not close enough to equal (100 vs 10). But, if you really want to write two branching paths and let one lead to a new mission and another lead to a bag of unique equipment (like say 8 pieces, or 100 vs 80), then I&#8217;m more likely to allow such a choice (as long as the storyline makes sense, of course).&lt;/p&gt;


	&lt;p&gt;What we end up with is less chances for &#8220;right&#8221; and &#8220;wrong&#8221; paths and more paths that are just &#8220;different&#8221; &#8211; and I&#8217;ve found that these can be much more interesting. You can see that I&#8217;ve made an assumption here that what players want most of all is to do more missions; I think for the majority, that&#8217;s part of the fun of the game. Completing a quest or a mission is an accomplishment. Therefore, a chance for another mission outweighs material rewards many times over.&lt;/p&gt;


	&lt;h3&gt;8. The best RPGs incorporate fun and engaging gameplay as well as quality story lines. These are two dimensions on one grid; to cover the maximum amount of area possible, both dimensions need to be stretched.&lt;/h3&gt;


	&lt;p&gt;At this point, I&#8217;m going to take a moment and re-iterate that these principles are largely based on my personal opinions when it comes to role-playing games. The first part is easy: if gameplay &#8211; and by that, let&#8217;s be frank, I&#8217;m mostly referring to combat &#8211; is weak, then I&#8217;m not going to play a game. Combat needs to be interesting, engaging, should not feel overly formulaic, should not be too long and should not be too short. That&#8217;s a pretty tall order to live up to, but remember, this is a principle &#8211; an ideal &#8211; I&#8217;m aiming for. I&#8217;m not claiming that I&#8217;ve reached it 100% with Aethora.&lt;/p&gt;


	&lt;p&gt;To be honest, if the gameplay of a particular &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt; is pretty good but the storyline is inane, there&#8217;s still a pretty good chance I will play the game. Let&#8217;s face it &#8211; storylines in CRPGs for the most part are pretty thin, so players have learned to deal with it. That being said, when I look back on my most memorable experiences with CRPGs, the games that had great storylines stand out the most.&lt;/p&gt;


	&lt;p&gt;So you see, these two factors can combine to make a great game. However, it&#8217;s my opinion that you&#8217;ll lose people quicker if gameplay is weak. If gameplay starts out good but becomes tedious later on, you may lose more people that way as well. Ranger Sheck&#8217;s inner voice: &#8220;If you want people to play the game, you better make the game fun to play.&#8221; But, then, I love to write, and I know how memorable a good storyline can be, so with this principle I&#8217;m recognizing that good stories are going to help make a mediocre game reach for greatness.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Image:Aybabtu.png&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/aybabtu.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I&#8217;m willing to bet some developers (especially browser-based games, where text is easier to work with than graphics) are going to disagree and claim that a good story should carry the most weight. I love a good story! And for that reason, I do a lot of reading. A lot. Even the best storyline in a game cannot come close to a good book, and so when I want a good story, I don&#8217;t want to sit in front of my computer screen and read page after page &#8211; I&#8217;ll sit down with a good book. That&#8217;s why it&#8217;s my opinion that quality writing can greatly enhance, but not carry, a &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt;.&lt;/p&gt;


	&lt;h3&gt;9. There is a third dimension that is unique to online RPGs: player community and interaction. While more difficult to stretch, this dimension bears much greater potential.&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/kurtxio/2182760200/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/web.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;This last principle expands on the previous one, to serve as a reminder of why &#8220;online&#8221; role-playing games are different than offline CRPGs. Aethora needs a lot of work in this area, because other than buying and selling equipment to other players and some sharing of information through chat and forums, there isn&#8217;t much other player interaction. I recognize the fact that having a more interactive community really has a profound effect on the popularity and &#8220;stickiness&#8221; of an online &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;. Therefore, this principle is here at the bottom, not because it&#8217;s the least important, but the one that Aethora needs the most work on.&lt;/p&gt;


	&lt;p&gt;I have some big plans in this area, and I just need to find some time to work on them:
 &#8211; Player crafting and tradeskills to increase market trading between players.
 &#8211; Contests and tournaments where players can face off against similar groups of NPCs and see who does the best
 &#8211; Player versus player combat (I&#8217;m still on the fence about this one, as the nature of a web-based game introduces a lot of potential issues)
 &#8211; The ability for players to own land and populate land with guardians &#8211; even to the point at which a player might create an entire &#8220;dungeon&#8221;, populate it with baddies and treasure and then invite other players to come try their hands at it. My ultimate goal, to put it simply, is to have ways for players to generate content.&lt;/p&gt;


	&lt;p&gt;Well, that about wraps it up. Comments? Questions?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2008-06-28:216</id>
    <published>2008-06-28T00:28:00Z</published>
    <updated>2008-06-28T00:55:58Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="game design"/>
    <category term="game development"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="web game"/>
    <link href="http://rangersheck.com/2008/6/28/game-design-principles" rel="alternate" type="text/html"/>
    <title>Game Design Principles</title>
<content type="html">
            &lt;p&gt;A couple months ago, I made the change from being the sole developer and writer for my game and invited some of my players to join me in creating a design team. While all the coding responsibilities still rest on my shoulders, the other designers have been contributing artwork, mission plots, non-player character design, weapon and armor design, area design, and so forth. I quickly realized that while it&#8217;s possible for people to get a sense of what a coder&#8217;s thoughts and motivations are by playing their game, there are still many aspects of a game&#8217;s design that are not so easy to interpret.&lt;/p&gt;


	&lt;p&gt;When I set up a forum for our team to collaborate in, much of the initial conversation was brainstorming about changes or additions to make to the game. I found myself defending and explaining various methods and components of the current design and what those explanations meant for future design. I realized that while I am open to other ideas, there were certain things that I wasn&#8217;t likely to budge on. The more I thought about it, the more I began to understand that I had internalized a set of principles that guide the path of development for my game.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/walkercleaveland/1020606824/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/stone.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Do I think all games should follow these design principles? Certainly not! Many parts of this list were born out of being unhappy with one particular aspect or another of a game that I otherwise enjoyed; some other parts were born out of recognizing which parts of existing games I think were done really well. But without a wide diversity of drivers and factors behind game development, where would we be?&lt;/p&gt;


	&lt;p&gt;So you may agree with these principles, and you may not. The perspective they are written from lies in the development of a role-playing game; specifically a computer role-playing game (CRPG), and more specifically than that, an online, web-based, strategy (or tactical) role-playing game. To date, combat is the largest aspect of my game, and since it is a tactical &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; in terms of a combat system, some of these principles might only make sense in that context. Others, however, are more universal.&lt;/p&gt;


	&lt;p&gt;As you read these, please take note: The words are mine, but the thoughts behind them come from an accumulation of years of experience in playing, thinking, and talking about games. I don&#8217;t claim any kind of exclusivity or originality on any of these concepts.&lt;/p&gt;


	&lt;h2&gt;Game Design Principles behind Aethora (1 through 4 of 9)&lt;/h2&gt;


	&lt;h3&gt;1. No wrong path for character development.&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/taz/456653752/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/arrows.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;This principle is at the top of the list for a reason &#8211; it&#8217;s the one that was the foundation for the character system in Aethora. This character system, while not 100% unique, is very rare in the broad range of RPGs out there, because it is classless. In a role playing game, you need roles, and in most games this role is chosen from the start as a job or a class. In some cases, it can be changed or it has branches later on in a character&#8217;s development. In Aethora&#8217;s case, the character has no class, but simply a set of skills. There are no levels, no experience, no points to spend. When you want your character to learn how to fight with a sword, you have to put a sword in their hand and get them to battle. The more you use a skill (against better and better enemies) the better you get.&lt;/p&gt;


	&lt;p&gt;The big seeds for this principle are in my frustration with pretty much any role-playing game. As much as I love to game, there are always those people out there with much more time on their hands. There is always someone to figure out which combination of race and class is the best, which branch is the best part of the skill tree to take, etc, etc. Inevitably, I&#8217;d be feeling like I made a mistake at some low level or even at the point of character creation that didn&#8217;t fully manifest itself until I got to a higher level and realized I&#8217;m just not as effective a character as I could be, but there&#8217;s no way to correct it without &#8220;re-rolling&#8221;.&lt;/p&gt;


	&lt;p&gt;In Aethora, you are not allowed to delete any characters; you can only change their name or appearance at any time. If you decide that one of the roles a PC is playing is not the ideal role for the balance of your party, you simply re-equip them and start them down the path that works for you. &lt;strong&gt;No regrets means no re-specing and no re-rolling.&lt;/strong&gt;&lt;/p&gt;


	&lt;h3&gt;2. Roleplaying for roleplaying&#8217;s sake, not as an excuse for convenience.&lt;/h3&gt;


	&lt;p&gt;This principle is not so much a hard and fast rule, but more of a guiding ideal. I think, at the core, what this comes down to is honesty. If players are given some obviously convenient excuse for the blockage of a path or method, then they are going to lose trust in the game designer. Blatant abuse of &#8220;magic&#8221; explanation or other non-explanation of game mechanics weakens immersion, and when immersion breaks down, a player is going to start to see the &#8220;human side&#8221; of the developer. If you&#8217;ve ever played Pencil and Paper role-playing game, you may remember some moments when your Dungeon Master tried to railroad you down a path that they had meticulously laid out for you. Sometimes a player&#8217;s natural reaction to being railroaded, oddly enough, is to try to jump off the tracks. This is the kind of thing that reminds a player that they are playing a game with limitations; and that&#8217;s what I mean by &#8220;weakening immersion&#8221;.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/mercurialn/2099735247/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/teleport-sign.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Take the example of a 3D &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt;. A lot of times, travel can be a real pain for players in a ginormous 3D world. To keep people from getting frustrated, developers might introduce ridable mounts that increase travel speed. This example makes perfect sense &#8211; the player doesn&#8217;t have to stretch any imagination to get on a horse and move a little faster. Now say, after a while, the developers decide that players aren&#8217;t getting to all the new fancy areas they&#8217;ve put in, so they want to make travel even more convenient; so they introduce a magical teleport system where any player can walk up to an area and be beamed over to another area fairly easily. While the new system is certainly more convenient for players, this is, in my opinion, an example of breaking the &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; setting and simply making it easier to get to the hack-n-slashing. When a player has to cross a long expanse of land to get to their destination, they develop an appreciation for the vastness of the world their character inhabits. When they bounce around via a loosely-expounded teleportation device, the world becomes a lot smaller.&lt;/p&gt;


	&lt;h3&gt;3. Avoid imposing realism in favor of fun.&lt;/h3&gt;


	&lt;p&gt;In some ways, this principle is the opposite of #2, but it takes a slightly different mentality. When designing an &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; system, it&#8217;s tempting to try to be as realistic as possible, whether it&#8217;s in combat, travel, basic survival, etc. One of the classic examples is the notion of hunger. In EverQuest, like many text-based MUDs before it, a player is required to carry food and drink with them at all times. In the old MUDs, you used to have to manually eat and drink food until you were satiated. In Everquest, they automated it slightly by making your character  periodically eat something from their inventory. If the character had no food, they would start to get hungry (and eventually, once hungry enough, penalized in combat).&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/77106971@N00/1420127033/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/groceries.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;For a lot of players, this type of realism is part of the challenge of role-playing. For many others, however, it becomes just a big pain in the neck. It&#8217;s not really very mentally challenging, unless you consider trying to remember to buy food when in town a mental challenge. For me as a player, it became the most annoying when I regularly ran out of food while out adventuring and sometimes had to trek back to town just to fill up.&lt;/p&gt;


	&lt;p&gt;Whenever something like that happens, the player feels like they are doing work rather than playing. Sometimes, you have to do a little work in an &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; &#8211; that&#8217;s the nature of that style of game. As long as it&#8217;s balanced by fun, then a little work is okay &#8211; but too much work overshadows fun. That&#8217;s kind of a key point, so I&#8217;m going to restate it: &lt;strong&gt;If I feel like a game is making me do too much work, I&#8217;m not going to play it.&lt;/strong&gt;&lt;/p&gt;


	&lt;h3&gt;4. Heroes don&#8217;t have time for pest control jobs, I don&#8217;t care how inexperienced they are.&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/yaatra/258383522/&quot;&gt;&lt;img src=&quot;/assets/2008/6/28/rats.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;This principle might be specific to the setting, but honestly, I think it can be applied to most role-playing games out there. Ok, sure, the point of an &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; is that you start with small challenges and work up to larger challenges. But why, oh why, do I always have to start out killing rats? Don&#8217;t you think it would be a little more fun if we started our characters a little later in their careers? In D&#38;D terms, I&#8217;m talking about starting at level 3 or so instead of level 1; when I first start out let me fight some orcs instead of garden snakes. I mean, come on &#8211; can you even imagine trying to stab a rat with a dagger? Wouldn&#8217;t it make more sense for that shopkeeper to just put down some rat traps or some rat poison?&lt;/p&gt;


	&lt;p&gt;So why does a typical &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; start you out on pest control duty? To be honest, I think designers like to make those first couple of levels ridiculously easy so (a) you&#8217;ll get used to playing the game and (b) you&#8217;ll get addicted fast. All of us &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; addicts are sucked in by accomplishments. We live for that &#8220;ding&#8221; sound, and once we&#8217;ve gone from level one to level two, we feel like we&#8217;ve made an investment.&lt;/p&gt;


	&lt;p&gt;The &#8220;pest control&#8221; concept goes beyond those initial stages of character development, though. For this reason, I&#8217;ve made it one of my principles. Whenever you ask a player to: clear an area of infestation/invasion/etc; bring back N number of pelts/sashes/ears; scavenger hunt for ores/oysters/Easter eggs; in any kind of typical mindless hunter/gatherer scenario, you&#8217;re basically giving the player busywork. You&#8217;re not challenging them with making appropriate decisions or problem solving &#8211; you&#8217;re acting like that doddering old substitute teacher who would come in and make the class do macaroni pictures or origami rather than attempt the lesson on fractions.&lt;/p&gt;


	&lt;p&gt;Again, why do we see this style of &#8220;quest&#8221; so often in RPGs? They make good time-sinks. Sometimes mindless play is actually pretty entertaining; heck, sometimes that&#8217;s exactly what we&#8217;re looking for in a video game. But personally, I feel like there are enough opportunities in any online &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; to go out and enjoy mindless combat. If I&#8217;m really on some kind of Quest or Mission, I want a little more of a challenge. To me, that&#8217;s what defines a Quest or Mission: it&#8217;s a challenge (and there&#8217;s a reward when it&#8217;s complete).&lt;/p&gt;


	&lt;p&gt;Continue reading principles 5 through 9 in &lt;a href=&quot;/2008/6/28/game-design-principles-part-2&quot;&gt;Game Design Principles &#8211; Part 2&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2008-03-18:206</id>
    <published>2008-03-18T15:23:00Z</published>
    <updated>2008-03-18T15:25:41Z</updated>
    <category term="PBBG"/>
    <category term="browser-based"/>
    <category term="javascript"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="programming"/>
    <category term="web-based"/>
    <link href="http://rangersheck.com/2008/3/18/introducing-moveablemap" rel="alternate" type="text/html"/>
    <title>Introducing MoveableMap</title>
<content type="html">
            &lt;p&gt;I posted this on my other, more tech/web-dev oriented blog, but since it&#8217;s a great tool (or at least example to learn from) for web-based game developers, I figured I&#8217;d mention it here.&lt;/p&gt;


	&lt;p&gt;MoveableMap is a javascript library (open source, &lt;span class=&quot;caps&quot;&gt;MIT&lt;/span&gt; license) that allows you to turn any block of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; into a draggable, moveable entity within a viewport. Similar to the draggable behavior of Google Maps, but hopefully very easy to implement.&lt;/p&gt;


	&lt;p&gt;More information and demos can be found here:
&lt;a href=&quot;http://offtheline.net/2008/3/13/moveablemap-or-anything-else-in-a-viewport&quot; title=&quot;or anything else in a viewport&quot;&gt;MoveableMap&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2008-03-08:204</id>
    <published>2008-03-08T19:08:00Z</published>
    <updated>2008-03-08T19:41:42Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="Statistics"/>
    <category term="browser-based"/>
    <category term="PBBG"/>
    <category term="pbbg"/>
    <category term="probability"/>
    <category term="programming"/>
    <category term="randomness"/>
    <category term="rpg"/>
    <category term="RPG"/>
    <category term="statistics"/>
    <category term="web-based"/>
    <link href="http://rangersheck.com/2008/3/8/statistics-what-are-the-real-odds" rel="alternate" type="text/html"/>
    <title>Statistics: What are the real odds?</title>
<summary type="html">&lt;p&gt;Wow, it&#8217;s been a while since my last post. I wish I had time to do this more often, but such is life.&lt;/p&gt;


	&lt;p&gt;I&#8217;ve been thinking a lot about statistics lately, and how they can be used in game design. We&#8217;ve all seen this problem in any game, particularly indie games (including a lot of browser-based game) &#8211; a problem with randomness. Sometimes a game doesn&#8217;t appear to leave enough to chance, and it becomes predictable. Other times a game is too random, to the point of frustrating a player when despite skill or a &#8220;better hand&#8221;, fate can easily turn against them.&lt;/p&gt;


	&lt;p&gt;This article will be the first in a series of probably three articles on statistics and randomness. Today I&#8217;d like to talk about what it means to consider the odds that an event might happen, given multiple attempts at it. For example: if an event has a 25% chance of occurring, you might expect that given 4 attempts at it, you&#8217;re pretty much guaranteed success. Given a second thought, we know that not to be exactly true. So what are those odds, anyway? More after the jump.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Wow, it&#8217;s been a while since my last post. I wish I had time to do this more often, but such is life.&lt;/p&gt;


	&lt;p&gt;I&#8217;ve been thinking a lot about statistics lately, and how they can be used in game design. We&#8217;ve all seen this problem in any game, particularly indie games (including a lot of browser-based game) &#8211; a problem with randomness. Sometimes a game doesn&#8217;t appear to leave enough to chance, and it becomes predictable. Other times a game is too random, to the point of frustrating a player when despite skill or a &#8220;better hand&#8221;, fate can easily turn against them.&lt;/p&gt;


	&lt;p&gt;This article will be the first in a series of probably three articles on statistics and randomness. Today I&#8217;d like to talk about what it means to consider the odds that an event might happen, given multiple attempts at it. For example: if an event has a 25% chance of occurring, you might expect that given 4 attempts at it, you&#8217;re pretty much guaranteed success. Given a second thought, we know that not to be exactly true. So what are those odds, anyway? More after the jump.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/clearlyambiguous/55815919/&quot;&gt;&lt;img src=&quot;/assets/2008/3/8/coins.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Let&#8217;s start with a simpler example: the good ol&#8217; coin flip. Flip a coin once &#8211; what are the odds of getting heads? 1 out of 2, or 50%. If you flip a coin 8 times and it came up heads every single time, what are the odds of one more flip being heads? This is, of course, a trick question. The odds are still 50/50 because each flip of the coin is &lt;em&gt;unaffected&lt;/em&gt; by any other flip. The individual flips are &lt;em&gt;independent events&lt;/em&gt;. How about the probability that by flipping a coin twice, both times it comes up heads? There are four possible outcomes of two flips of a coin (H=heads, T=tails): HH, HT, TH, TT. Right there we can see that two heads occurs once out of four possible outcomes, so the chances are 1 in 4, or 25%.&lt;/p&gt;


	&lt;p&gt;This example leads us to the &lt;a href=&quot;http://en.wikipedia.org/wiki/Statistical_independence#Independent_events&quot;&gt;Multiplication Rule for Independent Events&lt;/a&gt;. Independently, each flip has a 50% chance of coming up heads. When events are independent, to find their cumulative probability, you can multiply their individual probabilities. Probabilities are always calculated as a number from 0 to 1; the equivalent of 0% to 100%. So to get the chance of a getting two heads out of two flips of a coin, we multiply:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(heads and heads) = P(heads) x P(heads) = 0.50&#215;0.50 = 0.25&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;In other words, 25%.&lt;/p&gt;


	&lt;p&gt;How does this relate to a game? Knowing how to calculate the cumulative odds that an event will occur can help identify when an event has been set up to happen too rarely. Imagine a scenario where a player has to search three chests and each time there is a 20% chance that a chest will contain some amulet. In order to get to a secret room, the player needs to get all three amulets. You might think that sure, the odds of getting the amulets from all three chests are against the player, but there&#8217;s still a pretty good chance. Let&#8217;s find out.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(amulet and amulet and amulet) = P(amulet)&lt;sup&gt;3&lt;/sup&gt; = (0.20)&lt;sup&gt;3&lt;/sup&gt; = 0.008&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;In other words, &lt;strong&gt;there&#8217;s a 0.8% of getting all three amulets&lt;/strong&gt;. Less than 1% &#8211; that&#8217;s pretty close to impossible! Even if the player is allowed to attempt the task periodically, it&#8217;s likely they will never achieve the goal.&lt;/p&gt;


	&lt;p&gt;Let&#8217;s try a different angle. What if we know what the percent chance is of an event and we want to know what are the odds that it will happen &lt;em&gt;at least once&lt;/em&gt; given a set number of trials? For example, taking the coin flip &#8211; if I flip a coin twice, what are the odds that I will get heads &lt;em&gt;at least once&lt;/em&gt;?&lt;/p&gt;


	&lt;p&gt;If you recall, the four possible outcomes of two flips of a coin (H=heads, T=tails): HH, HT, TH, TT. In this case, we win if the outcome is HH, HT, or TH. That&#8217;s 3 out of 4, or 75%. Another way to make the calculation is say the probability of the first coin getting heads is 0.50 (HH or HT), and the probability that the first coin was not heads but the second coin &lt;em&gt;was&lt;/em&gt; heads is 0.25 (TH). Since either of these combinations means success, we add them together:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(heads on first flip OR heads only on second flip) = 0.50 + 0.25 = 0.75&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Now of course, neither of those methods are very helpful when doing anything more complex than a couple coin flips. A third way we can look at the situation which lets us use the multiplication rule is to think of it in terms of what is the probability that the event &lt;em&gt;does not&lt;/em&gt; occur. In other words, what are the chances that both coin flips will come up tails? If we can find that, we can take the inverse of it to find the probability of our desired event.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(tails and tails) = (0.50)&lt;sup&gt;2&lt;/sup&gt; = 0.25&lt;br /&gt;
P(not both tails) = inverse of P(tails and tails) = 1 &#8211; 0.25 = 0.75&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/kahunna/1300007196/&quot;&gt;&lt;img src=&quot;/assets/2008/3/8/old-die.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;As you can see, the inverse of a probability is found by subtracting that probability from 1. All three methods have shown us that the chance of getting &lt;em&gt;at least one&lt;/em&gt; head out of two coin flips is 75%.&lt;/p&gt;


	&lt;p&gt;Now let&#8217;s think of a more useful scenario. Let&#8217;s go back to our three chests story, but this time we&#8217;ll say the player only has to get one amulet. The chance to get an amulet from a chest was 20%, so the odds that they &lt;em&gt;don&#8217;t get an amulet&lt;/em&gt; from a chest is 80%. They have three chances (because there are three chests), so let calculate the odds they don&#8217;t get a single amulet from any chest, then take the inverse again to find out if the player has a decent chance of getting at least one amulet:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(no amulet and no amulet and no amulet) = (0.80)&lt;sup&gt;3&lt;/sup&gt; = 0.512&lt;br /&gt;
P(at least one amulet) = 1 &#8211; 0.512 = 0.488&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;In other words, they have a 48.8% chance of getting at least one amulet in three tries.&lt;/p&gt;


	&lt;p&gt;Let&#8217;s take this example a little further, because I really want to point out a common misconception about odds. The chance to get an amulet is 20%, or one out of five. Logically, you might think that if you give a player 5 chances, they will be guaranteed to get the amulet once. This faulty logic is often referred to as the &lt;a href=&quot;http://en.wikipedia.org/wiki/Law_of_averages&quot;&gt;Law of Averages&lt;/a&gt; (which is not actually a &#8220;law&#8221; of real mathematics at all). Given what we&#8217;ve learned, let&#8217;s see what the real odds are for a player finding at least one amulet in 5 tries:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(no amulet and no amulet&#8230;.etc) = (0.80)&lt;sup&gt;5&lt;/sup&gt; = 0.32768&lt;br /&gt;
P(at least one amulet) = 1 &#8211; 0.32768 = 0.67232&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/lwr/2257952044/&quot;&gt;&lt;img src=&quot;/assets/2008/3/8/dice.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Given 5 tried, the chance of getting one amulet is actually only about 67%. It&#8217;s likely, but it&#8217;s far from a guaranteed success, isn&#8217;t it?&lt;/p&gt;


	&lt;p&gt;So how do you guarantee success based on probability? Well, you&#8217;re going to have to do it programmatically, because no combination of probabilities (other than all events getting a 100% chance) is ever going to combine to become 1.0. If you flip a coin 100 times, it&#8217;s extremely likely you&#8217;ll get at least one head, but technically there is one outcome that would result in 100 tails.&lt;/p&gt;


	&lt;p&gt;Let&#8217;s look at one last example so we can see how more chances increase the likelihood of a success. Let&#8217;s say a player is on a quest and has to get a special belt that some orcs wear. One out of ten orcs wear this belt, so we set up the game to give any slain orc a 10% chance to drop the belt. If the player kills just one orc, they&#8217;ve got a 10% chance to get their goal. Let&#8217;s look at the chances of getting a belt for 5, 10, and 20 slain orcs (notice that the chance of &lt;em&gt;not&lt;/em&gt; getting a belt is 90%):&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(at least one belt in 5) = 1 &#8211; (0.90)&lt;sup&gt;5&lt;/sup&gt; = 1 &#8211; 0.59 = 0.41 (&lt;em&gt;or 41%&lt;/em&gt;)&lt;br /&gt;
P(at least one belt in 10) = 1 &#8211; (0.90)&lt;sup&gt;10&lt;/sup&gt; = 1 &#8211; 0.35 = 0.65 (&lt;em&gt;or 65%&lt;/em&gt;)&lt;br /&gt;
P(at least one belt in 20) = 1 &#8211; (0.90)&lt;sup&gt;20&lt;/sup&gt; = 1 &#8211; 0.12 = 0.88 (&lt;em&gt;or 88%&lt;/em&gt;)&lt;br /&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Even after killing 20 orcs, there&#8217;s still only an 88% chance of success. When we said 10%, we were thinking the player would have to kill about 10 orcs, but turns out even killing 20 orcs is not as close to 100% as we&#8217;d like! Now that we&#8217;ve done the calculations, we can see that we may be frustrating players with these odds. Let&#8217;s readjust and try a 15% chance for an orc to drop a belt (85% chance they don&#8217;t drop one):&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;P(at least one belt in 5) = 1 &#8211; (0.85)&lt;sup&gt;5&lt;/sup&gt; = 1 &#8211; 0.44 = 0.56 (&lt;em&gt;or 56%&lt;/em&gt;)&lt;br /&gt;
P(at least one belt in 10) = 1 &#8211; (0.85)&lt;sup&gt;10&lt;/sup&gt; = 1 &#8211; 0.20 = 0.80 (&lt;em&gt;or 80%&lt;/em&gt;)&lt;br /&gt;
P(at least one belt in 20) = 1 &#8211; (0.85)&lt;sup&gt;20&lt;/sup&gt; = 1 &#8211; 0.04 = 0.96 (&lt;em&gt;or 96%&lt;/em&gt;)&lt;br /&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Hey, that&#8217;s a little more reasonable. We might even want to tweak it a little farther; at least now we have a method to determine the real odds.&lt;/p&gt;


	&lt;p&gt;In summary, when it comes to probabilities, don&#8217;t rely on &#8220;instinct&#8221; or faulty logic like the &#8220;Law&#8221; of Averages. Some simple calculations can give you a much more concrete idea of what kind of chances you&#8217;re giving your players.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2007-09-12:203</id>
    <published>2007-09-12T23:51:00Z</published>
    <updated>2007-09-13T00:00:28Z</updated>
    <category term="Game Design"/>
    <category term="PBBG"/>
    <category term="development"/>
    <category term="game design"/>
    <category term="game development"/>
    <category term="gamedev"/>
    <category term="web"/>
    <link href="http://rangersheck.com/2007/9/12/interface-design-in-a-pbbg-sound-familiar" rel="alternate" type="text/html"/>
    <title>Interface Design in a PBBG - Sound Familiar?</title>
<summary type="html">&lt;p&gt;Browser-Based Game designers, take note from some of the web-based app designers: the term &#8220;Look and Feel&#8221; means more than you think! Win back some of those players you frightened away by seeing your game through their eyes and giving them some familiarity to start with.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Browser-Based Game designers, take note from some of the web-based app designers: the term &#8220;Look and Feel&#8221; means more than you think! Win back some of those players you frightened away by seeing your game through their eyes and giving them some familiarity to start with.&lt;/p&gt;
&lt;h3&gt;Which came first?&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/adobemac/161310004/&quot;&gt;&lt;img src=&quot;/assets/2007/9/12/chicken_egg.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;In the web-based application development communities, once in a while you see this kind of &lt;a href=&quot;http://en.wikipedia.org/wiki/Chicken_and_egg&quot;&gt;chicken and egg&lt;/a&gt; argument pop up. The question is, which design comes first, &lt;strong&gt;code&lt;/strong&gt; or &lt;strong&gt;interface&lt;/strong&gt;? A lot of solo developers like myself go right for the &lt;strong&gt;code&lt;/strong&gt;. After all, without a solid code design plan, with data models and business functionality, the application is useless. Google didn&#8217;t become the most popular search engine because it looked pretty; it works well, that&#8217;s how it became popular.&lt;/p&gt;


	&lt;p&gt;Your graphical people, of course, will go the other way. Google is the exception to the norm, they&#8217;ll tell you. Especially in today&#8217;s Web Too Oh world, first impression is key, because people can leave a website just as quickly as they arrive.&lt;/p&gt;


	&lt;p&gt;Of course, it&#8217;s more than just visual aesthetics. As websites move deeper into that &lt;a href=&quot;http://billhiggins.us/weblog/2007/05/17/the-uncanny-valley-of-user-interface-design/&quot;&gt;uncanny valley&lt;/a&gt; and look more and more like real-deal applications, designers and developers must take into consideration their site&#8217;s interact-ability. The key questions are: What does it look like from the client&#8217;s perspective? What does it feel like to the client?&lt;/p&gt;


	&lt;p&gt;So, I switched sides. Yes, I know &#8211; code base is very important. Data structure is very important. &lt;em&gt;However&lt;/em&gt;, let&#8217;s be frank &#8211; that&#8217;s the easy stuff. That&#8217;s the logical stuff. The hard part &#8211; the thing that sets you apart from everyone else (or makes you look the same) &#8211; is the interface. Not to mention, when you start your design from the interface side, you&#8217;ll find some things you would have missed. You think a lot harder about what it&#8217;s like to be in your client&#8217;s shoes.&lt;/p&gt;


	&lt;h3&gt;It talks like a duck, but walks like a Sasquatch&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/chiceaux/85486910/&quot;&gt;&lt;img src=&quot;/assets/2007/9/12/sasquatch.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Familiarity is a design concept that becomes important here. The more your web-based application acts like real application, the more your clients are going to treat it like one. When they begin to recognize certain interface elements, they will start attempting to use other elements, like shortcuts, or they will start looking for familiar context menus, like the kind you get from right-clicking in a normal application. The moment they hit &lt;span class=&quot;caps&quot;&gt;CTRL&lt;/span&gt;-S expecting to save a record or a document and it doesn&#8217;t work, their trust in your site is broken. Their browser&#8217;s implementation for that key combo fires off and they are reminded once again that it&#8217;s not really a full blown application, it&#8217;s just a web site.&lt;/p&gt;


	&lt;p&gt;With browser-based games, the same problem exists. After all, computer games are nothing but &lt;em&gt;entertainment applications&lt;/em&gt;. As javascript, Flash, and other technologies allow web developers to create browser games that act more and more like full blown computer games (or even console or arcade games), we&#8217;re running into that &lt;em&gt;familiarity&lt;/em&gt; snag, but it&#8217;s &lt;strong&gt;two-fold&lt;/strong&gt;. Not only will your players be looking for familiar &lt;em&gt;interface&lt;/em&gt; elements, they will be looking for familiar &lt;em&gt;gameplay&lt;/em&gt; elements. Games are a lot more varied than business applications in both these respects, so it&#8217;s going to divide your client-base into two factions: (A) people that play tons of games and realize that every time they pick up a new game, they may have to learn some new gameplay concepts and they may have to master a new interface and (B) people that play only a few games and only really like something new when it closely resembles something they&#8217;ve seen before; if it doesn&#8217;t, then it better be something that&#8217;s not hard to learn or get the hang of.&lt;/p&gt;


	&lt;h3&gt;The Lost Players&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/tea_time/1331769706/&quot;&gt;&lt;img src=&quot;/assets/2007/9/12/lost_cart.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;The big problem is, those people in that second group &#8211; that&#8217;s the majority, and those people will walk away the fastest. I&#8217;ve seen people on dev boards say time and time again, &#8220;well, if it doesn&#8217;t look great but it&#8217;s fun to play, I&#8217;ll enjoy it&#8221;. That&#8217;s probably true for a lot of people, even people in group B &#8211; the problem is, most of them are leaving before they get a chance to find out that a game is &#8220;fun to play&#8221;. They&#8217;re not going to take the time to leave you feedback either and let you know what turned them off.&lt;/p&gt;


Let&#8217;s look at some possible reasons for new players to give up on your game within five minutes:
	&lt;ul&gt;
	&lt;li&gt;They got lost. Right from the beginning, they didn&#8217;t know what to do.&lt;/li&gt;
		&lt;li&gt;They thought they were getting into a game they would already know how to play (they were wrong).&lt;/li&gt;
		&lt;li&gt;They thought they were playing a game that would be &lt;em&gt;easy&lt;/em&gt; because it&#8217;s a game on the web (they were wrong).&lt;/li&gt;
		&lt;li&gt;They saw half-assed graphics and figured the game was unfinished and not worth their time.&lt;/li&gt;
		&lt;li&gt;They found little on-screen help and a separate manual consisting of tons of pages that were hard to read and probably uninteresting.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Some of these people, they&#8217;re on their coffee breaks, they&#8217;re killing time, they&#8217;ve got a meeting in 20 minutes; they&#8217;re looking to web-based games as a spend amounts of time in varied increments. Maybe they want to kill 10 minutes, maybe they want to kill an hour or two. If you hit them over the head with some interface that looks and acts like nothing they&#8217;ve ever seen before, and a game that plays like nothing they&#8217;ve seen before, they&#8217;re going to get frustrated and look for something easier.&lt;/p&gt;


	&lt;h3&gt;The Balancing Act&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://flickr.com/photos/55192999@N00/436033119/&quot;&gt;&lt;img src=&quot;/assets/2007/9/12/balancing.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Obviously, we don&#8217;t want to make cookie cutter games that all look and feel the same way. I&#8217;m suggesting that when you can create familiarity, you create comfort, and you alleviate frustration. When you can&#8217;t make an element familiar, whether it&#8217;s an interface element or a gameplay element, then make sure it&#8217;s easy. Easy to use, easy to understand &#8211; look at it from the perspective of someone else (someone who&#8217;s not a developer). The key is to find that balance between the unique and the familiar.&lt;/p&gt;


	&lt;p&gt;Many games pride themselves on their &lt;em&gt;depth&lt;/em&gt;. Too much complexity translates to a bunch of white noise, static, to the first time player. When you want to add complexity, do it in bite-sized increments &#8211; open up features one at a time to players after they get comfortable with the basics. During development, only add new features when you&#8217;re sure the simpler parts are solid. Honestly, it&#8217;s better to have a few concepts that work really well and look really good than a whole box of unfinished pieces (with lots of &#8220;potential&#8221;).&lt;/p&gt;


	&lt;p&gt;And definitely don&#8217;t hit your players with all the information available up front, let them discover some things on their own &#8211; it&#8217;s part of the reward of playing a &lt;strong&gt;Persistent&lt;/strong&gt; BBG.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2007-06-04:3</id>
    <published>2007-06-04T05:02:00Z</published>
    <updated>2007-06-24T16:18:17Z</updated>
    <category term="Game Design"/>
    <category term="crpg"/>
    <category term="game design"/>
    <category term="gaming"/>
    <category term="mmorpg"/>
    <category term="role playing game"/>
    <category term="rpg"/>
    <link href="http://rangersheck.com/2007/6/4/the-death-penalty-handling-defeat-in-crpg-design" rel="alternate" type="text/html"/>
    <title>The Death Penalty - Handling Defeat in CRPG Design</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;/assets/2007/6/4/terminator_robot_sm.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Computer Role-Playing Games are notorious for lacking in actual &#8216;Role-Playing&#8217;.&lt;/strong&gt; Your typical hack-n-slash &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt; takes the mechanical concepts behind pencil-and-paper role-playing games and automates them, giving these games a much greater focus on combat more than anything else. Once the mathematical base of a &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt; is established, often times the role-playing aspect is grafted on afterward, like fake skin on a robot. On the surface, it looks like a role-playing game, but underneath beats the gear-filled heart of a cold, calculating mechano-man.&lt;/p&gt;


	&lt;p&gt;Due to the combat-centric nature of most CRPGs, &lt;strong&gt;one of most malformed aspects of their &#8216;role-play&#8217; is Death.&lt;/strong&gt; CRPGs provide faster and more plentiful combat, which inevitably leads to a great deal more death than a pencil-and-paper RP session. Depending on the game setting, unchecked death of both non-player and player characters alike can really distort any kind of believable storyline. Many CRPGs go out of their way to explain the use of magic and divine intervention in their settings, but most of the time not only is the death of character usually extremely temporary, character &#8220;respawning&#8221; is generally flimsily explained (if at all). Non-player death fits into two categories: either non-player entities stay dead once killed, never to be heard of again, nor have their deaths questioned by anyone else; or upon death some cosmic timer ticks over and respawns them periodically.&lt;/p&gt;


	&lt;p&gt;I&#8217;d like to talk about the abuse of death and non-player entities some time, but today I want to focus on player death. In a pencil-and-paper &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;, death is usually permanent. If you have a generous Game Master, there may be ways around it, but chances are pretty good that there&#8217;s going to be a creative plot-line to go along with any form of resurrection. In a single-player &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt;, death is usually pseudo-permanent; I say pseudo because you can always reload a saved game. If the game is party-based, then you may have that typical flimsily-constructed method of resurrection (e.g. take them to church and say a little prayer/pay a little cash and presto, alive again).&lt;/p&gt;


	&lt;p&gt;In an online &lt;span class=&quot;caps&quot;&gt;CRPG&lt;/span&gt;, you don&#8217;t have the luxury of reloading a saved game. To keep people from just giving up, game designers need a way for players to respawn. &lt;strong&gt;Let&#8217;s face it, no one is going to keep coming back to a game if they have to make a new character every time they die.&lt;/strong&gt; The old telnet-based MUDs set the standard for player respawning &#8211; upon death, you found yourself back in your home town (usually in a church or other sanctuary). You probably lost a level and all of your equipment and maybe even your gold. Banks became extremely important to players that needed to get back into the game after a death and may have stashed extra equipment and money. MMORPGs started out following the &lt;span class=&quot;caps&quot;&gt;MUD&lt;/span&gt; standards; however, as time goes on, MMORPGs attract more players who have less and less gaming experience (RPG or otherwise), and have subsequently softened the blow of Death, so to speak. In many MMORPGs, dying does not result in loss of equipment or skills or levels or whatever. A player may lose &#8220;experience points&#8221;, or in some cases merely acquire an &#8220;experience debt&#8221; that has to be worked off.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;/assets/2007/6/4/underworld.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;In many cases, whatever the Death Penalty, &lt;strong&gt;player revival typically goes unexplained.&lt;/strong&gt; In your average fantasy &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt;, you die, you respawn at some kind of &#8220;home point&#8221;, and maybe you have to sit out some &#8220;death effects&#8221;. No one lets you know which god kindly plucked your body out of one place and trans-dimensionally reconstituted it in another place, dusting you off, patting your behind and wishing you well on your next adventure. A notable exception to this norm (speaking primarily of fantasy-based MMORPGs) is PlaneShift, in which if you die you awaken in the underworld. Not much explanation is needed for that situation, and I think it&#8217;s a creative way to deal with death. That being said, if you&#8217;re not familiar with the game, navigating your way out of the maze-like underworld can take you nearly an hour (unless you&#8217;re lucky enough to run into another lost soul who knows where they are going).&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;What&#8217;s a computer role-playing game designer to do?&lt;/strong&gt; History shows us that any integration of player death/resurrection and a believable role-playing storyline ain&#8217;t gonna happen. So we expect players to accept resurrection (with weapons and armor still in tact) as a run-of-the-mill activity. &lt;em&gt;Happens all the time, no big deal.&lt;/em&gt; They accept magic and monsters and all the rest of it, why should we focus on believable death scenarios?&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;/assets/2007/6/4/skeletor.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Sadly, &lt;strong&gt;we&#8217;re forced to resort to using death as a venue for penalizing a player&lt;/strong&gt; for biting off more than they can chew. This is the part where role-playing collides with game-play. The more you attempt to incorporate story-like role-playing into character death and recovery, the harder the game becomes. When death is frustrating, players quit, and with persistent online games, the loss of a player is the loss of regular revenue. So designers are forced to turn their backs on role-playing to compensate. In my opinion, as the years go by many games have over-softened the Death Penalty. This is especially true of MMORPGs, who prefer to keep players no matter what and often sacrifice &lt;strong&gt;challenge&lt;/strong&gt; for &lt;strong&gt;revenue.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;When I was in the initial planning stages of design for &lt;a href=&quot;http://aethora.com&quot;&gt;Pioneers of Aethora&lt;/a&gt;, I had a bug up my butt over the ever-weakening Death Penalty I&#8217;d seen in MMORPGs. In my game design, a player has a collection of eight characters, four of which can be placed into an active party at any given time. You go into combat with your four characters, facing off against a group of non-player characters. Winner takes all. The role-playing explanation is that defeat means surrender, and the victors should strip everything away from the defeated, no matter which side wins. The losers walk away empty-handed. Sounds fair, right? And &lt;strong&gt;I got out of trying to explain death, because no one actually dies!&lt;/strong&gt; Meanwhile, since you have eight characters total, you can bench injured characters and give them a rest while you play with fresh characters. No divine intervention or beam-me-back-to-town tricks called for. I thought I had the role-playing aspect and the death penalty nicely wrapped up.&lt;/p&gt;


	&lt;p&gt;Of course, &lt;strong&gt;there were a couple problems.&lt;/strong&gt; First of all, defeated characters lost all their equipment &#8211; not just what they were wearing and wielding, but what they had in their inventories as well. Since there is no bank (as of yet) in Aethora, the only way to stash extra equipment is to move it around and make sure it&#8217;s not in the inventory of any active characters. Obviously, this kind of stock-piling is quite the pain in the neck &#8211; but failing to do so would result in a player losing a ton of equipment in a defeat. Secondly, there is no way to judge what the ability of your opponents will be before you jump into a battle &#8211; in some areas, the encounters occur randomly without your choice to engage. This problem makes it possible for players to end up in combat they could never win. Finally, &lt;strong&gt;there was no way to retreat from battle.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Some players just dealt with these issues. Other players I believe accepted the penalty for what it was, but I fear many may have lost interest in the game along the way in unspoken frustration or perhaps even boredom &#8211; acquiring new equipment might mean going back to fighting enemies well below the player&#8217;s challenge level. One player (who happens to be a real life friend of mine) suddenly became extremely vocal about the issue a few weeks ago, and I decided to reevaluate my game&#8217;s Death Penalty. After mulling over the possibilities, I came up with some options that I feel provide some kind of balance to those &lt;strong&gt;ever-conflicting forces: role-playing, challenge, and player enjoyment.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;First off, I changed the loss of equipment to be only the equipment being worn and wielded by the characters upon defeat. The non-player characters aren&#8217;t carrying unused equipment around anyway, so it still seems fair. The RP explanation? The victors can only walk away with so much stuff, so they assume your best gear is the gear you went into battle with. Secondly, adding the ability to flee from battle was essential. There is no real role-playing reason for keeping this feature out of the game, my reason was purely mechanical. In &lt;em&gt;Pioneers of Aethora&lt;/em&gt;, skills are earned in real-time during combat &#8211; you take a swing with a sword, you have a chance of increasing your sword skill right at that moment. So my concern was that allowing players to flee from battle might entice some players to go into fights and notch up a few skills, then run off. Therefore, in order to maintain some challenge, fleeing characters lose a few skill points.&lt;/p&gt;


	&lt;p&gt;It&#8217;s actually worked out rather well so far. If a player senses defeat, they can choose whether they will lose equipment or skill points on a character-by-character basis. Since the fleeing option has been implemented, I&#8217;ve seen it used quite often. What&#8217;s encouraging is that a player who flees from battle often enters another battle somewhere else shortly afterward &#8211; a sign that the death penalty is not deterring defeated players from continuing play.&lt;/p&gt;


	&lt;p&gt;The party-system in &lt;em&gt;Pioneers of Aethora&lt;/em&gt; plays a large role in making &lt;strong&gt;defeat&lt;/strong&gt; play well with &lt;strong&gt;role-play.&lt;/strong&gt; MMORPGs and other CRPGs don&#8217;t have that luxury if a player represents just one character, but can&#8217;t they do better than &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;RETURNING TO HOME POINT&lt;/span&gt;&lt;/strong&gt;?&lt;/p&gt;


	&lt;p&gt;(if you&#8217;ve held on to the story this long and want to read the short blurb I wrote for the players, it&#8217;s in &lt;a href=&quot;http://docs.aethora.com/2007/6/3/june-update&quot;&gt;this update&lt;/a&gt;, with links to more details in the in-game forums. Registration required to read the in-game forums.)&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rangersheck.com/">
    <author>
      <name>RangerSheck</name>
    </author>
    <id>tag:rangersheck.com,2007-05-29:2</id>
    <published>2007-05-29T18:29:00Z</published>
    <updated>2007-06-24T17:06:42Z</updated>
    <category term="PBBG"/>
    <category term="browser-based"/>
    <category term="development"/>
    <category term="PBBG"/>
    <link href="http://rangersheck.com/2007/5/29/pbbg-persistent-browser-based-games" rel="alternate" type="text/html"/>
    <title>PBBG - Persistent Browser-Based Games</title>
<content type="html">
            &lt;p&gt;Today I learned a new acronym: &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt;&lt;/strong&gt;. Persistent Browser-Based Game. Acronyms are great because they are these kind of self-importing entities that have the potential to carve something substantial into the world&#8217;s vocabulary. Just by the very act of instantiating a new acronym, you&#8217;ve taken the first step towards establishment, acceptance, and eventually, &lt;em&gt;household knowledge&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Ok, maybe that&#8217;s a bit extreme, but one thing you can say about an acronym &#8211; the subject of an acronym is being talked about enough and with enough consistency to warrant abbreviation.&lt;/p&gt;


	&lt;p&gt;I&#8217;m here to embrace &lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt;. I happen to be the sole developer of a &lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt; (a label I applied just today, of course) called &lt;a href=&quot;http://aethora.com&quot; title=&quot;Pioneers of Aethora&quot;&gt;Pioneers of Aethora&lt;/a&gt; (more about that later). It&#8217;s actually an extreme convenience for this acronym to come along. I&#8217;ve been googling about, trying to find suitable testers for my game, and lemme tell ya &#8211; it&#8217;s hard to nail down what a &lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt; is. You&#8217;ve got your web-based games, probably 99% of which are Flash-based and are most definitely &lt;em&gt;not&lt;/em&gt; &lt;em&gt;persistent&lt;/em&gt; (unless you count scoreboards). Then there&#8217;s &#8220;online RPGs&#8221;, which typically lands you in &lt;span class=&quot;caps&quot;&gt;MMORPG&lt;/span&gt;-dreaming land. Or you can try &#8220;Indie games&#8221;, which will probably help you find some great sites and forums, but I&#8217;ve noticed that&#8217;s these places are usually looking at downloadable/installable games (they&#8217;re usually receptive to web-based games to some degree, but it&#8217;s not their focus). Lastly, trying to search on anything too generic with &#8220;rpg&#8221; in it drums up a whole lotta stuff about Pen and Paper RPGs (including independently produced P&amp;amp;P RPGs, which I would have found extremely cool at one time).&lt;/p&gt;


	&lt;p&gt;So what exactly is a &lt;em&gt;&lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt;&lt;/em&gt;? Well, there&#8217;s a definition at &lt;a href=&quot;http://pbbg.com/&quot;&gt;http://pbbg.com/&lt;/a&gt; that&#8217;s pretty good. Essentially, we&#8217;re talking a game that you play in your browser; as in &lt;em&gt;no installable/executable&lt;/em&gt;. But it&#8217;s not one of these puzzle/casual/action/arcade kinds of games where you play, get a score, try to beat your score, get addicted, try to beat everyone else&#8217;s score, etc. Instead, the game is &lt;em&gt;persistent&lt;/em&gt;. Typically, this means it&#8217;s going to be a role-playing game of some kind. You create a character (or characters, or a kingdom, or a pet monster), you play a little, you go away, you come back tomorrow and pick up where you left off.&lt;/p&gt;


	&lt;p&gt;It&#8217;s the pretty standard concept behind an &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt;, but I&#8217;m glad someone created this acronym to distinguish these browser-based RPGs from other web-based games, and as well from non-browser based &#8220;online/multiplayer&#8221; RPGs.&lt;/p&gt;


	&lt;p&gt;It&#8217;s not just the name, or the acronym, however, that makes me happy about this; it&#8217;s the fact that we&#8217;re witnessing a new gaming genre being established. Sure, it may be yet another spinoff or sub-genre of some pre-existing concepts, but the scaffolding for this &lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt; genre has some very unique and exciting characteristics. The last couple years have been all about Web 2.0, and while it&#8217;s hard to distinguish hype from reality, there are aspects of Web 2.0 that lend themselves very nicely to web-based gaming.&lt;/p&gt;


Let&#8217;s consider some of the hurdles an independent game developer faces when constructing a game.
&lt;ul&gt;
    &lt;li&gt;&lt;em&gt;UI development&lt;/em&gt;. Personally, I&#8217;ve started work on a few games myself that began as text-based, and when it came time to start adding a graphical interface, well&#8230; that just steepened my learning curve a bit, didn&#8217;t it? With a web-based game, you can do a hellavalotta presentation with &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, and when you need to, javascript can fill in the cracks.&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Data retention&lt;/em&gt;. Serializing classes and writing them to files, reading them later, trying to keep them indexed, etc. I never got very far with that part either. With a &lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt;, you&#8217;re most likely developing with a language that has built-in hooks into any database you could think of (not to mention memory caching options).&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Networking.&lt;/em&gt; I never got this far with any of my games. I had a lot of spectacular plans, lemme tell ya, but it wasn&#8217;t gonna happen. Obviously, not an issue in PBBGs &#8211; you get the networking for free.&lt;/li&gt;
&lt;/ul&gt;
There&#8217;s probably other stuff I&#8217;m not thinking of. All this &lt;span class=&quot;caps&quot;&gt;PBBG&lt;/span&gt; talk makes me think there are others out there just like me &#8211; big aspirations for developing a game independently, but too many obstacles. Now I&#8217;ve got &lt;a href=&quot;http://aethora.com&quot; title=&quot;Pioneers of Aethora&quot;&gt;this game&lt;/a&gt; that&#8217;s downright playable. The progress of web technology has given us a new platform, a new sandbox to play in, where our unrealistic and perpetually unfinished projects can get closer to actuality. Just like the youtubers who suddenly discovered that they too could film a video and share it with thousands of people, we&#8217;re realizing that we can develop our own multiplayer, networked, persistent games.

	&lt;p&gt;And we don&#8217;t have to use C. Or C++. Or C#. Or (as Q-Bert would say) C#$%^&amp;amp;.&lt;/p&gt;


	&lt;p&gt;Have &lt;a href=&quot;http://kingdomofloathing.com&quot; title=&quot;Kingdom of Loathing&quot;&gt;Kingdom of Loathing&lt;/a&gt; and &lt;a href=&quot;http://neopets.com/&quot; title=&quot;Neopets&quot;&gt;Neopets&lt;/a&gt; paved the way for a gaming revolution? Or just another cool acronym? Here&#8217;s hoping it&#8217;s both.&lt;/p&gt;
          </content>  </entry>
</feed>
