<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SyndicateX.com</title>
	<atom:link href="http://syndicatex.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://syndicatex.com</link>
	<description>Justin Johnson: CodeMonkey</description>
	<lastBuildDate>Mon, 14 May 2012 21:32:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>FlatRedBall and Procedural Textures</title>
		<link>http://syndicatex.com/flatredball/generating-textures-flatredball/</link>
		<comments>http://syndicatex.com/flatredball/generating-textures-flatredball/#comments</comments>
		<pubDate>Mon, 14 May 2012 21:30:38 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[FlatRedBall]]></category>
		<category><![CDATA[imagedata]]></category>
		<category><![CDATA[planet]]></category>
		<category><![CDATA[procedural]]></category>
		<category><![CDATA[space]]></category>
		<category><![CDATA[starfield]]></category>
		<category><![CDATA[texture2D]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=469</guid>
		<description><![CDATA[My buddy Vic (creator of FlatRedBall) and I were discussing issues with tilemap performance recently. Namely that large tilemaps suffer in performance because of the volume of Update calls on Sprite objects, even if the sprites are small. One of the ideas we discussed to deal with this is that of compositing multiple small tile [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://syndicatex.com/wp-content/uploads/2012/05/planet_3.jpg"><img class="aligncenter size-medium wp-image-470" title="planet_3" src="http://syndicatex.com/wp-content/uploads/2012/05/planet_3-600x469.jpg" alt="" width="600" height="469" /></a></p>
<p>My buddy Vic (creator of <a title="FlatRedBall" href="http://www.flatredball.com/frb/blog/" target="_blank">FlatRedBall</a>) and I were discussing issues with tilemap performance recently. Namely that large tilemaps suffer in performance because of the volume of Update calls on Sprite objects, even if the sprites are small. One of the ideas we discussed to deal with this is that of compositing multiple small tile textures into a single large texture at runtime. This texture could be roughly the size of the screen and you lazy load these textures to be ready just before you need them and unload them as they leave the screen. Vic mentioned that FlatRedBall has an <a title="ImageData in FlatRedBall" href="http://www.flatredball.com/frb/docs/index.php?title=FlatRedBall.Graphics.Texture.ImageData" target="_blank">ImageData </a>class that helps process images.</p>
<p>I&#8217;m really interested in procedural content generation. I&#8217;ve read a lot about how games like Minecraft create content but I haven&#8217;t really tried doing anything similar. I decided to play around with the ImageData class and see how to create textures on the fly. I love space and so the first thing I did was create a random starfield generator. It looks like this:</p>
<pre class="brush:csharp">public static Texture2D CreateStarfield(int width, int height)
{
	int numStars = FlatRedBallServices.Random.Next(width / 2, width * 2);
	ImageData imgData = new ImageData(width, height);
	imgData.Fill(new Color(0f, 0f, 0.05f));
	for (int i = 0; i &lt; numStars; i++)
	{
		int starSize = FlatRedBallServices.Random.Next(1, 3);
		int x = FlatRedBallServices.Random.Next(0, width - starSize);
		int y = FlatRedBallServices.Random.Next(0, height - starSize);
		float brightness = FlatRedBallServices.Random.Next(25, 100) / 100f;
		Color starColor = new Color(
		    FlatRedBallServices.Random.Next(85, 100) / 100f * brightness,
		    FlatRedBallServices.Random.Next(85, 100) / 100f * brightness,
		    FlatRedBallServices.Random.Next(75, 90) / 100f * brightness);
		for (int ix = 0; ix &lt; starSize; ix++)
		{
		    for (int iy = 0; iy &lt; starSize; iy++)
		    {
			imgData.SetPixel(x + ix, y + iy, starColor);
		    }
		}
	}
	return imgData.ToTexture2D();
}</pre>
<p>So that&#8217;s very simple. It creates an ImageData object at the specified size, comes up with a number of stars based on the texture size, and then draws stars into the image before returning it as a texture.</p>
<p>Next, I wanted to create planets. Stars are easy because they are just light-colored pixels on a dark background. Planets are much harder if you want them to be varied in color, texture, atmosphere, etc. Ideally, I would create the planet textures on the fly. However, I&#8217;m not quite ready to do anything that sophisticated because I&#8217;m pretty new to image manipulation algorithms. So I cheated and created some planet elements in photoshop. If you came here looking for purely procedural content, I&#8217;m sorry. I&#8217;m still working on that!</p>
<p>Here&#8217;s how my planet-creation works in concept:</p>
<ol>
<li><span style="line-height: 18px;">Create Basic Planet Shape</span></li>
<ol>
<li><span style="line-height: 18px;">Load a texture describing planet shape. This is easier than manually drawing a circle and can use photoshop&#8217;s nice anti-aliasing.</span></li>
<li><span style="line-height: 18px;">Choose a random color to be the base color of the planet.</span></li>
<li><span style="line-height: 18px;">Create an ImageData object the same size as the planet shape</span></li>
<li><span style="line-height: 18px;">Loop through the planet shape. Everywhere a pixel with alpha greater than zero exists, create a corresponding pixel in the new image using the random color.</span></li>
</ol>
<li><span style="line-height: 18px;">Apply a texture</span></li>
<ol>
<li><span style="line-height: 18px;">Load a surface texture at random from a selection of textures created in photoshop and pre-warped to look spherical</span></li>
<li><span style="line-height: 18px;">Choose a random color to be the texture color</span></li>
<li><span style="line-height: 18px;">Loop through the surface texture and composite the texture color and alpha onto the base pixel</span></li>
</ol>
<li><span style="line-height: 18px;">Apply clouds</span></li>
<ol>
<li><span style="line-height: 18px;">Load a random cloud texture</span></li>
<li><span style="line-height: 18px;">Composite cloud color and alpha onto the pixel</span></li>
</ol>
<li><span style="line-height: 18px;">Apply shadow</span></li>
<ol>
<li><span style="line-height: 18px;">Load the shadow texture, created in photoshop using a simple radial gradient from transparent to black</span></li>
<li><span style="line-height: 18px;">Composite the shadow onto the pixel</span></li>
</ol>
<li><span style="line-height: 18px;">Apply atmosphere</span></li>
<ol>
<li><span style="line-height: 18px;">Load an atmosphere texture, created in photoshop by adding inner and outer glow effects to a sphere and then just exporting the glow</span></li>
<li><span style="line-height: 18px;">Composite the atmosphere onto the pixel</span></li>
</ol>
</ol>
<div>So, I actually only loop through the ImageData object a single time. For each pixel I calculate the base color, apply each texture and then set the resulting pixel color in the ImageData. A few photoshop textures, composited in layers with random color applied gives you a pretty enormous selection of planets that look unique. The more textures you offer it, the more varied the final results could be.</div>
<div>Some of the planets turn out looking really amazing. Other planets look terrible and there are a lot of ways the algorithm could be improved to guide certain, favorable looks (ice, lava, terran, star, etc) while still keeping it pretty random. I was going to paste the planet creation source in here but, since I&#8217;ll probably continue to improve it, I&#8217;ll just link to the project:</div>
<div><a href="https://bitbucket.org/profexorgeek/infinityspace/src/77b69cf1fa6a/InfinitySpace/InfinitySpace/Generators/PlanetGenerator.cs">https://bitbucket.org/profexorgeek/infinityspace/</a></div>
<div><span style="line-height: 18px;"><br />
</span></div>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/flatredball/generating-textures-flatredball/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Guide to Purchasing a Monitor</title>
		<link>http://syndicatex.com/misc/monitor-purchasing-guide/</link>
		<comments>http://syndicatex.com/misc/monitor-purchasing-guide/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 18:18:52 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Dell]]></category>
		<category><![CDATA[IPS]]></category>
		<category><![CDATA[monitor]]></category>
		<category><![CDATA[resolution]]></category>
		<category><![CDATA[Twisted Nematic]]></category>
		<category><![CDATA[Ultrasharp]]></category>
		<category><![CDATA[VESA]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=455</guid>
		<description><![CDATA[For a few years now, my primary monitor at home has been a 28&#8243; HannsG with a native resolution of 1920&#215;1200. I bought it used from a buddy for around $200 which was a steal at the time. The monitor was big and had a variety of inputs but that&#8217;s about all it had going [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://syndicatex.com/wp-content/uploads/2012/04/monitor_resolutions.png"><img class="aligncenter size-full wp-image-456" title="monitor_resolutions" src="http://syndicatex.com/wp-content/uploads/2012/04/monitor_resolutions.png" alt="" width="544" height="419" /></a></p>
<p>For a few years now, my primary monitor at home has been a 28&#8243; HannsG with a native resolution of 1920&#215;1200. I bought it used from a buddy for around $200 which was a steal at the time. The monitor was big and had a variety of inputs but that&#8217;s about all it had going for it. There was terrible light bleed when the screen was dark, the color would vary drastically based on viewing angle, the response time was low enough that pixel smearing was pretty bad and the refresh rate of the fluorescent backlight gave me wicked headaches. The monitor has been on its way out for awhile. Parts of the screen would seem to vibrate randomly and occasionally it wouldn&#8217;t turn on or off. It finally died completely this weekend, refusing to respond to a battery of basic diagnostics.</p>
<p>Anticipating my monitor&#8217;s demise, I have been monitor shopping but I haven&#8217;t been that happy with what I&#8217;ve found. I like having lots of monitor real estate. Two or more monitors is great but it means dealing with bezel between your displays and four connection and power cords. I&#8217;d rather have a single, large screen but buying a bigger screen doesn&#8217;t actually get me anything. Every single screen I looked at was 1080i or lower. Additionally, the larger the screen the more your viewing angle changes across the surface, which makes colors appear different depending on where you&#8217;re looking. I do some color-sensitive work and this is important. So, big monitors have the same resolution, making everything more pixelated at close ranges and displaying color poorly across the surface. Keep in mind that I was shopping for a <em>monitor </em>and not a television. TVs are viewed from a much greater distance than a monitor and these factors are less important.</p>
<p>Apple has realized the importance of <em>density </em>over <em>size. </em>The new iPad/iPad3 (whatever you want to call it) has a pixel density of around 250dpi. That means that every square inch of the display has 62,500 pixels. My HannsG monitor&#8217;s density was around 72dpi or 5,184 pixels per square inch. That&#8217;s an enormous difference, which is exactly why Apple created the Retina display&#8230; the difference is amazing.</p>
<p>When looking at a monitor, the numbers they pack into the specs are overwhelming, misleading and generally not that useful. For instance, the <a title="Dot Pitch" href="http://en.wikipedia.org/wiki/Dot_pitch" target="_blank">dot pitch</a> can tell you how large the pixels are (which determines density) but it can be measured several different ways, which makes it impossible to compare. Additionally, most monitors really focus on the diagonal measurement and not the actual dimensions of the screen. So, the first thing I did was create a spreadsheet of common sizes for the two major aspect ratios (16:9 and 16:10). If you know the aspect ratio and diagonal measurement you can calculate the dimensions. If you know the horizontal resolution you can calculate the average pixel density across the screen and I created excel functions to do this. For years 72dpi was a standard, then it moved to 96dpi. I was looking for something significantly higher.</p>
<p>But that doesn&#8217;t address the color issues. I want to sit directly in front of a 28-30&#8243; display and have a solid color look the same across the screen. Most modern televisions are actually not very good at this. This is because they use an LCD technology called <a title="Twisted Nematic" href="http://en.wikipedia.org/wiki/Twisted_nematic" target="_blank">Twisted Nematic </a>(TN) display. TN displays have the advantage of being fast and cheap and are the most common LCD type on the market but they have relatively poor color production. <a title="In Plane Switching (IPS)" href="http://en.wikipedia.org/wiki/IPS_panel" target="_blank">In-Plane Switching</a> (IPS) LCDs have much, much better color range and viewing angle but traditionally have slower response times than TN. This makes them popular for graphic applications but more likely to have ghosting and smearing when displaying quickly-changing content.</p>
<p>Finding a monitor that offered consistent lighting, large display, high pixel density and IPS technology that was fast enough for gaming too is a challenge. This type of monitor is rare and thus, expensive. The most obvious choice are Apple&#8217;s new Thunderbolt displays. But, as usual, Apple doesn&#8217;t want their tech to be compatible with anything else. I couldn&#8217;t find any reasonable way to hook up a PC to a Thunderbolt display and Apple monitors are not VESA mount capable without an adapter (surprise, only available from Apple).</p>
<p>After looking at a variety of different displays, I finally settled on a 30&#8243; Dell Ultrasharp monitor at 16:10 (more vertical real estate) with a native display of 2560&#215;1600. On paper, everything about the display was perfect except that it uses CCFL for lighting instead of LED. I ordered mine from Amazon.com for the points and the $4 overnight shipping. It is an expensive monitor but I believe in good tools. I tested it pretty thoroughly last night after unboxing it and setting it up. The only complaint I have is that the awkwardness of the VESA mounting system is going to make adapting it to my existing wall mount a little difficult.</p>
<p>Here are some pictures of the unboxing including a screenshot of common applications I use to get an idea of what to do with all those pixels:</p>

<a href='http://syndicatex.com/misc/monitor-purchasing-guide/attachment/monitor_resolutions/' title='monitor_resolutions'><img width="150" height="150" src="http://syndicatex.com/wp-content/uploads/2012/04/monitor_resolutions-150x150.png" class="attachment-thumbnail" alt="monitor_resolutions" title="monitor_resolutions" /></a>
<a href='http://syndicatex.com/misc/monitor-purchasing-guide/attachment/photo-apr-24-15-00-08/' title='Photo Apr 24, 15 00 08'><img width="150" height="150" src="http://syndicatex.com/wp-content/uploads/2012/04/Photo-Apr-24-15-00-08-150x150.jpg" class="attachment-thumbnail" alt="Photo Apr 24, 15 00 08" title="Photo Apr 24, 15 00 08" /></a>
<a href='http://syndicatex.com/misc/monitor-purchasing-guide/attachment/photo-apr-24-15-04-09/' title='Photo Apr 24, 15 04 09'><img width="150" height="150" src="http://syndicatex.com/wp-content/uploads/2012/04/Photo-Apr-24-15-04-09-150x150.jpg" class="attachment-thumbnail" alt="Photo Apr 24, 15 04 09" title="Photo Apr 24, 15 04 09" /></a>
<a href='http://syndicatex.com/misc/monitor-purchasing-guide/attachment/photo-apr-24-15-06-31/' title='Photo Apr 24, 15 06 31'><img width="150" height="150" src="http://syndicatex.com/wp-content/uploads/2012/04/Photo-Apr-24-15-06-31-150x150.jpg" class="attachment-thumbnail" alt="Photo Apr 24, 15 06 31" title="Photo Apr 24, 15 06 31" /></a>
<a href='http://syndicatex.com/misc/monitor-purchasing-guide/attachment/photo-apr-24-17-04-21/' title='Photo Apr 24, 17 04 21'><img width="150" height="150" src="http://syndicatex.com/wp-content/uploads/2012/04/Photo-Apr-24-17-04-21-150x150.jpg" class="attachment-thumbnail" alt="Photo Apr 24, 17 04 21" title="Photo Apr 24, 17 04 21" /></a>
<a href='http://syndicatex.com/misc/monitor-purchasing-guide/attachment/pixel_happy/' title='pixel_happy'><img width="150" height="150" src="http://syndicatex.com/wp-content/uploads/2012/04/pixel_happy-150x150.png" class="attachment-thumbnail" alt="pixel_happy" title="pixel_happy" /></a>

<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/misc/monitor-purchasing-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Bug Game</title>
		<link>http://syndicatex.com/programming/the-bug-game/</link>
		<comments>http://syndicatex.com/programming/the-bug-game/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 17:29:02 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[life]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=449</guid>
		<description><![CDATA[I built this game in AS3 quite awhile ago. It&#8217;s very simple and is hardly a game in that there is no objective but to have fun. I started a version in FlatRedBall at one point but lost motivation. I think I should finish it because everyone that plays this enjoys it. This game is [...]]]></description>
			<content:encoded><![CDATA[<p>I built this game in AS3 quite awhile ago. It&#8217;s very simple and is hardly a game in that there is no objective but to have fun. I started a version in FlatRedBall at one point but lost motivation. I think I should finish it because everyone that plays this enjoys it.</p>
<p>This game is only 8k and has no pre-created assets. Bugs are drawn in code.</p>
<p>&nbsp;</p>
<p><span style="text-decoration: underline;"><strong>How To Play:</strong></span></p>
<p>The bugs start as very fast little whippersnappers. As they age they grow bigger and slower. Once they are old enough they will breed and the females (antennas) will have babies. Some bugs are more fertile than others and some are not fertile at all. Baby bugs will generally be a combination of their parents&#8217; color but there is a chance for anomalies to be born. Bugs will die of old age after awhile.</p>
<p>If you&#8217;re quick, you can squish bugs by clicking on them. If you want to squish them all press &#8220;S&#8221; (meanie).</p>
<p>If the bugs get too crowded they will stop having babies until some of the population dies off.</p>
<p>&nbsp;</p>
<p><object id="life" width="450" height="350" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="quality" value="high" /><param name="src" value="/wp-content/uploads/2012/04/life.swf" /><param name="allowscriptaccess" value="sameDomain" /><param name="allowfullscreen" value="false" /><param name="pluginspage" value="http://www.macromedia.com/go/getflashplayer" /><embed id="life" width="450" height="350" type="application/x-shockwave-flash" src="/wp-content/uploads/2012/04/life.swf" allowScriptAccess="sameDomain" allowFullScreen="false" quality="high" allowscriptaccess="sameDomain" allowfullscreen="false" pluginspage="http://www.macromedia.com/go/getflashplayer" /> </object></p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/programming/the-bug-game/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FlatRedBall and Lidgren: Multiplayer Networking</title>
		<link>http://syndicatex.com/flatredball/flatredball-and-lidgren-multiplayer-networking/</link>
		<comments>http://syndicatex.com/flatredball/flatredball-and-lidgren-multiplayer-networking/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 16:24:11 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[FlatRedBall]]></category>
		<category><![CDATA[babytanks]]></category>
		<category><![CDATA[flatredball]]></category>
		<category><![CDATA[lidgren]]></category>
		<category><![CDATA[multiplayer]]></category>
		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=442</guid>
		<description><![CDATA[I haven&#8217;t blogged in a while for two reasons: Work is insanely busy I&#8217;ve been either working hard or playing hard in my spare time But now, for your reading amusement, is another beautiful trainwreck blog with copious amounts of bad code! This post is going to talk about some of the challenges and the pattern [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://syndicatex.com/wp-content/uploads/2012/03/babytanks.png"><img class="aligncenter size-medium wp-image-443" title="babytanks" src="http://syndicatex.com/wp-content/uploads/2012/03/babytanks-600x469.png" alt="" width="600" height="469" /></a></p>
<p>I haven&#8217;t blogged in a while for two reasons:</p>
<ol>
<li><span style="line-height: 18px;">Work is insanely busy</span></li>
<li><span style="line-height: 18px;">I&#8217;ve been either working hard or playing hard in my spare time</span></li>
</ol>
<div>But now, for your reading amusement, is another beautiful trainwreck blog with copious amounts of bad code! <span style="line-height: 18px;">This post is going to talk about some of the challenges and the pattern I used to implement multiplayer networking in </span><a style="line-height: 18px;" title="FlatRedBall: Free game engine" href="http://www.flatredball.com/frb/blog/index2.php" target="_blank">FlatRedBall </a><span style="line-height: 18px;">using the </span><a style="line-height: 18px;" title="Lidgren Networking Library" href="http://code.google.com/p/lidgren-network-gen3/" target="_blank">Lidgren Gen 3</a><span style="line-height: 18px;"> networking library. I primarily used these resources, along with the Lidgrin library documentation, to plan my networking pattern:</span></div>
<div>
<ul>
<li><span style="line-height: normal;"><a href="http://udn.epicgames.com/Three/NetworkingOverview.html">http://udn.epicgames.com/Three/NetworkingOverview.html</a><br />
</span></li>
<li><a href="https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking">https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking</a></li>
<li><a href="http://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf">http://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf</a> (old but interesting)</li>
</ul>
<p><span style="line-height: 19px;">First of all, if you want to make a networked multiplayer game, do it from the first line of code. My goal with this project, from the very begining, was to make a networked game and it was hard enough. Trying to shoehorn networking into an existing game would be&#8230;very difficult. Second, there are a variety of patterns you can implement that work better for different game types. The pattern described in the PDF linked above is great for RTS games but probably wouldn&#8217;t work for an action game.</span></p>
</div>
<p>A strange but important thing to realize is: game instances never match across a network! Realizing this was integral to getting the network to work. I had to evaluate what actually <em>matters </em>to the gameplay and send that. Entities that cannot affect a client do not matter and shouldn&#8217;t be updated until the server decides they do matter.</p>
<p>So, this is not &#8220;the way&#8221; to implement networking with FlatRedBall but it is &#8220;a way&#8221; that seems to be working pretty well. It is a work in progress but it is off to a pretty good start. Read on and comment with questions or concerns.</p>
<p>&nbsp;</p>
<p><strong>Step 0: The pattern used</strong></p>
<p>I&#8217;m using a Client-Server pattern: one server, multiple clients connected. The server is the master record, both sides simulate the environment and exchange minimal data that describes changes to object states on each end without having to send updates for the entire world every frame. If you haven&#8217;t read the Unreal article above, do so. It&#8217;s a really good overview of how this works. I will be going into some detail about my specific implementation but that article was written by the pros!</p>
<p>Here&#8217;s the overview of how my implementation works:</p>
<ul>
<li><span style="line-height: 18px;">Keyboard input state is compressed into a bitmask each update and only sent to the server if the state changes using UnreliableSequenced send mode</span></li>
<li><span style="line-height: 18px;">Every T seconds, the client sends a reckoning input update using ReliableSequenced</span></li>
<li><span style="line-height: 18px;">Every T seconds, the server forces a &#8220;dead reckoning&#8221; of all interactive game objects (eventually limited to those affecting a specific client)</span></li>
<li><span style="line-height: 18px;">The value of T is set in Glue so it can be tweaked and tested easily, currently I&#8217;m using 0.5 seconds for dead reckoning but that may be too frequent</span></li>
<li><span style="line-height: 18px;">When an entity gets a new state via &#8220;dead reckoning&#8221; it <em>interpolates </em>to the new position instead of jumping straight there. This makes a big difference in perceived smoothness</span></li>
</ul>
<p>&nbsp;</p>
<p><strong>Step 1: Abstracting the Lidgrin Library for FlatRedBall</strong></p>
<p>I don&#8217;t want my entire project to depend on Lidgrin. First, I&#8217;d like others to be able to use my abstraction. Second, I might update to a newer version of Lidgren, discover another networking library in the future, or otherwise change dependencies. If that happens, I only need to make changes in one place: my adapter between Lidgren and the FlatRedBall engine. My abstraction is (as of this post) three files: a <a title="NetworkAgent class" href="http://syndicatex.com/wp-content/uploads/code/NetworkAgent.cs" target="_blank">NetworkAgent</a>, an <a title="Incoming Network Message Class" href="http://syndicatex.com/wp-content/uploads/code/NetworkMessageIn.cs" target="_blank">incoming message</a> class, an <a title="Outgoing Network Message Class" href="http://syndicatex.com/wp-content/uploads/code/NetworkMessageOut.cs" target="_blank">outgoing message</a> class (links go to actual codez).</p>
<p>The NetworkAgent is the only object instantiated by a Game Screen. It can be instantiated as a Server or a Client. It provides the Game with a unique ID (which actually comes from Lidgren), latency measurement, and ways to send and receive messages. The NetworkAgent&#8217;s GetMessages method returns processes the queue of messages, writes any non-data messages to a provided logger, and pushes all data messages into a List of incoming messages and returns the list. The Game Screen calls this method every Update and processes the List returned.</p>
<p>The incoming/outgoing message classes mostly wrap Lidgren message types. However, they can be tidily extended to send more complex objects than Lidgren allows. For instance, I added methods that can send/receive Vector3 objects, which are actually broken into their three discreet float values and packetized.</p>
<p>The NetworkAgent doesn&#8217;t care what type of game you make. It doesn&#8217;t care what type of messages can be sent (other than Lidgren&#8217;s generic &#8220;data&#8221; type). All of this game-specific stuff should be implemented in your Game Screen. The Network Agent just makes it easy to send/receive messages without having Lidgren dependencies sprinkled all over your project.</p>
<p>&nbsp;</p>
<p><strong>Step 2: Input Management</strong></p>
<p>Since my game uses keyboard for movement and mouse for aiming, all movement-related input states are boolean: either a key is down or it&#8217;s not. Sending this as a bunch of Boolean values or something even heavier would slow down the network. I pack up to eight different key states into a single byte using bit operations. I can also send the mouse position as two floats. Since the mouse only controls the turret rotation, and that&#8217;s not really important unless the player is actively firing a weapon, I&#8217;m planning to test sending the mouse state <em>only</em> during the input reckoning or when firing and interpolating the tank rotation between these updates.</p>
<p>The important thing here is to understand the chain of events. If a player is holding down a single key, input state does not change until they release it. This type of update is <em>only </em>sent on state change and is sent UnreliableSequenced. This state update is received by the server and forwarded to other clients. However, since it is Unreliable it may not be delivered at all, which would result in the server not realizing the player had released the forward key and keep moving the tank forever. This is why I <em>also </em>need an input reckoning. This forces a reliable update to the server of the current state.</p>
<p>Note that the server also broadcasts its own input updates. And, when it forwards an input update, it forwards it to <em>all </em>clients (including the one that sent it). This means that a client must check the ID of the entity the update is affecting and discard it if it applies to the entity the client owns.</p>
<p>&nbsp;</p>
<p>This is the Input State object:</p>
<pre class="brush:csharp">// An enum who's values are ready for bitwise ops
[Flags]
public enum InputTypes
{
	None = 0,
	UpPress = 1,
	DownPress = 2,
	LeftPress = 4,
	RightPress = 8,
	FirePress = 16,
	SpecialPress = 32
}

// extension method to make input testing easy!
public static class InputTypeExtensions
{
	public static bool ContainsFlag(this InputTypes flagSource, InputTypes testFlag)
	{
		return ((flagSource &amp; testFlag) == testFlag);
	}
}</pre>
<p>&nbsp;</p>
<p>The Game Screen does this each update cycle to create a new state:</p>
<pre class="brush:csharp">private void HandleInput()
{
	// for readability
	Keyboard kb = InputManager.Keyboard;
	Mouse ms = InputManager.Mouse;
	mCurrentMousePosition = new Vector3(ms.WorldXAt(0), ms.WorldYAt(0), 0);

	// Use bitwise and a ternary to "OR" input states into the object
	mPreviousInputState = mCurrentInputState;
	mCurrentInputState = InputTypes.None;
	mCurrentInputState |= (kb.KeyDown(Keys.W) ? InputTypes.UpPress : InputTypes.None);
	mCurrentInputState |= (kb.KeyDown(Keys.S) ? InputTypes.DownPress : InputTypes.None);
	mCurrentInputState |= (kb.KeyDown(Keys.A) ? InputTypes.LeftPress : InputTypes.None);
	mCurrentInputState |= (kb.KeyDown(Keys.D) ? InputTypes.RightPress : InputTypes.None);
	mCurrentInputState |= (ms.ButtonDown(Mouse.MouseButtons.LeftButton) ? InputTypes.FirePress : InputTypes.None);
	mCurrentInputState |= (ms.ButtonDown(Mouse.MouseButtons.RightButton) ? InputTypes.SpecialPress : InputTypes.None);

	// only send input state if we own an entity
	if (mOwnedTank != null)
	{
		// apply the input state to our owned entity
		mOwnedTank.ChangeInputState(mCurrentInputState, mCurrentMousePosition);

		// send the server an update
		if (mCurrentInputState != mPreviousInputState)
		{
			// false means don't send reliably
			SendInputUpdateMessage(false);
		}
	}
}</pre>
<p>&nbsp;</p>
<p>How the Game Screen sends an input state:</p>
<pre class="brush:csharp">// mInputMessage is an Outgoing Message instance
// mNetwork is a NetworkAgent instance
// note that we also send the entity owner id
private void SendInputUpdateMessage(bool isReliableMessage)
{
	mInputMessage = mNetwork.CreateMessge();
	mInputMessage.Write((byte)NetworkMessageType.InputState);
	mInputMessage.Write(mNetwork.GetId());
	mInputMessage.Write((byte)mCurrentInputState);
	mInputMessage.Write(mCurrentMousePosition);
	mInputMessage.SendToAll(isReliableMessage);
}</pre>
<p>&nbsp;</p>
<p>Whether it comes directly from the Game Screen or via a network message, an input state is handled by an Entity like this (just a snippit):</p>
<pre class="brush:csharp">public void ApplyInputState()
{
	// uses extension method to check input state
	if (CurrentInputState.ContainsFlag(InputTypes.UpPress))
	{
		CurrentSpeed += AccelRate;
		TankTracks.Animate = true;
	}
	// handle other key states here...not shown

	// apply turret rotation
	TankTurret.RelativeRotationZ = (float)Math.Atan2(mTarget.Y - Position.Y, mTarget.X - Position.X) - RotationZ;

	// affect velocity with speed and rotation
	Velocity.X = (float)(Math.Cos(RotationZ) * CurrentSpeed);
	Velocity.Y = (float)(Math.Sin(RotationZ) * CurrentSpeed);

	// interpolate from reckoning (see next section)
	InterpolateReckoningDelta();
}</pre>
<p>&nbsp;</p>
<p><strong>Step 3: Reckoning</strong></p>
<p>If you didn&#8217;t read the articles linked at the top and you haven&#8217;t figured it out by now: reckoning is the process of forcing clients and server back into sync with each other. A complete override of all client states by the server is called a &#8220;dead reckoning.&#8221; Input reckoning is not a full-on dead reckoning because it doesn&#8217;t reposition or change the entire state of an entity, merely updates it&#8217;s input. The entity could still be way out of position. Thus the server needs to force a reckoning on all entities in the game to make sure they are where they should be. This is simple in concept: every N seconds, the server loops through it&#8217;s entities and broadcasts a state message for each entity to all clients. The problem is, this state _never_ exactly matches the entity state on the client. Plus, the message will take a bit of time to transfer and be applied. So, even if the entity states exactly match when the server broadcasts a message, they probably won&#8217;t by the time the message is received. This means that even with latency close to zero and no packet loss you get jerky performance. There are two ways of mitigating this and neither works perfectly by itself:</p>
<p><span style="text-decoration: underline;">Prediction</span>: use the average latency, rotation and velocity to broadcast where the entity should be by the time the message arrives. This helps a little but if the player is actively turning or changing direction it can compound the difference between states.</p>
<p><span style="text-decoration: underline;">Interpolation</span>: Instead of immediately forcing the entity to a new position, interpolate the current position into the destination position smoothly. This is more (and less) complicated than it sounds because the entity&#8217;s current position and the received reckoning position are a snapshot of a moment in time. These values are actively changing. So you have to interpolate where the entity is going to be given the Client&#8217;s state with where the entity is going to be given the Server&#8217;s state, while also accounting for new input even as the interpolation happens!</p>
<p>The solution I found (after about 5 tries) was actually really simple in retrospect. I simply take the delta of the current position and the destination position and apply a percentage of the delta each update until there is no more discrepancy. This means that the client and server instances of an Entity do not match but are frequently, smoothly, shifted closer together. Making these shifts smoother makes them much harder to perceive, improving gameplay. If the discrepancy is big enough to cause collision problems with world geometry or enemy fire, the server position ultimately rules. This sucks but it is present in all games, how often have you died in a FPS because the enemy wasn&#8217;t actually where you were shooting?</p>
<pre class="brush:csharp">// reckoning difference
Vector3 mPositionDelta;

// called by the client's Game Screen when it receives a reckoning message
public void ForceNewState(Vector3 position, float rotation, float speed, int health, InputTypes input)
{
	// the important line: set the delta
	mPositionDelta = Vector3.Subtract(position, Position);

	RotationZ = rotation;
	CurrentInputState = input;
	CurrentSpeed = speed;
	CurrentHealth = health;
}

// each frame the entity applies its current input state
// after the normal movement is applied this interpolation is called
// Interpolation rate is a global var that all entities can reference
private void InterpolateReckoningDelta()
{
	if (mPositionDelta.X != 0)
	{
		Position.X += mPositionDelta.X * GlobalData.GameData.InterpolationRate;
		mPositionDelta.X -= mPositionDelta.X * GlobalData.GameData.InterpolationRate;
	}

	if (mPositionDelta.Y != 0)
	{
		Position.Y += mPositionDelta.Y * GlobalData.GameData.InterpolationRate;
		mPositionDelta.Y -= mPositionDelta.Y * GlobalData.GameData.InterpolationRate;
	}
	// some clamping could happen here for really small deltas
	// but I have tuned interpolation rate so that it finishes up
	// just in time for the next reckoning!
}</pre>
<p>&nbsp;</p>
<p>Hopefully this has made some level of sense. Currently the game doesn&#8217;t implement shooting, collision, etc so there is still much to be done that will likely affect my pattern.</p>
<p>Love or hate? Drop it in a comment!</p>
<p><strong>Update: </strong>Forgot to mention one little thing. Entity creation. When the client receives a reckoning update it checks the ID and then searches its list of entities for a matching ID and applies the reckoning to the matching ID. If it doesn&#8217;t find an ID it creates a new entity with that ID and applies the reckoning. This results in a slight delay in new entity appearance if you connect to an existing game between reckonings. Lots of ways to improve this with more explicit entity creation requests but I haven&#8217;t gotten there yet <img src='http://syndicatex.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/flatredball/flatredball-and-lidgren-multiplayer-networking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kicked out by Kickstarter</title>
		<link>http://syndicatex.com/projects/kicked-out-by-kickstarter/</link>
		<comments>http://syndicatex.com/projects/kicked-out-by-kickstarter/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 21:07:49 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[grimwar]]></category>
		<category><![CDATA[kickstarter]]></category>
		<category><![CDATA[MVC3]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=435</guid>
		<description><![CDATA[I&#8217;ve written about Grimwar several times on here. I keep trying to rebuild it and make it better but it&#8217;s a very big site with a lot of users and there is a lot of work involved with rebuilding. That being said, I AM rebuilding it. Even though it makes no money, even though I don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written about Grimwar several times on here. I keep trying to rebuild it and make it better but it&#8217;s a very big site with a lot of users and there is a lot of work involved with rebuilding. That being said, I AM rebuilding it. Even though it makes no money, even though I don&#8217;t even <em>play </em>Magic the Gathering, I think it <em>could </em>be profitable and I want to build it for the community, if nothing else.</p>
<p>I am rebuilding Grimwar in .NET MVC3 and it&#8217;s going really well. Unfortunately, Windows servers are more expensive than the LAMP servers I&#8217;m used to rolling on. I created and submitted a Kickstarter proposal to help raise money for some marketing expenses, printing expenses and server costs. Unfortunately my request was denied. Here&#8217;s what they had to say:</p>
<blockquote><p>Hi Justin,</p>
<p>Thank you for taking the time to share your idea. Unfortunately, this isn&#8217;t the right fit for Kickstarter. We receive many project proposals daily and review them all with great care and appreciation. We see a wide variety of inspiring ideas, and while we value each one&#8217;s uniqueness and creativity, Kickstarter is not the right platform for all of them. We wish you the best of luck as you continue to pursue your endeavor.</p>
<p>Best,<br />
Kickstarter</p></blockquote>
<p>So&#8230;denied! I think Kickstarter is more interested in projects that further the arts, or technology. Grimwar is unique in that no other site serves the same function. However, it&#8217;s not particularly ground-breaking. So, I&#8217;m disappointed that I don&#8217;t even get the <em>chance </em>to try to get funding but I like that Kickstarter has a good gatekeeping system.</p>
<p>Anyway, I thought the processes of submitting a proposal, getting reviewed by real people and the gatekeeping thing was interesting. I still love you Kickstarter, maybe we can work together another time.</p>
<p>&nbsp;</p>
<p><em>Note: I can make Grimwar work regardless of securing funding. I&#8217;ll dump an existing server and pick up some shared Windows hosting. So, if you&#8217;re reading this and concerned about the future of Grimwar&#8230;the show will go on!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/projects/kicked-out-by-kickstarter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Binary Serialization in C#</title>
		<link>http://syndicatex.com/programming/binary-serialization-in-c/</link>
		<comments>http://syndicatex.com/programming/binary-serialization-in-c/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 23:09:28 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[auto-properties]]></category>
		<category><![CDATA[binary]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[deserialization]]></category>
		<category><![CDATA[persistent storage]]></category>
		<category><![CDATA[serialization]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=433</guid>
		<description><![CDATA[Let me preface this by saying I&#8217;m not sure the information here is correct. Prior to this, I have not worked with binary serialization. I serialized to XML or JSON because it was easy to transfer and was human readable. But binary really makes sense for what I&#8217;m doing now. I deserialize JSON into objects [...]]]></description>
			<content:encoded><![CDATA[<p>Let me preface this by saying I&#8217;m <strong>not sure the information here is correct</strong>. Prior to this, I have not worked with binary serialization. I serialized to XML or JSON because it was easy to transfer and was human readable. But binary really makes sense for what I&#8217;m doing now. I deserialize JSON into objects from a Web API. To make the app run faster, I cache the deserialized objects. Many of them could be cached for quite awhile because they rarely change. So, persistent cache storage is good but I need to keep the cache footprint small on disk and keep serialization speedy. Binary is faster and smaller than any other type (afaik). It also supposedly preserves links and hierarchies more reliably.</p>
<p>Here&#8217;s a shortened example of a type of object I get from JSON and want to save persistently:</p>
<pre class="brush:csharp">[Serializeable()]
public class Department {
   public int Id {get; set;}
   public string Name {get; set;}
   public Drawable Thumbnail {get; set;} // Drawable is an android type that holds image data
}</pre>
<p>&nbsp;</p>
<p>The above example will not serialize because the Android Drawable class is not serializable. We probably don&#8217;t want to be serializing image data into our cache anyway so&#8230;let&#8217;s mark that as [NonSerialized]. Now we get a new exception because you can&#8217;t mark a property as non-serialized&#8230;because Properties aren&#8217;t serialized! Yet, if you comment out the Thumbnail property the rest of the class can be serialized and deserialized with no problems. Why?</p>
<p>Traditionally, auto-properties didn&#8217;t exist. You had to have an explicit class member defined and manually create the accessors. When we create an auto-property (which are awesome, IMHO) the compiler creates a class member behind the scenes that the auto-property references. But this is given an arbitrary name and is not accessible. So, when you serialize a property, the property is not being serialized, the hidden member behind it is being serialized. This has some very important consequences.</p>
<p>Let&#8217;s say you create the class above and the data is serialized and stored on disk. As time moves on you have some updates to make that require name to perform some logic. Perhaps it simply needs to upper case the name before returning it. So, you create an explicit member variable and your code looks like this:</p>
<pre class="brush:csharp">[Serializeable()]
public class Department {
   public int Id {get; set;}
   public Drawable Thumbnail {get; set;} // Drawable is an android type that holds image data
   public string Name {
      get {
         return mName.ToUpper();
      }
      private set {
         mName = value;
      }
   }
   private string mName;
}</pre>
<p>Unfortunately for you, when your program deserializes the data from the old version, Name and mName are going to be <em>null</em>. This is because the actual serialized member behind Name was called something else and that&#8217;s what was serialized. If you serialize again and save before you realize this, your binary data will now have a bunch of empty names. The worst part is: it won&#8217;t even warn you! It simply doesn&#8217;t inflate the old member because it no longer exists as part of the class and the new member is left as its default (null for strings).</p>
<p>The above would still fail because it doesn&#8217;t solve the problem of Drawables being unserializeable (is that even a word?). To fix this, you have to give Thumbnail an explicit class member and mark the member as [NonSerialized]. Remember, if you mark a class as [Serializeable()] it will try to serialize the whole thing, even private members.</p>
<p>So, the ultimate thing to be aware of is: be really careful using auto-properties with binary serialization. If you have auto-properties that have ANY CHANCE of changing and data integrity is important&#8230;explicitly define the backing members.</p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/programming/binary-serialization-in-c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mono for Android List Optimization</title>
		<link>http://syndicatex.com/programming/monodroid-list-optimization/</link>
		<comments>http://syndicatex.com/programming/monodroid-list-optimization/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 17:21:56 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[ViewHolder]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=426</guid>
		<description><![CDATA[One of the big things I&#8217;ve worked on lately is optimization of the Android app I&#8217;m working on for my employer. I want the app to run at its absolute full potential using every realistic optimization I can. One of the most-frequently-used components in Android applications are ListViews. Android ListViews are good and bad. They [...]]]></description>
			<content:encoded><![CDATA[<p>One of the big things I&#8217;ve worked on lately is optimization of the Android app I&#8217;m working on for <a title="Sierra Trading Post" href="http://www.sierratradingpost.com/" target="_blank">my employer</a>. I want the app to run at its absolute full potential using every realistic optimization I can.</p>
<p>One of the most-frequently-used components in Android applications are ListViews. Android ListViews are good and bad. They are good in that, if you do it properly, they handle view recycling and can be pretty efficient. They are bad in that the abstraction is so leaky that 90% of the so-called tutorials and examples I&#8217;ve seen do it poorly. Many of the tutorials don&#8217;t even take advantage of the view recycling and the ones that do still miss out on some important optimizations.</p>
<p>This is a quick example of how to optimize a list view, starting with bad implementation and moving to better implementation. Note that I&#8217;m mocking up this code so please point out any mistypes in the comments.</p>
<p>&nbsp;</p>
<p>Here&#8217;s an example of the most basic implementation of a ListAdapter&#8217;s GetView method. Please <strong>do not</strong> create your list like this. This would be fine for viewing just a few items but it doesn&#8217;t take advantage of any recycling. This is inflating a new view every, single time &#8211; which is extremely wasteful and will definitely slow your lists down. Notice that we&#8217;re not using the &#8220;convertView&#8221; parameter at all! We will implement that in the next example.</p>
<pre class="brush:csharp">public override View GetView(int position, View convertView, ViewGroup parent)
{
   // get our data object from the list
   MyObject dataObject = mObjectList[position];

   // inflate our custom line item
   LinearLayout view = mContext.LayoutInflater.Inflate(Resource.Layout.my_line_item, parent, false) as LinearLayout;

   // get references to our views
   TextView title = view.FindViewById(Resource.Id.myLineItemTitle) as TextView;
   TextView subText = view.FindViewById(Resource.Id.myLineItemSubtext) as TextView;
   ImageView thumbnail = view.FindViewById(Resource.Id.myLineItemThumb) as ImageView;

   // bind data to our line item
   title.Text = dataObject.Title;
   subText.Text = dataObject.Description;
   thumbnail.SetImageDrawable(dataObject.Thumb);

   return view;
}</pre>
<p>&nbsp;</p>
<p>This version improves slightly. Here we are using the recycled convertView, if it exists, instead of inflating a new view. This will help a lot but we still have to instantiate references to our sub views before we can bind data. FindViewById is expensive enough that this still adds overhead. If your line item is simple enough that it doesn&#8217;t have subviews or only has a single subview this method might be okay but use it with caution.</p>
<pre class="brush:csharp">public override View GetView(int position, View convertView, ViewGroup parent)
{
   // get our data object from the list
   MyObject dataObject = mObjectList[position];

   // check if we have a recycled view, if not then inflate
   var view = convertView;
   if(convertView == null)
   {
      view = mContext.LayoutInflater.Inflate(Resource.Layout.my_line_item, parent, false) as LinearLayout;
   }

   // get references to our views
   TextView title = view.FindViewById(Resource.Id.myLineItemTitle) as TextView;
   TextView subText = view.FindViewById(Resource.Id.myLineItemSubtext) as TextView;
   ImageView thumbnail = view.FindViewById(Resource.Id.myLineItemThumb) as ImageView;

   // bind data to our line item
   title.Text = dataObject.Title;
   subText.Text = dataObject.Description;
   thumbnail.SetImageDrawable(dataObject.Thumb);

   return view;
}</pre>
<p>&nbsp;</p>
<p>So, that was an easy way to make sure we&#8217;re using our recycled views. But we still are finding sub views every time. To fix this we implement something called the ViewHolder Pattern. Views in Android have something called a Tag. A Tag can be any type of Java.Lang.Object that is stored in the View.Tag for future use. The idea here is to create a ViewHolder class that will store references to our subviews so that we only have to find them once. Then we store that reference in the View.Tag and retrieve it when we need it. I take this even further and create a &#8220;Bind&#8221; method so that my GetView method is really clean!</p>
<pre class="brush:csharp">// our GetView method is now very clean!
public override View GetView(int position, View convertView, ViewGroup parent)
{
   ViewHolder vh;

   // attempt to recycle existing view
   var view = convertView;
   if(view == null)
   {
      view = mContext.LayoutInflater.Inflate(Resource.Layout.my_line_item, parent, false) as LinearLayout;
      vh = new ViewHolder();

      // here's where we get our subview references
      vh.Initialize(view);

      // push the viewholder reference into the view tag
      view.Tag = vh;
   }

   // get our data object
   MyObject dataObject = mObjectList[position];

   // get our viewholder from the tag
   vh = (ViewHolder)view.Tag;

   // bind our data!
   vh.Bind(dataObject);
   return view;
}

// extend Java.Lang.Object or you will run into all kinds of type/cast issues when trying to push/pull on the View.Tag
private class ViewHolder : Java.Lang.Object
{
   TextView mTitle;
   TextView mSubText;
   ImageView mThumb;

   // this method now handles getting references to our subviews
   public void Initialize(View view)
   {
      mTitle = view.FindViewById(Resource.Id.myLineItemTitle) as TextView;
      mSubText = view.FindViewById(Resource.Id.myLineItemSubtext) as TextView;
      mThumb = view.FindViewById(Resource.Id.myLineItemThumb) as ImageView;
   }

   // this method now handles binding data
   public void Bind(MyObject data)
   {
      mTitle.Text = data.Title;
      mSubText.Text = data.Description;

      // we've also improved the thumbnail to use a default image if missing
      if(data.Thumb == null)
      {
         mThumb.SetImageResource(Resource.Drawable.missing_thumb);
      }
      else
      {
         mThumb.SetImageDrawable(data.Thumb);
      }
   }
}</pre>
<p>Now we only instantiate a view if we don&#8217;t already have one. We only find subviews if we haven&#8217;t already. The only step that is done every time is getting the ViewHolder from the tag and binding data to it. There is a tiny inefficiency left here: when I instantiate the ViewHolder the first time, I push it into the tag and then pull it back out instead of using it directly. I do this intentionally because the overhead required is very tiny and it proves that the system is working immediately. If you have any casting issues with your ViewHolder and View.Tag it&#8217;ll happen the first time a view is created, instead of just when a view is recycled.</p>
<p><em>Note: There are lots of ViewHolder pattern descriptions out there but few (none?) of them use the Initialize/Bind system that I show here. I like this style a lot but I can&#8217;t claim credit for it: <a title="Joel Martinez on code" href="http://codecube.net/" target="_blank">Joel Martinez</a> gave me a lot of ideas here and may be the first to use ViewHolders like this. I just adapted it from Java to Mono.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/programming/monodroid-list-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Construct 2: Kicking the Tires</title>
		<link>http://syndicatex.com/programming/construct-2-kicking-the-tires/</link>
		<comments>http://syndicatex.com/programming/construct-2-kicking-the-tires/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 07:59:50 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[construct2]]></category>
		<category><![CDATA[engines]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[html5]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=405</guid>
		<description><![CDATA[I love playing with GameDev tools such as engines, frameworks/libraries, game creators and new languages. I&#8217;ve been a big advocate, fan and user of FlatRedBall for some time as you may know. Today, while reading up on something totally unrelated, I saw a reference to an HTML5 game maker called Creator2. Curious, I read a [...]]]></description>
			<content:encoded><![CDATA[<p><iframe src="http://syndicatex.com/files/c2test/" width="640px" height="600px"></iframe></p>
<p>I love playing with GameDev tools such as engines, frameworks/libraries, game creators and new languages. I&#8217;ve been a big advocate, fan and user of FlatRedBall for some time as you may know.</p>
<p>Today, while reading up on something totally unrelated, I saw a reference to an HTML5 game maker called <a title="Scirra Creator 2" href="http://www.scirra.com/" target="_blank">Creator2</a>. Curious, I read a little about it and decided to play with it this weekend.</p>
<p>I&#8217;ve been pleasantly surprised by how awesome this tool actually is. While I don&#8217;t think it&#8217;s suitable for a super-feature-rich and complex game, it is a pretty solid tool for prototyping or creating casual 2D games. I also was pretty impressed by how smoothly it ran.</p>
<p>I built a tiny but mostly-complete space game in just a few hours. The game features Box2D physics integration, health and scoring. Being able to download the editor, follow a single, short tutorial and immediately create a working prototype is pretty incredible.</p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/programming/construct-2-kicking-the-tires/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The R word</title>
		<link>http://syndicatex.com/philosophy/the-r-word/</link>
		<comments>http://syndicatex.com/philosophy/the-r-word/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 19:06:05 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Philosophy]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[professionalism]]></category>
		<category><![CDATA[retard]]></category>
		<category><![CDATA[Rett Syndrome]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=399</guid>
		<description><![CDATA[I avoid using strong language. I also try to avoid words that cause offense or harm to specific groups in a professional or public forum. That being said, I generally find jokes that poke fun at racial, religious and other stereotypes funny when they are joking and in the right company or context. As you may [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://syndicatex.com/wp-content/uploads/2012/01/nora_and_i.jpg"><img class="aligncenter size-full wp-image-400" title="nora_and_i" src="http://syndicatex.com/wp-content/uploads/2012/01/nora_and_i.jpg" alt="" width="480" height="444" /></a></p>
<p>I avoid using strong language. I also try to avoid words that cause offense or harm to specific groups in a professional or public forum. That being said, I generally find jokes that poke fun at racial, religious and other stereotypes funny when they <em>are </em>joking and in the right company or context.</p>
<p>As you may know, my beautiful, wonderful, four-year-old daughter <a title="Nora on GirlPower2Cure" href="http://girls.girlpower2cure.org/nora" target="_blank">Nora</a> has a horrible neuro disorder called <a title="Rett Syndrome on Wikipedia" href="http://en.wikipedia.org/wiki/Rett_syndrome" target="_blank">Rett Syndrome</a>. Dealing with Rett Syndrome is a major part of the lives of my family, extended family and friends. When we first found out we were simultaneously crushed by the news and uplifted by the amazing support of our family and friends, that continues to be touching.</p>
<p>My wife and I went to a few meetings that were intended to be a sort of group therapy. We were positive and hopeful but found many of the group members to be bitter, depressed and angry at the world. In one session a parent went off about the use of the word &#8220;retard&#8221; by a large cross-section of people. While I understood the point, my wife and I did not like the anger and bitterness at the world that was a common attitude in the group and quit going.</p>
<p>Words like &#8220;fag&#8221; and &#8220;nigger&#8221; garner a ton of attention because they have an enormous and vocal advocacy group. Professionals that would never use those words on their blogs, twitter or in a public setting are often quick to use the word &#8220;retard,&#8221; which is admittedly surprising to me. The sad thing is, most people that do suffer from some form of mental retardation can&#8217;t defend themselves and thus the word &#8220;retard&#8221; rarely has the backlash that it&#8217;s racial and sexual-orientation counterparts do.</p>
<p>Despite all that, the word rarely bothers me. The internet at large uses it ALL the time. My friends use it frequently. Sometimes my wife and I even slip and use it (we try not to after seeing how offensive it is to some). The word seems to be pretty thoroughly decoupled from its association with disabled individuals. To put it another way, the two offensive words mentioned above still refer to specific groups whereas &#8220;retard&#8221; rarely actually refers to disabled people. Similarly, the words &#8220;stupid&#8221; and &#8220;dumb&#8221; at one time referred to the mentally or physically disabled but now seem to be generally accepted in informal speech. The only time &#8220;retard&#8221; does bother me is when it <em>is </em>used to refer to disabled people, which is highly offensive.</p>
<p>What bothers me more than the R word is the stigma around disabilities &#8211; but who&#8217;s fault is that? It is hard not to look (read: stare) at someone that obviously has a disability. And there&#8217;s nothing wrong with curiosity. I think the stigma is often negatively perpetuated<em> by the caretakers</em> of disabled people when they are rude to people who are curious. In our short-lived support group experience one of the parents ranted about people staring at her child at the park playground and talked about how &#8220;she showed them.&#8221; Of course people are going to stare! They&#8217;re curious and probably afraid to ask if you act like a total jerk because they&#8217;re interested! I&#8217;ve had some really positive experiences with strangers that asked about Nora with genuine concern and a desire to learn about her disability. I also think it&#8217;s awesome when people <a title="Target Ad With Down Syndrome Star" href="http://www.adweek.com/adfreak/boy-down-syndrome-becoming-unlikely-ad-star-137326" target="_blank">treat disabled people like anyone else</a>.</p>
<p>The thing that is absolutely unacceptable is mockery of people with disabilities. I watched a marketing professional, probably in his 30s, make a drunken spectacle of himself at a conference &#8211; impersonating someone with special needs in a public setting. It goes on record as one of the most insulting and pathetic things I&#8217;ve ever seen. So while I may not flinch at the R word, I might get violent at outright mockery or disrespect that&#8217;s actively directed at a disabled person.</p>
<p>Ultimately, if you&#8217;re unfamiliar with the world of disabled people and their caretakers try to treat them like anybody else. Be considerate with your language because it does offend some. If you are a disabled person, caretaker or otherwise related&#8230;focus on the positives: people are fascinated, interested and occasionally legitimately concerned about disabilities. While some of them may be rude, punishing everyone for it only hurts us all.</p>
<p>&nbsp;</p>
<p><em>Note: In case you missed the point, this post is NOT giving you license to say the R word any more than having an African American friend gives you the right to say the N word.</em></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/philosophy/the-r-word/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Digital Economics 101</title>
		<link>http://syndicatex.com/philosophy/digital-economics/</link>
		<comments>http://syndicatex.com/philosophy/digital-economics/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 02:18:11 +0000</pubDate>
		<dc:creator>jjohnson</dc:creator>
				<category><![CDATA[Philosophy]]></category>
		<category><![CDATA[economics]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[music]]></category>

		<guid isPermaLink="false">http://syndicatex.com/?p=392</guid>
		<description><![CDATA[As with all of my thoughts, these are hardly original. I have read a bunch of good stuff about economics and the evolution of digital content across the web that got me thinking about these things. But I like to think that I have a knack for reading and understanding the issues, swirling all of [...]]]></description>
			<content:encoded><![CDATA[<p>As with all of my thoughts, these are hardly original. I have read a bunch of good stuff about economics and the evolution of digital content across the web that got me thinking about these things. But I like to think that I have a knack for reading and understanding the issues, swirling all of the ideas around, and spitting out a somewhat cohesive explanation of what it all means without using big fancy words. Incidentally, this has ties to my last post about how <a title="Free services are not free and the Matrix exists" href="http://syndicatex.com/philosophy/the-real-matrix/" target="_blank">&#8220;free&#8221; services aren&#8217;t free</a> so it might be worth reading that too!</p>
<p>&nbsp;</p>
<p>I&#8217;m not an economist but, as far as I know, the main law of economics is the relationship between supply, demand and value. If supply goes down, demand and value go up, etc. Digital content causes problems with this equation because it&#8217;s theoretically infinite. Since the content can be replicated perfectly over and over there is no scarcity of supply and demand can be instantly fulfilled, meaning value is zero. So: infinite supply equals zero value.</p>
<p>I&#8217;ve seen this point argued both ways with people in the middle saying that the supply is not actually infinite and so on. The truth is when you can replicate something as easily and perfectly as you can with anything binary, the supply is practically infinite. I also believe that the law of economics is true, meaning that digital content&#8217;s value goes to near-zero. The preachers-of-doom are right, content has lost its value. Does this mean that good content will die in favor of mass-produced, regurgitated garbage?</p>
<p>&nbsp;</p>
<p>In the late 90s the infamous mp3 caught the music industry by surprise. The way I see it, there were two big catalysts. First, the development of the mp3 compression algorithm (I&#8217;m not sure exactly when this happened and I&#8217;m too lazy to look it up because I&#8217;m a blogger, not a journalist). Second, the steady increase in bandwidth at reasonable prices. Suddenly you could create a 10:1 compressed file of a song, at similar quality, and download it in less than 20 minutes on dialup. When DSL and Cable dropped in price it added fuel to the fire. I&#8217;ll skip the history lesson because you know what happened: Media piracy exploded via P2P networks.</p>
<p>Music, video game, film and other content industries freaked out and are still freaked out because the content they offer is increasingly under valued.</p>
<p>&nbsp;</p>
<p>I felt this burn personally when I created <a title="Get Whirlygig Free Right Now This Minute!" href="http://www.windowsphone.com/en-US/apps/41817089-0da1-e011-986b-78e7d1fa76f8" target="_blank">Whirlygig for WP7</a>. I&#8217;ll readily admit that Whirlygig is not a great game. It&#8217;s not bad, but it&#8217;s not great. And I couldn&#8217;t sell it for a dollar. After working for months on a game, pouring my sweat and soul into something, it was hard to accept that it was worth less than 1/3 of a Starbucks latte. I realized that my hard work had very little perceived value and, at the time, got pretty depressed about the future of indie game dev (which I now find ironic because I consider 2011 to be a pretty stellar year for indies).</p>
<p>I spoke at a mobile marketing conference in Houston in October, 2011 and, as part of my research, I looked at total volume of apps on the market. At the time iTunes had almost 500k apps, Android was nearing 250k and WP7 was working towards 50k for a nice round 800k number. I&#8217;m sure it&#8217;ll hit 1 million total apps soon. So, even without the digital music revolution, the sheer volume of choice makes the perceived value of individual apps very low because supply outweighs demand.</p>
<p>Industry pundits lament the demise of quality content, blah, blah, blah and indies like me either get burned out and quit or continue to do it for the love of it, without hope for financial success. The digital revolution has happened and there is no money to be made in content creation.</p>
<p>Or is there?</p>
<p>&nbsp;</p>
<p>Every equation has inverse equations. If the value of digital content has dropped to zero it is a hard product to sell. But if you think of digital content as a <em>resource </em>and not a <em>product </em>it suddenly has enormous potential because it&#8217;s a FREE RAW MATERIAL.</p>
<p>In 1901 a blacksmith would have to put a moderate amount of labor into creating a tiny metal ring. Now there are factories in China that do nothing but churn thousands of them out a minute. The value of that tiny metal ring has dropped so much that it may as well be valueless. But Victoria Secret combines a few of those metal rings with some lace to create a $35 fancy bra <strong>[1]</strong>. There are two important things happening here. First, Victoria Secret is creating a high-value product from low-value materials. Second, there is artificial scarcity. While all of the materials exist in abundance, the combination is unique, hard to reproduce and thus valuable.</p>
<p>In 2003, <a title="Apple Incorporated" href="http://en.wikipedia.org/wiki/Apple_Inc." target="_blank">some smart company</a> created a way to deliver a product that was dropping in value and create a business around delivering that content. They called their product the iTunes Store and sold individual songs digitally instead of full, physical CDs. Apple took a material that was dropping in value and wrapped it in a unique service that created value. The industrialization of music was becoming complete.</p>
<p>This transition has been further realized by Spotify, Pandora and other streaming services. These services do not sell you songs as a product. You don&#8217;t <em>pay</em> for individual songs at all&#8230;you either pay for a service or even <a title="Not really free" href="http://syndicatex.com/philosophy/the-real-matrix/" target="_blank">get it for free</a> thanks to advertising. The songs are a raw material that powers the service as opposed to a product themselves. These companies have realized that content is getting harder to sell due to the volume available. Additionally, the volume itself creates its own problems that are solved by streaming services. They create playlists and stations of like-music that combine the raw materials (songs) into unique experiences (playlists) just like clasps and fabric in a fancy bra.</p>
<p>Smart game developers have leveraged this. <a title="SpryFox" href="http://www.spryfox.com/" target="_blank">SpryFox</a>&#8216; created Realm of the Mad God (RotMG) and Triple Town, that leverage the exploding Free-To-Play (F2P) business model. In Triple Town you have a limited amount of turns that slowly recharge over time. If you run out of turns you can wait or buy more turns with real money. In RotMG you are limited to a single character at a time unless you buy more slots. You can also pay for cosmetic and other upgrades. League of Legends, TeamFortress 2 and countless other well-known games have similar models. Note that this is very different than in-game ads. In game ads generate some revenue but the model overall is not sustainable long term for any but the highest-downloaded games<strong>[2]</strong>. Additionally, it doesn&#8217;t really view the game as a raw material for a higher-level experience, it&#8217;s just a billboard for a different product that someone else is selling.</p>
<p>So F2P has circumvented the infinite availability by creating a scarcity of supply. You can play TripleTown for free and it&#8217;s a good game (this is a key point, more on this in a bit) but then you run out of supply (turns) <em>after the demand has been generated </em>(when the gamer has been pulled into the game flow). Suddenly the product has value. Even better, it creates a reliable revenue stream for the developer that enables them to add even more content and charge for that too. The game becomes a self-sustaining platform by managing its own supply and demand. But Triple Town&#8217;s model works because it is a good game at its core. The turn threshold is just long enough to get gamers into the flow but short enough that it runs out before you&#8217;re satisfied and the game is good enough that you <em>want </em>to keep going. So, even as I make the point that the value of content is dropping and that content has become a raw material, you have to have GOOD raw material to build a product on top of it. Weak content has no value as a product <em>or </em>a resource.</p>
<p>But I don&#8217;t think these events define the future of the industry. I personally do not like the F2P model in most cases. While I enjoy TripleTown, RotMG, League of Legends and other F2P games, they have gotten a minimum of cash from me (maybe $1). I paid the game price for SWTOR and the monthly fee to play. I also bought Skyrim and often buy indie games on Steam. I like to pay up front or at least know the fixed cost of a media experience. <a title="Indie City: Steam for Indie Games!" href="http://www.indiecity.com" target="_blank">New indie markets</a> are springing up and <a title="Minecraft Creators" href="http://mojang.com/" target="_blank">some indies</a> are making it really big. Some people are content to stream music, pay for a service, and never actually own songs. I prefer to own my collection. Everybody has their own preference: mainstream markets, niche markets, F2P and other evolving models will coexist.</p>
<p>The point is that content creators need to understand the economics of the market. I think we all see and understand the <em>what </em>of the business models that rise around us but do we understand the <em>why </em>of it? Do we know which pie will give us the best exposure and the biggest slice? I discovered this the hard way when I worked hard on Whirlygig and realized that only close friends and fellow devs were really willing to purchase the game<strong>[3] </strong>and mostly out of the goodness of their hearts. The thing I still believe is core to any of these models: you have to create good content. Triple Town&#8217;s model wouldn&#8217;t work if the game didn&#8217;t really suck you in, gamers would hit the barrier and simply walk away. I personally hope to make Whirlygig better and integrate things that will keep people playing and maybe even find a way to make it financially worth it.</p>
<p>We content creators wear a lot of hats as we produce, market and deliver our content. It&#8217;s time to put on your economist hat and find the business model that will earn your shining content the revenue it deserves.</p>
<p>&nbsp;</p>
<p><strong>[1]</strong> I didn&#8217;t use the example of bras to be juvenile, I read about a Chinese factory that does nothing but create the metal rings used in bras in this <a title="Chinese Industrialization" href="http://ngm.nationalgeographic.com/2007/06/instant-cities/hessler-text/1" target="_blank">National Geo Article</a> and have found it fascinating every since.</p>
<p><strong>[2]</strong> Here&#8217;s why ad-supported games are not viable long term:</p>
<ol>
<li>Advertisers (usually brands or retailers) have a product to sell.</li>
<li>Advertisers will never spend more on ads than they make in sales and prefer that cost to be a predictable ratio.</li>
<li>Thus Advertisers prefer to pay for revenue-share on sales (exactly predictable) or clicks (fairly predictable)</li>
<li>Since the Advertiser drives the market they only buy impressions at high volume, for low cost.</li>
<li>New ad markets usually subsidize the impression payouts to get Publishers (developers, website owners, etc) to integrate their ads and have big enough impression blocks to drive deals with Advertisers.</li>
<li>Once the market matures, the Ad Market and Advertisers can forecast sales driven by impressions and stable prices are negotiated</li>
<li>Now that the Ad Market has predictable income they relax the payout subsidies and ad payouts drop for Publishers</li>
<li>The Publisher payout starts as a percentage of the Net Sales price of the Advertiser&#8217;s product and gets further cut by the Ad Market&#8217;s take</li>
</ol>
<p>So, armed with the above knowledge, think about how likely that in-game ad is to actually drive a sale of an Advertiser&#8217;s product. Not likely. Eventually Advertisers will pull out of in-game marketing unless it either drives sales hard or gets really, really cheap. I have purchased ads as an Advertiser long enough to see this happen in several new web markets and I don&#8217;t think mobile will be any different.</p>
<p><strong>[3]</strong> Note that Whirlygig doesn&#8217;t have a trial mode, which probably would have greatly increased the number of purchases. That being said, my research for the Houston talk drove home the point that the conversion rate (conversion rate = purchases / trials) for games is much, much lower than the conversion rates that online retailers and other businesses enjoy. All of the research I have done indicates that it&#8217;s easier to get someone to pay a dollar for a cup of coffee than for an app.</p>
]]></content:encoded>
			<wfw:commentRss>http://syndicatex.com/philosophy/digital-economics/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

