Norberto Rojas - XNA (El Mago)

12
Ejemplo en 2D, movimiento, salto y fuego ”El Mago” Tecnología: XNA Games Studio Introducción XNA Game Studio permite a estudiantes y programadores de juegos, crear juegos usando .NET, para que funcionen en Windows y su Xbox 360. El sistema XNA Framework es el sistema de bibliotecas de clases de .NET con las cuales los programadores disfrutaran construir sus juegos. Esta disponible aquí para su descarga gratuita XNA Games Studio El objetivo fundamental es hacer fácil el desarrollar de los juegos. Usando el XNA Framework los juegos funcionan en Windows y en Xbox 360. Aun así existen funcionalidades distintas entre una y otra plataforma pero el objetivo primordial fue unificarlas en la medida de lo posible. De esta manera podemos resumir que el objetivo principal de XNA que es: “hacer fácil el desarrollo de video juegos”. Creación del Proyecto Para Windows Lo primero que hacemos es cargar el C# Express, para esto damos clic en Inicio->Todos los Programas -> Microsoft Visual C# 2005 Express Edition aquí nos carga el IDE de C#

Transcript of Norberto Rojas - XNA (El Mago)

Page 1: Norberto Rojas - XNA (El Mago)

Ejemplo en 2D, movimiento, salto y fuego ”El Mago”

Tecnología: XNA Games Studio

Introducción

XNA Game Studio permite a estudiantes y programadores de juegos, crear juegos usando .NET,

para que funcionen en Windows y su Xbox 360. El sistema XNA Framework es el sistema de

bibliotecas de clases de .NET con las cuales los programadores disfrutaran construir sus juegos.

Esta disponible aquí para su descarga gratuita XNA Games Studio

El objetivo fundamental es hacer fácil el desarrollar de los juegos. Usando el XNA Framework los

juegos funcionan en Windows y en Xbox 360. Aun así existen funcionalidades distintas entre una y

otra plataforma pero el objetivo primordial fue unificarlas en la medida de lo posible. De esta

manera podemos resumir que el objetivo principal de XNA que es: “hacer fácil el desarrollo de

video juegos”.

Creación del Proyecto Para Windows

Lo primero que hacemos es cargar el C# Express, para esto damos clic en Inicio->Todos los

Programas -> Microsoft Visual C# 2005 Express Edition aquí nos carga el IDE de C#

Page 2: Norberto Rojas - XNA (El Mago)

Aquí creamos un nuevo proyecto y en la ventana de Nuevo Proyecto seleccionamos la opción de:

Windows Game y lo guardamos como TheWizard.

Vamos a crear una clase que se va a llamar “sprite”, damos clic derecho en el solution explorer a

agregamos clase y después agregar item y lo guardamos como sprite.cs.

Introduciendo Código a la clase sprite

Ahora empecemos rellenando algunas propiedades de la clase. El propósito de la clase es

mantener la información importante sobre los varios sprites usados en un juego, y clasifican según

su tamaño. Para que nosotros empecemos con aquéllos. Agregue las propiedades siguientes a la

clase sprite

private Vector2 mPosition;

public Vector2 Position

{

get

{

return mPosition;

}

set

{

mPosition = value;

}

}

Vector2 mStartPosition;

public Vector2 StartPosition

{

get

{

return mStartPosition;

}

set

{

mStartPosition = value;

}

private int mWidth;

public int Width

{

get

{

return mWidth;

}

set

{

mWidth = value;

}

}

private int mHeight;

public int Height

{

get

{

return mHeight;

}

set

{

mHeight = value;

}

}

Page 3: Norberto Rojas - XNA (El Mago)

Ahora, incluso reforcemos más allá la clase sprite y agregue algunas Propiedades que tratan con la

textura de el sprite.

Unas propiedades más importantes para la clase son Destino y Fuente.

private int mTexturePositionX = 0;

public int TexturePositionX

{

get

{

return mTexturePositionX;

}

set

{

mTexturePositionX = value;

}

}

private int mTexturePositionY = 0;

public int TexturePositionY

{

get

{

return mTexturePositionY;

}

set

{

mTexturePositionY = value;

}

}

private int mTextureWidth = 0;

public int TextureWidth

{

get

{

return mTextureWidth;

}

set

{

mTextureWidth = value;

}

}

private int mTextureHeight = 0;

public int TextureHeight

{

get

{

return mTextureHeight;

}

set

{

mTextureHeight = value;

}

}

public Rectangle Destination

{

get

{

return new Rectangle((int)Position.X,

(int)Position.Y, Width, Height);

}

}

public Rectangle Source

{

get

{

return new Rectangle(TexturePositionX,

TexturePositionY, TextureWidth, TextureHeight);

}

}

Page 4: Norberto Rojas - XNA (El Mago)

Finalmente, nosotros agregaremos al constructor de clase sprite

Cuando una nueva clase sprite se crea, deben proporcionarse dos rectángulos dando la situación

inicial y tamaño del sprite así como el área de la textura inicial a ser desplegada para el sprite.

El proyecto todavía no hace mucho. Nosotros tenemos nuestro proyecto listo y una clase para el

sprite, pero ningún objeto real o algo a ser desplegado. Para remediar, prosigamos y agregamos

nuestra imagen al proyecto para que nosotros podemos empezar haciendo el trabajo un poco más

interesante.

Ahora vamos a crear la clase wizard, en donde se alojara nuestro mago

Para crear la case, damos clic derecho en el Solution Explorer y escogemos Agregar->Clase

después agregamos un nuevo ítem. Le damos el nombre de Wizard

public Sprite(Rectangle theLocationAndSize, Rectangle

theTextureLocationAndSize)

{

Position = new Vector2(theLocationAndSize.X,

theLocationAndSize.Y);

Width = theLocationAndSize.Width;

Height = theLocationAndSize.Height;

TexturePositionX =

theTextureLocationAndSize.X;

TexturePositionY =

theTextureLocationAndSize.Y;

TextureWidth =

theTextureLocationAndSize.Width;

TextureHeight =

theTextureLocationAndSize.Height;

mStartPosition = new

Vector2(theLocationAndSize.X, theLocationAndSize.Y);

}

Page 5: Norberto Rojas - XNA (El Mago)

Agregamos algunos objetos

Nosotros inicializaremos y crearemos estos objetos en el constructor de la clase wizard.

Nosotros expondremos una Actualización y un procedimiento que dibuje dentro de la clase

wizard. Los procedimientos se llamarán de la clase principal poner al actualizar y dibujar el Mago y

sus objetos relacionados cuando sea apropiado.

Nosotros necesitamos poder rastrear los varios estados del Mago.

Los juegos pueden estar en los varios estados (cargando, game over, pausa, etc.) y los personajes

también pueden estar en los varios estados (corriendo, saltando, etc.).

Para empezar rastreando el estado del Mago, nosotros agregaremos un estado enum , una

variable para guardar el estado actual y una Propiedad para recuperar y poner el estado actual del

Mago.

Texture2D mWizardTexture;

Sprite.Sprite mWizard;

Dictionary<string, Sprite.Sprite>mFireballs

= new

Dictionary<string,global::TheWizard.Sprite.

Sprite>();

public Wizard(GraphicsDevice theDevice,

ContentManager theLoader)

{

mWizardTexture =

theLoader.Load<Texture2D>("./Images/WizardSheet") as

Texture2D;

mWizard = new Sprite.Sprite(new

Rectangle(20, 500, 50, 100), new Rectangle(0, 0, 90,

220));

mWizard.Visible = true;

}

public void Draw(SpriteBatch theSpriteBatch)

{

theSpriteBatch.Draw(mWizardTexture,

mWizard.Destination, mWizard.Source, Color.White);

foreach (KeyValuePair<string, Sprite.Sprite>

aFireball in mFireballs)

{

if (aFireball.Value.Visible == true)

{

theSpriteBatch.Draw(mWizardTexture,

aFireball.Value.Destination, aFireball.Value.Source,

Color.White);

}

}

}

Page 6: Norberto Rojas - XNA (El Mago)

Usted puede ver en la propiedad de CurrentWizardState que cuando el estado es el cambiado, hay

código que automáticamente dispara para cambiar algo en el Mago. Ése es uno de los beneficios

de poder rastrear un carácter por su estado.

Ahora que nosotros tenemos el estado del Mago agregado a la clase, prosigamos y empezamos

agregando algunos de esos nuevos procedimientos de actualización que se llamaron en la

Update() antes.

protected enum WizardState

{

Standing,

Walking,

Magicking,

Ducking,

Jumping

}

protected WizardState mWizardState = WizardState.Standing;

protected WizardState CurrentWizardState

{

get

{

return mWizardState;

}

set

{

mWizardState = value;

switch (mWizardState)

{

case WizardState.Standing:

{

mWizard.TexturePositionX = 0;

mWizard.TexturePositionY = 0;

break;

}

case WizardState.Walking:

{

mWizard.TexturePositionX = 0;

mWizard.TexturePositionY = 0;

break;

}

case WizardState.Ducking:

{

mWizard.TexturePositionX = 180;

mWizard.TexturePositionY = 220;

break;

}

case WizardState.Magicking:

{

mWizard.TexturePositionX = 180;

mWizard.TexturePositionY = 0;

AddFireball();

break;

}

}

}

}

Page 7: Norberto Rojas - XNA (El Mago)

Primero, nosotros agregaremos en el UpdateWizard () el procedimiento

Cuando el Mago es actualizado, nosotros haremos un chequeo para ver en qué estado el Mago

esta actualmente. Si él está caminando, entonces nosotros ejecutaremos algún código particular

para llamar el UpdateWizardWalking () y si él está saltando, nosotros ejecutaremos algún código

particular para llamar el UpdateWizardJumping ()

UpdateWizardWalking () cuida de la animación para mover al mago para adelante o hacia atrás

sobre el eje x

protected void UpdateWizard(double elapsed)

{

switch (CurrentWizardState)

{

case WizardState.Walking:

{

UpdateWizardWalking(elapsed);

break;

}

case WizardState.Jumping:

{

UpdateWizardJumping(elapsed);

break;

}

}

}

private double mWizardHeadBobElapsed = 0;

private void UpdateWizardWalking(double elapsed)

{

mWizardHeadBobElapsed += elapsed;

if (mWizardHeadBobElapsed > 0.2)

{

mWizardHeadBobElapsed = 0;

if (mWizard.TexturePositionX == 0)

{

mWizard.TexturePositionX = 90;

}

else

{

mWizard.TexturePositionX = 0;

}

}

switch (mWizard.Direction)

{

case Sprite.Sprite.eDirection.Right:

{

mWizard.Position = new Vector2(mWizard.Position.X + 3,

mWizard.Position.Y);

break;

}

case Sprite.Sprite.eDirection.Left:

{

mWizard.Position = new Vector2(mWizard.Position.X - 3,

mWizard.Position.Y);

break;

}

}

}

Page 8: Norberto Rojas - XNA (El Mago)

UpdateWizardJumping () cuida de cambiar la animación cuando el mago esta saltando y moverlo

de arriba abajo sobre el eje y.

private double mWizardJumpElapsed = 0;

private Sprite.Sprite.eDirection mJumpDirection =

Sprite.Sprite.eDirection.None;

private void UpdateWizardJumping(double elapsed)

{

mWizardJumpElapsed += elapsed;

if (mWizardJumpElapsed < .3)

{

mWizard.TexturePositionX = 0;

mWizard.TexturePositionY = 220;

}

else if (mWizardJumpElapsed < .6)

{

mWizard.TexturePositionX = 90;

MoveWizard(mJumpDirection, 1, Sprite.Sprite.eDirection.Up,

5);

}

else if (mWizardJumpElapsed < .9)

{

MoveWizard(mJumpDirection, 2, Sprite.Sprite.eDirection.Up,

5);

}

else if (mWizardJumpElapsed < 1.2)

{

MoveWizard(mJumpDirection, 2,

Sprite.Sprite.eDirection.Down, 5);

}

else if (mWizardJumpElapsed < 1.5)

{

MoveWizard(mJumpDirection, 1,

Sprite.Sprite.eDirection.Down, 5);

}

else if (mWizardJumpElapsed < 1.8)

{

mWizard.TexturePositionX = 0;

mWizard.TexturePositionY = 220;

}

else

{

mWizardJumpElapsed = 0;

mPreviousKeyPressed = Keys.None;

CurrentWizardState = WizardState.Walking;

}

}

private void MoveWizard(Sprite.Sprite.eDirection theXDirection, int

theXDistance, Sprite.Sprite.eDirection theYDirection, int theYDistance)

{

if (theXDirection == Sprite.Sprite.eDirection.Left)

{

theXDistance *= -1;

}

else if (theXDirection == Sprite.Sprite.eDirection.None)

{

theXDistance = 0;

}

if (theYDirection == Sprite.Sprite.eDirection.Up)

{

theYDistance *= -1;

}

else if (theYDirection == Sprite.Sprite.eDirection.None)

{

theYDistance = 0;

}

mWizard.Position = new Vector2(mWizard.Position.X +

theXDistance, mWizard.Position.Y + theYDistance);

}

Page 9: Norberto Rojas - XNA (El Mago)

Ahora, nosotros necesitamos mover las bolas de fuego a lo largo en la pantalla

Para determinar como mover al Mago alrededor, tenemos que ser capaces de leer las teclas que

están siendo presionadas por el usuario y cambian el estado del Mago de manera apropiada.

Hacemos esto por añadiendo el último de los procedimientos de Actualización y creamos

UpdateKeyboard ()

protected void UpdateFireballs(double elapsed)

{

mFireballElapsed -= elapsed;

if (mFireballElapsed < 0)

{

mFireballElapsed = 0;

}

bool aFireballVisible = false;

foreach (KeyValuePair<string, Sprite.Sprite>

aFireball in mFireballs)

{

if (aFireball.Value.Visible == true)

{

if (aFireball.Value.Position.X >

aFireball.Value.StartPosition.X + 400)

{

aFireball.Value.Visible = false;

}

else

{

aFireball.Value.Position = new

Vector2(aFireball.Value.Position.X + 5,

aFireball.Value.Position.Y);

aFireballVisible = true;

}

}

}

if (aFireballVisible == false)

{

mFireballElapsed = 0;

}

}

Keys mPreviousKeyPressed = Keys.None;

protected void UpdateKeyboard(double elapsed)

{

KeyboardState aKeyboard = Keyboard.GetState();

if (aKeyboard.IsKeyDown(mPreviousKeyPressed) == false &&

CurrentWizardState != WizardState.Jumping)

{

mPreviousKeyPressed = Keys.None;

CurrentWizardState = WizardState.Standing;

if (aKeyboard.IsKeyDown(Keys.Space) == true)

{

mPreviousKeyPressed = Keys.Space;

mFireballElapsed = 0;

CurrentWizardState = WizardState.Magicking;

}

else if (aKeyboard.IsKeyDown(Keys.Up) == true)

{

mJumpDirection = Sprite.Sprite.eDirection.None;

if (aKeyboard.IsKeyDown(Keys.Left) == true)

{

mJumpDirection = Sprite.Sprite.eDirection.Left;

}

else if (aKeyboard.IsKeyDown(Keys.Right) == true)

{

mJumpDirection = Sprite.Sprite.eDirection.Right;

}

mPreviousKeyPressed = Keys.Up;

Page 10: Norberto Rojas - XNA (El Mago)

CurrentWizardState = WizardState.Jumping;

}

else if (aKeyboard.IsKeyDown(Keys.Down) == true)

{

mPreviousKeyPressed = Keys.Down;

CurrentWizardState = WizardState.Ducking;

}

else if (aKeyboard.IsKeyDown(Keys.Left) == true)

{

mWizard.Direction = Sprite.Sprite.eDirection.Left;

mPreviousKeyPressed = Keys.Left;

CurrentWizardState = WizardState.Walking;

}

else if (aKeyboard.IsKeyDown(Keys.Right) == true)

{

mWizard.Direction = Sprite.Sprite.eDirection.Right;

mPreviousKeyPressed = Keys.Right;

CurrentWizardState = WizardState.Walking;

}

}

else if (CurrentWizardState == WizardState.Magicking)

{

CurrentWizardState = WizardState.Magicking;

}

else if (CurrentWizardState != WizardState.Jumping &&

aKeyboard.IsKeyDown(Keys.Up) == true)

{

mJumpDirection = Sprite.Sprite.eDirection.None;

if (aKeyboard.IsKeyDown(Keys.Left) == true)

{

mJumpDirection = Sprite.Sprite.eDirection.Left;

}

else if (aKeyboard.IsKeyDown(Keys.Right) == true)

{

mJumpDirection = Sprite.Sprite.eDirection.Right;

}

mPreviousKeyPressed = Keys.Up;

CurrentWizardState = WizardState.Jumping;

}

}

UpdateKeyboard () hace muchas comprobaciónes suplementarias para no sólo ver que teclas que

están siendo presionadas, si no también para rastrear que teclas han sido presionado antes (la vez

pasada se UpdateKeyboard) y determinar como el Mago debería reaccionar dependiendo(según)

lo que el estado el Mago actualmente está (por ejemplo, el Mago no puede encender una bola de

fuego saltando).

Finalmente, para redondear la clase de Mago, tenemos que añadir nuevas bolas de fuego

private double mFireballElapsed = 0;

protected void AddFireball()

{

if (mFireballElapsed == 0)

{

bool aAddFireball = true;

foreach (KeyValuePair<string, Sprite.Sprite> aFireball in mFireballs)

{

if (aFireball.Value.Visible == false)

{

aFireball.Value.StartPosition = new Vector2(mWizard.Position.X + 30,

mWizard.Position.Y);

aFireball.Value.Position = new Vector2(mWizard.Position.X + 30,

mWizard.Position.Y);

aFireball.Value.Visible = true;

mFireballElapsed = (float)0.5;

aAddFireball = false;

break;

Page 11: Norberto Rojas - XNA (El Mago)

}

}

if (aAddFireball == true)

{

string aKey = "Fireball" + (mFireballs.Count + 1).ToString();

mFireballs.Add(aKey, new Sprite.Sprite(new

Rectangle((int)mWizard.Position.X + 30,

(int)mWizard.Position.Y, 50, 100), new Rectangle(270, 0, 90, 220)));

mFireballs[aKey].Visible = true;

mFireballElapsed = (float)0.5;

}

}

} private double mFireballElapsed = 0;

protected void AddFireball()

{

if (mFireballElapsed == 0)

{

bool aAddFireball = true;

foreach (KeyValuePair<string, Sprite.Sprite> aFireball in mFireballs)

{

if (aFireball.Value.Visible == false)

{

aFireball.Value.StartPosition = new Vector2(mWizard.Position.X +

30, mWizard.Position.Y);

aFireball.Value.Position = new Vector2(mWizard.Position.X + 30,

mWizard.Position.Y);

aFireball.Value.Visible = true;

mFireballElapsed = (float)0.5;

aAddFireball = false;

break;

}

}

if (aAddFireball == true)

{

string aKey = "Fireball" + (mFireballs.Count + 1).ToString();

mFireballs.Add(aKey, new Sprite.Sprite(new

Rectangle((int)mWizard.Position.X + 30,

(int)mWizard.Position.Y, 50, 100), new Rectangle(270, 0, 90, 220)));

mFireballs[aKey].Visible = true;

mFireballElapsed = (float)0.5;

}

}

}

Nosotros necesitamos todavía crear un objeto del Mago en nuestra clase lista principal y llamar a

las demás clases.

Agregando el objeto del Mago a la clase main Game:

Para conseguir el sprite del Mago moviéndose alrededor en la pantalla y haciendo todos sus trucos

usted necesitará crear un nuevo objeto del Mago en la clase game. nosostros agregaremos el

objeto spritebatch para dibujar nuestros sprites a la clase.

SpriteBatch mSpriteBatch;

Wizard mWizard;

Ahora, nosotros agregaremos el código al empezar la función para inicializar nuestros objetos

cuando el juego este iniciando.

protected override void Initialize() {

mSpriteBatch = new SpriteBatch(this.graphics.GraphicsDevice);

ContentManager aLoader = new ContentManager(Services);

mWizard = new Wizard(this.graphics.GraphicsDevice, aLoader);

Page 12: Norberto Rojas - XNA (El Mago)

base.Initialize();

}

En Update, nosotros agregaremos algún código para terminar el juego si presionamos Escape y

para actualizar al mago.

Finalmente, nosotros agregaremos nuestro último pedazo de código para dibujar todo realmente

en la pantalla. En Draw, nosotros agregaremos algún código para empezar dibujando con el

SpriteBatch (recordando poner el SpriteBlendMode a AlphaBlend para que nuestras

transparencias del duende trabajen apropiadamente) y entonces nosotros llamamos a Draw ()

para dibujar al mago y todos es los objetos relacionados.

Y hemos acabado, ahora tenemos un mago que camina, salta y usa sus habilidades misteriosas

creando una poderosa bola de fuego si presionas la barra espaciadora, y se sale de el juego si

presionas escape, es hora de ver como quedo!!!

protected override void Update(GameTime gameTime)

{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back

== ButtonState.Pressed)

this.Exit();

KeyboardState aKeyboard = Keyboard.GetState();

if (aKeyboard.IsKeyDown(Keys.Escape) == true)

{

this.Exit();

}

mWizard.Update(gameTime.ElapsedGameTime.TotalSeconds);

base.Update(gameTime);

}

protected override void Draw(GameTime gameTime)

{

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend);

mWizard.Draw(mSpriteBatch);

mSpriteBatch.End();

base.Draw(gameTime);

}