Zurück   Flashforum > Flash > Stuff

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 24-03-2011, 07:11   #1 (permalink)
Neuer User
 
Registriert seit: Nov 2005
Beiträge: 548
Filaments (Flames) - A Tribute To FlamePainter

Hi,
inspiriert von FlamePainter, auch genannt in diesem Thread, musste ich mal sehen ob und wie man sowas in Flash hinbekommen kann...
Das Proof-Of-Concept unten entspricht in etwa den Formen der o.g. Applikation, wenn man dort "Chaos" auf 0 dreht und "Smooth" und "Fill" ausschaltet.
Das Prinzip: eine Mauszeigerverfolgung mit n Punkten mit leicht verschiedenen Eigenschaften (Reaktion, Geschwindigkeit, Deckkraft,...). Bei gedrückter Maustaste wird für jeden Punkt eine Linie von der alten zur neuen Position gezeichnet. That's all. Damit es schnell bleibt, werden je Frame nur die aktuellen Linien gezeichnet und in ein BitmapData mit "add" kopiert, dadurch kommt auch der "Glüheffekt" zustande. Zeile 83 (//grid drawing) zeichnet bei Bedarf auch die Querlinien, dann hat man einen Netzeffekt.
Die nächsten Schritte wären nun: Kurven statt Linien zwischen den Punkten zeichnen und die Flächen des Grids interpoliert füllen (Farben auf Flächen interpolieren wäre die perfekte Aufgabe für Molehill), dann bekäme man diese weichen Flächen wie in FlamePainter.

Da das Grundprinzip sehr übersichtlich ist, dachte ich, ich bereichere mal diesen Thread mit dieser grafischen Spielerei :-)

Als Dokumentklasse angelegt:
ActionScript:
  1. package
  2. {
  3.    import flash.display.Bitmap;
  4.    import flash.display.BitmapData;
  5.    import flash.display.BlendMode;
  6.    import flash.display.Sprite;
  7.    import flash.events.Event;
  8.    import flash.events.MouseEvent;
  9.    import flash.display.StageAlign;
  10.    
  11.    /**
  12.     * ...
  13.     * @author jo
  14.     */
  15.    
  16.     [SWF(backgroundColor = "#000000", frameRate = "80", quality = "LOW", width = "1920", height = "1080")]
  17.  
  18.    public class Filaments extends Sprite
  19.    {
  20.       private var mbt:Boolean=false;
  21.       private var spots:Array=new Array();
  22.       private var cursors:Sprite=new Sprite();
  23.       private var drawing:Sprite=new Sprite();
  24.       private var drawing2:Sprite = new Sprite();
  25.       private var bmp:BitmapData;
  26.       private var bitmap:Bitmap = new Bitmap();
  27.  
  28.       public function Filaments():void
  29.       {
  30.          if (stage) init();
  31.          else addEventListener(Event.ADDED_TO_STAGE, init);
  32.       }
  33.        
  34.       private function init(e:Event = null):void
  35.       {
  36.          removeEventListener(Event.ADDED_TO_STAGE, init);
  37.          // entry point
  38.                    
  39.          stage.addChild(bitmap);
  40.      bitmap.smoothing=true;
  41.          stage.addChild(cursors);
  42.          resize(null);
  43.          
  44.          for(var i:int=0;i<80;i++){
  45.             spots[i]={ox:0,oy:0,px:0,py:0,vx:0,vy:0,speed:i/80+0.1,alpha:1-Math.pow(Math.sin(i/40*3.14),2),delay:0.88};
  46.          }
  47.        
  48.          stage.frameRate = 80;
  49.          stage.align=StageAlign.TOP_LEFT;
  50.          stage.addEventListener(Event.RESIZE, resize);
  51.          stage.addEventListener(Event.ENTER_FRAME,mainloop);
  52.          stage.addEventListener(MouseEvent.MOUSE_DOWN,mButton);
  53.          stage.addEventListener(MouseEvent.MOUSE_UP,mButton);
  54.       }
  55.        
  56.        
  57.       private function mainloop(event:Event):void{
  58.          cursors.graphics.clear();
  59.          cursors.graphics.lineStyle(1, 0xCCCCCC);
  60.          drawing.graphics.clear();
  61.          drawing2.graphics.clear();
  62.          for(var i:int=0;i<spots.length;i++){
  63.            var spot:Object=spots[i];
  64.            var dx:Number=stage.mouseX-spot.px;
  65.            var dy:Number=stage.mouseY-spot.py;
  66.            spot.vx=spot.vx*spot.delay+dx*(1-spot.delay);
  67.            spot.vy=spot.vy*spot.delay+dy*(1-spot.delay);
  68.            spot.px+=spot.vx*spot.speed;
  69.            spot.py+=spot.vy*spot.speed;
  70.            cursors.graphics.drawCircle(spot.px,spot.py,1);
  71.            if(mbt){
  72.              drawing.graphics.lineStyle(1,0xFF4422,spot.alpha*0.3+0.1);
  73.              drawing2.graphics.lineStyle(1,0xFF4422,spot.alpha*0.3+0.1);
  74.              drawing.graphics.moveTo(spot.ox,spot.oy);
  75.              drawing.graphics.lineTo(spot.px,spot.py);
  76.              if(i==0)drawing2.graphics.moveTo(spot.px,spot.py);
  77.              drawing2.graphics.lineTo(spot.px,spot.py);
  78.            }
  79.            spot.ox=spot.px;
  80.            spot.oy=spot.py;
  81.          }
  82.          bmp.draw(drawing,null,null,BlendMode.ADD);//track drawing
  83.          //bmp.draw(drawing2,null,null,BlendMode.ADD);//grid drawing
  84.       }
  85.  
  86.       private function mButton(event:MouseEvent):void{
  87.          mbt=(event.type==MouseEvent.MOUSE_DOWN);
  88.       }
  89.        
  90.        
  91.       private function resize(event:Event):void {
  92.          bmp=new BitmapData(stage.stageWidth,stage.stageHeight,false,0x000000);
  93.          bitmap.bitmapData = bmp;
  94.       }
  95.        
  96.        
  97.    }
  98.    
  99. }

Geändert von joeydee (24-03-2011 um 07:22 Uhr)
joeydee ist offline   Mit Zitat antworten
Alt 28-03-2011, 15:25   #2 (permalink)
Keine Panik
 
Registriert seit: Apr 2010
Ort: Düsseldorf (im ernst)
Beiträge: 1.869
sehr schön.
nachdem ich jetzt paar Tage mit rumgespielt habe häng ich auch mal an, was bei mir rumgekommen ist:
Zitat:
Die nächsten Schritte wären nun: Kurven statt Linien zwischen den Punkten zeichnen und die Flächen des Grids interpoliert füllen (Farben auf Flächen interpolieren wäre die perfekte Aufgabe für Molehill), dann bekäme man diese weichen Flächen wie in FlamePainter.
die Umsetzung auf curveTo war nicht sonderlich schwer, das füllen der Flächen war da schon aufwändiger.
in dem Code unten hab ich nun beide Varianten kombiniert:

Die Punkte (spot.px und spot.ox alias mouseX), werden nur noch als "Stützpunkte" für die Kurve verwendet.
nun wird eine beliebige Anzahl an Zwischenschritten auf einer quadratischen Bezierkurve berechnet (pro Spot), und mit diesem "Gitter" und der Funktion drawTriangles lassen sich schon jetzt sehr schön die Flächen füllen.

Der code müsste noch aufgeräumt werden, aber hier schonmal was zum kosten.
Bon Appétit (Demo im Anhang)
PHP-Code:
package  
{
    
import flash.display.Bitmap;
    
import flash.display.BitmapData;
    
import flash.display.BlendMode;
    
import flash.display.Graphics;
    
import flash.display.Shape;
    
import flash.display.Sprite;
    
import flash.display.TriangleCulling;
    
import flash.events.Event;
    
import flash.events.MouseEvent;
    
import flash.geom.Point;
    
import flash.ui.Mouse;
    
    
/**
     * ...
     * @author thomas ersosi
     */
    
[SWF(width="800"height="600"frameRate="40"backgroundColor="#000000"quality "LOW")]
    public class 
Filaments5 extends Sprite 
    
{
        
//Anzahl der Schritte die interpoliert werden sollen/frame
        //aus 1 neuen Punkt mach 1P+3Zwischenschritte
        
private var numSteps:uint 4;
        
//Anzahl der Punkte die an der Maus hängen
        
private var numSpots:uint 60;
        private var 
effect:String BlendMode.ADD;
        
        private var 
spots:Vector.<Spot> = new Vector.<Spot>();
        private var 
drawing:Shape = new Shape();
        private var 
cursors:Shape = new Shape();
        
        private var 
buffer:BitmapData;
        private var 
canvas:BitmapData;
        private var 
bCanvas:Bitmap = new Bitmap();
        private var 
palette:BitmapData = new BitmapData(10241true0);
        private var 
bPalette:Bitmap = new Bitmap(palette);
        
        private var 
vertices:Vector.<Number>;
        private var 
indices:Vector.<int>;
        private var 
uvtData:Vector.<Number>;

        private var 
isMouseDown:Boolean false;
        
        public function 
Filaments5() 
        {
            
super();
            
            if (
stageinit();
            else 
addEventListener(Event.ADDED_TO_STAGEinit);
        }
        
        private function 
init(e:Event=null):void 
        
{
            
removeEventListener(Event.ADDED_TO_STAGEinit);
            
Mouse.hide();
            
            
stage.scaleMode "noScale";
            
stage.align "TL";
//            stage.frameRate = 10;    // ;) hier zeigt sich die Stärke dieser Variante
                                    // der cursor ruckelt, aber die Kurven sind "rund"
            
            
bCanvas.smoothing true;
            
addChild(bCanvas);
            
addChild(cursors);
            
addChild(bPalette);
            
resize(null);
            
            
stage.addEventListener(Event.RESIZEresize);
            
addEventListener(MouseEvent.MOUSE_DOWNmouseDownHandler);
            
addEventListener(MouseEvent.MOUSE_UPmouseDownHandler);
            
addEventListener(Event.ENTER_FRAMEloop);
            
            
            
setPalette1([0xFF4422], 10);
//            setPalette2([0xFF0000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF, 0xFF00FF, 0xFF0000], [0, 1, 0]);
//            palette.perlinNoise(Math.random() * 300 + 50, Math.random() * 100 + 30, 1, Math.random() * int.MAX_VALUE, false, false, 15, false);


            
for (var i:int 0;  numSpots; ++i) {
                var 
spot:Spot = new Spot();
                    
spot.speed 1.1 - (numSpots);
                    
spot.delay 0.75;
                    
spot.color palette.getPixel(numSpots palette.width0);
                    
spot.reset(mouseXmouseY);
                
spots[i] = spot;
            }
            
            
buildUVMap();
        }
        
        
        private function 
buildUVMap():void
        
{
            var 
numPoints:uint numSteps;
            var 
i:intj:intk:int;
            
            
vertices = new Vector.<Number>();
            
indices = new Vector.<int>();
            
uvtData = new Vector.<Number>();
            
            for (
00numSpots; ++i+= numPoints) {
                var 
f:Number / (numSpots 1);
                if (
i) {
                    for (
0numSteps; ++k) {
                        
indices.push(
                            
k+numPoints 1k+numPointsk+j,
                            
k+jk+j+1k+j-numPoints+1
                        
);
                    }
                }
                
                for (
0<= numSteps; ++k) {
                    
vertices.push(0.00.0);
                    
uvtData.push(fk/numSteps1);
                }
            }
        }
        
        

        
        
        
        
//RGB wird gleichmässig interpoliert
        //alpha wird anhand einer Sinuskurve von 0 nach 1 nach 0 interpoliert
        
public function setPalette1(cols:Array, alpha:Number 1outerAlpha:Number NaN):void
        
{
            var 
a:Number = (alpha 255) << 24;
            var 
da:Number isNaN(outerAlpha)? 0alpha outerAlpha;
            
            var 
l:int cols.length 1;
            var 
col:int cols[0];

            for (var 
i:int 1024i--; ) {
                var 
f:Number 1023;
                if(
l){
                    var 
f1:Number l;
                    var 
j:int f1>>0;
                        
f1 -= j;
                    
                    if (
f1) {
                        var 
f2:Number f1;
                        var 
c1:int cols[j];
                        var 
c2:int cols[1];
                        
                        
col = (((c1>>16)&0xFF)*f2 + ((c2>>16)&0xFF)*f1)<<16 | (((c1>>8)&0xFF)*f2 + ((c2>>8)&0xFF)*f1)<<| ((c1&0xFF)*f2 + (c2&0xFF)*f1);
                    }else{
                        
col cols[j];
                    }
                }
                
                if(
da){
//                    a = Math.sin(Math.PI * f);                    //halbe Sinuskurve
                    
.5 Math.cos(Math.PI f) * .5;    //etwas richtung Gausssche-Glockenkurve
                    
                    
= ((a*da outerAlpha) * 0xFF) << 24;
                }
                
palette.setPixel32(i00xFFFFFF&col a);
            }
        }
        
        
//RGB wird gleichmässig interpoliert. Alpha auch. jedoch beide unabhängig voneinander
        
public function setPalette2(cols:Array, alphas:Array=null):void
        
{
            var 
cl:int cols.length 1;
            var 
al:int alphasalphas.length 10;
            
            var 
col:int cols[0];
            var 
a:Number alphas? ((alphas[0]*0xFF)<<24): 0xFF000000;

            for (var 
i:int 1024i--; ) {
                var 
f:Number 1023f1:Numberf2:Numberj:int;
                if(
cl){
                    
f1 cl;
                    
f1>>0;
                    
f1 -= j;
                    
                    if (
f1) {
                        
f2 f1;
                        var 
c1:int cols[j];
                        var 
c2:int cols[1];
                        
                        
col = (((c1>>16)&0xFF)*f2 + ((c2>>16)&0xFF)*f1)<<16 | (((c1>>8)&0xFF)*f2 + ((c2>>8)&0xFF)*f1)<<| ((c1&0xFF)*f2 + (c2&0xFF)*f1);
                    }else{
                        
col cols[j];
                    }
                }
                
                if (
al) {
                    
f1 al;
                    
f1 >> 0;
                    
f1 -= j;
                    
                    
f1? (alphas[j] * (f1) + alphas[1] * f1): alphas[j];
                    
= (0xFF) << 24;
                }
                
palette.setPixel32(i00xFFFFFF&col a);
            }
        }
        
        
        
        private function 
loop(e:Event):void 
        
{
            
cursors.graphics.clear();
            
cursors.graphics.lineStyle(10xFFFFFF);
            
cursors.graphics.drawCircle(mouseXmouseY5);

            var 
i:int 0;
            for 
each(var spot:Spot in spots
            {
                
spot.vx += ((mouseX spot.px) * spot.speed spot.vx) * spot.delay;
                
spot.vy += ((mouseY spot.py) * spot.speed spot.vy) * spot.delay;
                
spot.px += spot.vx;
                
spot.py += spot.vy;
                
                
spot.mx = (spot.ox spot.px) / 2;
                
spot.my = (spot.oy spot.py) / 2;
                
                
vertices[i  ] = spot.omx;
                
vertices[i+1] = spot.omy;
                
+= 2;
                
                for (var 
j:int 1numSteps; ++j) {
                    var 
t:Number numStepst2:Number t;
                    var 
c0:Number t2 t2c1:Number 2.0 t2c2:Number t*t;
                    
                    
vertices[i  ] = c0 spot.omx c1 spot.ox c2 spot.mx;
                    
vertices[i+1] = c0 spot.omy c1 spot.oy c2 spot.my;
                    
+= 2;
                }
                
                
vertices[i  ] = spot.mx;
                
vertices[i+1] = spot.my;
                
+= 2;
                
                
spot.ox spot.px;
                
spot.oy spot.py;
                
spot.omx spot.mx;
                
spot.omy spot.my;
                
//                cursors.graphics.lineStyle(1, 0xFFFFFF);
                
cursors.graphics.lineStyle(1spot.color);
                
cursors.graphics.drawRect(spot.px 1spot.py 122);
            }
            
            if (
isMouseDown) {
                
drawing.graphics.clear();
                
drawing.graphics.beginBitmapFill(palettenullfalsetrue);
                
drawing.graphics.drawTriangles(verticesindicesuvtDataTriangleCulling.NONE);
                
                
//TODO: durchprobieren, bei welchen BlendModes der buffer weggelassen werden kann
                
if (effect == BlendMode.NORMAL) {
                    
canvas.draw(drawingnullnulleffect);
                }else{
                    
buffer.fillRect(buffer.rect0);
                    
buffer.draw(drawing);
                    
canvas.draw(buffernullnulleffect);
                }
            }
        }
        
    


        private function 
mouseDownHandler(e:MouseEvent):void 
        
{
            
isMouseDown e.type == MouseEvent.MOUSE_DOWN;
        }
        
        private function 
resize(e:Event):void 
        
{
            var 
canvas2:BitmapData = new BitmapData(stage.stageWidthstage.stageHeight 12false0);
            if (
canvas) {
                
//alte Inhalte kopieren (zentriert)
                
canvas2.copyPixels(canvascanvas.rect, new Point((canvas2.width canvas.width) / 2, (canvas2.height canvas.height) / 2));
                
canvas.dispose();
            }
            
bCanvas.bitmapData canvas canvas2;
            if (
buffer)    buffer.dispose();
            
buffer = new BitmapData(canvas2.widthcanvas2.heighttrue0);    //immer Transparent!
            
            //Farbpalette unten anordnen
            
bPalette.width stage.stageWidth;
            
bPalette.stage.stageHeight-10;
            
bPalette.height 10;
        }
    }
}



class 
Spot
{
    public var 
px:Number 0;
    public var 
py:Number 0;
    public var 
ox:Number 0;
    public var 
oy:Number 0;
    
    public var 
mx:Number 0;
    public var 
my:Number 0;
    public var 
omx:Number 0;
    public var 
omy:Number 0;
    
    public var 
vx:Number 0;
    public var 
vy:Number 0;
    
    public var 
delay:Number 1;
    public var 
speed:Number 1;
    public var 
color:uint 0xFFFFFF;
    
    function 
Spot()
    {    }
    
    public function 
reset(targetX:Number=0targetY:Number=0):void 
    
{
        
px ox targetX;
        
py oy targetY;
        
vx vy 0;
    }

Angehängte Dateien
Dateityp: swf Filaments5.swf (3,0 KB, 45x aufgerufen)
__________________
greetz Thomas

plz RTFM & Coding Conventions
thomas_E ist gerade online   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 19:12 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele