umxprime lab Carnet de bricodage

21juin/110

Metaballs en AS3

metaballs

Voici un code AS3 pour Flash qui permet de générer des metaballs en mouvement à l'aide de cercles animés et d'effets bitmaps.

C'est quoi des metaballs ?

Ce code tourne en 30 i/s sur un MacBook Pro de 2008 dans une scène de 400x300 pixels.

Pour avoir une version pseudo antialiasée (lissée) il faut passer AA à true ligne 26; on gagne en "qualité" mais on perd en fluidité (accessoirement le processeur risque de s'y donner à cœur joie).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
 * 
 * Copyright© 2011 Maxime CHAPELET (umxprime_at_umxprime_dot_com)
 * This is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this.  If not, see <http://www.gnu.org/licenses/>.
 *
 **/
 
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Point;
import flash.filters.BlurFilter;
import flash.events.Event;
 
 
var AA:Boolean = false;
var i:int;
var circle:Sprite = new Sprite();
var surfaceWidth:int = AA?stage.stageWidth*2:stage.stageWidth;
var surfaceHeight:int = AA?stage.stageHeight*2:stage.stageHeight;
var surface:BitmapData = new BitmapData(surfaceWidth,surfaceHeight);
 
 
var particleCount:int = 200;
var particles:Vector.<Object> = new Vector.<Object>();
var particleRadius:int = 20;
 
var backSurface:BitmapData = new BitmapData(surfaceWidth,surfaceHeight);
var bitmap:Bitmap = new Bitmap(backSurface);
addChild(bitmap);
bitmap.scaleX = bitmap.scaleY = AA?0.5:1;
 
var particleGlue:int = 15;
var blur:BlurFilter = new BlurFilter(AA?particleGlue*2:particleGlue,AA?particleGlue*2:particleGlue,3);
 
var metaballColor:uint = 0xFF000000;
var metaballBorderColor:uint = 0xFFFF0000;
 
for(i=0;i<particleCount;i++)
{
	var particle:Object = new Object();
	particle.x = Math.random()*surfaceWidth;
	particle.y = Math.random()*surfaceHeight;
	particle.radius = AA?(Math.random()*(particleRadius-2)+2)*2:(Math.random()*(particleRadius-2)+2);
	particle.angle = Math.random()*360;
	particle.speed = Math.random()*5+1;
	particles.push(particle);
}
 
this.addEventListener(Event.ENTER_FRAME, loop);
 
function loop(e:Event)
{
	surface.fillRect(surface.rect,0xFFFFFFFF);
	backSurface.fillRect(surface.rect,0xFFFFFFFF);
	for(i=0;i<particleCount;i++)
	{
		circle.graphics.clear();
 
		circle.graphics.beginFill(0x0);
		circle.graphics.drawCircle(particles[i].x,particles[i].y,particles[i].radius);
		circle.graphics.endFill();
		surface.draw(circle);
		particles[i].x += Math.cos(particles[i].angle/180*Math.PI)*particles[i].speed;
		particles[i].y += Math.sin(particles[i].angle/180*Math.PI)*particles[i].speed;
		if(particles[i].x>surfaceWidth+(particles[i].radius*2))particles[i].x=-(particles[i].radius*2);
		if(particles[i].x<-(particles[i].radius*2))particles[i].x=surfaceWidth+(particles[i].radius*2);
		if(particles[i].y>surfaceHeight+(particles[i].radius*2))particles[i].y=-(particles[i].radius*2);
		if(particles[i].y<-(particles[i].radius*2))particles[i].y=surfaceHeight+(particles[i].radius*2);
	}
	surface.applyFilter(surface,surface.rect,new Point(),blur);
	backSurface.threshold(surface,surface.rect,new Point(),"<",0x00FAFAFA,metaballBorderColor,0xFFFFFF);
	backSurface.threshold(surface,surface.rect,new Point(),"<",0x00CCCCCC,metaballColor,0xFFFFFF);
}

Voici une vidéo d'archive que j'avais enregistrée lors d'un test antérieur à l'écriture finale du code publié dans l'article :

Et enfin la vidéo d'un système à metaballs qui tourne en temps réel avec un code un peu plus évolué (basé sur le code publié dans cet article) :

.maxime

Commentaires (0) Trackbacks (0)

Aucun commentaire pour l'instant


Leave a comment

(required)

Aucun trackbacks pour l'instant