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 Art Series – 02 – Random Color

gen-art-02-1gen-art-02-2gen-art-02-3

With this example we’re taking a look at having randomly changing color. I liked the limits to the color in the last post, but couldn’t help myself and wanted to see it with the full range of colors to command. Also, I wasn’t a huge fan when the color would “wrap” and jump from one color to the next so fast. I wanted to use the same velocity (rate of change) principle from the line width experiment but apply it to color, and have it meander aimlessly among all colors. I created a color object to store a value for each of the RGB color values, and then had each element of the color change independently. I didn’t want to complicate my loop function so I made a new function that is called from loop that steps along to a color which should be pretty close to the previous color. I enjoy the range, but as I expected it was a bit much, or too many colors at once, also the step is a bit too fast at times it seems.

02 Color, play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/02/gen-art-02-color.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(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 = 50;
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;

var colors:Object = new Object();
colors.r = 0;
colors.g = 0;
colors.b = 255;
colors.rv = 0;
colors.gv = 0;
colors.bv = 0;

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() * 6 – 3;
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; }

color_step();

this.graphics.lineStyle(line_width, rgb2hex(colors.r, colors.g, colors.b), 1);
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 > 255) {
colors.r = 255;
} else if (colors.r < 0){ colors.r = 0; } colors.gv += Math.random() * 20 – 10; colors.g += colors.gv; colors.gv *= dampen; if (colors.g > 255) {
colors.g = 255;
} else if (colors.g < 0){ colors.g = 0; } colors.bv += Math.random() * 20 – 10; colors.b += colors.bv; colors.bv *= dampen; if (colors.b > 255) {
colors.b = 255;
} else if (colors.b < 0){
colors.b = 0;
}
}
[/cc]

Download

View the swf and get the fla here

Interactive Generative Art Series – 01 – Color

gen-art-01-color-1gen-art-01-color-2gen-art-01-color-3
After updating the line width to be still random, but more of a gradual step in variation (in the first experiment in this series), the second most obvious edit to the original in this generative art series is the color of the line. While it would be pretty simple to update the code to use any one solid color in place of the black, I wanted the color to vary over time. The simplest way I know to achieve this is to create a variable to hold the color value (as a number) and then change it over time. So here, I have a color chosen at random and just increment it every time the loop function executes by 1024. I chose this amount because it would loop through and eventually get back to where it started while restricting the color scheme. I think it brings a lot to the design to have color – and I especially like how it randomly creates a color scheme and sticks to it. Totally random colors may look a bit much, while problematically it’s not too difficult to get, it may be difficult to look at once it’s created. Above are a few screen shots of the random colors generated:

01 Color, play here

[kml_flashembed publishmethod=”dynamic” fversion=”9.0.0″ replaceId=”gen-art-01″ movie=”https://circlecube.com/circlecube/wp-content/uploads/sites/10/2011/01/gen-art-01-color.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 = 50;
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;

var color:Number = Math.floor(Math.random() * 16777215);

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() * 6 – 3;
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, color+=1024, 1);
this.graphics.lineTo(ball.x, ball.y);
}

setInterval(loop, 1000/30);
[/cc]
You’ll see if you’re following along that this only add 2 lines of code from the last version. We simply create and instantiate (with a random value) the color variable and then apply it in place of the black to the lineStyle and simultaneously increment it. Check the example swf here and get the fla here.

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.