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

<channel>
	<title>Cold Constructs &#187; particles</title>
	<atom:link href="http://coldconstructs.com/tag/particles/feed/" rel="self" type="application/rss+xml" />
	<link>http://coldconstructs.com</link>
	<description>Creations of Corey Birnbaum</description>
	<lastBuildDate>Fri, 03 Feb 2012 02:07:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Pixel-perfect collision detection with 5000+ particles</title>
		<link>http://coldconstructs.com/2009/11/pixel-perfect-collision-detection-with-5000-particles/</link>
		<comments>http://coldconstructs.com/2009/11/pixel-perfect-collision-detection-with-5000-particles/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 19:39:49 +0000</pubDate>
		<dc:creator>Corey</dc:creator>
				<category><![CDATA[Experiments]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[collision detection]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[particles]]></category>
		<category><![CDATA[source]]></category>

		<guid isPermaLink="false">http://coldconstructs.com/?p=172</guid>
		<description><![CDATA[UPDATE: This post is here for historical purposes. The SWF has been moved to a new location. And yes, it runs perfectly fine. I&#8217;ve run it at 60+ FPS with 7,000 particles, but that actually isn&#8217;t the limitation (unless your particles are crunching heavy math for eg movement). Rather it&#8217;s the size and number of... <a href="http://coldconstructs.com/2009/11/pixel-perfect-collision-detection-with-5000-particles/">Read More &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>UPDATE: This post is here for historical purposes. The SWF has been moved to <a href="http://coldconstructs.com/?interactives=particle-collision-detection">a new location</a>.</p>
<p>And yes, it runs perfectly fine. I&#8217;ve run it at 60+ FPS with 7,000 particles, but that actually isn&#8217;t the limitation (unless your particles are crunching heavy math for eg movement). Rather it&#8217;s the size and number of sprites that we&#8217;re colliding with the particles.</p>
<p><img src="http://labs.coldconstructs.com/i/vonlocalcd.jpg" alt="vonLocal Collision Detection" class="centered" /></p>
<p>To squeeze all the juice out of Flash I employed a couple tricks. <strong>The first</strong> was the particles themselves&#8211;they&#8217;re blitted to a single bitmap which is used as the source image for grabbing collision data from. The particles are also drawn with the raster engine in Flash (multiple <code>setPixel32()</code> ops to give the illusion of a line&#8230; a choppy one anyway) instead of the vector renderer (<code>lineTo()</code>). <strong>The second trick</strong> was to only grab a Vector of pixels from the regions we cared about (within sprite boundaries) every so often, then to loop through the Vector and test it against our desired conditions. Also, since the particle bitmap is more sparse than our sprites as far as opaque pixels go, we test the particle bitmap first, resulting in a lot fewer passes on the first round of conditional statements.</p>
<p><span id="more-172"></span></p>
<p>So my poor man&#8217;s method of making lines is done by interpolating the position of a particle from the previous to the current frame, for a total of 3 <code>setPixel32()</code> operations per iteration. (We can use <code>setPixel()</code> for a solid performance gain, but at a different kind of cost that I&#8217;ll explain later.) To give the particles a long tail we simply decrease the alpha of the particle bitmap a little bit every frame, making older particles fade more as time goes by. This means we can skip <code>fillRect()</code> to clear the bitmap every frame, but I&#8217;m wondering if that&#8217;s faster or slower than <code>ColorTransform</code>. Haven&#8217;t tested, for shame.</p>
<p>I&#8217;ll admit that I haven&#8217;t tried this method with bitmap-based particles but those would work just as well, in theory (using blitted rendering). One of my current projects demands those trailing things so I didn&#8217;t look into it. If you try it, please comment on this post below with your findings <img src="http://coldconstructs.com/random/pint.gif"></img></p>
<p><code class="block">particleMap.lock();<br />
for (i = 0; i < _numParticles; ++i) {<br />
&nbsp;&nbsp;p = particles[i];<br />
&nbsp;&nbsp;// get our velocity from the perlin noise map<br />
&nbsp;&nbsp;vel = noiseMap.getPixel(p.x>>3, p.y>>3); // because noiseMap is 1/9 the size of particleMap<br />
&nbsp;&nbsp;var brightness:Number = vel / 0xFFFFFF;<br />
&nbsp;&nbsp;var speed:Number = 0.1 + brightness * p.speed;<br />
&nbsp;&nbsp;var angle:Number = 360 * (brightness * p.wander) * 0.0175; // roughly PI / 180 to convert to radians<br />
&nbsp;&nbsp;p.vx = Math.cos(angle) * speed;<br />
&nbsp;&nbsp;p.vy = Math.sin(angle) * speed;<br />
&nbsp;&nbsp;// absolute value for velocity calculations<br />
&nbsp;&nbsp;var pvx:Number = p.vx < 0 ? -p.vx : p.vx; // use bitwise sign flippage<br />
&nbsp;&nbsp;var pvy:Number = p.vy < 0 ? -p.vy : p.vy;<br />
&nbsp;&nbsp;// poor man's lineTo ENGAGED<br />
&nbsp;&nbsp;var nx:Number = p.x + (p.vx >> 1); // where we are now + half the distance to where we will be<br />
&nbsp;&nbsp;var ny:Number = p.y + (p.vy >> 1);<br />
&nbsp;&nbsp;var mx:Number = nx - p.x; // then half THAT distance for a third position...<br />
&nbsp;&nbsp;var my:Number = ny - p.y;<br />
&nbsp;&nbsp;// actually apply velocity to pixel<br />
&nbsp;&nbsp;p.x += p.vx;<br />
&nbsp;&nbsp;p.y += p.vy;<br />
&nbsp;&nbsp;// bounds-check<br />
&nbsp;&nbsp;if (p.y < 0) p.y = h - 1;<br />
&nbsp;&nbsp;else if (p.y > h) p.y = 1;<br />
&nbsp;&nbsp;if (p.x < 0) p.x = w - 1;<br />
&nbsp;&nbsp;else if (p.x > w) p.x = 1;<br />
&nbsp;&nbsp;// pick our color based on speed<br />
&nbsp;&nbsp;speed *= 60;<br />
&nbsp;&nbsp;if (speed > 255) speed = 255;<br />
&nbsp;&nbsp;color = 255 << 24 | speed << 16 | speed << 8 | speed;<br />
&nbsp;&nbsp;// render the particle three times, each in different places to get a line-ish thing going<br />
&nbsp;&nbsp;particleMap.setPixel32(p.x, p.y, color);<br />
&nbsp;&nbsp;particleMap.setPixel32(mx, my, color);<br />
&nbsp;&nbsp;particleMap.setPixel32(nx, ny, color);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;// and we're done. release the pixels!<br />
&nbsp;&nbsp;particleMap.unlock(_r);</code></p>
<p>So that gives us some spotty-but-close-enough trails to help with our collision detection. It works like this: We create a single bitmap to use as a canvas for our particles. We render those particles using <code>setPixel32()</code> as mentioned above. <strong>Sprites will use this bitmap as a source for collision data.</strong> Every other frame or so (more on this later) the sprites will grab a section of pixels from the particle bitmap using something like <code>getVector()</code> (>= Flash 10) or <code>getPixels()</code> (< Flash 10), using their own position and dimensions for the <code>sourceRect</code> parameter.</p>
<p><code class="block">shipVec = buffer.getVector(_rc); // get an array of pixels from the whole sprite<br />
_rc.x = int(this.x); // change rect to particleBMD's coordinate space<br />
_rc.y = int(this.y);<br />
pixVec = _particlebmd.getVector(_rc); // grab an array of the same area of pixels that our sprite is occupying<br />
var a:uint;<br />
var i:int = 0;<br />
buffer.lock();<br />
for (i; i < _l; ++i) {<br />
&nbsp;&nbsp;_pval = pixVec[int(i)]; // first look at the particle's image for opaque pixels<br />
&nbsp;&nbsp;a = _pval >> 24;<br />
&nbsp;&nbsp;if (a < 100) continue;<br />
&nbsp;&nbsp;// it found an opaque-ish pixel, so let's see if there's an opaque pixel in the ship there too<br />
&nbsp;&nbsp;_sval = shipVec[int(i)];<br />
&nbsp;&nbsp;a = _sval >> 24;<br />
&nbsp;&nbsp;if (a < 100) continue;<br />
&nbsp;&nbsp;/* if we get this far then we have a collision because one<br />
&nbsp;&nbsp;&nbsp;&nbsp;* of the ship's pixels is overlapping a particle's pixel.<br />
&nbsp;&nbsp;&nbsp;&nbsp;* we're only going to collide with red-colored particles though */<br />
&nbsp;&nbsp;_pval = _pval >> 16 &#038; 0xFF; // red channel extraction<br />
&nbsp;&nbsp;if (_pval > 100) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;var px:int = int(i % w); // translate 1d array coordinate to 2d grid coordinates<br />
&nbsp;&nbsp;&nbsp;&nbsp;var py:int = int(i / h);<br />
&nbsp;&nbsp;&nbsp;&nbsp;buffer.setPixel32(px,py,0xFF4e88c9); // colliding pixels are painted on the top of our sprite in a cold blue-ish color<br />
&nbsp;&nbsp;}<br />
}<br />
buffer.unlock();</code></p>
<p>As you can see on line 133 and 136, each sprite has a block of pixels ready to examine on each tick. The sprite loops through that block and compares every pixel of its own with the pixels in the Vector it got. If there's a match (eg both pixels are opaque) then look at the particle's pixel in detail to see if it's the <del datetime="2009-10-10T20:40:55+00:00">droid</del> one we're looking for and record its findings. </p>
<p>So you can alter line 151 so that the sprites check for specific colors in the particle bitmap, like anything brighter than dark grey (which I did here, or anything with an alpha greater than <code>0.1</code> or... use your imagination I guess?).</p>
<p>Because grabbing a new Vector from the particle bitmap can be so expensive (depending on the size of the sprite), you can time limit the collection so it only samples the particle bitmap once in a short while. In the demo SWF above I sample it once every 100 milliseconds or so, which comes out to about 24 samples a second (given 25 milliseconds per frame at 60 FPS)... as opposed to 2400 samples a second. The casual human eye can't tell the difference but it yields a significant increase in performance. Most performance tricks I've learned are based are smoke and mirror stuff like this.</p>
<p>You can use <code>setPixel()</code> (no alpha) but you'll <em>have</em> to test for color--obviously for a color that isn't what the background of the particle bitmap is, so it's a little more tricky. It's also totally possible to use other sprites as particles as long as you blit them (using <code>copyPixels()</code> or <code>setVector()</code>) to a single bitmap that can be checked by other sprites that collide with them. If you don't know what blitting is, 8bitRocket <a href="http://www.8bitrocket.com/newsdisplay.aspx?newspage=13430">has a good rundown</a> (it's where I first learned about it actually).</p>
<p>And that's pretty much it. You can download the example files/source below.</p>
<p><a title="download source" href="http://labs.coldconstructs.com/e/vonLocalCD.zip"><img class="centered" src="http://coldconstructs.com/siteFiles/download_button.png" alt="download source" /></a></p>
 <p><a href="http://coldconstructs.com/?flattrss_redirect&amp;id=172&amp;md5=d882953187532fd2fba4e97e6a3bc125" title="Flattr" target="_blank"><img src="http://coldconstructs.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://coldconstructs.com/2009/11/pixel-perfect-collision-detection-with-5000-particles/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

