Juni 2009
Generative Kunst
Fortsetzung, Teil 2
Einfach gezeichnet
Ohne großen Aufwand haben wir somit ein recht komfortables System, das autonom zeichnet. Ab dieser Stelle können wir uns überlegen, den gesamten Prozess noch etwas zu verfeinern. Haben wir eben nur simple Formen gezeichnet, so fügen wir dem Regelwerk jetzt noch ein paar weiterführende Methoden hinzu:
- DropShadows: um die Konturen ein wenig zu verfeinern
- Ordnungsanweisungen: Formen können 2D- und 3D-rotieren
- BlendModes: nur der hellere/nur der dunklere Pixel wird gezeichnet
- Mix-Modus: das System wechselt ständig zwischen den Formen
Diese Erweiterung der Regelanweisungen erlaubt nun ein recht breites Spektrum an gezeichneten Resultaten. Um das Ganze anwenden zu können, müssen wir in unserem Script nur noch die if-Anweisung für level ausweiten (Listing 3).
if ( this.level == "plain" ) {///////////////////////////////////// ...plain-anweisungen haben wir// bereits definiert//////////////////////////////////////////////////////////////////////// enhanced zeichnungs-level///////////////////////////////////} else if ( this.level == "enhanced" ) {var shapeNode:Sprite = new Sprite();shapeNode.x = i;shapeNode.y = j;if ( this.mode == "FreeLines" ) {shapeNode.graphics.lineStyle( 10, this.imgMap.getPixel( i, j ) );shapeNode.graphics.moveTo( 0, 0 );shapeNode.graphics.lineTo( this.rnd() * 19, this.rnd() * 19 );} else if ( this.mode == "StructLines" ) {shapeNode.graphics.lineStyle( 14, this.imgMap.getPixel( i, j ) );shapeNode.graphics.moveTo( 0, 0 );shapeNode.graphics.lineTo( 12, 12 );} else if ( this.mode == "Circles" ) {shapeNode.graphics.beginFill( this.imgMap.getPixel( i, j ), 1.0 );shapeNode.graphics.drawCircle( 0, 0, 4 + this.rnd() * 20 );} else if ( this.mode == "FineSquares" ) {shapeNode.graphics.beginFill( this.imgMap.getPixel( i, j ), 1.0 );shapeNode.graphics.drawRect( 0, 0, 4 + this.rnd() * 6, 4 + this.rnd() * 6 );} else if ( this.mode == "BigSquares" ) {shapeNode.graphics.beginFill( this.imgMap.getPixel( i, j ), 1.0 );shapeNode.graphics.drawRect( 0, 0, 14 + this.rnd() * 26, 14 + this.rnd() * 26 );} else if ( this.mode == "StructSquares" ) {shapeNode.graphics.beginFill( this.imgMap.getPixel( i, j ), 1.0 );shapeNode.graphics.drawRect( 0, 0, 20, 20 );} else if ( this.mode == "StampedSquares" ) {w_x = 10 + rnd() * 20;w_y = 5 + rnd() * 10;shapeNode.graphics.lineStyle( 4, this.imgMap.getPixel( i, j ) );shapeNode.graphics.moveTo( 0, 0 );shapeNode.graphics.lineTo( w_x, 0 );shapeNode.graphics.lineTo( w_x, w_y );shapeNode.graphics.lineTo( 0, w_y );shapeNode.graphics.lineTo( 0, 0 );}if ( this.order == "rotate" ) {shapeNode.rotation = this.rnd() * 360;} else if ( this.order == "z_space" ) {shapeNode.rotationX = this.rnd() * 360;shapeNode.rotationY = this.rnd() * 360;shapeNode.rotationZ = this.rnd() * 360;} else if ( this.order == "chaos" ) {shapeNode.rotation = this.rnd() * 360;shapeNode.scaleX = shapeNode.scaleX + this.rnd() * 0.9;shapeNode.scaleY = shapeNode.scaleY + this.rnd() * 0.9;shapeNode.rotationX = this.rnd() * 360;shapeNode.rotationY = this.rnd() * 360;shapeNode.rotationZ = this.rnd() * 360;}if ( this.blend == "normal" ) {shapeNode.blendMode = "normal";} else if ( this.blend == "lighten" ) {shapeNode.blendMode = "lighten";} else if ( this.blend == "darken" ) {shapeNode.blendMode = "darken";}if ( this.anim ) {} else {shapeNode.filters = [ new DropShadowFilter( 4, 45, 0x0, .4, 2, 2, 1.2, 2, false, false, false ) ];}this.rootNode.addChild( shapeNode );}this.canvasMap.lock();this.canvasMap.draw( this.rootNode );this.canvasMap.unlock();if ( this.level == "enhanced" ) {if ( this.rootNode.getChildAt(0).name.indexOf( "anim", 0 ) == -1 ) {this.rootNode.removeChildAt( 0 );}}
Bewegende Momente
An sich ist das System nun gut ausgestattet, um alleine möglichst vielfältige Ergebnisse zu produzieren. Als eine letzte Bedingung bringen wir unserem Programm noch die Möglichkeit bei, einzelne Farbkleckse zu animieren. Damit wirkt der gesamte Zeichenprozess dynamischer. Aber auch das ist kein Voodoo, sondern bedarf nur einer kleinen Anpassung im Script (Listing 4, Abb. 2)
if ( this.anim ) {shapeNode.name ="anim"+String(i)+"_"+ String(j);if ( this.order == "rotate" ) {TweenLite.to( shapeNode, 1.2, { x:-15 + shapeNode.x + rnd() * 30, y:-15 + shapeNode.y + rnd() * 30, rotation:rnd()*360, onComplete:setName, onCompleteParams:[shapeNode], ease:Circ.easeOut} );} else {TweenLite.to( shapeNode, 1.2, { x:-15 + shapeNode.x + rnd() * 30, y:-15 + shapeNode.y + rnd() * 30, onComplete:setName, onCompleteParams:[shapeNode], ease:Sine.easeOut } );}shapeNode.filters = [ new DropShadowFilter( 4, 45, 0x0, .01, 2, 2, 1.2, 2, false, false, false ) ];} else {shapeNode.filters = [ new DropShadowFilter( 4, 45, 0x0, .4, 2, 2, 1.2, 2, false, false, false ) ];}private function setName( shape:Sprite ):void {shape.name = "done";}
Weitere Farbtupfer
Wie schon angedeutet, gleichen Bilder eines solchen Systems fast niemals einander. Somit ist mit einem einmal geschriebenen System eine fast unendliche Vielzahl an Resultaten möglich. Fast unbegrenzt sind ebenfalls die Möglichkeiten, den gesamten Prozess noch weiter auszubauen, zu verfeinern und komplexer zu gestalten.
Wer vorab erstmal seine Fühler ausstrecken und sich inspirieren lassen möchte, kann aber auch einfach ein schon fertiges Programm herunterladen und stöbern. Davon gibt es zu diesem Thema Unmengen an Quellen im Internet, z. B. Context Free Art oder Structure Synth, um nur zwei zu nennen.
Frank Reitberger (reitberger@anymotion.de) arbeitet und entwickelt als Flash-Teamleiter für anyMOTION GRAPHICS Internet- und Offlineanwendungen im B2C- und B2B-Bereich. Frank veröffentlicht unter seinem Nickname "pwdVergesser" auch viele seiner kleinen Flash-Snippets im Flashforum sowie in seinem Blog prinzipiell.com.
































