| Volver al Inicio | Microsoft Student Tech Club: Universidad Libre |
Tutorial de XNA: Sonidos en el juego
Hasta ahora nuestro juego es mudo. Es momento de añadirle mas emoción y realismo, y el camino para eso es agregándole sonidos. Estos son los pasos:
Paso 1: Buscar en Internet sonidos o generar sus propios sonidos y guardarlos en archivos con extensión .wav

Paso 2: Ejecutar el Microsoft Cross-Platform Audio Creation Tool 3 (XACT3) y crear un nuevo proyecto




Paso 3: Se crea un nuevo "Wave Bank"


Paso 4: Arrastre los archivos .wav a la ventana de Wave Bank

Paso 5: Creamos un nuevo "Sound Bank"


Paso 6: Arrastramos de "Wave Bank" a "Sound Bank"

Paso 7: Y arrastramos de "Sound Bank" a "Cue Name" y grabamos el proyecto.


Paso 8: Esto es lo que se obtiene

Paso 9: En "Content" damos Agregar "Nueva carpeta" y la llamamos "Audio"


Paso 10: Vamos a la carpeta donde tenemos nuestro proyecto de Visual C# y navegamos por las carpetas hasta llegar a la de Content, allí debe estar la de Audio vacía


Paso 11: Arrastramos del escritorio todo el proyecto de sonido (junto con los sonidos) a esa carpeta de Audio

Paso 12: A la carpeta de Audio le agregamos "Elemento existente..."

Paso 13: Y escogemos a SonidosJuego.xap

Paso 14: Ya queda en nuestro proyecto, ahora veamos las propiedades de SonidosJuego.xap

Paso 15: Cambiamos la propiedad "Content Processor" por Sound Effect - XNA Framework

Paso 16: Agregar el código requerido para el manejo de sonidos. Atributos de la clase Game1.cs
| //Audio AudioEngine MotorAudio; SoundBank BancoSonido; WaveBank BancoAudio; |
Cargando los sonidos en LoadContent()
| //Cargar el sonido (ojo con la extension .xgs) MotorAudio = new AudioEngine("Content\\Audio\\SonidosJuego.xgs"); //xna game studio BancoSonido = new SoundBank(MotorAudio, "Content\\Audio\\Sound Bank.xsb"); //xna sound bank BancoAudio = new WaveBank(MotorAudio, "Content\\Audio\\Wave Bank.xwb"); //xna wave bank |
Ejecutando los sonidos cuando se dispara o cuando hay una colisión.
| //Sonido de la explosión BancoSonido.PlayCue("Explosion"); y //Sonido del cohete |
Este es el código completo
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; namespace PrimerJuego
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch; //Contenedor de los sprite
Texture2D Fondo; //Variable de tipo textura que tendrá el fondo
Rectangle rectFondo; //Un rectángulo donde estará la textura del fondo ObjetosJuego lanzador; //El lanzador
ObjetosJuego baselanzador; //Base del lanzador //Almacena el estado anterior del ratón
MouseState anteriorRaton; //Almacena el estado anterior del teclado
KeyboardState anteriorTeclado; //Cohetes
ObjetosJuego[] cohetes;
const int MAXCOHETES = 7; //Enemigos
ObjetosJuego[] enemigos;
const int MAXENEMIGOS = 6; const float alturaMax = 0.1f; //No pegado del techo
const float alturaMin = 0.5f; //La mitad de la pantalla
const float velocidadMax = 5.0f; //Máxima velocidad
const float velocidadMin = 1.0f; //Mínima velocidadRandom aleatorio = new Random(); //Puntaje
int Puntaje = 0; //Lleva cuantos enemigos han sido destruidos
SpriteFont fuente; //Variable tipo de letra para mostrar el puntaje //Sonidos del Juego
AudioEngine MotorAudio;
SoundBank BancoSonido;
WaveBank BancoAudio; 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 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 //Utiliza genéricos <> por eso el uso de <> En C++ se llaman plantillas. Content carga el contenido binario.
Fondo = Content.Load<Texture2D>("Imagenes\\FondoJuego"); //El rectángulo en el que estará contenido el fondo
rectFondo = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height); //Cargar e inicializar el Lanzador
lanzador = new ObjetosJuego(Content.Load<Texture2D>("Imagenes\\Lanzador")); //No es necesaria la extension .tga
lanzador.posicion = new Vector2(160, 530); //Posicion del lanzador //Cargar e inicializar la base
baselanzador = new ObjetosJuego(Content.Load<Texture2D>("Imagenes\\Base")); //No es necesaria la extension .tga
baselanzador.posicion = new Vector2(70, 560); //Posicion de la base del lanzador //Cargar e inicializar los cohetes
cohetes = new ObjetosJuego[MAXCOHETES];
for (int Cont = 0; Cont < MAXCOHETES; Cont++)
cohetes[Cont] = new ObjetosJuego(Content.Load<Texture2D>("Imagenes\\Cohete")); //Cargar e inicializar los enemigos
enemigos = new ObjetosJuego[MAXENEMIGOS];
for (int Cont = 0; Cont < MAXENEMIGOS; Cont++)
enemigos[Cont] = new ObjetosJuego(Content.Load<Texture2D>("Imagenes\\Chatarra")); //Cargar la fuente
fuente = Content.Load<SpriteFont>("Fuentes\\TipoLetraJuego"); //Cargar el sonido (ojo con la extension .xgs)
MotorAudio = new AudioEngine("Content\\Audio\\SonidosJuego.xgs"); //xna game studio
BancoSonido = new SoundBank(MotorAudio, "Content\\Audio\\Sound Bank.xsb"); //xna sound bank
BancoAudio = new WaveBank(MotorAudio, "Content\\Audio\\Wave Bank.xwb"); //xna wave bank
} /// <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(); // Código para leer el estado del Gamepad de una XBOX. Se considera que hay un jugador al menos.
GamePadState estadoControl = GamePad.GetState(PlayerIndex.One); //Como hay que tener en cuenta los controles del XBOX llamados thumbstick, se
//observa que botón del XBOX oprimió, eso genera una constante algo grande por lo que se multiplica por 0.1
lanzador.rotacion += estadoControl.ThumbSticks.Left.X * 0.1f;//Esta es una compilación condicional. El teclado y el mouse solo son leídos si la aplicación ejecuta en un PC
#if !XBOX
//Código para leer el teclado
KeyboardState estadoTeclado = Keyboard.GetState();
if (estadoTeclado.IsKeyDown(Keys.Left)) lanzador.rotacion -= 0.1f; //Gira el lanzador hacia la izquierda
if (estadoTeclado.IsKeyDown(Keys.Right)) lanzador.rotacion += 0.1f; //Gira el lanzador hacia la derecha //Dispara un solo cohete.
//Chequea si el usuario mantiene presionada la tecla de disparo por lo que hace caso omiso a eso,
//el usuario debe presionar y soltar la tecla de disparo para lanzar mas misiles.
if (estadoTeclado.IsKeyDown(Keys.Space) && anteriorTeclado.IsKeyUp(Keys.Space))
DispararCohete(); //Se actualiza el estado del teclado
anteriorTeclado = estadoTeclado; //Código para leer el ratón
MouseState Raton = Mouse.GetState(); //Si movió el ratón entonces el lanzador cambia de ángulo
if (Raton != anteriorRaton)
{
int DiferX = Raton.X - anteriorRaton.X; //La diferencia entre la anterior posición del ratón y la nueva.
lanzador.rotacion += (float)DiferX / 100; //El movimiento en X del ratón cambia el ángulo del lanzador
} //Se actualiza el estado del ratón
anteriorRaton = Raton;
#endif //Esta instrucción limita entre 0 y 90 grados el giro del lanzador. Recordar que se hace uso de radianes.
lanzador.rotacion = MathHelper.Clamp(lanzador.rotacion, -MathHelper.PiOver2, 0); //Actualiza los cohetes
ActualizaCohetes(); //Actualiza los enemigos
ActualizaEnemigos(); 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 //Se inicia el spritebatch (Entre Begin y End se dibuja en cada unidad de tiempo los sprites)
spriteBatch.Begin(SpriteBlendMode.AlphaBlend); //Dibujar el fondo combinando el color blanco con el fondo
spriteBatch.Draw(Fondo, rectFondo, Color.White); //Dibuja la base del lanzador combinando con blanco
spriteBatch.Draw(baselanzador.sprite, baselanzador.posicion, Color.White); /* Dibuja el lanzador como tal, estos son los parámetros
* Parámetro 1: El sprite del lanzador
* Parámetro 2: La posición del lanzador
* Parámetro 3: null porque es solo una imagen (no una sucesión de estas
* Parámetro 4: Color.White, combinación de color
* Parámetro 5: Angulo de rotación por defecto
* Parámetro 6: Centro, el centro del sprite para girarlo después
* Parámetro 7: Escala a dibujar
* Parametro 8: Dibujar tal como es el sprite (no reflejo vertical ni horizontal)
* Parámetro 9: Ponerlo en la capa superior */
spriteBatch.Draw(lanzador.sprite, lanzador.posicion, null, Color.White, lanzador.rotacion, lanzador.centro, 0.6f, SpriteEffects.None, 0); //Dibuja cada cohete
foreach (ObjetosJuego cohete in cohetes)
if (cohete.esta_activo == true)
spriteBatch.Draw(cohete.sprite, cohete.posicion, null, Color.White, cohete.rotacion, cohete.centro, 0.2f, SpriteEffects.None, 0); //Dibuja cada enemigo
foreach (ObjetosJuego enemigo in enemigos)
if (enemigo.esta_activo == true)
spriteBatch.Draw(enemigo.sprite, enemigo.posicion, null, Color.White, enemigo.rotacion, enemigo.centro, 0.2f, SpriteEffects.None, 0); //Dibuja el puntaje
spriteBatch.DrawString(fuente, "Destruido: " + Puntaje.ToString(), new Vector2(80, 60), Color.White); //Finaliza el "ciclo" de los sprite
spriteBatch.End(); base.Draw(gameTime);
} //Metodo llamado desde Update
public void DispararCohete()
{
//Busca un cohete inactivo
foreach (ObjetosJuego cohete in cohetes)
{
//Si encuentra un cohete inactivo
if (cohete.esta_activo == false)
{
//Activa el cohete (para que sea dibujado)
cohete.esta_activo = true; //El cohete inicia en la posición del lanzador
cohete.posicion = lanzador.posicion; //En que dirección y a que velocidad sale el cohete. Hay que tener en cuenta la rotación del lanzador
cohete.velocidad = new Vector2((float)Math.Cos(lanzador.rotacion), (float)Math.Sin(lanzador.rotacion)) * 4.0f; //Rote el sprite del cohete para que coincida con el del lanzador
cohete.rotacion = lanzador.rotacion; //Sonido del cohete
BancoSonido.PlayCue("disparo"); return;
}
}
} //Método llamado desde Update
public void ActualizaCohetes()
{
//Va de cohete en bala
foreach (ObjetosJuego cohete in cohetes)
if (cohete.esta_activo == true)
{
//Solo es actualizar la velocidad porque el vector se actualiza gracias a esa magnitud
cohete.posicion += cohete.velocidad;//Chequea la colisión //Deduce el rectángulo del cohete y debe tener en cuenta el tamaño con que se esté dibujando en pantalla en Draw()
Rectangle rectCohete = new Rectangle((int)cohete.posicion.X, (int)cohete.posicion.Y, (int) (cohete.sprite.Width*0.2), (int) (cohete.sprite.Height*0.2)); //Chequea de enemigo en enemigo si el cohete lo colisiona
foreach (ObjetosJuego enemigo in enemigos)
{
//Deduce el rectángulo del enemigo y debe tener en cuenta el tamaño con que se esté dibujando en pantalla en Draw()
Rectangle rectEnemigo = new Rectangle((int)enemigo.posicion.X, (int)enemigo.posicion.Y, (int) (enemigo.sprite.Width*0.2), (int) (enemigo.sprite.Height*0.2)); //Si ambos rectángulos se intersectan
if (rectCohete.Intersects(rectEnemigo) == true)
{
enemigo.esta_activo = false; //inactiva el enemigo
cohete.esta_activo = false; //inactiva el cohete
Puntaje++; //Sonido de la explosion
BancoSonido.PlayCue("explosion"); break;
}
} //Si el cohete se sale de la pantalla entonces se desactiva
if (rectFondo.Contains(new Point((int)cohete.posicion.X, (int)cohete.posicion.Y)) == false)
cohete.esta_activo = false;
}
} //Método llamado desde Update
public void ActualizaEnemigos()
{
foreach (ObjetosJuego enemigo in enemigos)
{
if (enemigo.esta_activo == true)
{
//El enemigo avanza a determinada velocidad
enemigo.posicion += enemigo.velocidad; //Si el enemigo se sale de la pantalla
if (rectFondo.Contains(new Point((int)enemigo.posicion.X, (int)enemigo.posicion.Y)) == false)
enemigo.esta_activo = false;
}
else
{
//Activa el enemigo
enemigo.esta_activo = true; //Interpolación. Posición Y aleatoria.
enemigo.posicion = new Vector2(rectFondo.Right, MathHelper.Lerp((float)rectFondo.Height * alturaMin, (float)rectFondo.Height * alturaMax, (float)aleatorio.NextDouble())); //Velocidad del enemigo. Aleatoria.
enemigo.velocidad = new Vector2(MathHelper.Lerp(-velocidadMin, -velocidadMax, (float)aleatorio.NextDouble()), 0);
}
}
}
}
} |
| Volver al Inicio | Célula Microsoft. Universidad Libre |