<?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>zero point nine &#187; tutorial</title>
	<atom:link href="http://www.zeropointnine.com/blog/category/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zeropointnine.com/blog</link>
	<description>lee felarca - personal work and findings</description>
	<lastBuildDate>Fri, 04 Nov 2011 13:19:35 +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>An SEO implementation for Flash</title>
		<link>http://www.zeropointnine.com/blog/an-seo-implementation-for-flash/</link>
		<comments>http://www.zeropointnine.com/blog/an-seo-implementation-for-flash/#comments</comments>
		<pubDate>Thu, 23 Apr 2009 15:37:28 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[sourcecode]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=299</guid>
		<description><![CDATA[I recently added SEO to my current (Flash-based) portfolio site, which I did as an experiment more than for any particular use value. You can navigate the HTML &#8216;back-end&#8217; pages starting from here, if interested. I figured I should jot down my findings on how it can be done, for the record. I. Client Side [...]]]></description>
			<content:encoded><![CDATA[<p>I recently added SEO to my current (Flash-based) <a href="http://portfolio2008.felar.ca" target="_blank">portfolio site</a>, which I did as an experiment more than for any particular use value. You can navigate the HTML &#8216;back-end&#8217; pages starting <a href="http://portfolio2008.felar.ca/?noflash=true" target="_blank">from here</a>, if interested. I figured I should jot down my findings on how it can be done, for the record.</p>
<p><b>I. Client Side</b></p>
<p>On the Flash end, two requirements:</p>
<div class="paragraph1">
<div class="imageright"><a href="http://portfolio2008.felar.ca/#/work/evb/stives_elements/" target="_blank"><img src="/blog/assets/seo_flashpage_t.jpg" border="0" /></a>
<div class="altlink">Original page view, in Flash</div>
<div class="altlink"><a href="http://portfolio2008.felar.ca/work/evb/stives_elements/" target="_blank"><img src="/blog/assets/seo_htmlpage_t.jpg" vspace="4" border="0" /></a><br/>SEO-friendly HTML page, drawing on the same data</div>
</div>
</div>
<p><b>(A)</b> Your site must implement deeplinking, presumably using <a href="http://www.asual.com/swfaddress/" target="_blank">SWFAddress</a>, such that every page view has its own URL path. And your shell class must be intelligent enough to go directly to any given deeplinkable page view on startup via the URL deeplink.</p>
<p>(<i>Sidenote:</i> While not strictly necessary from an SEO standpoint, having gone that far, you&#8217;ll probably want all changes to the page view to be driven by the SWFAddress URL-change event, rather than directly by user events like mouse clicks, etc. Which will force you to throw your familiar, tried-and-true coding patterns out the window. And potentially, your laptop thereafter. But is beyond the scope of this entry. ;)</p>
<p><b>(B)</b> Your site should use an external data source that describes the site structure and contains the site&#8217;s text content, as well as, typically, image and/or video URL&#8217;s and the like. Usually, this would be a well structured, static XML file whose node structure corresponds to the site&#8217;s actual page structure. The deeplink &#8216;crumbs&#8217; should be included therein as well &#8211; as an attribute of each node, for example. (Extra points for using a database or a CMS instead). And it goes without saying that your Flash should be building its site structure, nav, and page content dynamically using all of the above.</p>
<p><span id="more-299"></span></p>
<p><br/><b>II. Server Side</b></p>
<p>On the server side, nothing too fancy. You want to create a script that parses the XML tree, constructs and writes out an HTML file for every deeplinked page in your site. You&#8217;ll run the script every time you make changes to the data, or create a chron job. So in the end, there&#8217;s nothing very &#8216;dynamic&#8217; happening on the back end, just using a script to create static HTML files from a static XML file. (* Extra points for using XSL to magically transform your XML into ready-to-use HTML pages, but since XSL makes my head hurt, I just procedurally concatenated lots and lots of HTML tags together to form one big string&#8230;)</p>
<p>The directory path for each generated &#8220;index.html&#8221; page should correspond to the deeplink used in your Flash (everything after the hash mark). So if you have a page whose URL is:</p>
<div style="margin-left:30px;font-size:11px;">     http://www.mylanguishingportfoliosite.com/#/work/2009/frivolous_viral_microsite/</div>
<p>- your script should create a corresponding HTML page whose filename is</p>
<div style="margin-left:30px;font-size:11px;">     [web root]/work/2009/frivolous_viral_microsite/index.html</div>
<p>Each HTML page should include all the text content for a given page view, since SEO is our goal, after all. Hopefully, you have a page title attribute on your XML nodes that you can leverage as well. Maybe you want to add some keyword metadata in there, too.</p>
<p>The last thing you want to do is have each of your generated html pages auto-redirect to its Flash equivalent using Javascript, or at least display a prominent link for the user to do it for themselves (Ie, strip &#8220;index.html&#8221; off the end of the URL and insert &#8220;/#&#8221; after the domain name). Personally, I chose to do the latter, since I took the trouble to create HTML that could stand &#8216;on its own&#8217;, without the Flash, if necessary. Your pages should link to each other as well; otherwise, the web crawlers may not have a way to get to them all.</p>
<p>So, here&#8217;s the <a href="/blog/assets_code/html_page_generator.php_.txt" target="_blank">PHP script</a> I wrote for my site which may help concretize the procedure described above. And the <a href="http://portfolio2008.felar.ca/assets/content.xml" target="_blank">XML file</a> for your reference, used by both the the Flash and the PHP based on their respective agendas. And for the hell of it, my <a href="http://www.google.com/search?q=hellogoogle666&#038;filter=0" target="_blank">magic keyword</a>, inserted into the HTML to easily verify if/when they were becoming visible to Google. xD</p>
<p class="creacom">Licensed under a <a href="http://creativecommons.org/licenses/by/3.0/" rel="license" target="_blank">Creative Commons Attribution 3.0 License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/an-seo-implementation-for-flash/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Using AMF3 for the cool shit</title>
		<link>http://www.zeropointnine.com/blog/using-amf3-for-the-cool-shit/</link>
		<comments>http://www.zeropointnine.com/blog/using-amf3-for-the-cool-shit/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 06:13:14 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[sourcecode]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=33</guid>
		<description><![CDATA[(A more descriptive but less catchy title would&#8217;ve been &#8220;Serializing and deserializing value objects with ByteArrays using AMFPHP, PHP, and MySQL.&#8221; But that&#8217;s ok.) As we are now in the year 2009, for some reason you feel like there ought to be a way to take your cool shit, send it over the wire and [...]]]></description>
			<content:encoded><![CDATA[<p><small><strong>(A more descriptive but less catchy title would&#8217;ve been &#8220;Serializing and deserializing value objects with ByteArrays using AMFPHP, PHP, and MySQL.&#8221; But that&#8217;s ok.)</strong></small></p>
<p>As we are now in the year 2009, for some reason you feel like there ought to be a way to take your cool shit, send it over the wire and get it back again, without having to resort to 99 searches on Google, a trip to Barnes &#038; Noble for a stack of books with ugly green covers and stupid illustrations of birds and salamanders, and a spare weekend you&#8217;d be doing nothing better with anyway. Your cool shit&#8217;s in Flash, most likely, and it&#8217;s not just text data, presumably, so by a process of elimination we conclude that your shit &#8212; not of a lukewarm nature by any means &#8212; is most appropriately represented by a series of ones and zeros &#8212; in binary format. And that you want to get it on the database. &#8216;Cuz you can&#8217;t create the next viral sensation if you can&#8217;t get your cool shit to the database, now can you?</p>
<p>And while many prosaic and generally annoying 3-to-4-letter acronyms exist for the transmission of information across the proverbial &#8216;series of tubes,&#8217; unfortunately, most of them are founded on that most old school of information encoding conventions: the alphabet. (But if it&#8217;s in UTF format, maybe we can be a little more forgiving and call it &#8220;Alphabet 2.0&#8243;). Sure, you could do something like <code>MyCoolAssStaticUtilitiesClass.convertMyCoolShitToBase64($o:Object)</code>, but nah, fuckit, it&#8217;s the year 2009 damnit, and you&#8217;d think there&#8217;d be an easy way to take your data &#8211; made on a computer &#8211; and store it &#8211; again, on another computer, without having to first convert it into &#8220;human-readable text,&#8221; whatever the fuck that means.</p>
<p>Furthermore, if your shit&#8217;s actually as cool as you say it is, we must be talking about something that&#8217;s not just a single block of binary data like an bitmap, oh no, but a complex data object, full of mixed primitive types, maybe some untyped objects and an array or two, other value objects nested inside of them, and _then_ maybe an image or two. But the main thing is, it&#8217;s stuff that you want to just dump into a field in a database record, and get back, without the extra drama of converting to and from XML with a couple extra hundred lines of code&#8230;</p>
<p>Anyway, presented here are the important points I learned about using AMFPHP with ByteArrays and VO&#8217;s while starting on a new project/experiment thing involving user-generated character animations of 3D models, which naturally involves lots of binary data and complex data types.</p>
<div style="color:#cc0000; font-size:10px; text-align:right;"><b>:P</b></div>
<p><span id="more-33"></span><br />
<img src="/blog/assets_main/bullet.gif" alt="Bullet" /> <strong style="font-size:14px;">Part 1: Moving binary data between Flash and the database</strong></p>
<p>So I&#8217;ve drawn up a kind-of minimal example where some simple images are generated and saved to the database as binary. You can get the full project for both the Part 1 and Part 2 examples <a href="/blog/assets_code/amfphpBinaryExamples.zip">here</a>. It&#8217;s written in as flat and as non-object-oriented a manner as possible for your (my) convenience. The two important files to look at for Part 1 are <a href="/blog/assets_code/AmfphpBinaryExample.as.txt" target="_blank">&#8220;AmfphpBinaryExample.as&#8221;</a> and <a href="/blog/assets_code/BaseService.php.htm" target="_blank">&#8220;BaseService.php&#8221;</a>.</p>
<div style="float:right; margin-left:15px;border:1px solid #000;">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="290" height="365" id="example1" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value=""/blog/assets/amfphpBinaryExamples/AmfphpBinaryExample.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="/blog/assets/amfphpBinaryExamples/AmfphpBinaryExample.swf" quality="high" bgcolor="#ffffff" width="290" height="365" name="example1" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /><br />
</object>
</div>
<p>This won&#8217;t be a literal step-by-step recipe, so use your working knowledge of the following to fill in the blanks: AS3, the AMFPHP Flash class package (v1.9 or whatever it ended up at), basic PHP5 using classes, and MySQL (tech stack of champions).</p>
<p><strong>AMFPHP setup</strong></p>
<p>First, a small point: After unzipping an undespoiled version of <a href="http://sourceforge.net/project/showfiles.php?group_id=72483&#038;package_id=72363" target="_blank">AMFPHP</a> to your project/server environment, <em>please</em> rename the file &#8220;.htaccess&#8221; in the unzipped &#8220;amfphp&#8221; directory to like &#8220;.htaccess_EXAMPLE&#8221;. If you don&#8217;t, it can make the directory inaccessible on Apache (20 minutes of my life I&#8217;ll never get back).</p>
<p>AMFPHP&#8217;s &#8216;encoding&#8217; property must be set to AMF3 for binary data to get properly sent to the Flash. Set <code>$amfphp['encoding']</code> to <code>'amf3'</code> in the file &#8220;amfphp/core/shared/app/Globals.php&#8221;, or in the file &#8220;amfphp/gateway.php&#8221; after the line <code>include "core/amf/app/Gateway.php";</code>.</p>
<p><strong>MySQL table setup</strong></p>
<p>Create a table and add an &#8220;id&#8221; field that auto-increments as the primary key, as is customary. Also add a field in that table named &#8220;image&#8221;. This is where our binary image data will go.</p>
<p>Most importantly, the data type for your binary field should be a blob, say, <code>MEDIUMBLOB</code> (which can have a maximum size of 16mb).</p>
<p>If you&#8217;re setting up the example project, use a SQL statement like this to set up your table if you&#8217;re so inclined:</p>
<pre><code>	CREATE TABLE `[mydatabase]`.`binaryexample` (
		`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
		`data` MEDIUMBLOB NOT NULL
	)
</code></pre>
<p><strong>PHP service classes</strong></p>
<p>When sending ByteArray to a PHP method, it comes in as on object with a property called &#8220;data&#8221;, as it turns out. So if you do something like &#8211;</p>
<pre><code>     netConnection.call("MyService.saveData", myResponder, myByteArray);</code></pre>
<p>&#8211; and your PHP function looks like  &#8211;</p>
<pre><code>     function saveData($argument) { ... }</code></pre>
<p>&#8211; you&#8217;d reference the binary data not with &#8220;<code>$argument</code>&#8220;, but &#8220;<code>$argument->data</code>&#8220;. Argh.</p>
<p>Once you have your variable with binary data in the PHP, before going to the database, you must use &#8220;mysql_real_escape_string&#8221; it first:</p>
<pre>     <code>$binaryData = mysql_real_escape_string($binaryData);</code></pre>
<p>If you&#8217;re savvy with PHP/MySQL, you already do this as a matter of course, but if you&#8217;re just a dabbler, like me, you may not know to. If you don&#8217;t, your SQL operation will probably fail and worse, leaves an easy opening for the hacking of your database.</p>
<p>Finally, when you send the binary data back to the Flash, you have to put it in a ByteArray object:</p>
<pre>     <code>return new ByteArray($myBinaryData);</code></pre>
<p><strong>AS3 setup</strong></p>
<p>In AS3, AMF3 is the default encoding format for Flash remoting, but you might want to do this just to make your intentions explicit:</p>
<pre>     <code>NetConnection.defaultObjectEncoding = ObjectEncoding.AMF3;</code></pre>
<p>At this point, sending your binary shiz back and forth from Flash to PHP to the database and back&#8230; should just work. Hah!<br />
<br/><br />
<img src="/blog/assets_main/bullet.gif" alt="Bullet" /> <strong style="font-size:14px;">Part II: Converting value objects to and from ByteArrays for database storage</strong></p>
<div style="float:right; margin-left:15px;border:1px solid #000;">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="290" height="565" id="example2" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value=""/blog/assets/amfphpBinaryExamples/AmfphpVoBinaryExample.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="/blog/assets/amfphpBinaryExamples/AmfphpVoBinaryExample.swf" quality="high" bgcolor="#ffffff" width="290" height="565" name="example2" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /><br />
</object>
</div>
<p>In this example, the user manually draws on the screen to create a picture, but rather than save the end product as a static image, we&#8217;re saving each &#8216;stroke&#8217; in order to play back the entire process in a procedural fashion a la <a href="http://www.roxik.com/pictaps/" target="_blank">Pictaps</a>. (The main AS source file to look at is &#8220;<a href="/blog/assets_code/AmfphpVoBinaryExample.as.txt" target="_blank">AmfphpVoBinaryExample.as</a>&#8220;; the PHP service class is the same as in Part 1.)</p>
<p>This kind of &#8216;use case&#8217; gives us an excuse to have to create a more complex data model than that of a bitmap or a WAV file, which can be treated as just a monolithic block of binary data. A conventional approach to this scenario might be to create an XML file like this:
<pre style="font-size:11px;"><code>
&lt;canvas&gt;
  &lt;stroke fromX="5" fromY="4"
    toX="6" toY="8" timecode="1"
    thickness="2" color="#ff0000" /&gt;
  &lt;stroke ... /&gt;
  &lt;stroke ... /&gt;
  etc.
&lt;/canvas&gt;
</code></pre>
<p>Instead, we&#8217;re gonna convert our data objects to ByteArray&#8217;s for storage, and coming back, convert the ByteArrays back to ready-to-use instances of our custom classes. Thanks to AMF, this gets done with basically one line of code.</p>
<p><strong>Creating the AS3 data classes</strong></p>
<p>But first, let&#8217;s explain the AS data structures used here. In this case, it makes sense to make a class called &#8220;Stroke&#8221;, or &#8220;StrokeVO&#8221;, if you will, which represents a line segment as drawn by the user, with the necessary variables for describing its properties:</p>
<pre><code>
     package vos {
          public class Stroke {
               public var startX:Number;
               public var startY:Number;
               public var endX:Number;
               public var endY:Number;
               public var color:uint;
               // etc.
          }
     }
</code></pre>
<p>The whole series of strokes will constitute a <code>Canvas</code>:</p>
<pre><code>     package vos {
          public class Canvas {
               public var strokes:Array;
               // etc.
          }
     }
</code></pre>
<p>Note, you might also add properties that are Strings, anonymous Objects, ByteArrays, etc., as well.</p>
<p><strong>Converting classes to/from ByteArray</strong></p>
<p>So let&#8217;s say the user has created their drawing, and it&#8217;s ready to be sent to the server. It&#8217;ll be just a matter of:</p>
<pre><code>
     var byteArray:ByteArray = new ByteArray();
     byteArray.writeObject(canvas);
</code></pre>
<p>Going in the other direction, it looks like this:</p>
<pre><code>     canvas = byteArray.readObject() as Canvas;</code></pre>
<p>The last critical piece of business is to register the class alias for each of the custom classes used for our data objects. Otherwise, Flash won&#8217;t know how to properly cast the anonymous Object created from the ByteArray.</p>
<pre><code>     registerClassAlias( "vos.Canvas", Canvas );
     registerClassAlias( "vos.Stroke", Stroke );</pre>
<p></code></p>
<p>Oh yeah, if you're setting up this example for yourself, the database table is identical to the last one except for the table name:</p>
<pre><code>     CREATE TABLE `[mydatabase]`.`vobinaryexample` (
          `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
          `data` MEDIUMBLOB NOT NULL
     )</code></pre>
<p><strong>Limitations</strong></p>
<p>There are some pretty important limitations to this system in terms of deserialization. One is that your custom classes to be deserialized can't use references to other objects. That just doesn't work. Another, unfortunately, is that the constructors can't take arguments. This throws errors when you do "ByteArray.readObject()".   Also, apparently, implicit getter/setters can introduce subtle or not-so-subtle side-effects when the setters do anything other than just store a value.</p>
<p>So in other words, your VO classes should be designed to be just that -- VO's: Strongly typed data structures storing values, or containing subobjects or sub-sub-objects that ultimately do the same, with minimal or no built-in functionality of their own. But oh well.<br />
<br/><br />
<img src="/blog/assets_main/bullet.gif" alt="Bullet" /> <strong style="font-size:14px;">Part III: 'Class mapping', plus, a convenient service wrapper class</strong></p>
<p>Finally, there's the issue of sending VO's from PHP to Flash, while having both PHP and Flash recognize the VO class for what it is. For this to work, you need to have matching class definitions for the VO in AS and PHP.</p>
<p>In this last example is my very own service 'wrapper' class for making remoting calls from Flash to PHP. It abstracts out NetConnection, Responder, and the "onResult"/"onFail" handler mechanics, making it easy to use. Here is the <a href="/blog/assets_code/RemotingService.zip">source</a>.</p>
<p>In any case, in its Netconnection response handler, this class expects a VO from PHP called 'RemotingVO', which contains the 'payload' and any error information. A VO with the same name and the same properties exists on the Flash end. For this to work requires two steps:</p>
<p>(1) You have to "registerClassAlias" on the Flash side, as discussed earlier:</p>
<pre><code>     registerClassAlias("leelib.remoting.RemotingVo", RemotingVo);</code></pre>
<p>(2) You have to add a line like this in your AMFPHP VO class:</p>
<pre><code>     var $_explicitType="leelib.remoting.RemotingVo";</code></pre>
<p>Anyway, I get this info from <a href="http://www.joshuaostrom.com/2008/07/01/amfphp-class-mapping-primer-19-beta/" target="_new">this blog post</a>, which does a much better job of explaining it than I'm doing now.</p>
<p>So now I'm done. That's everything I know about using AMFPHP. Too bad at my job, we use .NET on the backend, LOL.</p>
<p class="creacom">Licensed under a <a href="http://creativecommons.org/licenses/by/3.0/" rel="license" target="_blank">Creative Commons Attribution 3.0 License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/using-amf3-for-the-cool-shit/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Personal wiki of developer notes</title>
		<link>http://www.zeropointnine.com/blog/personal-wiki-of-developer-notes/</link>
		<comments>http://www.zeropointnine.com/blog/personal-wiki-of-developer-notes/#comments</comments>
		<pubDate>Thu, 01 May 2008 05:58:38 +0000</pubDate>
		<dc:creator>Lee</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[other]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.zeropointnine.com/blog/?p=25</guid>
		<description><![CDATA[Kind-of just for the hell of it as much as for any potential use value, I&#8217;ve converted all my notes related to programming, Flash, etc. &#8211; which used to live in various text files as various versions on various computers &#8211; into a wiki format. And have made it publicly viewable. Because, I figure, why [...]]]></description>
			<content:encoded><![CDATA[<p>Kind-of just for the hell of it as much as for any potential use value, I&#8217;ve converted all my notes related to programming, Flash, etc. &#8211; which used to live in various text files as various versions on various computers &#8211; into a wiki format. And have made it publicly viewable. Because, I figure, why not?</p>
<div style="padding:10px 0 10px 45px; font-weight:bold;"><a href="http://wiki.zeropointnine.com">http://wiki.zeropointnine.com</a></div>
<p>Much thanks to <a href="http://www.undefinedcreations.com/" target="_new">Adam Smith</a> for the idea. Have fun in L.A.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zeropointnine.com/blog/personal-wiki-of-developer-notes/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

