Animação de partículas em Silverlight

Animação de partículas em Silverlight


Para simular fogo, fumaça, chuva, neve, fontes d’ água, entre outros fenômenos, precisamos desenvolver um Sistema de Partículas. O termo Sistema de Partículas refere-se a um conjunto de técnicas de animação para simulação de alguns destes fenômenos físicos. Primeiramente, devemos conhecer o que é uma partícula. Uma partícula é definida como o menor elemento de um sistema, e sobre cada partícula atuam forças externas e mútuas. Para os nossos propósitos, vamos definir uma partícula como uma única ocorrência de um objeto.

Um sistema de partícula é formado basicamente por três tipos de entidade:

1.    Emissor: é onde as partículas vão ser geradas. Pode ser um ponto, uma reta, uma curva, uma superfície ou até mesmo um objeto. O emissor que controla a posição de onde a partícula vai nascer sua direção e a sua velocidade inicial;

2.    Partícula: O menor elemento dentro de um sistema;

3.    Forças: é o que fazem as partículas alterarem seu movimento e produzem comportamento ao sistema.

Então, baseado nas entidades pode-se criar um modelo básico para os sistemas de partículas. Para cada unidade de tempo o aplicativo deverá criar novas partículas com base em algumas condições, atribuir um único conjunto de atributos para quaisquer novas partículas que são criadas, remover todas as partículas com base em alguma condição, pois cada partícula deverá ter um tempo de vida e atualizar a posição das partículas na tela.

Criando o Sistema de partículas

Inicie um projeto Silverlight, forneça o nome de App_ParticulasI.  Inclua dentro do projeto Silverlight um Usercontrol e forneça o nome de Particula.xaml, conforme mostrado na Figura 01.
Projeto

Figura 01
- Adicionando UserControl

Dentro do arquivo Particula. Xaml, vamos criar o formato da nossa partícula. Para isso adicione um objeto do tipo Elipse, conforme mostrado na Listagem 01.

<UserControl x:Class="App_ParticulasI.Particula"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Width="70" Height="70">

<Canvas x:Name="LayoutRoot" RenderTransformOrigin="0.5,0.5">

<Canvas.RenderTransform>

<TransformGroup>

<ScaleTransform x:Name="Escala" ScaleY="1" ScaleX="1"/>

<SkewTransform/>

<RotateTransform/>

<TranslateTransform X="0"/>

</TransformGroup>

</Canvas.RenderTransform>

<Ellipse x:Name="eParticula" Stroke="#FF000000" Height="70" Width="70">

<Ellipse.Fill>

<RadialGradientBrush>

<GradientStop Color="#FF2F739E"/>

<GradientStop Color="White" Offset="1"/>

<GradientStop Color="#FFB9D0DE" Offset="0.752"/>

</RadialGradientBrush>

</Ellipse.Fill>

</Ellipse>

</Canvas>

</UserControl>

Listagem 01 – Criando formato da partícula

O formato da partícula ficou como mostrado na Figura 02.

elipse azul

Figura 02 - Partícula

Neste ponto devemos criar alguns atributos para a partícula, que são: tempo de vida, idade e velocidade.  No arquivo Particula.xaml.cs insira o código como traz na listagem 02.

namespace App_ParticulasI

{

public partial class Particula : UserControl

{

 

public int TempoVida { get; set; }

public int Idade { get; set; }

public Point Velocidade;

 

 

public Particula()

{

InitializeComponent();

}

}

}

Listagem 02 – Atributos da partícula

Abra o arquivo MainPage.Xaml ou Page.Xaml e mude o Container Grid para Canvas e adicione a dimensão para o Canvas na propriedade Width e Height, conforme mostrado na Listagem 03.

<UserControl x:Class="App_ParticulasI.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600">

<Canvas x:Name="LayoutRoot" Width="800" Height="600">

 

</Canvas>

</UserControl>

Listagem 03 – Trocando container para Canvas


Abra o Page.xaml.cs ou MainPage.xaml.cs. Adicione uma variável do tipo inteiro, uma lista do Tipo Particula e um objeto do tipo Random. A Listagem 04 traz a codificação.

private List<Particula> SistemParticula;

private int _qtParticulas = 150;

private Random rand = new Random();

Listagem 04 – Adicionando objetos e Lista

Agora, será criado um método para criar as partículas, forneça o nome do método, tal como, CriarParticulas. Na Listagem 05, você pode observar a codificação sem grandes novidades.

public void CriarParticulas(int _qtParticulas)

{

for (int i = 0; i < _qtParticulas; i++)

{

Particula particula = new Particula();

Canvas.SetLeft(particula, rand.Next((int)LayoutRoot.Width));

Canvas.SetTop(particula, rand.Next((int)LayoutRoot.Width));

Particulas.Add(particula);

LayoutRoot.Children.Add(particula);

}

 

}

 

Listagem 05 – Método gerar Partículas

Analisando o código da Listagem 05, é possível observar, que apenas foi feito a Instancia da classe Particula a cada Loop e adicionada dentro do LayoutRoot, que nada mais é, do que um Container Canvas Os métodos SetLeft e SetTop apenas delimitam o espaço das partículas dentro do Canvas. A elipse, que neste caso é classe Particula depende da propriedade Left e Top do Canvas. A variável _qtParticulas, apenas limita a quantidade máxima de partículas dentro do Canvas. E por fim, cada partícula é adiciona na Lista.
Dentro do Construtor da página Page ou MainPage, chame o método CriarParticulas e crie o objeto da Lista particulas, conforme a Listagem 06.

public MainPage()

{

InitializeComponent();

Particulas = new List<Particula>(_qtParticulas);

CriarParticulas(_qtParticulas);

}

Listagem 06 – Chamando método

Execute a aplicação e deverá ter um resultado similar conforme apresentado na Figura 03.
Note que as partículas estão estáticas, então precisamos adicionar uma animação “Storyboard” para que as mesmas tenham movimentação. Na MainPage.xaml adicione o código descrito na Listagem 07.

<UserControl x:Class="App_ParticulasI.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600">

<UserControl.Resources>

<Storyboard x:Name="Move" Duration="00:00:00"/>

</UserControl.Resources>

 

<Canvas x:Name="LayoutRoot" Width="800" Height="600">

</Canvas>

</UserControl>

Listagem 07 – Adicionando Storyboard

Na MainPage.xalm.cs adicione o evento Completed e o método Begin da Storyboard nolinhas no construtor da MainPage.xaml.cs, como apresentada na Listagem 08.

 

Move.Completed += new EventHandler(Move_Completed);

Move.Begin();

Listagem 08 – Adicionando evento e chamando o método Begin

Dentro do método CriarParticulas vamos adicionar o tempo de vida para particula. Para isso, iremos usar o objeto rand, o qual irá designar de forma aleatória o tempo de vida para cada partícula do sistema.  A Listagem 09 traz a codificação.

particula.TempoVida = rand.Next(120);

Listagem 09 – Tempo de vida

Como as partículas possuem idade e um tempo de vida, devemos  incrementar a idade e verificar se a mesma alcançou o seu tempo de vida, caso seja verdadeiro a mesma será removida da tela. Para fazer isso, dentro do evento Move, adicione o código conforme mostrado na Listagem 10.

void Move_Completed(object sender, EventArgs e)

{

foreach (Particula particula in Particulas)

{

particula.Idade += 1;

if (particula.Idade >= particula.TempoVida)

{

 

LayoutRoot.Children.Remove(particula);

}

 

}

Move.Begin();

}

 

Listagem 10 – Removendo Partículas


Execute a aplicação . As partículas iram ser desenhadas e após alguns segundos todas são removidas.Este não é um efeito legal, então precisamos criar novas partículas.


Nota: Repare que não removemos as partículas da Lista. O que devemos também fazer.



Então Mude o código conforme traz a Listagem 11.


void Move_Completed(object sender, EventArgs e)

{

for (int i = 0; i < Particulas.Count; i++)

{

Particulas.Idade += 1;

if (Particulas.Idade >= Particulas.TempoVida)

{

 

LayoutRoot.Children.Remove(Particulas);

Particulas.Remove(Particulas);

CriarParticulas(1);

}

 

}

Move.Begin();

}        }

Listagem 11 - Removendo e adicionando novas partículas

Para terminar, falta adicionar velocidade para as partículas, no eixo x e y. Para isso adicone no método CriarParticulas o código da Listagem 12.

particula.Velocidade.X = rand.Next(-5, (int)5);

particula.Velocidade.Y = rand.Next(-5, (int)5);

if (particula.Velocidade.X == 0) particula.Velocidade.X = 2;

if (particula.Velocidade.Y == 0) particula.Velocidade.Y = 2;

Listagem 12 – Adicionando velocidade para cada partícula

Porém, falta acrescentar no Evento move antes do incremento da idade da partícula, o código da

da Listagem 13.

 

Canvas.SetLeft(Particulas, Canvas.GetLeft(Particulas) + Particulas.Velocidade.X);

Canvas.SetTop(Particulas, Canvas.GetTop(Particulas) + Particulas.Velocidade.Y);

Listagem 13 –  Posicionando partículas

Aprendemos neste artigo a criar partículas de forma dinâmica, considerando a velocidade, tempo de vida e a idade. Porém, não consideramos as forças que exercem sobre as partículas, como o efeito de gravidade e até mesmo a força que uma partícula exerce sobre a outra.

 

abraços,

Flávia Moreira








blog comments powered by Disqus

NewsLetter

Por favor preencher os campos.
Quer receber artigos?


Receber em HTML?