martes, 7 de octubre de 2008

Moviendo la nave.

Como comente en el anterior post, primero voy a poner el código del juego para que te vayas animando al ver algo en movimiento y para los que ya tienen algo de conocimientos no se aburran, lo explicare muy por encima, pero no te preocupes si no entiendes muchas cosas, en los siguientes tutoriales lo iré explicando.


Bien, abrimos el proyecto que ya creamos en anteriores capítulos, ahora creamos una nueva clase:


1. Click derecho en el fichero de proyecto, agregar -> Clase.


2. Ahora ponle de nombre NaveProtagonista.cs


Ahora ya podemos empezar a programar la lógica de nuestra nave.


Primero de todo, agregamos las referencias necesarias:



[sourcecode language='csharp']
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
[/sourcecode]


Acto seguido hacemos que nuestra clase herede de DrawableGameComponent, la herencia la veremos en un capitulo para ella solita.



[sourcecode language='csharp']
class NaveProtagonista : DrawableGameComponent
[/sourcecode]

Ahora creamos las variables que necesitaremos más adelante:



[sourcecode language='csharp']
float rotacion = 0.0f;
Vector2 posicion;
Vector2 velocidad;
Asteroids juegoActual = null;
Texture2D SpriteNave;
[/sourcecode]

Se crea un constructor para la clase:



[sourcecode language='csharp']
public NaveProtagonista(Game juego) : base(juego)
{
juegoActual = (Asteroids)juego;
}
[/sourcecode]

Ahora, gracias a la herencia podemos hacer una sobreescritura de algunos metodos que nos permitiran manejar el grafico.


En la clase Initialize cargamos el grafico de la nave y lo colocamos en pantalla, en este caso en el centro.



[sourcecode language='csharp']
public override void Initialize()
{
posicion.X = juegoActual.Window.ClientBounds.Width / 2;
posicion.Y = juegoActual.Window.ClientBounds.Height / 2;
SpriteNave = juegoActual.Content.Load("Graficos/nave2");
}
[/sourcecode]

Ahora sobreescribimos el metodo que nos permitira mover la nave:



[sourcecode language='csharp']
public override void Update(GameTime gameTime)
{
KeyboardState estadoTeclado = Keyboard.GetState();
Keys[]teclapulsada = estadoTeclado.GetPressedKeys();
foreach (Keys tecla in teclapulsada)
{
if (tecla == Keys.Left)
{
rotacion -= ((float)gameTime.ElapsedGameTime.TotalSeconds) * 3f;
}
if (tecla == Keys.Right)
{
rotacion += ((float)gameTime.ElapsedGameTime.TotalSeconds) * 3f;
}
if (tecla == Keys.Up)
{
Vector2 VelocityAdd = Vector2.Zero;
//calculamos la direccion de la nave
VelocityAdd.X = (float)Math.Sin(rotacion);
VelocityAdd.Y = -(float)Math.Cos(rotacion);
velocidad += VelocityAdd;
}
}
//le sumamos el vector de velocidad calculado
posicion += velocidad;
velocidad *= 0.91f;

base.Update(gameTime);
}
[/sourcecode]

Por ultimo dibujamos el gráfico:



[sourcecode language='csharp']
public override void Draw(GameTime gameTime)
{
juegoActual.SpriteBatch.Draw(SpriteNave, posicion,
new Rectangle(0, 0, SpriteNave.Width, SpriteNave.Height),
Color.White, rotacion, new Vector2(SpriteNave.Width / 2,
SpriteNave.Height / 2), 1.5f, SpriteEffects.None, 0);

base.Draw(gameTime);
}
[/sourcecode]

Con esto tenemos toda la lógica de la nave para moverse por la pantalla.


Ahora tenemos que inicializarla, como os comente en el capitlo de orientación a objetos, para poder usarla tenemos que instanciarla, ¿Dónde haremos esto?, en el fichero base del juego.


Haz doble click en Game1.cs


Creamos las variables y propiedades necesarias:



[sourcecode language='csharp']
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
NaveProtagonista protagonista;

public SpriteBatch SpriteBatch
{
get { return spriteBatch; }
}

private GraphicsDeviceManager _propiedadesGraficos;
public GraphicsDeviceManager propiedadesGraficos
{
get { return _propiedadesGraficos; }
set { _propiedadesGraficos = value; }

}
[/sourcecode]

Ahora creamos el constructor de la clase(todo esto se explicará, tranquilo) donde instanciamos la nave protagonista que hemos creado antes.



[sourcecode language='csharp']
public Asteroids()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 768;
graphics.PreferredBackBufferWidth = 1024;
graphics.IsFullScreen = true;

protagonista = new NaveProtagonista(this);

_propiedadesGraficos = graphics;
}
[/sourcecode]

En el metodo LoadContent creamos el objeto spriteBatch.



[sourcecode language='csharp']
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
protagonista.Initialize();

// TODO: use this.Content to load your game content here
}
[/sourcecode]

En el método Update hacemos que al darle a escape se salga del juego:



[sourcecode language='csharp']
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();

// TODO: Add your update logic here
protagonista.Update(gameTime);
base.Update(gameTime);
}
[/sourcecode]

Y por ultimo dibujamos…



[sourcecode language='csharp']
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();

protagonista.Draw(gameTime);

spriteBatch.End();
// TODO: Add your drawing code here

base.Draw(gameTime);
}
[/sourcecode]

Sé que todo ha sido muy a saco, pero necesito que tengas algo de código real para ir trabajando en los tutoriales, en siguientes capítulos veremos el ciclo que sigue XNA al ejecutar un juego, porque métodos pasa primero y que hacer en cada uno de ellos, también veremos la sintaxis que estamos usando en el tutorial de C#


Ahora solo nos queda una cosa para que esto funcione, cargar el grafico en el proyecto,


En la carpeta content, click derecho, agregar nueva carpeta, la llamamos Graficos, click derecho en la carpeta recién creada y agregar elemento existente, acto seguido seleccionamos el grafico, mañana subiré el que estoy usando yo al blog, puedes probar con cualquier grafico, pero ten en cuenta que has de cambiar la ruta con el nombre de tu grafico en el método Initialize de la clase NaveProtagonista:


SpriteNave = juegoActual.Content.Load<Texture2D>("Graficos/nave2"); <- Cambialo!

5 comentarios:

  1. Roberto Castillo5 de marzo de 2009, 1:08

    Hermano tengo un problema a la hora de compilar...
    El problema es con el constructor de la clase...donde se hace referencia al namespace... lo tengo tal y como tu lo tienes


    Error 1 'Asteroids' es 'espacio de nombres' pero se utiliza como 'tipo' naveprotagonista.cs

    Excelente tutorial...de antemano, gracias

    ResponderEliminar
  2. Hola Roberto,
    ¿puedes ponerme aquí la linea que te da el error?

    ResponderEliminar
  3. Roberto Castillo5 de marzo de 2009, 9:30

    Muchas gracias por la pronta respuesta..Pero lo he resuelto...

    en Program.cs tengo esta línea
    using (Game1 game = new Game1())

    y en naveprotagonista.cs

    Game1 juegoActual= null;

    El error era que yo invocaba "Asteroids juegoActual=null" , es decir, como viene en tu ejemplo...
    y como yo no tenia declarado Asteroids en Program.cs , es por esto que el compilador se confundia con el "namespace" de la clase...
    Gracias gracias por este excelente blog!! sigue asi!!!

    ResponderEliminar
  4. Al comentarmerlo ahora me acabo de dar cuenta de una cosa... cuando creas un proyecto nuevo el nombre que le pone a la clase para el juego es Game1, yo se la cambie y le puse Asteroids, por eso te daba el error!
    Deduzco que no estabas trabajando con el proyecto que yo subí, si no que estabas picando tu propio código a partir del tutorial... muy bien, picando el código es como mas se aprende ;)
    Un saludo!

    ResponderEliminar
  5. Exacto, esa es la mejor forma de aprender..
    La retroalimentación al encontrar nuestras fallas...
    Gracias y espero la continuación de tus tutoriales...

    ResponderEliminar