Ornamental Heart (MVC test)
based on ornamental tree
http://www.openprocessing.org/visuals/?visualID=2614
I'm not sure what MVC really is, but anyway I've done it.
/**
* Copyright yuuganisakase ( http://wonderfl.net/user/yuuganisakase )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/JoPX
*/
//
// based on ornamental tree
// http://www.openprocessing.org/visuals/?visualID=2614
//
//
// I'm not sure what MVC really is, but anyway I've done it.
//
package
{
import com.flashdynamix.motion.effects.core.FilterEffect;
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.utils.Timer;
[SWF(width=465, height=465, frameRate=30, backgroundColor=0x000000)]
public class OrnamentalGrid extends Sprite
{
private var timer:Timer = new Timer(70);
private var model:Model;
private var view:View;
public function OrnamentalGrid()
{
super();
model = new Model();
view = new View();
this.addChild(view);
this.addEventListener(Event.ADDED_TO_STAGE, init);
timer.addEventListener(TimerEvent.TIMER, onTimer);
}
private function init(e:Event):void
{
var sh:Shape = new Shape();
sh.graphics.beginFill(0);
sh.graphics.drawRect(0,0,465,465);
this.addChildAt(sh, 0);
timer.start();
stage.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void
{
model.init();
removeChild(view);
view.dispose();
view = new View();
addChild(view);
}
private function onTimer(e:TimerEvent):void
{
trace("timer");
model.update();
view.update(model);
model.disposeAfterAnimated();
}
}
}
import com.flashdynamix.motion.effects.core.FilterEffect;
import com.flashdynamix.motion.guides.Bezier2D;
import com.flashdynamix.motion.layers.BitmapLayer;
import com.flashdynamix.motion.TweensyGroup;
import com.flashdynamix.motion.TweensyTimeline;
import fl.motion.easing.Linear;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.filters.BlurFilter;
import frocessing.core.GraphicsEx;
import org.papervision3d.objects.primitives.Plane;
import flash.display.Sprite;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
class Model
{
public static const Xnum:int = 18;
public static const Ynum:int = 18;
public var field:Vector.<Vector.<FieldObject> >;
public var nodeArray1:Array = new Array();
public var nodeArray2:Array = new Array();
private var iterator:Iterator;
public function Model()
{
init();
}
public function init():void
{
nodeArray1 = new Array();
nodeArray2 = new Array();
field = new Vector.<Vector.<FieldObject>>(Model.Xnum, true);
for(var i:int = 0; i < Xnum; i++)
{
field[i] = new Vector.<FieldObject>(Model.Ynum, true);
}
for(var xx:int = 0; xx < Model.Xnum; xx++)
{
for(var yy:int = 0; yy < Model.Ynum; yy++)
{
field[xx][yy] = new FieldObject();
}
}
for(var ll:int = 0; ll < 9; ll++)
{
addNodeAtRandomPoint();
}
iterator = new Iterator(nodeArray1);
}
private function addNodeAtRandomPoint():void
{
var xx:int = Math.random() * Xnum << 0;
var yy:int = Math.random() * Ynum << 0;
if (field[xx][yy].direction.x == 0)
{
var node:Node = new Node(xx, yy, field);
node.originFlag = true;
nodeArray2.push(node);
field[xx][yy].direction.x = (Math.random() > 0.5)? 1: - 1;
field[xx][yy].direction.y = (Math.random() > 0.5)? 1: - 1;
field[xx][yy].isBranch = true;
}
}
public function disposeAfterAnimated():void
{
for (var i:int = 0; i < nodeArray1.length; i++)
{
if ((nodeArray1[i] as Node).disposeFlag == true)
{
nodeArray1.splice(i, 1);
}
}
for (var j:int = 0; j < nodeArray2.length; j++)
{
if ((nodeArray2[j] as Node).disposeFlag == true)
{
nodeArray2.splice(j, 1);
}
}
}
public function update():void
{
trace("ar1 = " + nodeArray1.length + "ar2 = " + nodeArray2.length);
for(var i:int = 0; i < 7; i++)
{
var node:Node = (iterator.next() as Node);
if(node != null)
{
if (animeProbability())
{
var ar:Array = node.move();
if(ar[0] != -1)
{
nodeArray2.push(new Node(ar[1].x, ar[1].y, field) );
}
}
}else {
var temp:Array = nodeArray1;
nodeArray1 = nodeArray2;
nodeArray2 = temp;
iterator = new Iterator(nodeArray1);
addNodeAtRandomPoint();
}
}
}
private function animeProbability():Boolean
{
if (Math.random() > 0.2) {
return true;
}else {
return false;
}
}
}
class Iterator
{
private var ar:Array;
private var counter:int;
private var lastObject:*;
public function Iterator(_ar:Array)
{
ar = _ar;
counter = 0;
}
public function next():*
{
counter += 1;
if(ar.length >= counter){
lastObject = ar[counter-1];
return lastObject;
}else{
return null;
}
}
}
class View extends BitmapLayer
{
private const Margin:int = 30;
private const LineSize:int = 3;
private const col:uint = 0xFF37E1;
private var holder:Sprite = new Sprite();
private var tween:TweensyGroup = new TweensyGroup();
public static var xSize:Number;
public static var ySize:Number;
private var textArray:Array = new Array();
public function View()
{
View.xSize = (Util.WID-Margin)/Model.Xnum;
View.ySize = (Util.HEI-Margin)/Model.Ynum;
this.draw(holder);
this.clearOnRender = true;
this.add(new FilterEffect(new BlurFilter(2, 2)));
}
public function update(model:Model):void
{
displayMovingLine(model.nodeArray1);
displayMovingLine(model.nodeArray2);
}
private function displayNode(ar1:Array, ar2:Array):void
{
holder.graphics.lineStyle(2,0xff0000,0.2);
for each(var node:Node in ar1)
{
var pos:Point = getRealPosFromField(new Point(node.x, node.y));
holder.graphics.drawCircle(pos.x, pos.y,5);
}
for each(var node2:Node in ar2)
{
var pos2:Point = getRealPosFromField(new Point(node2.x, node2.y));
holder.graphics.drawCircle(pos2.x, pos2.y,5);
}
}
private function displayMovingLine(ar1:Array):void
{
holder.graphics.lineStyle(2, 0xff0000, 0.5);
for each(var node:Node in ar1)
{
if (node.originFlag == true)
{
drawOriginCircle(node);
node.originFlag = false;
}
if(node.movingFlag[0] != -1) // animated?
{
var start:Point = node.movingFlag[0];
start = getRealPosFromField(start);
var end:Point = node.movingFlag[1];
end = getRealPosFromField(end);
if (node.movingFlag.length == 3)
{
var control:Point = node.movingFlag[2];
control = getRealPosFromField(control);
drawCurve(start, end, control);
}else
{
drawLine(start, end);
}
node.movingFlag[0] = -1;
}else if (node.movingFlag[1] == false) // isbranch?
{
node.movingFlag[1] = true;
var center:Point = node.movingFlag[2];
center = getRealPosFromField(center);
drawHeart(center, node.movingFlag[3]);
}
}
}
private function drawOriginCircle(node:Node):void
{
var sp:Shape = new Shape();
holder.addChild(sp);
var po:Point = getRealPosFromField(new Point(node.x, node.y) );
sp.x = po.x;
sp.y = po.y;
sp.graphics.beginFill(0xffffff,1);
sp.graphics.drawCircle( 0,0, 5);
}
private function drawCurve(start:Point, end:Point, control:Point):void
{
var sh:Shape = new Shape();
var po:Point = new Point(start.x, start.y);
holder.addChild(sh);
sh.graphics.lineStyle(LineSize, col, 1);
sh.graphics.moveTo(start.x, start.y);
var bezi:Bezier2D = new Bezier2D(po, true, false, false);
bezi.push(start);
var po1:Point = Point.interpolate(start, control, 0.333);
bezi.push(po1);
var po2:Point = Point.interpolate(end, control, 0.333);
bezi.push(po2);
bezi.push(end);
var tl:TweensyTimeline = tween.to(bezi, { position:1 }, 0.6, Linear.easeNone, 0, null, removeObject, [po, sh]);
tl.onUpdate = movingPoint;
tl.onUpdateParams = new Array(po, sh);
}
private function drawLine(start:Point, end:Point):void
{
var sh:Shape = new Shape();
var po:Point = new Point(start.x, start.y);
var size:int = 2;
holder.addChild(sh);
sh.graphics.lineStyle(LineSize, col,1);
sh.graphics.moveTo(start.x, start.y);
var tl:TweensyTimeline = tween.fromTo(po,
{ x:start.x, y:start.y }, { x: end.x, y: end.y }, 0.6, Linear.easeNone, 0, null, removeObject, new Array(po,sh));
tl.onUpdate = movingPoint;
tl.onUpdateParams = new Array(po, sh);
}
private function movingPoint(po:Point, sh:Shape):void
{
sh.graphics.lineTo(po.x, po.y);
}
private function removeObject(po:Point, sh:DisplayObject):void
{
if (sh is Shape) {
(sh as Shape).graphics.lineTo(po.x, po.y);
}
//holder.removeChild(sh);
}
private function drawHeart(po:Point, dir:Point):void
{
var sh:Shape = new Shape();
var sp:Sprite = new Sprite();
//sp.addChild(sh);
holder.addChild(sh);
tween.fromTo(sh, { alpha:0 }, { alpha:1 }, 2);
sh.x = po.x;
sh.y = po.y;
var gra:GraphicsEx = new GraphicsEx(sh.graphics);
var sca :Number= 0.09;
var rad:Number = 40*sca;
var size:Number = 50*sca;
var posScale:Number = 0;
var random1:Number = 1;
var random2:Number = 1;
var random3:Number = 1;
var random4:Number = 1;
var random5:Number = 1;
var random6:Number = 1;
var xx:Number = 0;
var yy:Number = 0;
var p1:Point = new Point(xx+random5*posScale, yy+size+random6*posScale);
var p3:Point = new Point(xx+random1*posScale, yy-size+random3*posScale);
var p2:Point = new Point(xx-size*1.4*random2, yy-size+random4*posScale);
var p4:Point = new Point(xx+size*1.4*random3, yy-size+random5*posScale);
var c1:Point = new Point(xx-rad*0.5*random1, yy);
var c3:Point = new Point(xx-size-rad*0.5*random2, yy-size-rad);
var c2:Point = Point.interpolate(c3,p2,-0.8);
var c4:Point = new Point((p2.x+p3.x)/2+rad*0.4*random3, yy-size-rad*1.5);
var c8:Point = new Point((p3.x+p4.x)/2-rad*0.4*random4, yy-size-rad*1.5);
var c7:Point = new Point(xx+size+rad*0.5*random5, yy-size-rad);
var c6:Point = Point.interpolate(c7,p4,-0.8);
var c5:Point = new Point(xx + rad * 0.5 * random6, yy);
gra.lineStyle(LineSize,col,1);
gra.moveTo(p1.x, p1.y);
gra.bezierTo(c1.x, c1.y, c2.x, c2.y, p2.x, p2.y);
gra.bezierTo(c3.x, c3.y, c4.x, c4.y, p3.x, p3.y);
gra.bezierTo(c8.x, c8.y, c7.x, c7.y, p4.x, p4.y);
gra.bezierTo(c6.x, c6.y, c5.x, c5.y, p1.x, p1.y);
if (dir.x == 1 ) {
if (dir.y == 1) {
sh.rotation = 135;
sh.x += 2;
sh.y += 2;
}else if (dir.y == -1) {
sh.rotation = 45;
sh.x += 2;
sh.y -= 2;
}
}else {
if (dir.y == 1) {
sh.rotation = 225;
sh.x -= 2;
sh.y += 2;
}else if (dir.y == -1) {
sh.rotation = -45;
sh.x -= 2;
sh.y -= 2;
}
}
}
private function getRealPosFromField(node:Point):Point
{
var point:Point = new Point(node.x * View.xSize +View.xSize/2 + Margin/2, node.y * View.ySize + View.ySize/2 + Margin/2);
return point;
}
public function drawGrid(field:Vector.<Vector.<FieldObject>>):void
{
var grid:Sprite = new Sprite();
grid.graphics.lineStyle(1,0,0.2);
holder.addChild(grid);
for(var i:int = 0; i < field.length+1; i++)
{
grid.graphics.moveTo(Margin/2 + i*View.xSize, 0);
grid.graphics.lineTo(Margin/2 + i*View.xSize, Util.HEI);
}
for(var j:int = 0; j < field[0].length+1; j++)
{
grid.graphics.moveTo(0, Margin/2 + j*View.ySize);
grid.graphics.lineTo(Util.HEI, Margin/2 + j*View.ySize);
}
}
}
class Node
{
private var field:Vector.<Vector.<FieldObject>>;
public var x:int;
public var y:int;
public var movingFlag:Array = new Array( -1, -1);
public var disposeFlag:Boolean = false;
public var originFlag:Boolean = false;
public function Node(_x:int, _y:int, _field:Vector.<Vector.<FieldObject>>)
{
super();
this.x = _x;
this.y = _y;
field = _field;
}
public function move():Array
{
var ran:int = (Math.random()*3 << 0);
for(var i:int = 0; i < 5; i++)
{
if(ran == 1){
if(canMoveX() )
{
movingFlag = moveX();
return movingFlag;
}
}else if(ran == 0){
if(canMoveY() )
{
movingFlag = moveY();
return movingFlag;
}
}else if (ran == 2) {
if (canMoveXY() )
{
movingFlag = moveXY();
return movingFlag;
}
}
ran = (Math.random()*3 << 0)
}
movingFlag = new Array( -1, field[x][y].isBranch, new Point(x, y), field[x][y].direction);
disposeFlag = true;
return movingFlag;
}
private function canMoveX():Boolean
{
var newX:int = this.x + field[x][y].direction.x;
return newX>=0 && newX<Model.Xnum && field[newX][this.y].direction.x==0;
}
private function moveX():Array
{
var newX:int = this.x + field[x][y].direction.x;
field[newX][y].direction.x = field[x][y].direction.x;
field[newX][y].direction.y = -(field[x][y].direction.y);
field[x][y].isBranch = true;
return new Array(new Point(x,y), new Point(newX,y), new Point((x + newX)*0.5, y + field[x][y].direction.y*0.3) );
}
private function canMoveY():Boolean
{
var newY:int = this.y + field[x][y].direction.y;
return newY>=0 && newY<Model.Ynum && field[x][newY].direction.y==0;
}
private function moveY():Array
{
var newY:int = this.y + field[x][y].direction.y;
field[x][newY].direction.x = -(field[x][y].direction.x);
field[x][newY].direction.y = field[x][y].direction.y;
field[x][y].isBranch = true;
return new Array(new Point(x,y) , new Point(x,newY) , new Point(x + field[x][y].direction.x*0.3, (y+newY)*0.5));
}
private function canMoveXY():Boolean
{
var newX:int = this.x + field[x][y].direction.x;
var newY:int = this.y + field[x][y].direction.y;
return newX >= 0 && newX < Model.Xnum && newY >= 0 && newY < Model.Ynum && field[newX][newY].direction.y == 0 &&
(newX + field[newX][y].direction.x != x || y + field[newX][y].direction.y != newY) &&
(x + field[x][newY].direction.x != newX || newY + field[x][newY].direction.y != y);
}
private function moveXY():Array
{
var newX:int = this.x + field[x][y].direction.x;
var newY:int = this.y + field[x][y].direction.y;
field[x][y].isBranch = true;
field[newX][newY].direction.x = field[x][y].direction.x;
field[newX][newY].direction.y = field[x][y].direction.y;
return new Array(new Point(x, y), new Point(newX, newY));
}
public function dispose():void
{
field = null;
movingFlag = null;
}
}
class FieldObject
{
public var pos:Point = new Point(0,0);
public var direction:Point = new Point(0,0);
public var isBranch:Boolean= false;
public function FieldObject():void
{
}
}
class Util
{
public static const WID:int = 465;
public static const HEI:int = 465;
public static const test:Boolean = false;
}