| Volver al Inicio | Microsoft Student Tech Club: Universidad Libre |
Tutorial de XNA:
Aplicando Física. Parte 2.
En esta lección comenzamos a utilizar instrucciones para hacer uso del motor de física. Una vez tenga descargado el motor, estos son los pasos para usarlo:
Paso 1: Creamos un nuevo proyecto de videojuego




Paso 2: Descomprimimos la librería Farseer Physics

Nos interesa es la carpeta "Farseer Physics 2.1 XNA"

Paso 3: Vamos a la carpeta creada por nuestro proyecto de juego. Usualmente es "Visual Studio 2008 -> Projects ->" y arrastramos "Farseer Physics 2.1 XNA" a esa carpeta de nuestro juego.

Quedando así

Paso 4: Ahora debemos agregar el proyecto "Farseer Physics 2.1 XNA a la solución del videojuego". Hay que dar clic con el botón derecho del ratón a la solución.

Buscamos el archivo FarseerPhysicsXNA.csproj (ojo, se supone que Windows tiene habilitado ver las extensiones de archivos conocidos).

Quedando así

Ahora, como usamos XNA 3.1, debemos actualizar ese proyecto. Clic botón derecho sobre el proyecto "FarseerPhysicsXNA" y seleccionamos la opción "Upgrade Solution..."



Paso 5: Ahora nuestro proyecto de videojuego referencia a "FarseerPhysicsXNA" así:



Chequeamos que efectivamente nuestro proyecto tiene esa dependencia


Paso 6: Ahora si, vamos a nuestro código y lo primero es agregar las librerías del motor de física

//Librerías del motor de física using FarseerGames.FarseerPhysics; using FarseerGames.FarseerPhysics.Collisions; using FarseerGames.FarseerPhysics.Dynamics; using FarseerGames.FarseerPhysics.Dynamics.Joints; using FarseerGames.FarseerPhysics.Factories; using FarseerGames.FarseerPhysics.Interfaces; using FarseerGames.FarseerPhysics.Controllers; using FarseerGames.FarseerPhysics.Mathematics; |
Paso 7: Luego las variables de clase
//Las texturas de caja1 y caja 2
Texture2D TexturaCaja1;
Texture2D TexturaCaja2;
//Simulador de física que conecta los diferentes cuerpos en un solo contexto físico
PhysicsSimulator SimuladorFisica;
//Cuerpos (usados por el simulador de física)
Body CuerpoCaja1;
Body CuerpoCaja2;
//Geometría de los cuerpos
Geom GeometriaCaja1;
Geom GeometriaCaja2;
|
Paso 8: En el método Initialize debe ir la configuración de los cuerpos y geometría
//Configura la tasa de refresco
IsFixedTimeStep = true;
TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 10); //10ms => 100fps
//Crea el objeto SimuladorFisica y en el constructor se coloca el vector de gravedad
SimuladorFisica = new PhysicsSimulator(new Vector2(0, 200));
//Parámetros de la caja 1
CuerpoCaja1 = BodyFactory.Instance.CreateRectangleBody(SimuladorFisica, 190, 190, 1);
CuerpoCaja1.Position = new Vector2(400, 100);
GeometriaCaja1 = GeomFactory.Instance.CreateRectangleGeom(SimuladorFisica, CuerpoCaja1, 190, 190);
//Parámetros de la caja 2 la cual está inmóvil
CuerpoCaja2 = BodyFactory.Instance.CreateRectangleBody(SimuladorFisica, 190, 190, 1);
CuerpoCaja2.Position = new Vector2(500, 400);
GeometriaCaja2 = GeomFactory.Instance.CreateRectangleGeom(SimuladorFisica, CuerpoCaja2, 190, 190);
CuerpoCaja2.IsStatic = true;
|
Paso 9: En el método LoadContent se llama la textura. En este caso es una imagen de un cuadro amarillo.

TexturaCaja1 = Content.Load<Texture2D>("Caja");
TexturaCaja2 = Content.Load<Texture2D>("Caja");
|
Paso 10: En el método Update se actualiza lo que está sucediendo con la física de los diferentes objetos en pantalla
//Actualiza el simulador de física
SimuladorFisica.Update(gameTime.ElapsedGameTime.Milliseconds * 0.001f);
|
Paso 11: Finalmente en el método Draw se dibujan las cajas en la posición y giro que el motor de física está calculando.
//Dibuja las cajas haciendo uso de la posición y rotación de los cuerpos
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
spriteBatch.Draw(TexturaCaja1, CuerpoCaja1.Position, null, Color.White, CuerpoCaja1.Rotation,
new Vector2(TexturaCaja1.Width / 2, TexturaCaja1.Height / 2), 1, SpriteEffects.None, 0);
spriteBatch.Draw(TexturaCaja2, CuerpoCaja2.Position, null, Color.White, CuerpoCaja2.Rotation,
new Vector2(TexturaCaja2.Width / 2, TexturaCaja2.Height / 2), 1, SpriteEffects.None, 0);
spriteBatch.End(); |
El código completo de Game1.cs es el siguiente:
using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Net; using Microsoft.Xna.Framework.Storage; //Librerías del motor de física using FarseerGames.FarseerPhysics; using FarseerGames.FarseerPhysics.Collisions; using FarseerGames.FarseerPhysics.Dynamics; using FarseerGames.FarseerPhysics.Dynamics.Joints; using FarseerGames.FarseerPhysics.Factories; using FarseerGames.FarseerPhysics.Interfaces; using FarseerGames.FarseerPhysics.Controllers; using FarseerGames.FarseerPhysics.Mathematics; namespace UsandoFisica
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//Las texturas de caja1 y caja 2
Texture2D TexturaCaja1;
Texture2D TexturaCaja2;
//Simulador de física que conecta los diferentes cuerpos en un solo contexto físico
PhysicsSimulator SimuladorFisica;
//Cuerpos (usados por el simulador de física)
Body CuerpoCaja1;
Body CuerpoCaja2;
//Geometría de los cuerpos
Geom GeometriaCaja1;
Geom GeometriaCaja2;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
//Configura la tasa de refresco
IsFixedTimeStep = true;
TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 10); //10ms => 100fps
//Crea el objeto SimuladorFisica y en el constructor se coloca el vector de gravedad
SimuladorFisica = new PhysicsSimulator(new Vector2(0, 200));
//Parámetros de la caja 1
CuerpoCaja1 = BodyFactory.Instance.CreateRectangleBody(SimuladorFisica, 190, 190, 1);
CuerpoCaja1.Position = new Vector2(400, 100);
GeometriaCaja1 = GeomFactory.Instance.CreateRectangleGeom(SimuladorFisica, CuerpoCaja1, 190, 190);
//Parámetros de la caja 2 la cual está inmóvil
CuerpoCaja2 = BodyFactory.Instance.CreateRectangleBody(SimuladorFisica, 190, 190, 1);
CuerpoCaja2.Position = new Vector2(500, 400);
GeometriaCaja2 = GeomFactory.Instance.CreateRectangleGeom(SimuladorFisica, CuerpoCaja2, 190, 190);
CuerpoCaja2.IsStatic = true;
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
TexturaCaja1 = Content.Load<Texture2D>("Caja");
TexturaCaja2 = Content.Load<Texture2D>("Caja");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here //Actualiza el simulador de física
SimuladorFisica.Update(gameTime.ElapsedGameTime.Milliseconds * 0.001f);
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here //Dibuja las cajas haciendo uso de la posición y rotación de los cuerpos
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
spriteBatch.Draw(TexturaCaja1, CuerpoCaja1.Position, null, Color.White, CuerpoCaja1.Rotation,
new Vector2(TexturaCaja1.Width / 2, TexturaCaja1.Height / 2), 1, SpriteEffects.None, 0);
spriteBatch.Draw(TexturaCaja2, CuerpoCaja2.Position, null, Color.White, CuerpoCaja2.Rotation,
new Vector2(TexturaCaja2.Width / 2, TexturaCaja2.Height / 2), 1, SpriteEffects.None, 0);
spriteBatch.End(); base.Draw(gameTime);
}
}
}
|
Y este es el resultado, la caja 1 es la que cae sobre la caja 2 que permanece inmóvil



| Volver al Inicio | Célula Microsoft. Universidad Libre |