Integrador de Verlet Parte 1 – Introdução

por: Regis Machado

Olá pessoal esse é o meu primeiro post como colaborador aqui no Abrindo o Jogo, e pra isso eu vou mostrar como funcionam os verlet points, que são bem legais de usar e tem como simular uma física legal e descomplicada, ou criar um sistema de partículas simples.

“O Integrador Verlet é um metodo numérico usado para simular a equação de movimento de Newton’s. É usada frequentemente para calcular trajetorias de particulas em simulações de dinâmica molecular e video games”.-Wikipedia

O ponto de verlet que vou mostrar aqui é um vetor onde mantem armazenada a sua ultima posição e a posição atual e a partir da diferença entre essas duas posições ele calcula sua movimentação futura,  se pensarmos na parte física, se um corpo em um momento T0 está na posição x e em um segundo momento T1 está na posição x1, o seu deslocamento no tempo-espaço D(x1-x) pode (não obrigatoriamente) ser considerado como sua velocidade de deslocamento no futuro.

Para demonstrar isto, vou apresentar a implementação em AS3 (uma linguagem que eu gosto muito de trabalhar para fazer jogos). A IDE que vou usar é o FlashDevelop e vocês podem utilizar o tutorial aqui do Abrindo o Jogo para baixar e instalar.

Essa primeira parte vai ser composta de 3 classes, a classe principal, a  classe VerletPoint, e o VerletStick uma classe criado pelo yoambulante que nessa primeira parte vai nos ajudar muito a ver o poder e simplicidade dos verlet points.

Primeiro a Classe VPoint que implementa o integrador de verlet:

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
public class VerletPoint {
 
public var x:Number;
public var y:Number;
private var oldx:Number;
private var oldy:Number;
public function VerletPoint (x:Number, y:Number) {
 
setPos(x,y);
 
}
 
/* informa a posição do ponto*/
public function setPos(x:Number, y:Number):void{
this.x = oldx = x;
this.y = oldy = y;
}
 
/*Atualiza a posição do ponto, de acordo com o integrador de Verlet*/
public function refresh():void {
 
var tempx:Number = x;
var tempy:Number = y;
x += x - oldx;
y += y - oldy;
oldx = tempx;
oldy = tempy;
}
 
/* função que desenha o ponto na tela */
public function render(g:Graphics):void{
 
 g.beginFill(0xff8989);
 g.drawCircle(x,y,2);
 g.endFill();
}
 
}

E a classe que criada pelo yoambulante para limitar a movimentação entre dois pontos de verlet:

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
public class VerletStick{
 
public var pointa:VPoint;
public var pointb:VPoint;
private var _lenght:Number;
 
public function VerletStick(a:VPoint, b:VPoint, lenght:Number = -1) {
 
pointa = a;
pointb = b;
 
if(lenght == -1){
var dx:Number = a.x - b.x;
var dy:Number = a.y - b.y;
_lenght = Math.sqrt(dx * dx + dy * dy);
}else{
_lenght = lenght;
}
 
}
 
public function contract():void {
 
var dx:Number = pointb.x - pointa.x;
var dy:Number = pointb.y - pointa.y;
var h:Number = Math.sqrt(dx * dx + dy * dy);
var diff:Number = _lenght - h;
var offx:Number = (diff * dx / h) * .5; // or /2
var offy:Number = (diff * dy / h) * .5;// or /2
pointa.x -= offx;
pointa.y -= offy;
pointb.x += offx;
pointb.y += offy;
}
 
public function render(g:Graphics):void {
g.lineStyle(1,0xff00ff);
g.moveTo(pointa.x,pointa.y);
g.lineTo(pointb.x, pointb.y);
}
 
}

E finalmente a nossa classe main que ira fazer a mágica

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
public class Main extends Sprite{
 
public function Main():void
{
  if (stage) init();
  else addEventListener(Event.ADDED_TO_STAGE, init);
 
}
 
private function init(e:Event = null):void{
 
removeEventListener(Event.ADDED_TO_STAGE, init);
createPoints();//função encarregada de criar os Vpoints;
addEventListener(Event.ENTER_FRAME, render);
}
 
//constante com o numero de verlets points que será gerado
private const NUM_POINTS:int = 10;
//vetor com os pontos, somente flashplayer 10+
private var pontos:Vector.VerletPoint;
private var sticks:Vector.VerletStick;
 
public function createPoints():void {
 
pontos = new Vector.VerletPoint();
sticks = new Vector.VerletStick();
for (var i:int = 0 ; i < NUM_POINTS; i++ ) {
pontos.push(new VerletPoint(25*(i+1),25*(i+1)));
}
 
for (var a:int = 1 ; a < NUM_POINTS; a++ ) {
sticks.push(new VerletStick(pontos[a-1], pontos[a]));
}
 
}
 
public function render(e:Event):void {
 
this.graphics.clear(); //limpa a tela
pontos[0].setPos(mouseX, mouseY); //seta o ponto 0 com a posição do mouse
for each(var s:VerletStick in sticks) {
s.contract(); //atualiza os sticks
s.render(this.graphics);
 
}
 
for each (var p:VerletPoint in pontos) {
p.refresh(); //atualiza os pontos
p.render(this.graphics);
 
}
 
}
 
}

A versão final em Flash vocês podem conferir aqui:

Espero que tenham gostado se alguem tiver problemas comenta que eu tento resolver o mais rápido possivel.

Até a segunda parte do nosso Integrador de Verlet.

Autor: Regis Machado Ver todos os posts de

5 Comentários em "Integrador de Verlet Parte 1 – Introdução"

  1. Henrique Vilela 22/10/2010 at 14:52 - Reply

    O SWF não tá funcionado aqui. (Chrome, Flash Player 10.1)

  2. Regis.Machado 22/10/2010 at 16:37 - Reply

    Olá Henrique, também estou tendo problemas pra visualizar o swf em todos os navegadores.
    O Everton já me comentou sobre isso, e estamos buscando uma solução para este problema o mais rápido possivel.

  3. Leandro 22/10/2010 at 17:20 - Reply

    Também estou com esse problema aqui, mas achei que era algo relacionado ao Ubuntu+Chromium. :)

  4. everton 22/10/2010 at 18:16 - Reply

    Identifiquei o prolema com o SWF, resolvido! ;)

  5. Henrique Vilela 23/10/2010 at 21:05 - Reply

    Agora sim.
    Pô, bem legal o efeito.

    Pela imagem do post imagino que veremos uma malha na sequência, estou certo?

Deixar um Comentário