Olá pessoal, tudo certo?!
Depois de alguns dias falando sobre fractais, html5 e muito JavaScript, volto a escrever código em C# seguindo esta série sobre XNA. Hoje, nada de HLSL, só C#!
Neste post, mostro uma técnica simples de animação (sem intevenção do usuário). Embora esteja utilizando modelos 3D, a mesma técnica pode ser aplicada a sprites.
O código-fonte completo dessa série está disponível em https://github.com/ElemarJR/VamosAprenderXNA
O que vamos fazer?
No post de hoje, uso como ponto de partida o código da parte 07. O objetivo é fazer com que nossa “nave ande de um lado para o outro” repetidamente. Observe:
Fica muito mais fácil de entender o que está ocorrendo se você baixar os fontes e rodar o programa.
A classe ModelAnimation
Para realizar a animação, bastava “cuidar da atualização” das propriedades Position e Rotation do modelo 3d (a nave). Por isso, precisamos de um objeto que mantenha:
- as posições inicial e final que desejamos respeitar em nossa animação;
- as rotações inicial e final que desejamos respeitar em nossa animação;
- o tempo total de animação (em um período, desconsiderando looping e reverse);
- se desejamos que a animação ocorra em “looping” (sem parar);
- se desejamos executar uma animação oposta (autoreverse).
Esse mesmo objeto deve “calcular” posição e rotação atualizadas conforme o tempo avança. Eis minha implementação:
public class ModelAnimation
{
public Vector3 StartPosition { get; private set; }
public Vector3 StartRotation { get; private set; }
public Vector3 EndPosition { get; private set; }
public Vector3 EndRotation { get; private set; }
public Vector3 Position { get; private set; }
public Vector3 Rotation { get; private set; }
public TimeSpan Duration { get; private set; }
public bool Looping { get; private set; }
public bool AutoReverse { get; private set; }
TimeSpan elapsedTime = TimeSpan.FromSeconds(0);
public ModelAnimation(
Vector3 startposition,
Vector3 startrotation,
Vector3 endposition,
Vector3 endrotation,
TimeSpan duration,
bool looping,
bool autoreverse
)
{
this.StartPosition = startposition;
this.StartRotation = startrotation;
this.EndPosition = endposition;
this.EndRotation = endrotation;
this.Duration = duration;
this.Looping = looping;
this.AutoReverse = autoreverse;
}
bool reversing = false;
public void Update(TimeSpan elapsed)
{
this.elapsedTime += elapsed;
var amount = (float)this.elapsedTime.TotalSeconds / (float)Duration.TotalSeconds;
if (this.Looping)
{
if (amount > 1)
{
this.elapsedTime = TimeSpan.FromSeconds(0);
reversing = !reversing;
while (amount > 1) amount--;
}
}
else
amount = MathHelper.Clamp(amount, 0f, 1f);
if (this.AutoReverse && reversing) amount = 1 - amount;
Position = Vector3.Lerp(this.StartPosition, this.EndPosition, amount);
Rotation = Vector3.Lerp(this.StartRotation, this.EndRotation, amount);
}
}
Como você pode perceber, a “mágica” acontece dentro do método update. Perceba:
- calculo uma “quantidade” de animação considerando a razão entre o tempo total transcorrido e o duração programada;
- estando em looping , verifico a conclusão da animação (um ciclo). Em caso positivo, ligo um flag que “inverte” o amount causando a “inversão” de sentido;
- Utilizo a função utilitária Lerp para determinar a interpolação linear entre os vetores de início e fim, usando o amount calculado.
Configurando e executando a animação
Configurar a animação é muito simples. Basta criar uma instância de nossa classe no game, informando os parâmetros adequadamente. Observe:
animation = new ModelAnimation(
spaceship.Position,
Vector3.Zero,
spaceship.Position + new Vector3(0, 0, 2600),
new Vector3(0, MathHelper.Pi, 0),
TimeSpan.FromSeconds(5),
true,
true
);
Como pode perceber, determino que :
- a posição e rotação inicial devem ser iguais ao objeto que estamos animando (nossa nave);
- a posição final está a 2600 unidades na frente da posição atual;
- a rotação final será 90 graus no eixo y;
- o tempo de um ciclo será de cinco segundos;
- a animação ocorrerá em looping;
- haverá AutoRevese;
Para garantir que a animação ocorra, falta apenas atualizar o método Update. Perceba:
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
animation.Update(gameTime.ElapsedGameTime);
spaceship.Position = animation.Position;
spaceship.Rotation = animation.Rotation;
}
Pronto!
Era isso.
![]()



Vinicius
05/11/2011
Cara, parabéns, seus códigos são muito bem organizados e profissionais.
É difícil encontrar material bom de XNA, assim bem explicado. Com certeza esses tutoriais vão me ajudar muito a aprender XNA.
Sucesso.
elemarjr
05/11/2011
Obrigado pelo feedback. Bons estudos.