Interactive Physics Animations Javascript Canvas 01

Adding a second circle, always at twice the x and y as the first. The first is still draggable. View the source: interactive physics animations via javascript & canvas | 01

[cc lang=”javascript”]
$(function () {
var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
x = width / 2;
y = height / 2;
draw();

$(“#canvas”).mousedown(function (event) {
var dx, dy, dist;
dx = event.pageX – this.offsetLeft – x;
dy = event.pageY – this.offsetTop – y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) { drag = true; clickX = dx; clickY = dy; } else { drag = false; } }); $("#canvas").mouseup(function (event) { drag = false; }); $("#canvas").mousemove(function (event) { if(drag) { x = event.pageX - this.offsetLeft - clickX; y = event.pageY - this.offsetTop - clickY; draw(); } }); function draw() { context.clearRect(0, 0, width, height); context.beginPath(); context.arc(x, y, radius, 0, Math.PI * 2, false); context.arc(x*2, y*2, radius, 0, Math.PI * 2, false); context.fill(); } }); [/cc]

Interactive Javascript Canvas 00

I’ve played a lot with physics experiments in flash and moving more to javascript and canvas for simple things I wanted to test it out with some physics and animations. I’ve been curious to find out how the performance compares. Obviously this will depend on the browser, but the browsers that do support canvas should be able to handle some interactive physics animations.

I have this project I keep coming back to, it’s been in as2 and then in as3 and has have multiple faces. But the gist is there are a bunch of circles or balls and they float around in a specified area. There are physics “controls” exposed to the user and they can control the velocity of the balls, the gravity, air friction or drag, elasticity and they can even grab a ball and throw it across the stage (canvas). Here are a couple iterations of this: BFA Portfolio, Current Interactive POG Portfolio, Dribbble likes, Lastfm scrobbles.

I’m going to rebuild the basic functionality via javascript. I have had this on my list of things to explore for months now, in fact, ever since I saw Keith Peters go through his month long javascript exploration, he had a specific example that made me think I really needed to do it. I started and then life happened… But now I’m ready to start documenting my progress and trying to share what I’ve learned.

I’ll start with his initial example he titles JavaScript Day 27: Mouse Part II.
View my version here: interactive physics animations via javascript & canvas.

[cc lang=”javascript”]
$(function () {
var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
x = width / 2;
y = height / 2;
draw();

$(“#canvas”).mousedown(function (event) {
var dx, dy, dist;
dx = event.pageX – this.offsetLeft – x;
dy = event.pageY – this.offsetTop – y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) { drag = true; clickX = dx; clickY = dy; } else { drag = false; } }); $("#canvas").mouseup(function (event) { drag = false; }); $("#canvas").mousemove(function (event) { if(drag) { x = event.pageX - this.offsetLeft - clickX; y = event.pageY - this.offsetTop - clickY; draw(); } }); function draw() { context.clearRect(0, 0, width, height); context.beginPath(); context.arc(x, y, radius, 0, Math.PI * 2, false); context.fill(); } }); [/cc]

Interactive Javascript Canvas Series

I’ve been playing with canvas and different javascript drawing libraries a lot lately in my projects at work. I’ve been antsy to play with the techniques I’ve learned and apply it to some more interactive experiments. Much like my last series on generative art in flash, but this will all be in javascript! In case you’re extra interested in this type of stuff, go check out Keith Peters’ month long exploration into javascript on his bit-101 site, he’s did some great stuff, and I learned a lot from that. I’m not going to sign up to post every day or anything, but I’ll keep it going for a while at least. So, stay tuned! And let me know if you’re really wanting to see this go into any specific directions.

Here goes nothin’

A More Interactive Portfolio

I think a portfolio is something that should be very interactive and intuitive. Check out what that has led to: circlecube’s interactive pog portfolio. I’ve been toying with trying to get something that was fun to look at, but also showed some work. Here is a first look at my Interactive portfolio of work which includes physics simulations and many options to play with the presentation of the body of work. Showing it to a friend he said it made him think of pogs (since the thumbnails are round and moving everywhere).

Well, enough, I’ll let you see what you see… Interactive POG Portfolio

The details

Well, if you’re interested, this is the same portfolio that is listed statically on my website. That’s because I’m using amfphp to read my wordpress database and get the custom post type of portfolio and access all the tags, images and details of each portfolio item. I’m using TweenNano from greensock for some of the motion but all the physics is coded in as3. I’m using the slider and switch from Nick Jonas.

Enjoy playing with the settings!

Now I’m thinking of other ways to implement it: specifically hooking into API services like last.fm, dribbble or twitter. Or rebuild it with jQuery and html5!

Interactive Generative Art Series – 07 – multiple lines

gen-art-multi-lines 01gen-art-multi-lines 02gen-art-multi-lines 03

To make it more interesting and give more depth and texture to the display, I wanted to have more lines than one, so I’m now going with two for starters. Eventually I’d like to get up to a dozen or maybe even have them randomly self populate and die over time. Adding one more isn’t a whole lot of code, but it did require a bit of rearranging. I created a sprite container for each line, and then basically doubled any var used by one line for the other. When calculating the position for the second line I added a bit of randomness, so it wouldn’t be drawn in the exact same position of the first line. Plus, when drawing the second line I adjust the alpha/transparency a bit and the line width. A big issues that I notice right away is that the memory noticeably begins to suffer after a bit of drawing. After some investigation I determined it is (at least in part) the fact that the lines now have to blend with the lines below them with transparency. If I set the alpha properties in the lineGradientStyle to 1 and 1 the performance is much better. Any ideas of how to fix this? I’m guessing I should start investigating bitmap data.

07 multiline, play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ replaceId=”genart7″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/03/gen-art-07-multilines.swf” width=”550″ height=”550″ targetclass=”flashmovie”]

Please visit the blog article to view this interactive flash content. Flash plug-in required: Get Adobe Flash player

[/kml_flashembed]

actionscript source code

[cc lang=”actionscript”]
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x000000, 1);
ball.graphics.drawCircle(0, 0, 10);
ball.graphics.endFill();
addChild(ball);
var ball2:Sprite = new Sprite();
ball2.graphics.beginFill(0x000000, 1);
ball2.graphics.drawCircle(0, 0, 5);
ball2.graphics.endFill();
addChild(ball2);

var balllines:Sprite = new Sprite();
addChild(balllines);
var ball2lines:Sprite = new Sprite();
addChild(ball2lines);

var anchor:Sprite = new Sprite();

anchor.graphics.beginFill(0x333333, .6);
anchor.graphics.drawCircle(0, 0, 12);
anchor.graphics.endFill();
addChild(anchor);

var div:Number = .1;
var line_max_width:Number = 64;
var line_min_width:Number = 1;
var line_width:Number = randomRange(line_min_width, line_max_width);
var line_width_velocity:Number = 0;
var dampen:Number = 0.95;

var ballax:Number = 0;
var ballay:Number = 0;
var oldx:Number = ball.x;
var oldy:Number = ball.y;
var ball2ax:Number = 0;
var ball2ay:Number = 0;
var old2x:Number = ball2.x;
var old2y:Number = ball2.y;

var anchorvx:Number = 0;
var anchorvy:Number = 0;

anchor.x = stage.stageWidth/2;
anchor.y = stage.stageHeight/2;
ball2.x = randomRangeAxis(10);
var gradientBoxMatrix:Matrix = new Matrix();

var colors:Object = new Object();
colors.r = 255;
colors.g = 255;
colors.b = 255;
colors.rv = 0;
colors.gv = 0;
colors.bv = 0;
colors.rmin = 150; //0
colors.rmax = 250; //100
colors.gmin = 0; //100
colors.gmax = 150; //200
colors.bmin = 0; //150
colors.bmax = 100; //250
colors.rate_of_change = 12;
var color_first:Number = 0xFFFFFF;
var color_second:Number = rgb2hex(colors.r, colors.g, colors.b);

function loop () {

oldx = ball.x;
oldy = ball.y;
old2x = ball2.x;
old2y = ball2.y;

anchorvx += randomRangeAxis(10);
anchorvy += randomRangeAxis(10);

anchor.x += anchorvx;
anchor.y += anchorvy;

anchorvx *= dampen;
anchorvy *= dampen;

if(anchor.x > stage.stageWidth) {
anchor.x = 0 – anchor.width;
}
else if(anchor.x < 0 - anchor.width) { anchor.x = stage.stageWidth; } if(anchor.y > stage.stageHeight) {
anchor.y = 0 – anchor.height;
}
else if(anchor.y < 0 - anchor.height) { anchor.y = stage.stageHeight; } ball.x -= ballax = (ballax + (ball.x - anchor.x) * div) * .9; ball.y -= ballay = (ballay + (ball.y - anchor.y) * div) * .9; ball2.x -= ball2ax = (ball2ax + (ball2.x - (anchor.x + randomRangeAxis(line_width * 2))) * div) * .9; ball2.y -= ball2ay = (ball2ay + (ball2.y - (anchor.y + randomRangeAxis(line_width * 2))) * div) * .9; line_width_velocity += randomRangeAxis(1); line_width += line_width_velocity; line_width_velocity *= dampen; if(line_width > line_max_width) {
line_width = line_max_width;
line_width_velocity = 0;
}
else if (line_width < line_min_width) { line_width = line_min_width; line_width_velocity = 0; } color_step(); color_first = color_second; color_second = rgb2hex(colors.r, colors.g, colors.b); var dx:Number = ball.x - oldx; var dy:Number = ball.y - oldy; balllines.graphics.lineStyle(line_width, color_first, (line_width+100-line_max_width)/100, true, LineScaleMode.NONE, CapsStyle.NONE); gradientBoxMatrix.createGradientBox(Math.abs(dx), Math.abs(dy), Math.atan2(dy,dx), Math.min(oldx, ball.x), Math.min(oldy, ball.y)); balllines.graphics.lineGradientStyle(GradientType.LINEAR, [color_first, color_second], [(line_width+100-line_max_width)/100,(line_width+100-line_max_width)/100], [0, 255], gradientBoxMatrix); balllines.graphics.lineTo(ball.x, ball.y); dx = ball2.x - old2x; dy = ball2.y - old2y; ball2lines.graphics.lineStyle(line_width/2, color_first, (line_width+100-line_max_width)/100, true, LineScaleMode.NONE, CapsStyle.NONE); gradientBoxMatrix.createGradientBox(Math.abs(dx), Math.abs(dy), Math.atan2(dy,dx), Math.min(old2x, ball2.x), Math.min(old2y, ball2.y)); ball2lines.graphics.lineGradientStyle(GradientType.LINEAR, [color_first + 3072, color_second + 3072], [((line_width/2)+100-line_max_width)/100,((line_width/2)+100-line_max_width)/100], [0, 255], gradientBoxMatrix); ball2lines.graphics.lineTo(ball2.x, ball2.y); }setInterval(loop, 1000/30);function rgb2hex(r:Number, g:Number, b:Number):Number { return(r<<16 | g<<8 | b); } function color_step(){ colors.rv += randomRangeAxis(colors.rate_of_change); colors.r += colors.rv; colors.rv *= dampen; if (colors.r > colors.rmax) {
colors.r = colors.rmax;
} else if (colors.r < colors.rmin){ colors.r = colors.rmin; } colors.gv += randomRangeAxis(colors.rate_of_change); colors.g += colors.gv; colors.gv *= dampen; if (colors.g > colors.gmax) {
colors.g = colors.gmax;
} else if (colors.g < colors.gmin){ colors.g = colors.gmin; } colors.bv += randomRangeAxis(colors.rate_of_change); colors.b += colors.bv; colors.bv *= dampen; if (colors.b > colors.bmax) {
colors.b = colors.bmax;
} else if (colors.b < colors.bmin){ colors.b = colors.bmin; } } //random number between min and max function randomRange(max:Number, min:Number = 0):Number { return Math.random() * (max - min) + min; } //random number range centered at 0 with the specified max, randomRange(-max, max) function randomRangeAxis(max:Number, axis:Number = 0):Number { return Math.random() * (max * 2) - max + axis; } [/cc]

download

Here’s the gen-art-07-multilines.swf as well as the gen-art-07-multilines.fla to download and tinker.

Interactive Generative Art Series – 06 – lineStyle

gen-art-06-linestyle-1gen-art-06-linestyle-2gen-art-06-linestyle-3

The last example in this series discussed getting the anchor to move in a way that our ball would paint more interesting and we worked on restricting the colors to a certain RGB range. This one is a very simple change, but has a pretty significant effect. We’re just editing the cap style of our lines in lineStyle. The default value we’ve been using so far is ROUND, but now if we test NONE the lines drawn will have no ends and basically be rectangles (since the width is so wide). This gets interesting especially when the path curves and we can see all the angles and corners exposed by the rectangles and it makes me think of a wooden snake toy (Wooden Wiggle Snake). I started playing around with the opacity or alpha property of the lines as well so that the flat ended lines would show better. What else would you toy with in here?

06 lineStyle, play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ replaceId=”gen-art-6″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/02/gen-art-06-linestyle.swf” width=”550″ height=”550″ targetclass=”flashmovie”]

Please visit the blog article to view this interactive flash content. Flash plug-in required: Get Adobe Flash player

[/kml_flashembed]

actionscript source code

[cc lang=”actionscript”]
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x000000, 1);
ball.graphics.drawCircle(0, 0, 10);
ball.graphics.endFill();
addChild(ball);

var anchor:Sprite = new Sprite();

anchor.graphics.beginFill(0x333333, .6);
anchor.graphics.drawCircle(0, 0, 12);
anchor.graphics.endFill();
addChild(anchor);

var div:Number = .1;
var line_max_width:Number = 64;
var line_min_width:Number = 2;
var line_width:Number = randomRange(line_min_width, line_max_width);
var line_width_velocity:Number = 0;
var dampen:Number = 0.95;

var ballax:Number = 0;
var ballay:Number = 0;
var oldx:Number = ball.x;
var oldy:Number = ball.y;

var anchorvx:Number = 0;
var anchorvy:Number = 0;

anchor.x = stage.stageWidth/2;
anchor.y = stage.stageHeight/2;
var gradientBoxMatrix:Matrix = new Matrix();

var colors:Object = new Object();
colors.r = 255;
colors.g = 255;
colors.b = 255;
colors.rv = 0;
colors.gv = 0;
colors.bv = 0;
colors.rmin = 0;
colors.rmax = 150;
colors.gmin = 100;
colors.gmax = 200;
colors.bmin = 200;
colors.bmax = 250;
colors.rate_of_change = 12;
var color_first:Number = 0xFFFFFF;
var color_second:Number = rgb2hex(colors.r, colors.g, colors.b);

function loop () {

oldx = ball.x;
oldy = ball.y;

anchorvx += randomRangeAxis(10);
anchorvy += randomRangeAxis(10);

anchor.x += anchorvx;
anchor.y += anchorvy;

anchorvx *= dampen;
anchorvy *= dampen;

if(anchor.x > stage.stageWidth) {
anchor.x = 0 – anchor.width;
}
else if(anchor.x < 0 - anchor.width) { anchor.x = stage.stageWidth; } if(anchor.y > stage.stageHeight) {
anchor.y = 0 – anchor.height;
}
else if(anchor.y < 0 - anchor.height) { anchor.y = stage.stageHeight; } ball.x -= ballax = (ballax + (ball.x - anchor.x) * div) * .9; ball.y -= ballay = (ballay + (ball.y - anchor.y) * div) * .9; line_width_velocity += randomRangeAxis(1); line_width += line_width_velocity; line_width_velocity *= dampen; if(line_width > line_max_width) {
line_width = line_max_width;
line_width_velocity = 0;
}
else if (line_width < line_min_width) { line_width = line_min_width; line_width_velocity = 0; } color_step(); color_first = color_second; color_second = rgb2hex(colors.r, colors.g, colors.b); var dx:Number = ball.x - oldx; var dy:Number = ball.y - oldy; this.graphics.lineStyle(line_width, color_first, (line_width+100-line_max_width)/100, true, LineScaleMode.NONE, CapsStyle.NONE); gradientBoxMatrix.createGradientBox(Math.abs(dx), Math.abs(dy), Math.atan2(dy,dx), Math.min(oldx, ball.x), Math.min(oldy, ball.y)); this.graphics.lineGradientStyle(GradientType.LINEAR, [color_first, color_second], [(line_width+100-line_max_width)/100,(line_width+100-line_max_width)/100], [0, 255], gradientBoxMatrix); this.graphics.lineTo(ball.x, ball.y); }setInterval(loop, 1000/30);function rgb2hex(r:Number, g:Number, b:Number):Number { return(r<<16 | g<<8 | b); } function color_step(){ colors.rv += randomRangeAxis(colors.rate_of_change); colors.r += colors.rv; colors.rv *= dampen; if (colors.r > colors.rmax) {
colors.r = colors.rmax;
} else if (colors.r < colors.rmin){ colors.r = colors.rmin; } colors.gv += randomRangeAxis(colors.rate_of_change); colors.g += colors.gv; colors.gv *= dampen; if (colors.g > colors.gmax) {
colors.g = colors.gmax;
} else if (colors.g < colors.gmin){ colors.g = colors.gmin; } colors.bv += randomRangeAxis(colors.rate_of_change); colors.b += colors.bv; colors.bv *= dampen; if (colors.b > colors.bmax) {
colors.b = colors.bmax;
} else if (colors.b < colors.bmin){ colors.b = colors.bmin; } } //random number between min and max function randomRange(max:Number, min:Number = 0):Number { return Math.random() * (max - min) + min; } //random number range centered at 0 with the specified max, randomRange(-max, max) function randomRangeAxis(max:Number, axis:Number = 0):Number { return Math.random() * (max * 2) - max + axis; } [/cc]

download

Here’s the gen-art-06-linestyle.swf as well as the gen-art-06-linestyle.fla to download and tinker.

Reference

Interactive Generative Art Series – 05 – wild anchor

gen-art-05-wild-anchor-1gen-art-05-wild-anchor-2gen-art-05-wild-anchor-3

While in the previous step (Generative Art 04 Using a target other than the mouse) in this generative actionscript art tutorial series it was cool to see everything move on it’s very own, it seemed a bit slow or fake, or maybe just plain uninteresting. Tinkering with the color, I thought if we set a minimum and maximum value for each red green and blur we could control the colors a bit more and still let them be generative. Plus I wanted the anchor to move a bit more and thus paint the curves and lines in a more interesting fashion. To do this we ramp up the range of the change rate of the anchor velocity. I really enjoy this example because it is faster, so we get more of those sweeping arcs, but also when the anchor slows down we get some very delicate curves and twists. With just a couple changes from the last example (which frankly seemed a bit chaotic), now I’m starting to see for the first time how to set some controls in the code which will lead to a visually appealing and still randomly generative result.
gen-art-05-wild-anchor-4gen-art-05-wild-anchor-5gen-art-05-wild-anchor-6

For some reason I find it gratifying that the final swf is still a mere 2kb and change. Perhaps all this current focus on HD and 3D gives us the sense that to be good it needs to have a large footprint. Sometimes the magic or value is in how much you can accomplish with less (less is more)

05 Wild Anchor, play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/02/gen-art-05-wild-anchor.swf” width=”550″ height=”550″ targetclass=”flashmovie”]

Please visit the blog article to view this interactive flash content. Flash plug-in required: Get Adobe Flash player

[/kml_flashembed]

actionscript source code

[cc lang=”actionscript”]
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x000000, .5);
ball.graphics.drawCircle(0, 0, 5);
ball.graphics.endFill();
addChild(ball);

var anchor:Sprite = new Sprite();
anchor.graphics.beginFill(0x333333, .5);
anchor.graphics.drawCircle(0, 0, 12);
anchor.graphics.endFill();
addChild(anchor);

var div:Number = .1;
var line_max_width:Number = 48;
var line_min_width:Number = 1;
var line_width:Number = randomRange(line_min_width, line_max_width);
var line_width_velocity:Number = 0;
var dampen:Number = 0.95;

var ballax:Number = 0;
var ballay:Number = 0;
var oldx:Number = ball.x;
var oldy:Number = ball.y;

var anchorvx:Number = 0;
var anchorvy:Number = 0;

anchor.x = stage.stageWidth/2;
anchor.y = stage.stageHeight/2;

var colors:Object = new Object();
colors.r = 255;
colors.g = 255;
colors.b = 255;
colors.rv = 0;
colors.gv = 0;
colors.bv = 0;
colors.rmin = 150; //0
colors.rmax = 250; //100
colors.gmin = 0; //100
colors.gmax = 150; //200
colors.bmin = 0; //150
colors.bmax = 100; //250
colors.rate_of_change = 12;
var color_first:Number = 0xFFFFFF;
var color_second:Number = rgb2hex(colors.r, colors.g, colors.b);
var gradientBoxMatrix:Matrix = new Matrix();

function loop () {

oldx = ball.x;
oldy = ball.y;

anchorvx += randomRangeAxis(10);
anchorvy += randomRangeAxis(10);

anchor.x += anchorvx;
anchor.y += anchorvy;

anchorvx *= dampen;
anchorvy *= dampen;

if(anchor.x > stage.stageWidth) {
anchor.x = 0 – anchor.width;
}
else if(anchor.x < 0 – anchor.width) { anchor.x = stage.stageWidth; } if(anchor.y > stage.stageHeight) {
anchor.y = 0 – anchor.height;
}
else if(anchor.y < 0 – anchor.height) { anchor.y = stage.stageHeight; } ball.x -= ballax = (ballax + (ball.x – anchor.x) * div) * .9; ball.y -= ballay = (ballay + (ball.y – anchor.y) * div) * .9; line_width_velocity += randomRangeAxis(1); line_width += line_width_velocity; line_width_velocity *= dampen; if(line_width > line_max_width) {
line_width = line_max_width;
line_width_velocity = 0;
}
else if (line_width < line_min_width) {
line_width = line_min_width;
line_width_velocity = 0;
}

color_step();
color_first = color_second;
color_second = rgb2hex(colors.r, colors.g, colors.b);

var dx:Number = ball.x – oldx;
var dy:Number = ball.y – oldy;
this.graphics.lineStyle(line_width);
gradientBoxMatrix.createGradientBox(Math.abs(dx), Math.abs(dy), Math.atan2(dy,dx), Math.min(oldx, ball.x), Math.min(oldy, ball.y));
this.graphics.lineGradientStyle(GradientType.LINEAR, [color_first, color_second], [1,1], [0, 255], gradientBoxMatrix);
this.graphics.lineTo(ball.x, ball.y);
}

setInterval(loop, 1000/30);
function rgb2hex(r:Number, g:Number, b:Number):Number {
return(r<<16 | g<<8 | b); } function color_step(){ colors.rv += randomRangeAxis(colors.rate_of_change); colors.r += colors.rv; colors.rv *= dampen; if (colors.r > colors.rmax) {
colors.r = colors.rmax;
} else if (colors.r < colors.rmin){ colors.r = colors.rmin; } colors.gv += randomRangeAxis(colors.rate_of_change); colors.g += colors.gv; colors.gv *= dampen; if (colors.g > colors.gmax) {
colors.g = colors.gmax;
} else if (colors.g < colors.gmin){ colors.g = colors.gmin; } colors.bv += randomRangeAxis(colors.rate_of_change); colors.b += colors.bv; colors.bv *= dampen; if (colors.b > colors.bmax) {
colors.b = colors.bmax;
} else if (colors.b < colors.bmin){
colors.b = colors.bmin;
}
}
//random number between min and max
function randomRange(max:Number, min:Number = 0):Number {
return Math.random() * (max – min) + min;
}
//random number range centered at 0 with the specified max, randomRange(-max, max)
function randomRangeAxis(max:Number):Number {
return Math.random() * (max * 2) – max;
}

[/cc]

download

View the swf and get the fla source file.

Interactive Generative Art Series – 04 – anchor



Thanks for keeping up with this random generative art series. I know I’m having a ball just playing with code one step at a time. To watch each iteration, I was getting tired of drawing with my mouse to see the generative art, and as others had pointed out, in order for it to truly be generative, it shouldn’t depend on me moving my mouse. So instead of using the mouse position as my target anchor, I created a new node named anchor. This anchor I’m animating with simple random brownian motion which I’ve blogged about before. It just meanders along the stage as it pleases and the other ball will “chase” it just like it chased your mouse in the previous examples. The part that gets exciting is that my anchor wraps from one side of the stage to the other, while the ball does not. One second it’s target is far right and the next it switches to far left, this makes for some really interesting paths and lines. Experiment with the velocity of the anchor in lines 47 + 48 to see interesting effects. One thing I’m beginning to notice however is the performance of the little app gets a bit slower the longer you let it run, perhaps I didn’t realize it before since I didn’t have the attention to keep moving my mouse and watching it follow, now that it truly is generative (and less interactive btw), I watch it longer (seems kind of backwards to what I’d expect).

Note: in this example I have the anchor ball visible, as well as the other ball, but for an actual production, I’d have them both hidden and the lines just appearing. I prefer it that way but though you’d better see what was actually happening with them visible, even though it kills some of the magic. It’s like watching a magic trick when you already know how it’s done.

04 Anchor, play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ replaceId=”gen-art-4″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/02/gen-art-04-anchor.swf” width=”550″ height=”550″ targetclass=”flashmovie”]

Please visit the blog article to view this interactive flash content. Flash plug-in required: Get Adobe Flash player

[/kml_flashembed]

actionscript source code

[cc lang=”actionscript”]
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x000000, 0);
ball.graphics.drawCircle(0, 0, 5);
ball.graphics.endFill();
addChild(ball);

var anchor:Sprite = new Sprite();

anchor.graphics.beginFill(0x333333, 0);
anchor.graphics.drawCircle(0, 0, 12);
anchor.graphics.endFill();
addChild(anchor);

var div:Number = .1;
var line_max_width:Number = 42;
var line_min_width:Number = 2;
var line_width:Number = randomRange(line_min_width, line_max_width);
var line_width_velocity:Number = 0;
var dampen:Number = 0.95;

var ballax:Number = 0;
var ballay:Number = 0;
var oldx:Number = ball.x;
var oldy:Number = ball.y;

var anchorvx:Number = 0;
var anchorvy:Number = 0;

anchor.x = stage.stageWidth/2;
anchor.y = stage.stageHeight/2;

var colors:Object = new Object();
colors.r = 0;
colors.g = 122;
colors.b = 255;
colors.rv = 0;
colors.gv = 0;
colors.bv = 0;
colors.min = 0;
colors.max = 200;
var color_first:Number = 0xFFFFFF;
var color_second:Number = rgb2hex(colors.r, colors.g, colors.b);
var gradientBoxMatrix:Matrix = new Matrix();

function loop ()
{
oldx = ball.x;
oldy = ball.y;

anchorvx += randomRangeAxis(2);
anchorvy += randomRangeAxis(2);

anchor.x += anchorvx;
anchor.y += anchorvy;

anchorvx *= dampen;
anchorvy *= dampen;

if(anchor.x > stage.stageWidth) {
anchor.x = 0 – anchor.width;
}
else if(anchor.x < 0 – anchor.width) { anchor.x = stage.stageWidth; } if(anchor.y > stage.stageHeight) {
anchor.y = 0 – anchor.height;
}
else if(anchor.y < 0 – anchor.height) { anchor.y = stage.stageHeight; } ball.x -= ballax = (ballax + (ball.x – anchor.x) * div) * .9; ball.y -= ballay = (ballay + (ball.y – anchor.y) * div) * .9; line_width_velocity += randomRangeAxis(1); line_width += line_width_velocity; line_width_velocity *= dampen; if(line_width > line_max_width) {
line_width = line_max_width;
line_width_velocity = 0;
}
else if (line_width < line_min_width) {
line_width = line_min_width;
line_width_velocity = 0;
}

color_step();
color_first = color_second;
color_second = rgb2hex(colors.r, colors.g, colors.b);

var dx:Number = ball.x – oldx;
var dy:Number = ball.y – oldy;
this.graphics.lineStyle(line_width);
gradientBoxMatrix.createGradientBox(Math.abs(dx), Math.abs(dy), Math.atan2(dy,dx), Math.min(oldx, ball.x), Math.min(oldy, ball.y));
this.graphics.lineGradientStyle(GradientType.LINEAR, [color_first, color_second], [1,1], [85, 170], gradientBoxMatrix);
this.graphics.lineTo(ball.x, ball.y);
}

setInterval(loop, 1000/30);
function rgb2hex(r:Number, g:Number, b:Number):Number {
return(r<<16 | g<<8 | b); } function color_step(){ colors.rv += Math.random() * 20 – 10; colors.r += colors.rv; colors.rv *= dampen; if (colors.r > colors.max) {
colors.r = colors.max;
} else if (colors.r < colors.min){ colors.r = colors.min; } colors.gv += Math.random() * 20 – 10; colors.g += colors.gv; colors.gv *= dampen; if (colors.g > colors.max) {
colors.g = colors.max;
} else if (colors.g < colors.min){ colors.g = colors.min; } colors.bv += Math.random() * 20 – 10; colors.b += colors.bv; colors.bv *= dampen; if (colors.b > colors.max) {
colors.b = colors.max;
} else if (colors.b < colors.min){
colors.b = colors.min;
}
}
//random number between min and max
function randomRange(max:Number, min:Number = 0):Number {
return Math.random() * (max – min) + min;
}
//random number range centered at 0 with the specified max, randomRange(-max, max)
function randomRangeAxis(max:Number):Number {
return Math.random() * (max * 2) – max;
}

[/cc]

download

swf and fla source file.

Interactive Generative Flash Art Series – 00 – Line Width

After seeing the source code in the original experiment, I found myself wanting to play with the code. I saw many elements of the lines and actions that could be interesting to explore. This is the first in a series, of experiments I’ll post starting from this code and pushing different things each time. They’ll start slow and simple, like this one. All I’m doing is adding a few lines of code. The first thing I wanted to see from the original was a more gradual step in the width of the line. Here are a few screenshots from this iteration:

gen-art-00-line-width-1gen-art-00-line-width-2gen-art-00-line-width-3

Play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ replaceId=”gen-art-00″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/01/gen-art-00-line-width.swf” width=”550″ height=”550″ targetclass=”flashmovie”]

Please visit the blog article to view this interactive flash content. Flash plug-in required: Get Adobe Flash player

[/kml_flashembed]

Source Code

[cc lang=”actionscript”]
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x333333, 1);
ball.graphics.drawCircle(0, 0, 30);
ball.graphics.endFill();
addChild(ball);

var div:Number = .1;
var ax:Number = 0;
var ay:Number = 0;

var line_max_width:Number = 30;
var line_min_width:Number = 0;
var line_width:Number = Math.random() * line_max_width;
var line_width_velocity:Number = 0;
var dampen:Number = 0.95;

function loop () {
ball.x -= ax = (ax + (ball.x – mouseX) * div) * .9;
ball.y -= ay = (ay + (ball.y – mouseY) * div) * .9;

line_width_velocity += Math.random() * 4 – 2;
line_width += line_width_velocity;
line_width_velocity *= dampen;
if(line_width > line_max_width) { line_width = line_max_width; }
if (line_width < line_min_width) { line_width = line_min_width; }
this.graphics.lineStyle(line_width, 0, 1);
this.graphics.lineTo(ball.x, ball.y);
}

setInterval(loop, 1000/30);
[/cc]

Method Explained

If you need a little walk through on my method to achieve this, all I did was create a variable to hold my line width, and the line width velocity (or rate of change). Every frame the line velocity grows or shrinks randomly and is applied to the line width variable. I apply a dampen to the velocity so it doesn’t get too out of hand and then set some limits to the line width. Pretty simple and it applies the same method of applying velocity to an object to make it move, but this velocity is being applied to a property of the object (width) that may not be as obvious as position. This still gives an effect of random width to the lines, but they are randomly widening and thinning, rather than just having random widths. It gives it a more fluid appearance. Any other ways you would use to achieve the same effect?

Download

Here’s the swf in action as well as the fla.

Interactive Generative Flash Art Series Intro

The world has been excited by html5/css3 recently and has been pushing limits and experimenting. It’s been exciting and funny at the same time – most of the things that are amazing people in html5 experiments have been done 5 years ago in flash. I’ve enjoyed it so much though because it has brought me back to what made me fall for flash initially: sites like levitated.net and yugop.com. People that wrote books about programming actionscript like Keith Peters, Jim Bumgardener Colin Moock, Robert Penner etc… and then art by people like Erik Natzke. I’m a geek and these guys are some of my heros (and don’t think that list is exhausted, I’ve got plenty of unmentioned flash heros), but not just because they could/can do what they do, but because they selflessly (open source-ly) taught me how to do some of it. The magic of creating something so engaging, responsive, animated, unique, random. Little experiments that feel like they contain so much life and are so lightweight -easily less than 10,240 bytes (read 10kb). I knew in high school trig and calculus that those formulas had power, but seeing it unfold and interact with it really is magical to me.

ball-natzke-1ball-natzke-2ball-natzke-3

A little inspiration

So, I’ve been toying with a lot of the things that actually taught me (or at least pushed me to learn) the basics of programming. With the years experience under my belt now I’m understanding it on a totally different level and all I want to do is find more things to make balls and lines bounce, move and swirl. And I also want to share it. Well, I recently stumbled upon a flash sneak peak video by Erik Natzke about some of his technique and then his open source files and really had some fun. Anyways I wanted to share some of the experiments that came from it. Let me know your thoughts and download the code and play with it. Let me know what else you come up with and share what you learn. I’ll start this series with a post of the original experiment from Erik on his blog here, Flash Code 101.

Natzke’s Flash Code 101

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ replaceId=”alt-ball-natzke” movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/01/ball-natzke.swf” width=”550″ height=”550″ targetclass=”flashmovie”]

Please visit the blog article to view this interactive flash content. Flash plug-in required: Get Adobe Flash player

[/kml_flashembed]

If it looks like greek to you, I’d suggest going to Keith Peter’s tutorials (especially the first few on gravity, easing and elasticity).

Actionscript 3

For something so fun, it’s amazing that it’s barely over a dozen lines of code.
[cc lang=”actionscript”]
var Ball:Sprite = new Sprite();
Ball.graphics.beginFill(0x333333, 1);
Ball.graphics.drawCircle(0, 0, 30);
Ball.graphics.endFill();
addChild(Ball);

var div:Number = .1;
var ax:Number = 0;
var ay:Number = 0;

function loop () {
Ball.x -= ax = (ax + (Ball.x – mouseX) * div) * .9;
Ball.y -= ay = (ay + (Ball.y – mouseY) * div) * .9;
this.graphics.lineStyle(Math.random()*10, 0, 1);
this.graphics.lineTo(Ball.x, Ball.y);
}

setInterval(loop, 1000/30);
[/cc]

Here’s the swf in action, or download the fla to play (if you really would rather download a file than copy 15 lines of code).

Resolution

Well, I’ll be playing with this code and others and posting the experiments with some screenshots of what I create get’s created.