Monthly Archives: July 2009

BitmapData & Particles

Actionscript:
  1. stage.frameRate = 30;
  2. stage.quality = StageQuality.LOW;
  3.  
  4. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
  5. addChild(new Bitmap(canvas));
  6. var overlay:BitmapData = new BitmapData(400,400,true, 0x12000000);
  7. var particles:Dictionary = new Dictionary(true);
  8.  
  9. var blur:Array = [new BlurFilter(8,8,1)];
  10.    
  11. addEventListener(Event.ENTER_FRAME, onLoop);
  12. function onLoop(evt:Event):void {
  13.     for (var i:int= 0; i<3; i++) createParticle();
  14.     canvas.copyPixels(overlay, canvas.rect, new Point(0,0), null, null, true);
  15. }
  16.  
  17. function createParticle():void{
  18.     var s:MovieClip = new MovieClip();
  19.     var diameter:Number = Math.random()*50 + 2;
  20.     var radius:Number = diameter / 2;
  21.     var mat:Matrix = new Matrix();
  22.     mat.createGradientBox(diameter, diameter, 0, -radius, -radius);
  23.     mat.createGradientBox(diameter, diameter, 0, -radius, -radius);
  24.     s.graphics.beginGradientFill(GradientType.RADIAL, [ 0xFFCC32, 0xFF0000], [0.5,0.8], [0, 255], mat, SpreadMethod.PAD);
  25.     s.graphics.drawCircle(0,0,radius);
  26.     s.velX = 0;
  27.     s.velY =  -Math.random()*6 + 3;
  28.     s.posX = s.x = 150+ Math.random() * 100;
  29.     s.posY = s.y = 200;
  30.     s.theta= Math.random() * Math.PI * 2;
  31.     s.inc = Math.random() * 0.4 + 0.01;
  32.     s.rad = Math.random() * 4 + 1;
  33.     s.filters = blur;
  34.     // since the particles aren't on the display list, we need to keep a reference to them
  35.     particles[s] = s;
  36.     s.addEventListener(Event.ENTER_FRAME, onRunParticle);
  37. }
  38. function onRunParticle(evt:Event):void {
  39.     var s:MovieClip = MovieClip(evt.currentTarget);
  40.     s.posX += s.velX;
  41.     s.posY += s.velY;
  42.     s.velX = s.rad * Math.cos(s.theta);
  43.     s.theta += s.inc;
  44.     s.scaleX = s.scaleY -=  .03;
  45.     if (s.scaleX <0){
  46.         particles[s] = null;
  47.         s.removeEventListener(Event.ENTER_FRAME, onRunParticle);
  48.     }
  49.     s.x = s.posX;
  50.     s.y = s.posY;
  51.     canvas.draw(s, s.transform.matrix, null, BlendMode.ADD);
  52. }

This is a slight variation on a simple particle system that I show in my intermediate class. It is almost the same as this example. But it makes use of filters and BitmapData.

Here is a still generated with this snippet. You'll notice it vaguely resembles fire.

If you need more particles, there are other approaches that are more appropriate.

Posted in BitmapData, Graphics, motion | Tagged , , | Leave a comment

drawTriangles() 2D Textured Plane

Actionscript:
  1. [SWF(width = 700, height = 700)]
  2.  
  3. var loader:Loader = new Loader();
  4. loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
  5. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
  6. var tex:BitmapData;
  7. function onLoaded(evt:Event):void{
  8.     tex = Bitmap(loader.content).bitmapData;
  9.     addEventListener(Event.ENTER_FRAME, onLoop);
  10. }
  11.  
  12. var plane:Shape = Shape(addChild(new Shape()));
  13. plane.x = plane.y = 50;
  14.  
  15. var verts:Vector.<Number> = new Vector.<Number>();
  16. var uvs:Vector.<Number> = new Vector.<Number>();
  17. var indices:Vector.<int> = new Vector.<int>();
  18. var rows:int = 30;
  19. var size:Number = rows + 1;
  20. var vertNum:Number = size * size;
  21. var polySize:Number = 20;
  22. var vIndex:int = 0;
  23. var uvIndex:int = 0;
  24. var gridSize:Number = rows * polySize;
  25. for (var i:Number = 0; i<vertNum; i++){
  26.     var xp:Number = i % size * polySize;
  27.     var yp:Number =  int(i / size) * polySize;
  28.     verts[vIndex++] = xp
  29.     verts[vIndex++] = yp;
  30.     uvs[uvIndex++] = xp / gridSize;
  31.     uvs[uvIndex++] = yp / gridSize;
  32.     if (i % size != rows){
  33.           indices.push(i, i+1, i+size, i+size, i+size+1, i+1);
  34.     }
  35. }
  36.  
  37. // render and show that the verts can be changed around
  38. function onLoop(evt:Event):void {
  39.     // shake the verts
  40.     for (var i:int = 0; i<verts.length; i++){
  41.         verts[i] += Math.random() - 0.5;
  42.     }
  43.     with(plane.graphics){
  44.         clear();
  45.         beginBitmapFill(tex,null, false, true);
  46.         drawTriangles(verts, indices,uvs);
  47.     }
  48. }

This snippet is shows how to draw a textured 2D plane using drawTriangles(). This is similar to the wireframe 2D plane post from yesterday... the main difference is that you need to calculate UV coordinates if you want to use a bitmap fill with drawTriangles().

Here is a still of this snippet:

Posted in BitmapData, Graphics, Vector | Tagged , , | 2 Comments

Wireframe Plane 2D

Actionscript:
  1. var plane:Shape = Shape(addChild(new Shape()));
  2. plane.x = plane.y = 50;
  3.  
  4. var verts:Vector.<Number> = new Vector.<Number>();
  5. var indices:Vector.<int> = new Vector.<int>();
  6. var rows:int = 20;
  7. var size:Number = rows + 1;
  8. var vertNum:Number = size * size;
  9. var polySize:Number = 20;
  10. var vIndex:int = 0;
  11. for (var i:Number = 0; i<vertNum; i++){
  12.     verts[vIndex++] = i % size * polySize;
  13.     verts[vIndex++] = int(i / size) * polySize;
  14.     if (i % size != rows){
  15.           indices.push(i, i+1, i+size, i+size, i+size+1, i+1);
  16.     }
  17. }
  18.  
  19. // render and show that the verts can be changed around
  20. addEventListener(Event.ENTER_FRAME, onLoop);
  21. function onLoop(evt:Event):void {
  22.     // shake the verts
  23.     for (var i:int = 0; i<verts.length; i++){
  24.         verts[i] += Math.random() - 0.5;
  25.     }
  26.     with(plane.graphics){
  27.         clear();
  28.         lineStyle(0,0);
  29.         drawTriangles(verts, indices);
  30.     }
  31. }

This snippet shows a simple way to draw a 2D wireframe plane using drawTriangles(). To demonstrate the flexibility of the plane... the vertices are randomly shaken on enterframe.

Posted in Graphics, Vector | Tagged , , | Leave a comment

drawTriangles() Terrain

Actionscript:
  1. [SWF(width=500,height=500,backgroundColor=0x333333, frameRate=40)]
  2. var terrain:Shape = Shape(addChild(new Shape()));
  3. terrain.x = terrain.y = 250;
  4. var rows:int = 60;
  5. var size:int = rows + 1;
  6. var vertNum:int = size * size;
  7. var polySize:Number = 5;
  8. var gridWidth:Number = polySize * rows;
  9. var halfWidth:Number = gridWidth / 2;
  10. var verts:Vector.<Number> = new Vector.<Number>();
  11. var pVerts:Vector.<Number> = new Vector.<Number>();
  12. var indices:Vector.<int> = new Vector.<int>();
  13. var uvs:Vector.<Number> = new Vector.<Number>();
  14. var uvts:Vector.<Number> = new Vector.<Number>();
  15. var tex:BitmapData = new BitmapData(gridWidth, gridWidth, false, 0x000000);
  16. var pix:int = gridWidth * gridWidth;
  17. var perlin:BitmapData = new BitmapData(gridWidth, gridWidth, false, 0x000000);
  18. // generate the texture and the terrain
  19. function generate():void{
  20.     tex.fillRect(tex.rect, 0x000000);
  21.     var i:Number, xp:Number, yp:Number;
  22.     for (i = 0; i<pix; i++){
  23.         xp = i % gridWidth;
  24.         yp= int(i / gridWidth);
  25.         var dx:Number = xp - gridWidth / 2;
  26.         var dy:Number = yp - gridWidth / 2;
  27.         var d:Number = 255 - Math.sqrt(dx * dx + dy * dy) / halfWidth* 255;
  28.         if (d <0) d = 0;
  29.         if (d> 255) d = 255;
  30.         var c:uint = uint(d);
  31.         tex.setPixel(xp, yp, c <<16 | c <<8 | c);
  32.     }
  33.     perlin.perlinNoise(100,100,3,Math.random()*100,false,false,7,true);
  34.     perlin.draw(perlin, null, null, BlendMode.SCREEN);
  35.     tex.draw(perlin, null, null, BlendMode.MULTIPLY);
  36.     // calculate verts, uvs and indices
  37.     var vIndex:int = 0;
  38.     var uvIndex:int = 0;
  39.     indices = new Vector.<int>();
  40.     for (i = 0; i<vertNum; i++){
  41.         var xMod:Number = i % size;
  42.         xp = xMod * polySize;
  43.         yp = int(i / size) * polySize;
  44.         verts[vIndex++] = xp - halfWidth;
  45.         verts[vIndex++] = yp - halfWidth;
  46.         verts[vIndex++] = tex.getPixel(xp, yp) & 0xFF;
  47.         uvs[uvIndex++] = xp /  gridWidth;
  48.         uvs[uvIndex++] = yp / gridWidth;
  49.         if (xMod != rows){
  50.               indices.push(i, i+1, i+size, i+1, i+size+1, i+size);
  51.         }
  52.     }
  53. }
  54. generate();
  55. stage.addEventListener(MouseEvent.MOUSE_DOWN, onGenerate);
  56. function onGenerate(evt:MouseEvent):void{ generate() };
  57. var m:Matrix3D = new Matrix3D();
  58. var rot:Number = 0;
  59. addEventListener(Event.ENTER_FRAME, onLoop);
  60. function onLoop(evt:Event):void {
  61.         m.identity();
  62.         var destRot:Number = mouseX / stage.stageWidth * 90;
  63.         if (destRot <0) destRot = 0;
  64.         if (destRot> 90) destRot = 90;
  65.         rot += (destRot - rot) * 0.2;
  66.         m.appendRotation(rot,Vector3D.Z_AXIS);
  67.         m.appendRotation(60,Vector3D.X_AXIS);
  68.         Utils3D.projectVectors(m, verts, pVerts, uvts);
  69.         with(terrain.graphics){
  70.             clear();
  71.             beginBitmapFill(tex, null, false, true);
  72.             drawTriangles(pVerts, indices, uvs, TriangleCulling.NEGATIVE);
  73.         }
  74. }

This snippet draws a pretty simple isometric terrain using fp10 graphics stuff and perlin noise.


Have a look at the swf here...

Posted in BitmapData, Graphics, Vector, pixel manipulation, setPixel | Tagged , , | 4 Comments