superbacho
Usuario (México)
![Haz tu videojuego con XNA [Xbox/Windows] [parte 1]](https://storage.posteamelo.com/assets-adonis/assets/2013/04/08/Captura_252520de_252520pantalla_252520completa_25252014012012_252520033911_252520p.m-xneKl55x7lm.webp)
Hola, taringueros. Gracias por pasar.Antes de comenzar, debo decir que me he dado cuenta de varias cosas:=> En Taringa! hay mucho material acerca de videojuegos, recientemente hubo un TOP que hablaba sobre la creación de estos, pero usaba un lenguaje de programación que por lo personal no me gusta: C++. A mi me gusta programar en C#. Esto es cuestión de gustos, así que no pretendo sustituir ninguno de estos posts, ni mucho menos igualarlo, pues la temática es completamente distinta.=> No es fácil crear un videojuego, no soy un experto y no pretendo hacer el siguiente Gears of War con XNA Game studio 4. Hay mucho potencial en éste framework, pero no creo que puedas llegar a juegos tan profesionales como los que compras en Blockbuster o GamePlanet.=> Si tienes dudas, no hay nada como buscar información, no te van a resolver tus dudas así como así, no puedes pedir a los demás que te resuelvan tus problemas.Y además debo decir que como programador me gusta bastante XNA, no sé si ustedes concuerdan, pero a mi se me facilita. Hay por supuesto otras librerías para crear videojuegos en distintos lenguajes de programación. El ejemplo más común es SDL ( Simple DirectMedia Layer ) y estas librerías son muy poderosas. No tengo inconveniente en usarlas, las uso con Rubygame y es bastante cómodo usala. Sin embargo, no soy programador de videojuegos experto, y tengo fallas. Si tengo fallas en el post, por favor, no dudes ni un segundo en decirmelo.ANTES DE COMENZARPor supuesto que para leer el post hay que tener en cuenta algunas cosas:=> Debes tener alguna experiencia en programación, no te voy a enseñar a programar. Te voy a mostrar cómo se usa el XNA Game Studio Framework, si quieres aprender, usa C# y busca tutoriales en internet porque hay muchos. Si tienes conocimientos en C#, Java o Vala, vas a entender todo lo que aquí se expone.=> Instala Visual C# 2010 Express, descargalo desde , selecciona la versión en español en la parte de abajo en la pantalla, a la derecha.=> Instala el XNA Game Studio Framework, descargalo desde Esta descarga no está disponible en español, pero no importa, es un simple Framework, y no necesitas que esté en español necesariamente.Ya estamos listos, ahora a lo que vamos.Iniciar las herramientasAbrimos el Visual C# 2010 Express, los proyectos que he cargado aparecen en el historial, pero no necesariamente los debo abrir.Luego, vamos a Nuevo proyecto, y en el menu que nos despliega seleccionamos algo más o menos asi:Abrimos el proyecto, y lo que tenemos es algo parecido a esto:Aquí tenemos varias cosas pendientes para revisar. En el programa principal, en el archivo game1.cs tenemos varias cosas por las que tener atención. Son varios métodos, y te los explico a continuación:=> Initialize() en este método se inicializa el juego, no hay gran cosa que podemos modificar aquí, es el comenzo de la ejecución del juego. No vamos a profundizar en este método=> LoadContent() este método es importante, aquí se carga en la memoria operativa el contenido que se muestra y reproduce. Por ejemplo, aquí cargaremos la cara de nuestro personaje odiado, ya sea porque es un detractor de los gifs porno, un alien o lo que quieran, en un jueguito en donde hay que disparar a un tipo que valla pasando por ahí. Más adelante veremos detalles sobre esto.=> UnloadContent() en este método se saca de la memoria operativa los elementos que no se usarán más. Aquí se pone cada uno de los elementos que cargamos, para que antes de salir del juego se eliminen las entradas de la memoria que manejamos a lo largo del juego. Es una buena costumbre hacerlo, y recomiendo que lo hagan.=> Update() que es parte del bucle del juego, el cual se ejecuta varias veces en un segundo, lo cual es normal en cada juego. El método update lee la entrada de datos del usuario, hace cálculos y vigila el fin del juego.=> Draw() que igualmente es parte del bucle del juego, en éste método se ejecuta el código de la renderización, lo cual es necesario para mostar las actualizaciones de datos del juego en la pantalla.Ahora veremos la estructura básica del programa, abriendo el archivo Program.cs veremos un código muy sencillo:El archivo contiene el siguiente código: using System;namespace Pruba{#if WINDOWS || XBOX static class Program { /// <summary> /// The main entry point for the application. /// </summary> static void Main(string[] args) { using (Game1 game = new Game1()) { game.Run(); } } }#endif} Este código inicia el juego que está en el archivo principal, Game1.cs, y no es necesario modificarlo en ningun momento.Pero ahora es tiempo de probar lo que hemos hecho: vamos a iniciar una depuración para probar qué tal nos ha ido probando las herramientasY luego...Mierda!!!Pero... Yo tengo una gráfica HD:entonces, ¿qué pasa? Bueno, no eres el primero ni el último a quien le pasa esto, y la solución es muy sencilla:Vamos a las propiedades de la soluciónLuego cambiamos las cosas a como se muestra en este antes y después:Antes:Después:y así podemos ir a la depuración de nuevo:Listo! ahora tenemos funcionando un juego!Pero a mi no me gusta ese color azul, así que modificaremos en el método Draw() algo así: protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.LightGray); base.Draw(gameTime); } Y probamos de nuevo:Pero si oprimo una tecla no pasa nada! bueno, es que no hemos agregado nada aún, por lo que debemos tener un poco de código escrito en Update() para hacer algo en el juego, por lo menos poder cerrarlo oprimiento la tecla Escape: protected override void Update(GameTime gameTime) { KeyboardState state = Keyboard.GetState(); if (state.IsKeyDown(Keys.Escape)) this.Exit(); base.Update(gameTime); } Ahora, ¿qué hice? bueno, creaste una variable del tipo KeyboardState llamada state, la inicializaste como el estado actual del teclado, luego, un enunciado de control if() en donde, en caso de presionar la tecla Escape se invoca al método Exit() para cerrar el juego.¿Simple? bueno, es muy fácil hacer esto. Ahora vamos a aclarar algunos conceptos:CONCEPTOS CLAVEPrimero, tenemos una cosa que aclarar: ¿Qué es el bucle del juego? bueno, este bucle está constituido por los métodos Update() y Draw(), y el código contenido en ambos métodos es invocado cada vez que el juego inicia y corre en el ordenador, xbox o dispositivo. El código se ejecuta varias veces por segundo, y es importante para recibir órdenes del usuario, hacer cálculos (como los que se necesitan en un juego de disparos o en Pacman cuando un fantasma alcanza a nuestro personaje), y actualizar información clave.El código en Draw() actualiza la posición de todos los elementos del juego, y este código es importante para mostrar los cambios calculados por el método Update(), este método únicamente dibuja en pantalla todos los Sprites y demás objetos que tenemos.¿Sprites? Sí, un sprite es una imágen 2D que puede ser manipulada independientemente de toda la escena actual del juego. Contiene propiedades como Posición, tamaño y puede contener propiedades como Velocidad, aceleración, etc. Normalmente es usada junto a una textura.¿Textura? bueno, una textura es una imágen, como un mapa de bits que es mostrada en la pantalla como parte de un Sprite. Tambien puede ser usada en un modelo 3D, como en el caso de un juego de fórmula 1, donde todos los coches son iguales excepto por los distintos decorados y colores de los patrocinadores y fabricantes. Por lo tanto, es necesario un sólo modelo 3D, pero las texturas que se usarán son distintas. Las texturas se almacenan en la memoria gráfica, y en nuestro caso, usaremos una textura 2D formada por texeles.¿Texeles? Las texturas 2D se guardan en la memoria como un arreglo de Texeles (texels). Similares a los Pixeles, pero más pequeños, de hecho, son la unidad más pequeña que puede ser almacenada y mostrada por el GPU, e incluyen valores para color y transparencia.¿Posición? uf! aquí me estás metiendo en un aprieto... pero bueno, está bien, a mal paso darle prisa. La posición de un Sprite u otro objeto o punto de referencia es una coordenada (como en el plano cartesiano) pero estructurada de distinta forma. El plano cartesiano tiene esta forma:Pero aquí tenemos coordenadas negativas, y la forma en que está estructurado no es compatible con XNA. El plano de XNA está formado de otra forma.Suponiendo que nuestro juego tiene una resolución de 800x600, aproximadamente así sería nuestra distribución de coordenadas, siendo arriba a la izquierda el origen y de ahí parten los ejes X y Y, de forma que, aproximadamente esa imágen de arriba lo ilustra.AGREGAR UN SPRITEBueno, ahora conocemos más conceptos clave, pero, ¿cómo podemos agregar un Sprite a nuestro juego, para dibujarlo y poder manipularlo?Bueno, dibujarlo es una cosa sencilla. Manipularlo requiere un poco más de esfuerzo... primero vamos con lo fácil.Agregamos en nuestro proyecto una clase, un fichero llamado balon.cs, en donde definiremos las propiedades de nuestro Sprite, como la posición, la textura, el tamaño y más adelante definiremos la velocidad.Por lo mientras, agregaremos la clase...Y definiremos el nombre del fichero como balon.cs. Si ustedes quieren poner la cara del moderador predilecto de Taringa! pueden poner el nombre herni.cs, no hay ninguna diferencia.Y ahora tenemos un archivo vacío de clase, el cual llenaremos con lo siguiente:Codigo: using System;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;namespace Pruba{ class balon { public Vector2 Posicion { get; set; } public Vector2 Size { get; set; } public Texture2D Textura { get; set; } public balon(Texture2D _textura, Vector2 _posicion, Vector2 _tamano) { Textura = _textura; Posicion = _posicion; Size = _tamano; } }} Nota: Yo siempre defino los parámetros pasados desde las funciones, métodos o constructores con un guión bajo antecediendo el nombre, de esa forma no me confundo entre el nombre de un parámetro y el nombre de una variable o una propiedad. Es una costumbre que me he hecho con un poco de experiencia para que mis programas me resulten fáciles de leer. Puedes adoptar el estilo que desees para tus programas, este es mi estilo.Aquí hemos definido tres propiedades, dos de ellas almacenadas como clases del tipo Vector2. Esta clase almacena dos valores: un valor numérico para X y otro para Y. Logrando así almacenar datos como Velocidad, Tamaño, Posición, etc.Y la clase Texture2D en donde almacenaremos los datos referentes a la textura bidimensional que usaremos para nuestro proyecto. Yo usaré un balón, siéntete libre de usar la cara de Obama si lo deseas.El constructor recibe tres parámetros para invocarse, y estos tres parámetros los definiremos al editar más adelante.Yo voy a usar una textura del balón de Alemania 2006, el Teamgeist, porque el Jabulani me parece terrible.Y luego, lo agregamos a nuestro proyectoY seleccionamos la imagen que más nos acomoda...Seleccionamos la imágen en el explorador de propiedades, y luego damos Alt+Enter para entrar en las propiedades, luego seleccionamos algo parecido a esto:Assert name es el nombre con el cual insertamos la imágen en el juego, seleccionamos que compile la imágen y luego nos encargamos de esto...Vamos a nuestro código de balon.cs, porque tenemos que agregar un método para dibujar el Sprite en la pantalla, por lo que nuestro nuevo código quedará de la siguiente forma: using System;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics;namespace Pruba{ class balon { public Vector2 Posicion { get; set; } public Vector2 Size { get; set; } public Texture2D Textura { get; set; } public balon(Texture2D _textura, Vector2 _posicion, Vector2 _tamano) { Textura = _textura; Posicion = _posicion; Size = _tamano; } public void Draw(SpriteBatch _spritebatch) { _spritebatch.Draw(Textura, Posicion, Color.White); } }} Nota: El color White no altera los colores originales del balón, cualquier otro color sí lo hará.Y actualizaremos el código en Game1.cs, añadiendo la declaración de una variable del tipo balon llamada teamgeist, de forma que quede algo parecido a esto: public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; balon teamgeist; pero, falta crear el contenido del balón, para esto vamos a actualizar el método LoadContent() de forma que quede algo parecido a esto: protected override void LoadContent() { teamgeist = new balon(Content.Load<Texture2D>("teamgeist"), new Vector2(0f, 0f), new Vector2(64, 64)); spriteBatch = new SpriteBatch(GraphicsDevice); } Aquí tenemos varias cosas: El teamgeist lo igualamos a una clase balon nueva, primero cargamos la textura que nombramos "teamgeist" cuando fijamos las propiedades de la carga del balón.Luego, creamos un nuevo vector, que es requerido como parámetro para la posición de un objeto. Luego, como último parámetro fijamos un vector en 64x64 para fijar el tamaño del balón.Pero debemos también actualizar el método UnloadContent para descargar de la memoria todo lo demás. Quedando de la siguiente forma: protected override void UnloadContent() { teamgeist.Textura.Dispose(); } Luego, agregamos al método Draw de Game1.cs lo siguiente: protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.LightGray); spriteBatch.Begin(); teamgeist.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } Y probamos una depuración para revisar resultados:¿Qué pasó?Pues lo averiguarás en el siguiente post. Comenta, y dime qué te parece la idea de hacer videos en lugar de un post tan extenso, así podría explicarlo mejor. Este post es colaborativo de @OrlSan y mío. Podemos hacer el video explicando los conceptos y todo el código y demás cosas trabajando en equipo. Espero que les haya gustado.BIBLIOGRAFÍA=> Beginning XNA 3.0 Game Programming: From Novice to Professional. Alexandre Santos Lobão, Bruno Evangelista, José Antonio Leal de Farias, Riemer Grootjans. Apress, 2009. ISBN: 978-1-4302-1817-3=> http://en.wikipedia.org/wiki/Microsoft_XNA