tag:blogger.com,1999:blog-37533300820138886192024-03-13T19:02:42.817+00:00The ActActionscript, maths and game designJohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.comBlogger114125tag:blogger.com,1999:blog-3753330082013888619.post-56555651608168619782012-05-21T03:46:00.000+01:002012-05-21T03:46:07.041+01:00New shader, new screenshots<span style="font-family: 'Trebuchet MS', sans-serif;">Not got much done this week for family reasons, but the things I did do are rather visual so easy to show off. First I changed the width and height of the game, to 640 x 480. This is not as that will be the final size (though having it non-square does make the gameplay a little more interesting), but more so I could track down any dependencies on the screen size that shouldn't be there. I want to be able to change two numbers and everything updates.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The other thing I did was write a new shader, actually a combination of two others, that desaturates and blurs the game, to be used for a 'fade out when paused' effect. It's a first pass at it so could be tweaked, or have more parameters exposed, if necessary.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-m-_Vo9HCu84/T7mr7QuRXvI/AAAAAAAAARE/IePwStRgAJ8/s1600/Screen+shot+2012-05-21+at+01.29.07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://2.bp.blogspot.com/-m-_Vo9HCu84/T7mr7QuRXvI/AAAAAAAAARE/IePwStRgAJ8/s320/Screen+shot+2012-05-21+at+01.29.07.png" width="320" /></a></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">As always static images don't really do it justice but the combination of it and the new (but probably temporary) aspect ratio mean they looks very different from previous screenshots.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-sEESPVHAd7s/T7mr8k3hBdI/AAAAAAAAARM/qFxO67EyOSA/s1600/Screen+shot+2012-05-21+at+01.48.14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://1.bp.blogspot.com/-sEESPVHAd7s/T7mr8k3hBdI/AAAAAAAAARM/qFxO67EyOSA/s320/Screen+shot+2012-05-21+at+01.48.14.png" width="320" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com1tag:blogger.com,1999:blog-3753330082013888619.post-37221125006106330372012-05-14T19:06:00.000+01:002012-05-14T19:06:18.230+01:00Angle between two 3D vectors<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This is something I noticed the other day. Someone had posted a method for finding the angle between two vectors in three dimensions, using the dot product and inverse cosine. But there is better approach, i.e. one that is generally more efficient, is certainly more accurate for some vectors, and can be more informative.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">That usual method looks something like this.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span style="color: #0b5394;">function</span> AngleBetweenTwoVectors(vA:Vec3D, vB:Vec3D):<span style="color: #0b5394;">Number</span> {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">var</span> fDot:<span style="color: #0b5394;">Number</span>, fA:<span style="color: #0b5394;">Number</span>, fB:<span style="color: #0b5394;">Number</span>;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fA = <span style="color: #76a5af;">Math</span>.</span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">sqrt</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(vA.x * vA.x + vA.y * vA.y + vA.z + vA.z);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fB = </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Math</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.</span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">sqrt</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">(vB.x * vB.x + vB.y * vB.y + vB.z + vB.z);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fDot = vA.x * vB.x + vA.y * vB.y + vA.z + vB.z;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> return </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Math</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.<span style="color: #76a5af;">acos</span>(fDot / (fA * fB));</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">It assumes the vectors are non-zero and uses ActionScript </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Math</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> functions where necessary. </span><span style="font-family: 'Trebuchet MS', sans-serif;">It is based on the definition of the </span><a href="http://en.wikipedia.org/wiki/Dot_product" style="font-family: 'Trebuchet MS', sans-serif;">dot product</a><span style="font-family: 'Trebuchet MS', sans-serif;">:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-UhmgcirjSMU/T7EckxmmjNI/AAAAAAAAAQ0/uYYBrqh88Gc/s1600/a_dot_b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-UhmgcirjSMU/T7EckxmmjNI/AAAAAAAAAQ0/uYYBrqh88Gc/s1600/a_dot_b.png" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">It has two problems. Although compact it involves a lot of calculation, of the dot product and two square roots for two </span><a href="http://en.wikipedia.org/wiki/Vector_norm" style="font-family: 'Trebuchet MS', sans-serif;">vector norm</a><span style="font-family: 'Trebuchet MS', sans-serif;">s. And the inverse cosine although usually accurate is not well behaved for small angles: it becomes less accurate the smaller the angle, and can fail with an out of bounds error if the vectors are parallel and rounding errors cause the fraction </span><span style="font-family: 'Courier New', Courier, monospace;">fDot / (fA * fB)</span><span style="font-family: 'Trebuchet MS', sans-serif;"> to be greater than +1 or less than -1.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Instead the following can be used.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">function AngleBetweenTwoVectors(vA:Vec3D, vB:Vec3D):<span style="color: #0b5394;">Number</span> {</span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">var</span> fCrossX:<span style="color: #0b5394;">Number</span>, fCrossY:<span style="color: #0b5394;">Number</span>, fCrossZ:<span style="color: #0b5394;">Number</span>,</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fCross:<span style="color: #0b5394;">Number</span>, fDot:<span style="color: #0b5394;">Number</span>;</span></div>
<span style="font-family: 'Courier New', Courier, monospace;"> fCrossX = vA.y * vB.z - vA.z * vB.y;</span><br />
<div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fCrossY = vA.z * vB.x - vA.x * vB.z;</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fCrossZ = vA.x * vB.y - vA.y * vB.x;</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fCross = </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Math</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.<span style="color: #76a5af;">sqrt</span>(fCrossX * fCrossX +</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fCrossY * fCrossY + fCrossZ * fCrossZ);</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> fDot = vA.x * vB.x + vA.y * vB.y + vA.z + vB.z;</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> return </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Math</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.<span style="color: #76a5af;">atan2</span>(fCross, fDot);</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Although longer this has only one vector norm, not two. The other is replaced with a <a href="http://en.wikipedia.org/wiki/Cross_product">cross product</a> which can be quicker to calculate. It also avoids a division, instead passing both the dot product result and the cross product norm to </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">atan2</span><span style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Perhaps more importantly using </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">atan2</span><span style="font-family: 'Trebuchet MS', sans-serif;"> avoids the inaccuracies associated with </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">acos</span><span style="font-family: 'Trebuchet MS', sans-serif;">. In particular it does not fail due to rounding errors, so additional bounds checking or error catching code is not needed (or your app won't crash once a week deep in maths/physics code with an impossible to reproduce bug). And d</span><span style="font-family: 'Trebuchet MS', sans-serif;">epending on the <a href="http://www.blogger.com/goog_1389447898">precise </a></span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;"><a href="http://www.blogger.com/goog_1389447898">atan2</a></span><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://en.wikipedia.org/wiki/Atan2"> implementation</a> it should handle zero vectors better, returning a value instead of triggering a divide by zero exception.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">It can also be used to produce more information about the rotation, because of the nature of </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">atan2</span><span style="font-family: 'Trebuchet MS', sans-serif;">. If the positive norm </span><span style="font-family: 'Courier New', Courier, monospace;">fCross</span><span style="font-family: 'Trebuchet MS', sans-serif;"> is replaced with a signed value then the result is a signed angle, the sign of which indicates the direction of rotation.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">How this is done depends on the application but it is often obvious from the context. For example if there is a definite up direction then the cross product is positive or negative depending whether it faces up or down, corresponding to e.g. clockwise and anti-clockwise rotations in the horizontal plane.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Often the cross product may already be calculated, or be needed for some later calculation. For example the axis of rotation is obtained from the cross product by scaling it by the calculated norm.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">And this method generalises easily to dimensions other than three. In two dimensions the cross product is replaced with the <a href="http://johnblackburne.blogspot.co.uk/2012/02/perp-dot-product.html">perp dot product</a>, so no norm is needed. In higher dimensions the <a href="http://en.wikipedia.org/wiki/Bivector">bivector</a> valued <a href="http://en.wikipedia.org/wiki/Exterior_product">exterior product</a> can be used.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
</div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com3tag:blogger.com,1999:blog-3753330082013888619.post-79406929384209104022012-05-11T23:49:00.003+01:002012-05-11T23:49:46.246+01:00Another Pixel Bender bug<span style="font-family: 'Trebuchet MS', sans-serif;">For those interested I've created a test app to demonstrate a Pixel Bender bug (or at least a very strange behaviour) I encountered this week:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://wonderfl.net/c/dLHH">http://wonderfl.net/c/dLHH</a></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">And started a thread on Adobe's forums about it:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://forums.adobe.com/thread/1003124">http://forums.adobe.com/thread/1003124</a></span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-68281673647776430302012-05-11T22:28:00.000+01:002012-05-11T22:28:15.745+01:00Two more screenshots<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I took a bit of a break this week for the bank holiday, but otherwise have kept working on the game. The front end is in, though not working, and I've been adding code to handle starting and restarting the game without it falling over or running out of memory.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Mostly though I've been working on graphics, trying to fix a glitch in the way the gradient shaded circles are drawn. This was a subtle glitch in game but rather more obvious in the front end so it was time to fix it.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I tried creating two new shaders for it but that didn't work as expected, because of some oddity in how Pixel Bender shaders handle alpha in Flash. So I decided used a different approach relying on an existing shader and some </span><span class="Apple-style-span" style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> API calls, especially </span><span class="Apple-style-span" style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">copyPixels</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">It was a subtle glitch, probably only visible to me as I knew it was there, but it's now hopefully fixed. The rendering code becomes a little more complex but it's not code that runs every frame or few frames; at most it runs a few times a game.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-tP2t8ZIMbNo/T62DzrIh3uI/AAAAAAAAAQg/UqfeJuKoKYw/s1600/Screen+shot+2012-05-11+at+22.07.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://4.bp.blogspot.com/-tP2t8ZIMbNo/T62DzrIh3uI/AAAAAAAAAQg/UqfeJuKoKYw/s200/Screen+shot+2012-05-11+at+22.07.42.png" width="200" /></a><a href="http://2.bp.blogspot.com/-T2KoLFs1tXs/T62D00yiMyI/AAAAAAAAAQo/--vwQN3afVA/s1600/Screen+shot+2012-05-11+at+22.10.03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://2.bp.blogspot.com/-T2KoLFs1tXs/T62D00yiMyI/AAAAAAAAAQo/--vwQN3afVA/s200/Screen+shot+2012-05-11+at+22.10.03.png" width="200" /></a></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-18365815816355072252012-05-04T22:30:00.000+01:002012-05-04T23:13:37.362+01:00Shader bug update<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I made another shader today. Nothing that interesting as it's a variation on one I'd done before, but as I added it I uncommented out a line in the game which I must have disabled while trying to fix <a href="http://johnblackburne.blogspot.co.uk/2012/04/pixel-bender-bug.html">the shader bug</a> two weeks ago. And the bug re-appeared. Thankfully as I knew it was a shader bug and knew the last change I'd done it was easy to undo, but it was surprising as I thought I'd fixed it in the shader code.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The change was uncommenting out the following line</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>gGradShader.<span class="Apple-style-span" style="color: #76a5af;">precisionHint</span> = <span class="Apple-style-span" style="color: #76a5af;">ShaderPrecision</span>.<span class="Apple-style-span" style="color: #76a5af;">FAST</span>;</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">where </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">gGradShader</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> is the shader. The </span><span class="Apple-style-span" style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">precisionHint</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> is supposed to trade precision for performance, but I've not noticed it making any difference to either. But as there's no discernible visual difference and I'm always after more performance I've been setting it to </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #76a5af;">ShaderPrecision</span>.<span class="Apple-style-span" style="color: #76a5af;">FAST</span></span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> by default.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Except doing so for this shader causes the game to lock up. Thankfully its used where performance isn't so much of an issue, so I can comment out that line without concern. I've added a note on this to the <a href="http://forums.adobe.com/message/4379728#4379728">bug report thread</a> on Adobe's forums, where it will hopefully be spotted by anyone else encountering a similar problem.</span><br />
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The new shader is a slight modification of the one I did two weeks ago. I could have added the functionality to that shader, controlled by a switch, but its more efficient to create a separate shader.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The shaders are tiny, less than 2,500 bytes for both of them, so there's hardly any overhead in adding both to the game. But more importantly it's much more efficient to branch outside the shader than inside it on code that runs 100,000+ times, once per pixel. For an example of how not to do it the twirl.pbk example that comes with PixelBender passes an int which is used as a Boolean to decide which falloff method to use. Better to create two shaders, at least for use in Flash Player.</span></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-23297336979922475302012-05-01T05:12:00.002+01:002012-05-01T05:12:33.854+01:00Two more screenshots<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Two more screenshots, showing two different levels, in the much improved inverted colour scheme. I still haven't decided how to use this, so am alternating between it and the normal, light lines on a dark background, mode to make sure it works as well and get some idea of how to fit it in. Currently they are the second and fourth levels; early levels which accounts for the simple colour schemes.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-EJ9A14x04ik/T59iFhNDLNI/AAAAAAAAAQM/O4UthVy6QlQ/s1600/Screen+shot+2012-05-01+at+04.00.56.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-EJ9A14x04ik/T59iFhNDLNI/AAAAAAAAAQM/O4UthVy6QlQ/s320/Screen+shot+2012-05-01+at+04.00.56.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-NzAtm85BbXg/T59iHcU-xnI/AAAAAAAAAQU/8IJZtbOBxhI/s1600/Screen+shot+2012-05-01+at+04.07.32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-NzAtm85BbXg/T59iHcU-xnI/AAAAAAAAAQU/8IJZtbOBxhI/s320/Screen+shot+2012-05-01+at+04.07.32.png" width="320" /></a></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-86076946648071990282012-04-23T19:10:00.000+01:002012-04-23T19:15:58.446+01:00Update, new screenshot<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I've been quiet on my game for a week (except for <a href="http://johnblackburne.blogspot.com/2012/04/circular-gradient-shader.html">discussing a shader</a> I made for it) but I've still been busy, on two main things. One is a graphical overhaul, involving the shader but also a new way of drawing filled rings and a lot of tweaks to make it work, which I finished last week.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">But then I ran into a problem. One benefit of procedural code is the ability to recolour things on the fly, producing a different look much more cheaply than recolouring sprites in a graphics package. I used this a little in <a href="http://johnblackburne.blogspot.co.uk/search/label/BugTunnelDefense">Bug Tunnel Defense</a> but this game is built from the ground up procedurally.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">But the way I coded it had one constraint: the background had to be dark because of the blends I'd used. And more than anything I could see the benefit of inverting the look, so it was on a light background, both because of the extreme contrast and because there are some effects that work best on a light background.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">So I had to refactor the code so it did't depend on blends that could only darken. I also wanted to do it without making the game slower, knowing I would have to draw some things twice but could remove some other draw commands.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-nQ3ZTlKLrbY/T5WaGtTmxpI/AAAAAAAAAQE/ENVMickcrX0/s1600/Screen+shot+2012-04-23+at+18.35.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-nQ3ZTlKLrbY/T5WaGtTmxpI/AAAAAAAAAQE/ENVMickcrX0/s320/Screen+shot+2012-04-23+at+18.35.04.png" width="320" /></a></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I think I've succeeded. There are still a few glitches which I'll have to track down and colours are all very preliminary without even a first pass at adjusting them. But it already looks totally different but looks like and plays like the same game. As a bonus <a href="http://johnblackburne.blogspot.com/2012/04/circular-gradient-shader.html">the shader</a> I made last week appears in a couple of places, though it looks about the most broken by the colour inversion.</span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-69185545643209444482012-04-19T23:21:00.000+01:002012-04-19T23:21:20.439+01:00Pixel Bender bug<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The <a href="http://johnblackburne.blogspot.co.uk/2012/04/circular-gradient-shader.html">circular gradient fill shader</a> I wrote yesterday took more time than expected as for a while it would not work: more specifically it worked fine in Pixel Bender Toolkit but not in Flash. And it failed in a particular way: on use it would instantly lock up rather than fail with an error or produce the wrong result.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Looking at the code the only thing fundamentally different in this shader from ones I'd written before was the extended conditional block that decided which quadrant the point is in and so which pair of colours were being interpolated. The key variable in this section was the </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">dir</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> variable, which was being read and updated. So I changed it so it was not being updated, replacing this use with the no longer needed </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">dir2</span><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">, and it worked.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I posted both versions of the shader code to the Pixel Bender forum</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://forums.adobe.com/message/4346479#4346479">http://forums.adobe.com/message/4346479#4346479</a></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">And it seems it is a bug in Flash's pixel bender implementation, though not one that will be fixed soon. At least it's a simple workaround. It's a bit surprising it's not been encountered before, but this shows perhaps how underused Pixel Bender shaders are in Flash.</span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-56102645613897250292012-04-18T23:39:00.000+01:002012-04-19T01:38:03.925+01:00Circular gradient shader<span style="font-family: 'Trebuchet MS', sans-serif;">This is something I started coding today before I realised it wasn't available in the BitmapData APIs: the gradient fill available comes in two varieties, linear and radial. But the latter is always based on the distance from the centre, never the bearing from the centre as I wanted. So I wrote a shader for it, to generate a result like this:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-9HUqUJZWKk8/T48-sd8htUI/AAAAAAAAAP0/laesyVs6BHQ/s1600/Screen+shot+2012-04-18+at+23.21.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="200" src="http://4.bp.blogspot.com/-9HUqUJZWKk8/T48-sd8htUI/AAAAAAAAAP0/laesyVs6BHQ/s200/Screen+shot+2012-04-18+at+23.21.16.png" width="200" /></span></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The shader is different from others I've written in that it has no image input, just a pixel output. The Pixel Bender Toolkit complains about this but it still works, at least as a Flash Player shader. It still has access to the coordinates of the pixel being drawn and any parameters passed in.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The full shader code is embedded in the Wonderfl example <a href="http://wonderfl.net/c/3nhD">here</a>, with the main evaluatePixel routine below:</span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><span style="color: #0b5394;">void</span> <span style="color: #93c47d;">evaluatePixel</span>()</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> // calculate where we are relative to the center</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float2</span> relativePos = <span style="color: #93c47d;">outCoord</span>() - center;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> // get our bearing relative to start angle, wrap it and scale to (-2, 2)</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float</span> dir = <span style="color: #93c47d;">atan</span>(relativePos.y, relativePos.x);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir = dir - startAngle;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float</span> dir2 = dir + TWOPI;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir = dir < -PI ? dir2 : dir;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir = dir * <span style="color: #cc0000;">4.0</span> / TWOPI;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> // get colours to interpolate between and how far to interpolate</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float3</span> colFrom, colTo;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">if</span> (dir < <span style="color: #cc0000;">0.0</span>) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">if</span> (dir < <span style="color: #cc0000;">-1.0</span>) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir2 = dir + <span style="color: #cc0000;">2.0</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colFrom = col1;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colTo = col2;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> } <span style="color: #0b5394;">else</span> {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir2 = dir + <span style="color: #cc0000;">1.0</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colFrom = col2;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colTo = col3;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> } <span style="color: #0b5394;">else</span> {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">if</span> (dir < <span style="color: #cc0000;">1.0</span>) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir2 = dir;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colFrom = col3;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colTo = col4;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> } <span style="color: #0b5394;">else</span> {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dir2 = dir - <span style="color: #cc0000;">1.0</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colFrom = col4;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> colTo = col1;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> // linearly interpolate</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float3</span> interp = <span style="color: #93c47d;">mix</span>(colFrom, colTo, float3(dir2, dir2, dir2));</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> // convert to smooth interpolation through colours</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> interp = colFrom + (colTo - colFrom) * <span style="color: #93c47d;">smoothStep</span>(colFrom, colTo, interp);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dst = <span style="color: #0b5394;">pixel4</span>(interp.x, interp.y, interp.z, <span style="color: #cc0000;">1.0</span>);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The interpolation is between four colours which are specified as parameters. To determine which two colours to use the bearing is normalised to a value between 0 and 4 and used to pick a quadrant. Obviously more or less colours could be used.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The interpolation is done in the last few lines. It first does a simple blend using the </span><span style="color: #93c47d; font-family: 'Courier New', Courier, monospace;">mix</span><span style="font-family: 'Trebuchet MS', sans-serif;"> function, then a uses the </span><span style="color: #93c47d; font-family: 'Courier New', Courier, monospace;">smoothStep</span><span style="font-family: 'Trebuchet MS', sans-serif;"> function to smooth the blend. If that line is commented out the interpolation still takes place but the colours look spikier:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-CPed_P2anok/T48-tlTBdyI/AAAAAAAAAP8/DaQaXN23m4g/s1600/Screen+shot+2012-04-18+at+23.21.39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="200" src="http://4.bp.blogspot.com/-CPed_P2anok/T48-tlTBdyI/AAAAAAAAAP8/DaQaXN23m4g/s200/Screen+shot+2012-04-18+at+23.21.39.png" width="200" /></span></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The other interesting property of the shader is that the colours are not clamped to between 0 and 1, and if values outside that range are passed in even more colours appear as colours interpolate at different rates. E.g. the following was generated with the colours white and black but with some colour values set to +2 and -1.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-pw6zs7GaB7o/T48-reaKA1I/AAAAAAAAAPs/rqUBQ6urSEg/s1600/Screen+shot+2012-04-18+at+23.14.40.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="200" src="http://3.bp.blogspot.com/-pw6zs7GaB7o/T48-reaKA1I/AAAAAAAAAPs/rqUBQ6urSEg/s200/Screen+shot+2012-04-18+at+23.14.40.png" width="200" /></span></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The colours can't be modified in the Wonderfl example (except by recompiling the shader) but everything else can by moving and clicking the mouse. It's available <a href="http://wonderfl.net/c/3nhD">here</a> and embedded below.</span><br />
<br />
<script src="http://wonderfl.net/blogparts/3nhD/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/3nhD" title="Shader fill, ff: Quaternion rotation shader">Shader fill, ff: Quaternion rotation shader - wonderfl build flash online</a></div>
<br />
<br />
<br />JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-52286001942020534042012-04-12T13:19:00.000+01:002012-04-13T16:44:39.455+01:00Quaternion rotation shader<span style="font-family: 'Trebuchet MS', sans-serif;">After <a href="http://johnblackburne.blogspot.com/2012/04/multiplying-two-vectors.html">writing yesterday's</a> post I wondered how easy it would be to use the mathematics in a shader. This would be a natural way to extend my <a href="http://johnblackburne.blogspot.com/2012/03/cross-product-shader.html">cross product shader</a>, replacing the simple product in that with a more general geometric product.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><span style="font-family: 'Trebuchet MS', sans-serif;">In practice in three dimensions this meant it would use a </span><a href="http://en.wikipedia.org/wiki/Quaternion" style="font-family: 'Trebuchet MS', sans-serif;">quaternion</a><span style="font-family: 'Trebuchet MS', sans-serif;"> product and rotation. The code is rather more extensive than the cross product shader but still very compact.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float4</span> col = <span style="color: #0b5394;">sampleNearest</span>(src, <span style="color: #0b5394;">outCoord</span>());</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float2</span> diff = center - <span style="color: #0b5394;">outCoord</span>();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float</span> angle = <span style="color: #0b5394;">length</span>(diff);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float</span> rec = <span style="color: red;">1.0</span> / angle;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> diff = diff * rec;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> angle = angle * <span style="color: red;">0.002</span> * magnitude;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float</span> myCos = <span style="color: #0b5394;">cos</span>(angle);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float</span> mySin = <span style="color: #0b5394;">sin</span>(angle);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float3</span> imag = <span style="color: #76a5af;">float3</span>(mySin * diff.x, mySin * diff.y, <span style="color: red;">0</span>);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float3</span> ortho = col.xyz;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> ortho = ortho * <span style="color: red;">2.0</span> - <span style="color: #76a5af;">float3</span>(<span style="color: red;">1.0</span>, <span style="color: red;">1.0</span>, <span style="color: red;">1.0</span>);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float3</span> myCross = <span style="color: #45818e;">cross</span>(ortho, imag);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float</span> myDot = <span style="color: #45818e;">dot</span>(ortho, imag);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float</span> qReal = -myDot;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float3</span> qImag = myCos * ortho + myCross;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> ortho = qReal * imag + myCos * qImag - <span style="color: #45818e;">cross</span>(imag, qImag);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> ortho = (ortho + <span style="color: #76a5af;">float3</span>(<span style="color: red;">1.0</span>, <span style="color: red;">1.0</span>, <span style="color: red;">1.0</span>)) * <span style="color: red;">0.5</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dst = <span style="color: #76a5af;">float4</span>(ortho.x, ortho.y, ortho.z, <span style="color: red;">1.0</span>);</span><br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">It calculates the rotation through an angle, which increases based on the distance from the centre of the effect, scaled by the input </span><span style="font-family: 'Courier New', Courier, monospace;">magnitude</span><span style="font-family: 'Trebuchet MS', sans-serif;">. Because it's calculated from an angle trigonometry is needed to generate the quaternion. The displacement from the centre also acts as the axis, so the effect varies based on the bearing from the centre.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">The quaternion in stored as two parts, </span><span style="font-family: 'Courier New', Courier, monospace;">myCos</span><span style="font-family: 'Trebuchet MS', sans-serif;"> (the 'real' part) and the </span><span style="color: #a2c4c9; font-family: 'Courier New', Courier, monospace;">float3</span><span style="font-family: 'Trebuchet MS', sans-serif;"> valued </span><span style="font-family: 'Courier New', Courier, monospace;">imag</span><span style="font-family: 'Trebuchet MS', sans-serif;">. This avoids a four-vector for performance reasons, so the code can use the shader language's vector functions and as the input and result 'quaternions' have no real parts. The actual product </span><span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i><b>x</b><i>R</i><sup>-1</sup></span><span style="font-family: 'Trebuchet MS', sans-serif;"> takes place in the block of five lines above the last two. </span><span style="font-family: 'Courier New', Courier, monospace;">qReal</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="font-family: 'Courier New', Courier, monospace;">qImag</span><span style="font-family: 'Trebuchet MS', sans-serif;"> are the parts of the intermediate quaternion after the first product is done.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The result is <a href="http://wonderfl.net/c/5ls1">here</a> and embedded below. As before I've copied the whole shader source into a comment at the end.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<script src="http://wonderfl.net/blogparts/5ls1/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/5ls1" title="Quaternion rotation shader">Quaternion rotation shader - wonderfl build flash online</a></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-60492109941584363142012-04-12T01:37:00.000+01:002012-04-12T01:45:45.481+01:00Multiplying two vectors<span style="font-family: 'Trebuchet MS', sans-serif;">In mathematics there are a number of ways to multiply two vectors. The most common is the <a href="http://en.wikipedia.org/wiki/Dot_product">dot product</a>, which works for any two vectors of the same size. In three dimensions there's the <a href="http://en.wikipedia.org/wiki/Cross_product">cross product</a>, while in two dimensions there's the <a href="http://johnblackburne.blogspot.co.uk/2012/02/perp-dot-product.html">perp dot product</a>, sort of equivalent to the cross product.</span><br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">But they all have the weakness that they are not invertible. Given the cross product</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-7ZVhF21KzNA/T4XEKmEHQhI/AAAAAAAAAOo/ixVQJinzJq4/s1600/crossproduct.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-7ZVhF21KzNA/T4XEKmEHQhI/AAAAAAAAAOo/ixVQJinzJq4/s1600/crossproduct.png" /></a></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">and knowing </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>c</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> and another vector it isn't possible to calculate the third vector (</span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>c</b> × <b>c</b> = 0</span><span style="font-family: 'Trebuchet MS', sans-serif;">, so given a solution all points on a line through this solution parallel to </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>c</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> are also solutions).</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">This is annoying because many other products are invertible. Not just scalar multiplication but products of general complex numbers, quaternions and matrices can all be inverted. But there is a product of two vectors that is invertible, the <b>geometric product</b> of <a href="http://en.wikipedia.org/wiki/Geometric_algebra">geometric algebra</a>.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">This is simply the sum of the <a href="http://en.wikipedia.org/wiki/Inner_product">inner product</a> and <a href="http://en.wikipedia.org/wiki/Exterior_product">outer products</a>, which are the dot product and cross products generalised to higher dimensions. Except the outer product is not a scalar or vector but a <a href="http://en.wikipedia.org/wiki/Bivector">bivector</a>, a quantity associated with area, or thought of as two-dimensional (distinct from one-dimensional vectors).</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">The details of this are too technical for a blog post (I would recommend the above links for details, especially the one to <a href="http://en.wikipedia.org/wiki/Bivector">bivector</a> which I had a part in writing), but there is one further property worth highlighting. The geometric product of a vector with itself is a scalar, equivalent to the dot product with itself, numerically equal to the square of its length.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">This means vector division is possible. As if a vector times itself is a scalar then to divide by a vector simply multiply by the vector then divide by the scalar. Or multiply by the vector scaled by it's length squared.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">I have avoided algebra so far as it would make the post far too long and technical, but it is worth doing so for the following practical example: g</span><span style="font-family: 'Trebuchet MS', sans-serif;">iven two vectors, </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>x</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> any </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>y</b></span><span style="font-family: 'Trebuchet MS', sans-serif;">, the question 'what must </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>x</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> be multiplied by to give </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>y</b></span><span style="font-family: 'Trebuchet MS', sans-serif;">?' is answered using division. In particular given the following product:</span></div>
<div>
<div style="text-align: center;">
<a href="http://3.bp.blogspot.com/-gidfuTEtIhA/T4YddEc5vmI/AAAAAAAAAO0/HbR4qrSOl3I/s1600/y=Rx.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="http://3.bp.blogspot.com/-gidfuTEtIhA/T4YddEc5vmI/AAAAAAAAAO0/HbR4qrSOl3I/s1600/y=Rx.png" /></a></div>
<br />
<span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i></span><span style="font-family: 'Trebuchet MS', sans-serif;"> can be calculated by multiplying by </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>x</b><sup>-1</sup></span><span style="font-family: 'Trebuchet MS', sans-serif;">, the multiplicative inverse of </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>x</b></span><span style="font-family: 'Trebuchet MS', sans-serif;">:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-Z-5J2BqlYOc/T4YddgfwFdI/AAAAAAAAAO8/b-aIJ80UHe4/s1600/yx=Rxx=R.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-Z-5J2BqlYOc/T4YddgfwFdI/AAAAAAAAAO8/b-aIJ80UHe4/s1600/yx=Rxx=R.png" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Which gives the value for </span><span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i></span><span style="font-family: 'Trebuchet MS', sans-serif;">:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-EtWW6bjhmDc/T4Ydc8OHX4I/AAAAAAAAAOw/4zWqmLMjPKw/s1600/R=yx=yx.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-EtWW6bjhmDc/T4Ydc8OHX4I/AAAAAAAAAOw/4zWqmLMjPKw/s1600/R=yx=yx.png" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">R is a <a href="http://en.wikipedia.org/wiki/Spinor">spinor</a> or <a href="http://en.wikipedia.org/wiki/Rotor_(mathematics)">rotor</a>, which acts on vectors and rotates them through multiplication. It rotates not only </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>x</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> to </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>y</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> but any vector in the plane containing </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>x</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>y</b></span><span style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In two dimensions there is only one plane so </span><span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i></span><span style="font-family: 'Trebuchet MS', sans-serif;"> rotates any vector in the same way so by the same amount. The quantity </span><span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i></span><span style="font-family: 'Trebuchet MS', sans-serif;"> is a <a href="http://johnblackburne.blogspot.co.uk/2012/01/complex-numbers.html">complex number</a> with real and imaginary parts, and can be calculated as follows:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">R.real = (x.fX * y.fX + x.fY * y.fY) / fLengthSquared;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">R.imag = (x.fY * y.fY - x.fX * y.fY) / fLengthSquared;</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">To multiply this by a vector, e.g. to rotate a vector </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>u</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> into vector </span><span style="font-family: Georgia, 'Times New Roman', serif;"><b>v</b></span><span style="font-family: 'Trebuchet MS', sans-serif;">, the following is used:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">v.fX = u.fX * R.real + u.fY * R.imag;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">v.fY = u.fY * R.real - u.fX * R.imag;</span><br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This can be done with complex numbers but the above is in some ways simpler: no need to deal with the conjugate when dividing. It also treats vectors (which square to positive values) and complex numbers (with positive and negative squares) as separate, distinct things which makes more mathematical sense.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This generalises to higher dimensions, with one difference. Because in dimensions higher than two rotations are non-commutative the above will not work. Instead the product used to rotate a vector is two sided, that is:</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://4.bp.blogspot.com/-_WzfIF3cU_Q/T4Yg_oE3RqI/AAAAAAAAAPI/gLX2K5AddOQ/s1600/y=RxR.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-_WzfIF3cU_Q/T4Yg_oE3RqI/AAAAAAAAAPI/gLX2K5AddOQ/s1600/y=RxR.png" /></a></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Where </span><span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i><sup>-1</sup></span><span style="font-family: 'Trebuchet MS', sans-serif;"> is the reversion or inverse of </span><span style="font-family: Georgia, 'Times New Roman', serif;"><i>R</i></span><span style="font-family: 'Trebuchet MS', sans-serif;">. In three dimensions this is </span><a href="http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation" style="font-family: 'Trebuchet MS', sans-serif;">quaternion rotation</a><span style="font-family: 'Trebuchet MS', sans-serif;">, but it is not limited to two and three dimensions.</span></div>
<br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-1918356990116345322012-04-08T01:53:00.000+01:002012-04-08T01:53:26.024+01:00Oops<span style="font-family: 'Trebuchet MS', sans-serif;">I've been working on the front end, which also means I've been deciding how many levels, what distinguishes them etc. It's very different from Bug Tunnel Defense where <a href="http://johnblackburne.blogspot.co.uk/2011/12/bug-tunnel-defense-levels.html">every level was designed individually</a>. Here the levels are mostly numbers. But at the same time I've been changing and adding things to make it easier to introduce elements progressively, and make for a more varied experience.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-MB6NYIxOidM/T4DgJD1ar6I/AAAAAAAAAOg/xa3ihZjDRN4/s1600/Screen+shot+2012-04-08+at+00.52.38.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="320" src="http://1.bp.blogspot.com/-MB6NYIxOidM/T4DgJD1ar6I/AAAAAAAAAOg/xa3ihZjDRN4/s320/Screen+shot+2012-04-08+at+00.52.38.png" width="320" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<span style="font-family: 'Trebuchet MS', sans-serif;">While testing some of these changes I generated the above screenshot, which is a really bad way to start a game (hence the title), but is also more aesthetically pleasing than the usual cluttered mess of the screenshots the game produces. It shows off some elements of the game much more clearly than usual, although they really need to be seen in motion to appreciate.</span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com1tag:blogger.com,1999:blog-3753330082013888619.post-41522297865305122642012-04-06T15:52:00.000+01:002012-04-06T17:19:12.752+01:00Shader vs. ActionScript revisited<span style="font-family: 'Trebuchet MS', sans-serif;">Last week I created <a href="http://johnblackburne.blogspot.co.uk/2012/03/cross-product-shader.html">a shader based on the cross product</a>. This was a simple experiment, done mostly as it was very straightforward: the shader code has only three lines of simple vector maths. But since I realised that it should be possible to recreate it using ActionScript, in particular using a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">ColorMatrixFilter</span><span style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The theory of this relies on one property of the cross product, that it can be <a href="http://en.wikipedia.org/wiki/Cross_product#Conversion_to_matrix_multiplication">replaced by a matrix multiplication</a>. The other operations in the shader scale and offset the vector, and are equivalent to scaling and translation matrix operations. So it should be possible to create a matrix that transforms a colour the same way as the shader does, and use a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">ColorMatrixFilter</span><span style="font-family: 'Trebuchet MS', sans-serif;"> to apply it.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">At least that is the theory. In practice it turned out to be much more work than I expected. The resulting code is <a href="http://wonderfl.net/c/o4sv">here on Wonderfl</a>, forked from the shader code, and is much longer and more complex than that. In particular:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Everything is now matrices, so the operations to scale and offset, previously single lines of mathematics, now require matrices to be created, scaled and translated (although at least this can be done beforehand).</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">I subclassed the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Matrix3D</span><span style="font-family: 'Trebuchet MS', sans-serif;"> class as recommended by the documentation to avoid it complaining about being passed non-invertable matrices (though I did this before I got it working so don't know if it's necessary).</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">It seems there's no way to pass the raw values to the <span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Matrix3D</span> constructor, or at least that seemed not to work. Instead I had to get the existing </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">rawData</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and modify it.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">More generally one problem Flash has is a profusion of ways of handling matrices. As well as </span><span style="color: #a2c4c9; font-family: 'Courier New', Courier, monospace;">Matrix</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and <span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Matrix3D</span> classes many functions that use matrices such as the <span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">ColorMatrixFilter</span> actually take a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Vector</span><span style="font-family: 'Trebuchet MS', sans-serif;"> or </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Array</span><span style="font-family: 'Trebuchet MS', sans-serif;"> of numbers, making the code very verbose.</span></li>
</ul>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">This, together with the need to synthesise the cross product with a matrix, makes the code much longer. And it doesn't work identically. Compared to the shader it is much darker, as the 50% grey that should be added back in by the final transformation seems to be missing.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">This is a fairly artificial example, as it's not only an impractical shader but it's one written to experiment with the mathematical operations of the shader language. It's not surprising that it was hard to code in ActionScript. It does show though what's possible with a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">ColorMatrixFilter</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and despite the length of the code it performs pretty well.</span></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-66256530332330899562012-04-04T13:54:00.000+01:002012-04-04T13:54:15.190+01:00Five new screenshots<span style="font-family: 'Trebuchet MS', sans-serif;">It's two weeks since I lasted posted any screenshots. Lots of changes since then, most of them graphical. All of the core gameplay is in now, although much needs to be done, not least a front-end.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-tzMCQaEaGW0/T3xDjT_SA-I/AAAAAAAAAOA/_6IBBRfRUF4/s1600/Screen+shot+2012-04-02+at+23.28.37.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://1.bp.blogspot.com/-tzMCQaEaGW0/T3xDjT_SA-I/AAAAAAAAAOA/_6IBBRfRUF4/s320/Screen+shot+2012-04-02+at+23.28.37.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-Qx_mWGEfOto/T3xDkbPsjkI/AAAAAAAAAOI/d_-mVcIm9kA/s1600/Screen+shot+2012-04-02+at+23.30.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-Qx_mWGEfOto/T3xDkbPsjkI/AAAAAAAAAOI/d_-mVcIm9kA/s320/Screen+shot+2012-04-02+at+23.30.02.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-GYs4f77oMqE/T3xDlpWUUfI/AAAAAAAAAOQ/-r_ssoHlTP0/s1600/Screen+shot+2012-04-03+at+00.06.20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/-GYs4f77oMqE/T3xDlpWUUfI/AAAAAAAAAOQ/-r_ssoHlTP0/s320/Screen+shot+2012-04-03+at+00.06.20.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-u6Kt0qqgsjI/T3xDnQTdeTI/AAAAAAAAAOY/pnIT75nExfA/s1600/Screen+shot+2012-04-03+at+04.01.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/-u6Kt0qqgsjI/T3xDnQTdeTI/AAAAAAAAAOY/pnIT75nExfA/s320/Screen+shot+2012-04-03+at+04.01.04.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-E9z3RdtuXXU/T3xDX50PEKI/AAAAAAAAAN4/ar-gHYCljwg/s1600/Screen+shot+2012-04-04+at+01.00.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-E9z3RdtuXXU/T3xDX50PEKI/AAAAAAAAAN4/ar-gHYCljwg/s320/Screen+shot+2012-04-04+at+01.00.42.png" width="320" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-24330091485183932382012-04-02T17:30:00.000+01:002012-04-02T17:30:19.273+01:00100th postAccording to Blogger I've written ninety-nine posts to date, making this the one-hundredth, a good point to look back and review my progress so far. All of the lists are in date order. These are based on the tags but not exactly so, and there's some overlap with some posts linked more than once, so they don't add up to ninety-nine.<br />
<br />
<a name='more'></a><br />
I should also mention <a href="http://wonderfl.net/user/John_Blackburne/codes">my codes on Wonderfl</a>; for more complex or extensive examples I would post them there then write about them in a post. In particular many of my shader posts and collision/dynamics posts have accompanying example there, so it serves as an index of some of my more substantial examples.<br />
<br />
Now I've reached this point I'll be easing back on the schedule of posting, no longer posting every day/five days a week. Posts may get more substantial as I stop posting just a screenshot and paragraph and have more to write on any one topic.<br />
<br />
<b>Bug Tunnel Defense;</b> on my last game, some re-posted from my last blog:<br />
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/bug-tunnel-defense.html">Bug Tunnel Defense</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/bug-tunnel-defense-information.html">Bug Tunnel Defense information</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/bug-tunnel-defense-tunnels.html">Bug Tunnel Defense: Tunnels</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/bug-tunnel-defense-first-screenshots.html">Bug Tunnel Defense: First Screenshots</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/less-is-more.html">Less is More</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/bug-tunnel-defense-names.html">Bug Tunnel Defense: Names</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/bug-tunnel-defense-release-notes.html">Bug Tunnel Defense release notes</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/bug-tunnel-defense-levels.html">Bug Tunnel Defense: Levels</a></li>
</ul>
<b>Design;</b> far fewer posts than I expected on design related topics:<br />
<ul>
<li><a href="http://buttons/">Buttons</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/on-framerate.html">On framerate</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/why-circles-and-spheres.html">Why circles (and spheres)?</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/review-triple-town.html">Review: Triple Town</a></li>
</ul>
<b>Screenshots; </b>all from my current game, working name "Rings". I started posting these very early, days after I started work on the game, so they start off very primitive:<br />
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/new-screenshot.html">New screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/new-screenshot.html">New screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/another-screenshot.html">Another screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/another-screenshot.html">Another screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/new-screenshot-flex-update.html">New screenshot, Flex update</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/screenshot-and-update.html">Screenshot and update</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/screenshots.html">Screenshots</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/new-screenshot.html">New Screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/linked-lists-screenshots.html">Linked lists + screenshots</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/screenshots_22.html">Screenshots</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/more-shaders.html">More shaders</a></li>
</ul>
<b>Links;</b> to various sites I use and recommend:<br />
<div>
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/links-actionscript-communities.html">ActionScript communities</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/wonderfl.html">Wonderfl</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/flash-game-license.html">Flash Game License</a></li>
</ul>
</div>
<div>
</div>
<b>Shaders;</b> I started making shaders with Pixel Bender while working on this game, and these include discussions of those and experiments I did on Wonderfl:<br />
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/shaders.html">Shaders</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/another-screenshot.html">Another screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/search/label/Shaders">Shader from string</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/search/label/Shaders">A simple shader</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/shader-vs-actionscript.html">Shader vs. ActionScript</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/more-shaders.html">More shaders</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/game-of-life-shader.html">Game of Life shader</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/3-channel-game-of-life-shader.html">3-channel Game of Life Shader</a></li>
</ul>
<div>
<b>Flex;</b> while working on this game I started using Flex and recorded my progress with it:</div>
<div>
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/flex.html">Flex</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/new-screenshot-flex-update.html">New screenshot, Flex update</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/more-on-flex.html">More on Flex</a></li>
</ul>
<div>
<b>Maths;</b> on various two-dimensional mathematics topics:</div>
</div>
<div>
<div>
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/maths-matrices.html">Matrices</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/more-matrices.html">More matrices</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/direction.html">Direction</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/angle-free-rotation.html">Angle-free rotation</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/complex-numbers.html">Complex numbers</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/trig-free-rotation-blending.html">Trig-free rotation blending</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/varying-rotation-speed.html">Varying the rotation speed</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/accuracy.html">Accuracy</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/angles.html">Angles</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/variable-speed-rotation-with-complex.html">Varying speed rotation with complex numbers</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/more-on-angles.html">More on angles</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/circles.html">Circles</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/more-on-circles.html">More on circles</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/circle-line-incidence.html">Circle-line incidence</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/circle-line-intersection.html">Circle-line intersection</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/inverse-trigonometry.html">Inverse trigonometry</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/angle-between-two-vectors.html">Angle between two vectors</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/lines.html">Lines</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/perp-dot-product.html">Perp dot product</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/circle-circle-intersection.html">Circle-circle intersection</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/collision-theory.html">Collision theory</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/trig-performance-test.html">Trig performance test</a></li>
</ul>
</div>
</div>
<div>
<b>Collisions;</b> how to do collisions in two dimensions:<br />
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/ball-wall-collisions.html">ball-wall collisions</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/more-ball-wall-collisions.html">More ball-wall collisions</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/collision-theory.html">Collision theory</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/ball-ball-collisions.html">Ball-ball collisions</a></li>
</ul>
</div>
<div>
<b>Optimisation;</b> on writing better, faster code:<br />
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/faster-random.html">A faster random</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/on-optimisation.html">On optimisation</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/accessors-are-slow.html">Accessors are slow</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/getters-and-setters-are-evil.html">getters and setters are evil</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/getters-and-built-in-classes.html">getters and built-in classes</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/setter-perfomance-test-conclusions.html">setter performance test, conclusion</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/accessing-members-by-name.html">Accessing members by name</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/dereferencing-array-members.html">Dereferencing array members</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/notes-on-testing.html">Notes on testing</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/01/fast-path-member-access.html">Fast path member access</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/another-screenshot.html">Another screenshot</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/half-angle-formulae.html">Half-angle formulae</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/flash-isnt-slow.html">Flash isn't slow</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/trig-performance-test.html">Trig performance test</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/practical-optimisation.html">Practical optimisation</a></li>
</ul>
<b>ActionScript;</b> anything about the language itself:</div>
<div>
<div>
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/twips.html">Twips</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/colourise-class.html">The Colourise class</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/header-files.html">Header files</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/more-on-colours.html">More on Colours</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/maths-distance-check.html">Distance check</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/11/jit-compiler-and-constructors.html">The JIT compiler and constructors</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/bitfield-class.html">The Bitfield class</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/my-textfield-class.html">My Textfield class</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/my-2d-vector-class-and-why-i-no-longer.html">My 2D Vector class - and why I no longer use it</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/faster-random.html">A faster random</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2011/12/string-to-bytearray.html">String to ByteArray</a></li>
</ul>
<div>
<b>BitmapData;</b> on this particular class and its uses:</div>
</div>
<div>
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/drawing-bitmap.html">Drawing a bitmap</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/jpeg-data-with-alpha.html">JPEG data with alpha</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/more-on-copypixels.html">More on copyPixels</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/why-bitmapdata.html">Why BitmapData?</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/bitmapdata-recolouring.html">BitmapData recolouring</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/drawing-pie-chart.html">Drawing a pie chart</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/text-revisited.html">Text revisited</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/practical-optimisation.html">Practical optimisation</a></li>
</ul>
<div>
<b>Vector graphics;</b> using the Graphics class in ActionScript:</div>
<div>
<ul>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/drawcircle-is-slow.html">drawCircle is slow</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/02/quadratic-curve-through-three-points.html">Quadratic curve through three points</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/radial-gradient-fill.html">Radial gradient fill</a></li>
<li><a href="http://johnblackburne.blogspot.co.uk/2012/03/practical-optimisation.html">Practical optimisation</a></li>
</ul>
</div>
</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-28467891857048313692012-03-30T08:00:00.000+01:002012-03-30T19:25:41.866+01:003-channel Game of Life shader<span style="font-family: 'Trebuchet MS', sans-serif;">Following on from <a href="http://johnblackburne.blogspot.co.uk/2012/03/game-of-life-shader.html">yesterday's post</a> I decided to act on my own suggestion and make a 3-channel version of the <a href="http://wonderfl.net/c/Ad8W">Game of Life</a> shader. The result is <a href="http://wonderfl.net/c/oHVd">here</a> on Wonderfl and embedded below, with the full shader code as a comment at the end of the source on Wonderfl.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The code is a straightforward port of the previous shader. The first eight lines are identical except instead of adding red values it's adding all three channels at once. This makes the code more compact, showing how shaders are particularly suited to manipulating vector values (code like this would be much worse to do in ActionScript).</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">But while there are vector versions of the subtract and less than operations there is no vector version of the tenary operator, "</span><span style="font-family: 'Courier New', Courier, monospace;">condition ? value1 : value2</span><span style="font-family: 'Trebuchet MS', sans-serif;">". That has to be done component by component so the rest of the code is done a component at a time, before the values are combined to produce the vector result.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The ActionScript code this time produces an image which is randomised in all three channels (if it started with a black and white image the result would be a less efficient version of the <a href="http://johnblackburne.blogspot.co.uk/2012/03/game-of-life-shader.html">previous shader</a>). Because at the start and subsequently every channel is 0x00 or 0xff the </span><span style="color: #a2c4c9; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span style="font-family: 'Trebuchet MS', sans-serif;"> has only a colour depth of three bits or eight colours. </span><span style="font-family: 'Trebuchet MS', sans-serif;">The effect is reminiscent of art produced on old 8-bit computers, such as the Sinclair Spectrum, especially when applied to photographic art.</span><br />
<br />
<script src="http://wonderfl.net/blogparts/oHVd/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/oHVd" title="3-channel Game of Life shader">3-channel Game of Life shader - wonderfl build flash online</a></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-17178549573547890232012-03-29T08:00:00.000+01:002012-03-29T08:00:11.398+01:00Game of Life shader<span style="font-family: 'Trebuchet MS', sans-serif;">This is another simple and quick shader, this time done to see how easy it would be to implement <a href="http://en.wikipedia.org/wiki/Conway's_Game_of_Life">Conway's Game of Life</a> after seeing the same logic <a href="http://lysisgames.com/articles/2012/filtercode1.html">implemented using filters</a>. It's an ideal fit for shaders not only as the code that runs on each pixel is identical but also as the 'game' is essentially a graphics algorithm. Turned out to be every straightforward, taking only an hour to write, test and deploy <a href="http://wonderfl.net/c/Ad8W">here</a> at Wonderfl.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><span style="font-family: 'Trebuchet MS', sans-serif;">The code implements the Life algorithm straightforwardly. The most interesting part is the threshold checking, done in three lines based on the sums of the cells around the cell being drawn and the cell itself:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float</span> deadTo = <span style="color: #76a5af;">abs</span>(neighbours - <span style="color: #cc0000;">3.0</span>) < <span style="color: #cc0000;">0.5</span> ? <span style="color: #cc0000;">1.0</span> : <span style="color: #cc0000;">0.0</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float</span> liveTo = <span style="color: #76a5af;">abs</span>(neighbours - <span style="color: #cc0000;">2.5</span>) < <span style="color: #cc0000;">1.0</span> ? <span style="color: #cc0000;">1.0</span> : <span style="color: #cc0000;">0.0</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #0b5394;">float</span> goesTo = <span style="color: #76a5af;">sampleNearest</span>(src, outCoord()).<span style="color: #76a5af;">r</span> > <span style="color: #cc0000;">0.5</span> ? liveTo : deadTo;</span><br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">It actually uses the red channel, but could use any or with a bit of work do all three channels at the same time, using the vector types and functions in the Pixel Bender language.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">The code that runs the filter, in full, is</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> dat.<span style="color: #76a5af;">applyFilter</span>(dat, dat.<span style="color: #76a5af;">rect</span>, pt, filter);</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">as it has no parameters to update or user interaction. The data is just a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span style="font-family: 'Trebuchet MS', sans-serif;"> (initially filled with random black and white cells), but it could use any graphic as source. In testing in the Pixel Bender Toolkit the effect on a photographic source is sort of a untidy posterising find-edges filter. The image could be created by a user in an editor, or the result used to generate further effects.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">It's embedded below, with source available on Wonderfl and the full shader code in a comment at the end. Again the shader is embedded as base64 in the source, generated using the following command line:</span></div>
<div>
<br /></div>
<div>
<span style="background-color: white; color: #444444; font-family: 'Courier New', Courier, monospace; font-size: 13px; line-height: 18px;">openssl base64 -in Life.pbj -out Life.b64</span></div>
<div>
<span style="color: #444444; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span style="line-height: 18px;"><br /></span></span></div>
<script src="http://wonderfl.net/blogparts/Ad8W/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/Ad8W" title="Game of Life shader">Game of Life shader - wonderfl build flash online</a></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-3634401576679026272012-03-28T11:44:00.001+01:002012-03-28T11:50:40.543+01:00Practical optimisation<span style="font-family: 'Trebuchet MS', sans-serif;">While browsing on <a href="http://wonderfl.net/">Wonderfl</a> to see how my <a href="http://johnblackburne.blogspot.com/2012/03/cross-product-shader.html">cross product shader</a> was doing I came across someone else's code, the evocatively named <a href="http://wonderfl.net/c/jPs7">"forked from: flash on 2012-3-23"</a>. Running it I noticed it was slow: it was not doing much but got slower and used more CPU as it ran. So I decided to look into it.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The result was my <a href="http://wonderfl.net/c/4ooT">"forked from: forked from: flash on 2012-3-23"</a>. Wonderfl indicates the chain of forks/dependencies in both the name and the comments at the top of the source code, and although these can be edited it's nice to leave them in if the code depends on the code it's forked from.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">What I did was optimised it. The initial code was repeatedly calling </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">drawCircle</span><span style="font-family: 'Trebuchet MS', sans-serif;"> with random colours, placement and size. But it was doing so in the same </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Graphics</span><span style="font-family: 'Trebuchet MS', sans-serif;"> object, adding more and more circles which Flash slowly bogged down over. I changed that to clear the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Graphics</span><span style="font-family: 'Trebuchet MS', sans-serif;"> object after using </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">draw</span><span style="font-family: 'Trebuchet MS', sans-serif;"> to render them to a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span style="font-family: 'Trebuchet MS', sans-serif;">, for a massive speedup. More importantly doing it like this does not slow down over time.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The other main optimisation was using the best graphics objects. For the drawing I used the most lightweight </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Graphics</span><span style="font-family: 'Trebuchet MS', sans-serif;"> rendering object, a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shape</span><span style="font-family: 'Trebuchet MS', sans-serif;">. And to contain the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span style="font-family: 'Trebuchet MS', sans-serif;"> the best thing was a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Bitmap</span><span style="font-family: 'Trebuchet MS', sans-serif;">, which is the only thing added to the scene. </span><span style="font-family: 'Trebuchet MS', sans-serif;">Apart from that I get the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">stage</span><span style="font-family: 'Trebuchet MS', sans-serif;"> width and height once, but more to make the code more readable. And I sped it up by a factor of 4: may as do something with the extra performance.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">I use similar optimisations extensively in the game I'm working on. It would be fair to say that almost all of the graphics are done this way, as I can think of only one thing onscreen that's not either generated using </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span style="font-family: 'Trebuchet MS', sans-serif;"> </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">draw()</span><span style="font-family: 'Trebuchet MS', sans-serif;"> or passed to it after it's drawn. The game would not be possible without it.</span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-35947430982765498202012-03-27T19:16:00.000+01:002012-03-27T23:48:59.271+01:00Cross product shader<span style="font-family: 'Trebuchet MS', sans-serif;">This is something I did to try out the mathematical functions in Pixel Bender's shader language. I also wanted to work out how to upload an image to Wonderfl, and upload another more interesting shader example to there. Seeing how its turned out I can't imagine using in game though with a bit of work it could produce some interesting effects which might be useful.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><span style="font-family: 'Trebuchet MS', sans-serif;">The shader simply does a <a href="http://en.wikipedia.org/wiki/Cross_product">cross product</a> of the input colour and a fixed vector (though one that varies as you move the mouse) to generate another colour. So the colours range over almost all possible colours they are treated as vectors around a colour (0.5, 0.5, 0.5), i.e. 0x808080 or mid-grey.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The function in full, including the normalisation and cross product, is</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">evaluatePixel()</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">{</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float4</span> col = <span style="color: #76a5af;">sampleNearest</span>(src, <span style="color: #76a5af;">outCoord</span>());</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span style="color: #76a5af;">float3</span> ortho = col.<span style="color: #76a5af;">xyz</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> ortho = ortho * <span style="color: red;">2.0</span> - <span style="color: #76a5af;">float3</span>(<span style="color: red;">1.0</span>, </span><span style="color: red; font-family: 'Courier New', Courier, monospace;">1.0</span><span style="font-family: 'Courier New', Courier, monospace;">, </span><span style="color: red; font-family: 'Courier New', Courier, monospace;">1.0</span><span style="font-family: 'Courier New', Courier, monospace;">);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> ortho = <span style="color: #76a5af;">cross</span>(ortho, adj);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> ortho = (ortho + <span style="color: #76a5af;">float3</span>(</span><span style="color: red; font-family: 'Courier New', Courier, monospace;">1.0</span><span style="font-family: 'Courier New', Courier, monospace;">, </span><span style="color: red; font-family: 'Courier New', Courier, monospace;">1.0</span><span style="font-family: 'Courier New', Courier, monospace;">, </span><span style="color: red; font-family: 'Courier New', Courier, monospace;">1.0</span><span style="font-family: 'Courier New', Courier, monospace;">)) * <span style="color: red;">0.5</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> dst = <span style="color: #76a5af;">float4</span>(ortho.<span style="color: #76a5af;">x</span>, ortho.<span style="color: #76a5af;">y</span>, ortho.<span style="color: #76a5af;">z</span>, </span><span style="color: red; font-family: 'Courier New', Courier, monospace;">1.0</span><span style="font-family: 'Courier New', Courier, monospace;">);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
As moving the mouse only updates two coordinates one of the values passed to the shader is fixed. Clicking changes which it is, copying the fixed value from the last y value and changes which two colours moving the mouse affects. See the source for details; the full shader source is embedded at the end of the Flash example code.</div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
As noted above I can't see a real use for this as it is, but the performance is good enough that it could be made more complex and still be usable. Possible improvements include changing it to rotate (so all colour information is preserved) or changing it to work in another colour space where fixing one axis will have more meaning. Or even using the colour from a second image rather than a fixed vector as input.</div>
<script src="http://wonderfl.net/blogparts/dGRT/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/dGRT" title="Cross product shader">Cross product shader - wonderfl build flash online</a></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-20859396637353129282012-03-26T08:00:00.000+01:002012-03-26T08:11:40.232+01:00Radial gradient fill<span style="font-family: 'Trebuchet MS', sans-serif;">I first tried using gradient fills (via the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">beginGradientFill</span><span style="font-family: 'Trebuchet MS', sans-serif;"> method of the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Graphics</span><span style="font-family: 'Trebuchet MS', sans-serif;"> class) in Bug Tunnel Defense. I wanted to use them for shading along <a href="http://johnblackburne.blogspot.co.uk/2011/11/bug-tunnel-defense-tunnels.html">the tunnels</a> but could never get them to work, and eventually did it the long way by drawing a series of differently coloured rectangles. The problem was the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">createGradientBox</span><span style="font-family: 'Trebuchet MS', sans-serif;"> </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Matrix</span><span style="font-family: 'Trebuchet MS', sans-serif;"> function, which no matter what I passed to it would never return the right matrix for a linear fill.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Over the weekend I tackled the similar but simpler problem of radial shading. It's simpler because the shading is rotationally symmetric so the angle does not come into it. But it's not described in the official documentation so I had to use trial and error to get to the right matrix.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The correct way to call </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">createGradientBox</span><span style="font-family: 'Trebuchet MS', sans-serif;"> for circles is as follows, where </span><span style="font-family: 'Courier New', Courier, monospace;">fX</span><span style="font-family: 'Trebuchet MS', sans-serif;">, </span><span style="font-family: 'Courier New', Courier, monospace;">fY</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="font-family: 'Courier New', Courier, monospace;">fR</span><span style="font-family: 'Trebuchet MS', sans-serif;"> are the coordinates and radius of the circle. The zero is the angle which is not needed.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">mat.<span style="color: #76a5af;">createGradientBox</span>(<span style="color: #cc0000;">2</span> * fR, <span style="color: #cc0000;">2</span> * fR, <span style="color: #cc0000;">0</span>, fX - fR, fY - fR);</span><br />
<div>
</div>
<br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">To demonstrate it I've written a simple app, only 26 lines only ten of which do anything, available <a href="http://wonderfl.net/c/guKK">here on Wonderfl</a> and embedded below.</span></div>
<br />
<script src="http://wonderfl.net/blogparts/guKK/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/guKK" title="Radial gradient fill example">Radial gradient fill example - wonderfl build flash online</a></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-80156474713344813292012-03-23T20:23:00.000+00:002012-03-23T20:23:29.625+00:00More shaders<span style="font-family: 'Trebuchet MS', sans-serif;">I wrote two new </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;">s today. One is for a screen that's not in the game yet, which the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;"> will be a fundamental part of. As the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;"> is rather complex I wanted to write it first to see if what I wanted to do was possible. It seems to work, so now I need to write the code for that screen.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The second is much simpler. It does edge detection on the layer I added yesterday, to highlight the boundary of the region indicated. The </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;"> code is very straightforward and it took much less time than either of the other </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;">s I've done for this game.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">What's interesting though is that as soon as I realised that I wanted to add something like this I started thinking of how to do it using a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;">, not using </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">BitmapData</span><span style="font-family: 'Trebuchet MS', sans-serif;"> functions. The latter is probably possible though it wouldn't be easy, and would require quite a number of steps. The </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">ShaderFilter</span><span style="font-family: 'Trebuchet MS', sans-serif;"> only needs setting up once (the brightness and colour of the effect are exposed) and is applied like any other filter as that layer is redrawn or composited.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">It was made much easier by the Pixel Bender Toolkit. To see how it would work with the layer in-game I could just load up a screenshot of the game I took earlier and experiment with the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">Shader</span><span style="font-family: 'Trebuchet MS', sans-serif;"> until it did what I wanted, finally adding parameters so I could also adjust it in game.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-ZbehOrHJ71E/T2za2pIHz0I/AAAAAAAAANw/1QyhCqv_-Mw/s1600/Screen+shot+2012-03-23+at+19.33.24.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://1.bp.blogspot.com/-ZbehOrHJ71E/T2za2pIHz0I/AAAAAAAAANw/1QyhCqv_-Mw/s320/Screen+shot+2012-03-23+at+19.33.24.png" width="320" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<br />JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-66280659726605368202012-03-22T23:35:00.000+00:002012-03-22T23:35:02.789+00:00Screenshots<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Catching up today after spending much of yesterday performing my civic duty, and spent some time adding a new graphical layer that slots between existing layers in just the right way. I had to re-work a few things to get it right, but the result not only looks better and helps a lot in the gameplay but is a little more efficient to draw.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-p3S6BGSFeeA/T2u2V9AQHdI/AAAAAAAAANg/ZPMb31pvlAE/s1600/Screen+shot+2012-03-22+at+22.11.45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="320" src="http://2.bp.blogspot.com/-p3S6BGSFeeA/T2u2V9AQHdI/AAAAAAAAANg/ZPMb31pvlAE/s320/Screen+shot+2012-03-22+at+22.11.45.png" width="320" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-XbuoYrFvgBg/T2u2WyiHoXI/AAAAAAAAANk/N-8F6UUXIvE/s1600/Screen+shot+2012-03-22+at+22.12.11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="320" src="http://2.bp.blogspot.com/-XbuoYrFvgBg/T2u2WyiHoXI/AAAAAAAAANk/N-8F6UUXIvE/s320/Screen+shot+2012-03-22+at+22.12.11.png" width="320" /></span></a></div>
<br />JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-73004917822197008532012-03-21T22:55:00.001+00:002012-03-21T22:55:10.946+00:00Review: Triple Town<span style="font-family: 'Trebuchet MS', sans-serif;">Triple Town by Spry Fox started out on the Kindle, but I first noticed it on Facebook and subsequently on Google+, one of the first game on that platform. Most recently it has been released for iOS devices. </span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-o3CQ4kGD49k/T2paq827xBI/AAAAAAAAANY/JQxAj1ag2Ig/s1600/Screen+shot+2012-03-21+at+21.44.27.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-o3CQ4kGD49k/T2paq827xBI/AAAAAAAAANY/JQxAj1ag2Ig/s320/Screen+shot+2012-03-21+at+21.44.27.png" width="277" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The gameplay is an innovative take on the match three mechanism. Objects (grass, bushes, trees, cottage) are placed on the playing area to form groups of three or more matching objects. But instead of simply disappearing as they match they are replaced by the next object in the sequence. Three grasses become a bush for example.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This bush can then match two other other bushes and be replaced by the next higher object, a tree. And so-on, through houses, mansions and castles up to the ultimate in Triple Town architecture, a floating triple castle. This makes the game very strategic, much like Chess or Reversi, as the placement of objects can become important dozens or even hundreds of turns later.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">If that were all there was too it the game would be interesting enough, but an extra level of strategy is added by 'bears' which once placed can move if not blocked. They can, and often do, obstruct anything you are trying to do. The can be killed by trapping them so they cannot move, and turn into gravestones, which can be matched with other gravestones to make churches, cathedrals and treasure chests.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">After a short while ninja bears appear which can teleport to any free square so cannot be blocked. These can be killed if there are no free squares or by an Imperial Bot which can also kill regular bears or remove any object on the board. Finally there are crystals that can match any object, especially useful for matching higher level objects (houses and above) that don't appear.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-NXIls_Q9kGs/T2papUzBCUI/AAAAAAAAANQ/ynvdREQg-x0/s1600/Screen+shot+2012-03-21+at+21.43.24.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-NXIls_Q9kGs/T2papUzBCUI/AAAAAAAAANQ/ynvdREQg-x0/s320/Screen+shot+2012-03-21+at+21.43.24.png" width="282" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The thing that really distinguishes the game is the visual design. All elements are distinct and recognisable, with the progression of higher value objects matching the complexity of their design. They fit into a deceptively simple design where they are the building blocks of a town. The game mechanics stop you loosing your inner city planner on the design of your town but the pieces fit together so well they almost by accident keep forming patterns and designs that look like a working town.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This is helped by the small characters that come out of the buildings, strolling chatting, and even picking apples off trees, and the subtle but effective sound effects. The overall effect is of a living, breathing town or city which keeps running as you play your game. These elements are almost irrelevant to the gameplay, but lift it above other games that just sit there waiting for you to make your move.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">On Facebook and Google+ it is a free app, monetized through in-game sales. As with other games it has a free currency, coins, and a premium currency, crystals, with which you can buy extra moves, objects when you need them (normally they drop randomly), and some special objects to help the game.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The weakest element is perhaps the store. There are only so many items you can buy for each town, and it's not unusual to run out of things to buy long before the town is finished, and so have money but nothing to spend it on (except extra moves although I prefer to wait for them to build up over time).</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Another limitation of the game is it does not change. Over time as you play and get better you find your towns and cities last longer, and so earn higher scores. But the game mechanics don't change and there's little progression apart from this. Finally the social elements are pretty weak for a Facebook game: there's not the same incentive to recruit friends as in a game from Zynga or one of the other social game specialists.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Perhaps the biggest sign of its originality is that it has been unashamedly copied by other game makers a number of times since its release. None though of the other games have the same quality or attention to detail. </span><span style="font-family: 'Trebuchet MS', sans-serif;">My own interest is that more than any other recent game it has informed the design of my current game, although the influence is buried very deep.</span>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-37486871284544129412012-03-20T08:00:00.000+00:002012-03-20T08:00:07.308+00:00Linked lists + screenshots<span style="font-family: 'Trebuchet MS', sans-serif;">I moved some of my data structures over to linked lists today, in preparation for adding more functionality and gameplay. I was once fairly sceptical of their applicability in Flash but I've been persuaded around by the performance work I was doing a few months ago. In particular the overhead of accessing array (</span><span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">Vector</span><span style="font-family: 'Trebuchet MS', sans-serif;"> or </span><span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">Array</span><span style="font-family: 'Trebuchet MS', sans-serif;"> types) members is non-trivial, comparable to other function calls. I may do some performance tests to confirm this but I'm pretty sure this is an optimal solution for what I'm doing.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">I've been tweaking the graphics code, in subtle ways so as not impact the performance. Not finished but the effect so far is quite nice and worth another screenshot:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-nXVUuJIDK8c/T2fMyulyYcI/AAAAAAAAANI/8meoVv4WHFg/s1600/Screen+shot+2012-03-19+at+15.54.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="320" src="http://1.bp.blogspot.com/-nXVUuJIDK8c/T2fMyulyYcI/AAAAAAAAANI/8meoVv4WHFg/s320/Screen+shot+2012-03-19+at+15.54.02.png" width="320" /></span></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Apart from that I was playing with a </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">ConvolutionFilter</span><span style="font-family: 'Trebuchet MS', sans-serif;"> over the weekend, so see if it was faster or better than what I'm now using. The result was definitely worse, both from a performance point of view and because of artefacts I was unable to eliminate, but the effect still was quite interesting if I got the values for the </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">matrix</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="color: #76a5af; font-family: 'Courier New', Courier, monospace;">divisor</span><span style="font-family: 'Trebuchet MS', sans-serif;"> wrong:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-bKeKRKPT0g0/T2fMxjp3VcI/AAAAAAAAANA/hq0R3ep_4Z0/s1600/Screen+shot+2012-03-17+at+14.51.47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: 'Trebuchet MS', sans-serif;"><img border="0" height="320" src="http://3.bp.blogspot.com/-bKeKRKPT0g0/T2fMxjp3VcI/AAAAAAAAANA/hq0R3ep_4Z0/s320/Screen+shot+2012-03-17+at+14.51.47.png" width="320" /></span></a></div>
<br />JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0tag:blogger.com,1999:blog-3753330082013888619.post-79577458421076951662012-03-19T08:00:00.000+00:002012-03-19T08:00:04.784+00:00Ball-ball collisions<span style="font-family: 'Trebuchet MS', sans-serif;">In <a href="http://johnblackburne.blogspot.co.uk/2012/02/collision-theory.html">this post</a> I discussed how to handle collisions in general, at least when one of the objects is a ball for collision purposes. My intention was to follow it up with an example but I never got around to it. Well now I have, and it shows how to turn the theory in that post into practice.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<a name='more'></a><span style="font-family: 'Trebuchet MS', sans-serif;">The demo app is </span><a href="http://johnblackburne.blogspot.co.uk/2012/02/collision-theory.html" style="font-family: 'Trebuchet MS', sans-serif;">here</a><span style="font-family: 'Trebuchet MS', sans-serif;">. It is based on my previous ballistics app with one addition, a slightly off-centre fixed circle which the ball bounces off as well as the walls. This is simpler than having two moving balls but not by much as the calculations are the same up to a point.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The main code change (apart from initialising and drawing the circle) is the following few lines.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">var</span><span style="font-family: 'Courier New', Courier, monospace;"> fDX:<span style="color: #0b5394;">Number</span> = fBallX - fColX;</span><br />
<span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">var</span><span style="font-family: 'Courier New', Courier, monospace;"> fDY:</span><span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">Number</span><span style="font-family: 'Courier New', Courier, monospace;"> = fBallY - fColY;</span><br />
<span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">var</span><span style="font-family: 'Courier New', Courier, monospace;"> fDist:</span><span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">Number</span><span style="font-family: 'Courier New', Courier, monospace;"> = fDX * fDX + fDY * fDY;</span><br />
<span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">var</span><span style="font-family: 'Courier New', Courier, monospace;"> fRSum:</span><span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">Number</span><span style="font-family: 'Courier New', Courier, monospace;"> = fSize + fColR;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span style="color: #0b5394;">if</span> (fDist < fRSum * fRSum) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>fDist = <span style="color: #0b5394;">Math</span>.<span style="color: #0b5394;">sqrt</span>(fDist);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>fDX /= fDist;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>fDY /= fDist;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #0b5394;">var</span> fApproachSpeed:</span><span style="color: #0b5394; font-family: 'Courier New', Courier, monospace;">Number</span><span style="font-family: 'Courier New', Courier, monospace;"> = -(fDX * fBallU + fDY * fBallV);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #0b5394;">if</span> (fApproachSpeed > 0) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>fBallU += fApproachSpeed * fDX * <span style="color: #cc0000;">1.9</span>; </span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>fBallV += fApproachSpeed * fDY * <span style="color: #cc0000;">1.9</span>;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>}</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Initially it checks whether the circles overlap using Pythagoras's theorem. </span><span style="font-family: 'Courier New', Courier, monospace;">fDist</span><span style="font-family: 'Trebuchet MS', sans-serif;"> at this point is the square of the distance between the centres, and this is compared with the (square of the) sum of the radii as the circles overlap if the distance between the centres is less than this.</span></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">fDX</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="font-family: 'Courier New', Courier, monospace;">fDY</span><span style="font-family: 'Trebuchet MS', sans-serif;"> are then scaled by the length of the vector (</span><span style="font-family: 'Courier New', Courier, monospace;">fDX</span><span style="font-family: 'Trebuchet MS', sans-serif;">, </span><span style="font-family: 'Courier New', Courier, monospace;">fDY</span><span style="font-family: 'Trebuchet MS', sans-serif;">), to normalise this vector, generating a unit vector. This is the normal vector </span><b><span style="font-family: Times, 'Times New Roman', serif;">n</span></b><span style="font-family: 'Trebuchet MS', sans-serif;"> in </span><a href="http://johnblackburne.blogspot.co.uk/2012/02/collision-theory.html" style="font-family: 'Trebuchet MS', sans-serif;">the theory</a><span style="font-family: 'Trebuchet MS', sans-serif;">. The normal vector in this case can't be pre-calculated, it has to be determined on the fly. This is common though, especially once rotation and friction are incorporated into such systems.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The dot product of </span><span style="font-family: Times, 'Times New Roman', serif;"><b>n</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> with the ball's velocity gives the approach speed </span><span style="font-family: Times, 'Times New Roman', serif;"><i>s</i></span><span style="font-family: 'Trebuchet MS', sans-serif;">. This is compared with zero to make sure the ball is approaching (if moving nearly parallel to the fixed ball it could move within range but already be separating from it. Not doing this check would then pull one ball into the fixed one).</span></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">The last two lines calculate the new velocity by adding the product of </span><span style="font-family: Times, 'Times New Roman', serif;"><i>s</i></span><span style="font-family: 'Trebuchet MS', sans-serif;">, </span><span style="font-family: Times, 'Times New Roman', serif;"><b>n</b></span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="font-family: Times, 'Times New Roman', serif;">(1 + <i>e</i>)</span><span style="font-family: 'Trebuchet MS', sans-serif;">, where </span><span style="font-family: Times, 'Times New Roman', serif;"><i>e</i></span><span style="font-family: 'Trebuchet MS', sans-serif;"> is the coefficient of restitution. In this case the coefficient of restitution is 0.9, increased slightly so it will bounce more often before coming to rest. It doesn't do anything to move the ball out from the surface, but this could easily be added.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Everything up to the last two lines is the same if two balls are moving. For two moving balls two velocities need to be updated and the masses of the balls needs to be taken into account.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">As before this ignores friction and rotational effects, including air resistance. But as before provided the simulation does not go on for too long (so it doesn't come too close to coming to rest) it works very well. </span><span style="font-family: 'Trebuchet MS', sans-serif;">The application is </span><a href="http://wonderfl.net/c/rh6W" style="font-family: 'Trebuchet MS', sans-serif;">available on Wonderfl</a><span style="font-family: 'Trebuchet MS', sans-serif;">, where the code can be examined and forked, and embedded below.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<script src="http://wonderfl.net/blogparts/rh6W/js" type="text/javascript">
</script><br />
<div class="ttlBpWonderfl" style="font-size: 11px; margin: 0; text-align: right; width: 465px;">
<a href="http://wonderfl.net/c/rh6W" title="ball-ball collision">ball-ball collision - wonderfl build flash online</a></div>JohnBhttp://www.blogger.com/profile/16091342691331957962noreply@blogger.com0