Content

Bill Gates Touched My Mac Book Pro

Blobs

Friday 7 August 2009 - Filed under ActionScript + Flash

Just kicking back with some good old fashioned Flash experimentation.


Get Adobe Flash player

Here’s the code:

[as]package
{
import com.bit101.components.CheckBox;
import com.bit101.components.Component;
import com.bit101.components.HUISlider;
import com.bit101.components.Knob;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;

[SWF(width=600, height=600, backgroundColor=0xdddddd, frameRate=31)]
public class Blobs extends Sprite
{
private var firm:Number;
private var firmSlider:HUISlider;

private var gravity:Number;
private var gravitySlider:HUISlider;

private var radius:Number;
private var radiusSlider:HUISlider;

private var rotate:Number;
private var rotationAmount:Number;
private var rotateKnob:Knob;

private var points:Array;
private var numPoints:int;

private var renderLinesCB:CheckBox;
private var renderLines:Boolean;

private var renderPointsCB:CheckBox;
private var renderPoints:Boolean;

private var renderOutlineSegments:Boolean;
private var renderOutlineSegmentsCB:CheckBox;

private var renderOutlineCurves:Boolean;
private var renderOutlineCurvesCB:CheckBox;

public function Blobs()
{
Component.initStage(stage);

points = new Array();
numPoints = 20;

firm = 0.05;
firmSlider = new HUISlider(this, 10, 10, “Firmness”, onFirmChange);
firmSlider.width = 580;
firmSlider.setSliderParams(0, .5, firm);
firmSlider.labelPrecision = 3;

gravity = 1.5;
gravitySlider = new HUISlider(this, 10, 22, “Gravity”, onGravityChange);
gravitySlider.width = 580;
gravitySlider.setSliderParams(0, 5, gravity);
gravitySlider.labelPrecision = 2;

radius = 100;
radiusSlider = new HUISlider(this, 10, 34, “Radius”, onRadiusChange);
radiusSlider.width = 580;
radiusSlider.setSliderParams(1, 250, radius);
radiusSlider.labelPrecision = 0;

renderPoints = true
renderPointsCB = new CheckBox(this, 10, 55, “Render Points”, onRenderPoints);
renderPointsCB.selected = true;

renderLines = true;
renderLinesCB = new CheckBox(this, 10, 70, “Render Lines”, onRenderLines);
renderLinesCB.selected = true;

renderOutlineSegments = true;
renderOutlineSegmentsCB = new CheckBox(this, 10, 85, “Render Outline Segments”, onRenderOutlineSegments);
renderOutlineSegmentsCB.selected = true;

renderOutlineCurves = false;
renderOutlineCurvesCB = new CheckBox(this, 10, 100, “Render Outline Curves”, onRenderOutlineCurves);
renderOutlineCurvesCB.selected = false;

rotate = 0;
rotationAmount = 0;
rotateKnob = new Knob(this, 250, 60, “Rotate”, onRotateChange);
rotateKnob.minimum = -.1;
rotateKnob.maximum = .1;
rotateKnob.value = 0;
rotateKnob.labelPrecision = 3;

for(var i:int = 0; i < numPoints; i++)
{
var angle:Number = Math.PI * 2 / numPoints * i;
points.push(new Dot(400 + Math.cos(angle) * 100, 400 + Math.sin(angle) * 100));
}

addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}

private function onFirmChange(event:Event):void
{
firm = firmSlider.value;
}

private function onGravityChange(event:Event):void
{
gravity = gravitySlider.value;
}

private function onRadiusChange(event:Event):void
{
radius = radiusSlider.value;
}

private function onRotateChange(event:Event):void
{
rotationAmount = rotateKnob.value;
}

private function onRenderPoints(event:Event):void
{
renderPoints = renderPointsCB.selected;
}

private function onRenderLines(event:Event):void
{
renderLines = renderLinesCB.selected;
}

private function onRenderOutlineSegments(event:Event):void
{
renderOutlineSegments = renderOutlineSegmentsCB.selected;
}

private function onRenderOutlineCurves(event:Event):void
{
renderOutlineCurves = renderOutlineCurvesCB.selected;
}

private function enterFrameHandler(event:Event):void
{
graphics.clear();
var cx:Number = 0;
var cy:Number = 0;
for(var i:int = 0; i < numPoints; i++)
{
var point:Dot = points[i];
point.update(gravity);
cx += point.x;
cy += point.y;
if(renderPoints)
{
graphics.beginFill(0);
graphics.drawCircle(point.x, point.y, 2);
graphics.endFill();
}
}
cx /= numPoints;
cy /= numPoints;
if(renderPoints)
{
graphics.beginFill(0xff0000);
graphics.drawCircle(cx, cy, 5);
graphics.endFill();
}

for(i = 0; i < numPoints; i++)
{
var angle:Number = Math.PI * 2 / numPoints * i + rotate;
var tx:Number = cx + Math.cos(angle) * radius;
var ty:Number = cy + Math.sin(angle) * radius;
point = points[i];
point.vx += (tx - point.x) * firm;
point.vy += (ty - point.y) * firm;
if(renderLines)
{
graphics.lineStyle(0, 0, .25);
graphics.moveTo(cx, cy);
graphics.lineTo(point.x, point.y);
}
if(renderOutlineSegments && i > 0)
{
graphics.lineStyle(0, 0x0000ff, 0.5);
graphics.moveTo(points[i - 1].x, points[i - 1].y);
graphics.lineTo(point.x, point.y);
}
}
if(renderOutlineSegments)
{
graphics.lineStyle(0, 0x0000ff, 0.25);
graphics.moveTo(points[i - 1].x, points[i - 1].y);
graphics.lineTo(points[0].x, points[0].y);
}
if(renderOutlineCurves)
{
renderCurves();
}
rotate += rotationAmount;
}

private function renderCurves():void
{
var mids:Array = new Array();
for(var i:int = 0; i < points.length - 1; i++)
{
mids[i] = new Point((points[i].x + points[i + 1].x) / 2, (points[i].y + points[i + 1].y) / 2);
}
mids[i] = new Point((points[i].x + points[0].x) / 2, (points[i].y + points[0].y) / 2);
graphics.lineStyle(0, 0xff0000, .5);
graphics.moveTo(mids[0].x, mids[0].y);
for(i = 1; i < points.length; i++)
{
graphics.curveTo(points[i].x, points[i].y, mids[i].x, mids[i].y);
}
graphics.curveTo(points[0].x, points[0].y, mids[0].x, mids[0].y);
}
}
}[/as]

And you'll need this too:

[as]package
{
public class Dot
{
public var x:Number;
public var y:Number;
public var vx:Number;
public var vy:Number;

public function Dot(x:Number, y:Number)
{
this.x = x;
this.y = y;
vx = Math.random() * 10 - 5;
vy = Math.random() * 10 - 5;
}

public function update(gravity:Number):void
{
x += vx;
y += vy;
vy += gravity;
if(x < 0)
{
x = 0;
vx = 0;
vy = 0;
}
if(x > 600)
{
x = 600;
vx = 0;
vy = 0;
}
if(y > 600)
{
y = 600;
vy = 0;
vx = 0;
}
vx *= .99;
vy *= .99;
}
}
}[/as]

And, if you want it to run as-is, you’ll need my minimal comps.

2009-08-07  »  keith

Talkback x 9

  1. sascha/hdrs
    8 August 2009 @ 1:39 am

    It’s good to have you back in AS land again! It was a hard and tough time for us all but now that you’re back things are getting back to positive again. ^_-

  2. nicoptere
    8 August 2009 @ 2:45 am

    hi,
    glad to have you back to AS indeed ^^

    I think you can make your blob more robust by adding a second row of balls & sticks as described in this article : http://cowboyprogramming.com/2007/01/05/blob-physics/

  3. Julien
    8 August 2009 @ 6:15 am

    Pretty cool !
    Now I remember why I subscribed to this blog in the first place.
    I kept reading though, don’t get me wrong ;)

  4. kp
    8 August 2009 @ 9:52 am

    nicoptere, thanks for the link. interesting that I started out on a similar path.

  5. Paul Gregoire
    8 August 2009 @ 11:25 am

    Cool.. and while trying to get it to walk up the walls, I managed to get a circle floating on the bottom right.. ;)

  6. Isak
    8 August 2009 @ 2:17 pm

    Wow, that is really cool.

  7. david
    9 August 2009 @ 1:09 am

    I don’t like the knob. It doesn’t respond quite like I expect.

  8. dVyper
    10 August 2009 @ 11:59 am

    Very nice. I played with it for quite a while :)

  9. Michael
    21 August 2009 @ 9:23 pm

    love it – really interesting how satisfying physics toys are to play with

Share your thoughts

Re: Blobs







Tags you can use (optional):
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>