Particles in a perlin field
Space to render a new perlin heightmap and to launch new particles (and remove the current ones).
The sliders change:
Height - how much the particles is affected by the heightmap. Zero means no effect at all; higher values equals more powerful reaction (try it for yourselves!)
Count - The number of particles (duh)
Speed - The speed in which the particles travel (pixels per frame)
/**
* Copyright antalg ( http://wonderfl.net/user/antalg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/duDT
*/
package {
import flash.events.KeyboardEvent;
import flash.text.TextField;
import flash.utils.ByteArray;
import flash.geom.Rectangle;
import flash.filters.ColorMatrixFilter;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.filters.BlurFilter;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import com.bit101.components.HUISlider;
[SWF(backgroundColor="0x000000")]
public class FlashTest extends Sprite {
public function FlashTest() {
// Assign main bitmapData to bitmap and add it to stage
addChild(new Bitmap(_canvas));
// Add heightmap to stage
//addChild(new Bitmap(_hmap));
// Set-up event listeners
addEventListener(Event.ENTER_FRAME, onFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
// Set-up sliders
_sliderHeight = new HUISlider (null, 0, 0, "Height", updSlider);
_sliderHeight.setSliderParams(0, 1, _slopeAdjust);
_sliderHeight.labelPrecision = 2;
_sliderHeight.width = 300;
addChild(_sliderHeight);
_sliderCount = new HUISlider (null, 0, 0, "Count", updSlider);
_sliderCount.setSliderParams(1, 3000, _particleCount);
_sliderCount.labelPrecision = 0;
_sliderCount.tick = 1;
_sliderCount.width = 300;
_sliderCount.y = 20;
addChild(_sliderCount);
_sliderSpeed= new HUISlider (null, 0, 0, "Speed", updSlider);
_sliderSpeed.setSliderParams(0, 30, _baseV);
_sliderSpeed.width = 300;
_sliderSpeed.y = 40;
addChild(_sliderSpeed);
// Trace textField
addChild(txt);
txt.textColor = 0xFF2222;
txt.x = 4;
txt.y = 440;
// The first rendering
renderNew();
}
private var txt:TextField = new TextField();
private var _sliderHeight:HUISlider;
private var _sliderCount:HUISlider;
private var _sliderSpeed:HUISlider;
private var _particleCount:int = 700;
private var _particles:Array;
private var _particleColor:Array = [0xFF8888, 0x88FF88, 0x8888FF, 0xFFFFFF];
private var _slopeAdjust:Number = 0.1;
private var _baseV:Number = 4;
private const HGT:Number = 465;
private const WDT:Number = 465;
private var _canvas:BitmapData = new BitmapData(WDT, HGT, false, 0x000000);
private var _hmap:BitmapData = new BitmapData(WDT, HGT, true, 0x000000);
private function renderNew():void {
_particles = new Array();
addParticles(_particleCount);
_hmap.perlinNoise(100,100,2,Math.random()*int.MAX_VALUE, true, true, 0xFFFFFF, true);
}
// Event functions
private function keyDown(e:KeyboardEvent):void {
if(e.keyCode == 32) renderNew();
}
private function updSlider(e:*):void {
// Active setting, affects without reset
_slopeAdjust = _sliderHeight.value;
_baseV = _sliderSpeed.value;
// Requires reset
if(_particleCount != _sliderCount.value) {
_particleCount = _sliderCount.value;
renderNew();
}
}
private function onFrame(e:Event):void {
move();
processBMD();
if(txt.alpha>0) {
txt.alpha -= 0.01;
}
}
private function addParticles(n:int):void {
var x:Number;
var y:Number;
var vx:Number;
var vy:Number;
var angle:Number;
for(var i:int = 0; i<n; i++) {
angle = 2*Math.PI*Math.random();
vx = Math.cos(angle)*_baseV;
vy = Math.sin(angle)*_baseV;
x = Math.random()*WDT;
y = Math.random()*HGT;
var p:Object = {x:x, y:y, v:new Point(vx,vy)};
_particles.push(p);
}
}
////////////////////////
private function move():void {
for(var i:int = 0; i<_particles.length; i++) {
var p:Object = _particles[i];
// Calculate slope at point
var slope:Point = calcSlope(p.x, p.y);
// Update speed and position
p.x += (p.v.x+=slope.x);
p.y += (p.v.y+=slope.y);
// Keep a constant speed
p.v.normalize(_baseV);
// Wrap around
p.x = p.x<0 ? (p.x+WDT) : (p.x>WDT ? (p.x-WDT) : p.x);
p.y = p.y<0 ? (p.y+HGT) : (p.y>HGT ? (p.y-HGT) : p.y);
//var r:int = Math.random()*3.0+1;
var r:int = i%_particleColor.length;
//_canvas.fillRect(new Rectangle(p.x,p.y,2,2), _particleColor[r]);
_canvas.setPixel(p.x, p.y, _particleColor[r]);
}
}
private var bf:BlurFilter = new BlurFilter(2,2,1);
private var cmf:ColorMatrixFilter = new ColorMatrixFilter(
[ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, .98, 0]
);
private function processBMD():void {
_canvas.applyFilter(_canvas, _canvas.rect, new Point(0,0), bf);
_canvas.applyFilter(_canvas, _canvas.rect, new Point(0,0), cmf);
}
private function calcSlope(x:int, y:int):Point {
var slope:Point = new Point();
var rect:Rectangle = new Rectangle(x-1, y-1, 3, 3);
var p:Array =
[_hmap.getPixel(x-1, y-1)>>16, _hmap.getPixel(x, y-1)>>16, _hmap.getPixel(x+1, y-1)>>16,
_hmap.getPixel(x-1, y)>>16, _hmap.getPixel(x, y)>>16, _hmap.getPixel(x+1, y)>>16,
_hmap.getPixel(x-1, y+1)>>16, _hmap.getPixel(x, y+1)>>16, _hmap.getPixel(x+1, y+1)>>16];
slope.x = p[0]+p[3]+p[6]-(p[2]+p[5]+p[8]);
slope.y = p[0]+p[1]+p[2]-(p[6]+p[7]+p[8]);
slope.x*=_slopeAdjust;
slope.y*=_slopeAdjust;
return slope;
}
}
}