{"id":475,"date":"2009-09-30T02:41:36","date_gmt":"2009-09-30T00:41:36","guid":{"rendered":"http:\/\/labs.miaumiau.cat\/?p=41"},"modified":"2011-07-29T14:43:07","modified_gmt":"2011-07-29T14:43:07","slug":"dotted-meow-from-the-crypt","status":"publish","type":"post","link":"https:\/\/www.miaumiau.cat\/?p=475","title":{"rendered":"dotted meow from the crypt"},"content":{"rendered":"<p><a title=\"dotted meow from the crypt\" href=\"http:\/\/miaumiau.cat\/examples\/dottedMeow\/Main.swf\" rel=\"shadowbox;width=800;height=600\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-54\" title=\"dotted meow\" src=\"http:\/\/www.miaumiau.cat\/wp-content\/uploads\/2009\/08\/splashmiaumi.jpg\" alt=\"dotted meow\" width=\"515\" height=\"265\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">WEBCAM REQUIRED.<\/p>\n<p style=\"text-align: justify;\">I&#8217;ve been playing around with the webcam on AS3 and finally i got into something i liked.<\/p>\n<p style=\"text-align: justify;\">Basically what I&#8217;m doing here is to generate a grid of shapes keeping references between objects using a linked list. I am working with a small video size to optimize performance, so I keep two positions in each properties at Particle class: origin and staticPosition.<\/p>\n<p style=\"text-align: justify;\"><span style=\"color: #f80662;\">origin<\/span> is a Point keeping the coordinates of the pixel on the Video object which corresponds to the particle.<\/p>\n<p><span style=\"color: #f80662;\">staticPosition<\/span> is a Point keeping the coordinate that corresponds at stage.<\/p>\n<p>Here there is a sample of the generate grid method, it has comments and the complete source is ready to download at the end of this post.<\/p>\n<p>[as]<br \/>\nprivate function setupGrid() : void{<\/p>\n<p>\/\/ iniatialize the linked list with initLink Particle<br \/>\nvar p : Particle = initLink;<br \/>\n\/\/ set the x \/ y coordinates to zero<br \/>\nvar _x : uint = 0;<br \/>\nvar _y : uint = 0;<br \/>\n\/\/ this bucle creates the particles<br \/>\nfor (var i : int = 0; i &lt; quantity; i++) {<br \/>\n\/\/ if the x coordinate exceeds the defined width limit<br \/>\nif(i % nw == 0 &amp;&amp; i!= 0){<br \/>\n\/\/ set the &#8216;x&#8217; coordinate to zero<br \/>\n_x = 0;<br \/>\n\/\/ ad the height of the particle to the &#8216;y&#8217; coordinate<br \/>\n_y += particleHeight;<br \/>\n}<\/p>\n<p>\/\/ storing the next particle at current<br \/>\np.next = new Particle();<br \/>\n\/\/ define the coordinate that corresponds this iteration at the source video<br \/>\nvar origin : Point = new Point(_x \/ particleWidth, _y \/ particleHeight);<br \/>\n\/\/ send it to the origin propertie at the particle<br \/>\np.origin = origin;<br \/>\n\/\/ define the current position at stage<br \/>\nvar point : Point = new Point(_x, _y);<br \/>\n\/\/ place it to two properties at the particle<br \/>\n\/\/ at &#8216;staticPosition&#8217; , this value will not change<br \/>\np.staticPosition = new Point(point.x, point.y);<br \/>\n\/\/ and at &#8216;position&#8217;, this value will change to animate flight<br \/>\np.position = point;<br \/>\n\/\/ place the particle at stage coords<br \/>\np.x = point.x;<br \/>\np.y = point.y;<br \/>\n\/\/ add the displayObject to the container<br \/>\nparticles.addChild(p);<br \/>\n\/\/ refresh the &#8216;p&#8217; variable to store the next particle at next iteration of this bucle<br \/>\np = p.next;<br \/>\n\/\/ add a particle width to the &#8216;_x&#8217; var for the next iteration<br \/>\n_x += particleWidth;<\/p>\n<p>}<\/p>\n<p>}<br \/>\n[\/as]<\/p>\n<p style=\"text-align: justify;\">We can color each particle based on each pixel rgb value that points to the origin coords, doing so we can win a nice semitone effect for the video capture.<\/p>\n<p style=\"text-align: justify;\">On the other side, the class MotionTracker has a very simple motion detection implementation, it draws each frame of the Video Object\u00a0 over the last frame using BlendMode.DIFFERENCE and then thresholding filtering the pixels with a color higher than 0x111111<\/p>\n<p style=\"text-align: justify;\">Here the code of the detection<\/p>\n<p>[as]<br \/>\nprivate function tictac(event:TimerEvent) : void{<\/p>\n<p>\/\/ locking bitmapdatas for better performance<br \/>\ncurrent.lock();<br \/>\noutput.lock();<br \/>\ninput.lock();<br \/>\n\/\/ a current copy from the source<br \/>\ncurrent.draw(source);<br \/>\n\/\/ making a temporary copy of currentFrame to work with both input and current<br \/>\nvar temp : BitmapData = current.clone();<br \/>\n\/\/ here we are drawing the previous frame on top of the current and the difference blendMode will make the rest<br \/>\ntemp.draw(input, null, null, BlendMode.DIFFERENCE);<br \/>\n\/\/ filter the pixels tha are greater than darkgrey #111111 and thresholding them into blue #0000FF overwriting the previous bmp<br \/>\ntemp.threshold(temp, temp.rect, temp.rect.topLeft, &#8220;&gt;&#8221;, 0xFF111111, 0xFF0000FF, 0x00FFFFFF, true);<br \/>\n\/\/ resets output&#8217;s color information<br \/>\noutput.fillRect(output.rect, 0xFF000000);<br \/>\n\/\/ stores the current frame wich will be the previous on the next tictac<br \/>\ninput = current.clone();<br \/>\n\/\/ thresholding the temp bitmapdata into the output bitmapdata with &#8216;equal&#8217; colors<br \/>\noutput.threshold(temp, output.rect, output.rect.topLeft, &#8220;==&#8221;, 0xFF0000FF, 0xFF0000FF, 0x00FFFFFF, false);<br \/>\n\/\/ unlocking bitmapdatas<br \/>\ncurrent.unlock();<br \/>\noutput.unlock();<br \/>\ninput.unlock();<br \/>\n\/\/ cleaning memory<br \/>\ntemp.dispose();<\/p>\n<p>}<br \/>\n[\/as]<\/p>\n<p style=\"text-align: justify;\">I think it would be interesting if the particles would move randomly at the same point where the movement was detected by the motionTracker, and here we go.<\/p>\n<p>The Particle class has two methods to move scale and position, it implements a wonderful bouncing easing equation seen at <a href=\"http:\/\/jot.eriknatzke.com\/?p=217\" target=\"_blank\">Erik Natzke&#8217;s blog<\/a> and one method to modify the internal position Point to a random value.<\/p>\n<p>[as]<br \/>\npublic function moveScale(scale : Number) : void{<\/p>\n<p>scaleX -= ax = (ax + (scaleX &#8211; (scale * 3)) * div) * .9;<br \/>\nscaleY -= ay = (ay + (scaleY &#8211; (scale * 3)) * div) * .9;<\/p>\n<p>}<\/p>\n<p>public function movePosition(p : Point) : void{<\/p>\n<p>x -= bx = (bx + (x &#8211; (p.x)) * div) * .5;<br \/>\ny -= by = (by + (y &#8211; (p.y)) * div) * .5;<\/p>\n<p>}<\/p>\n<p>public function flight() : void{<\/p>\n<p>position.x = staticPosition.x &#8211; (Math.random() * 200 * sign());<br \/>\nposition.y = staticPosition.y &#8211; (Math.random() * 200 * sign());<\/p>\n<p>}<\/p>\n<p>public function unFlight() : void{<\/p>\n<p>position.x = staticPosition.x;<br \/>\nposition.y = staticPosition.y;<\/p>\n<p>}<br \/>\n[\/as]<br \/>\nThese methods are called from the Main class at the enterframe handler<br \/>\n[as]<br \/>\nwhile(p.next != null){<\/p>\n<p>var color : uint = bmd.getPixel(p.origin.x, p.origin.y);<br \/>\nvar scale : Number = color \/ 0xFFFFFF;<\/p>\n<p>if(motion.output.getPixel(p.origin.x, p.origin.y) != 0){<\/p>\n<p>p.flight();<\/p>\n<p>} else{<br \/>\np.unFlight();<br \/>\n}<\/p>\n<p>p.moveScale(scale);<br \/>\np.movePosition(p.position);<br \/>\np.color = color;<br \/>\n\/\/ p.color = colors[Math.floor( scale * colors.length )];<br \/>\np = p.next;<\/p>\n<p>}<br \/>\n[\/as]<\/p>\n<p style=\"text-align: justify;\">And <a href=\"http:\/\/labs.miaumiau.cat\/examples\/dottedMeow\/Dotted.zip\" target=\"_blank\">here<\/a> the complete <a href=\"http:\/\/labs.miaumiau.cat\/examples\/dottedMeow\/Dotted.zip\" target=\"_blank\">source<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WEBCAM REQUIRED. I&#8217;ve been playing around with the webcam on AS3 and finally i got into something i liked. Basically what I&#8217;m doing here is to generate a grid of shapes keeping references between objects using a linked list. I am working with a small video size to optimize performance, so I keep two positions [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-475","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=\/wp\/v2\/posts\/475","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=475"}],"version-history":[{"count":2,"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=\/wp\/v2\/posts\/475\/revisions"}],"predecessor-version":[{"id":673,"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=\/wp\/v2\/posts\/475\/revisions\/673"}],"wp:attachment":[{"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.miaumiau.cat\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}