martes, 16 de agosto de 2011

XNA – PingPong, Bola


Ya tenemos la Paletas echas, ahora toca hacer la Bola. Crearemos en nuestro proyecto la clase Bola.cs.


Variables
Texture2D textura;
Vector2 posicion;
Vector2 posicionIni;
Vector2 vel;
BoundingBox bbox;
Vector2 tamañoventana;
textura y posicion: Guardamos la textura y su posición. posicionIni: La utilizamos luego para el reset. vel: La velocidad de movimiento de nuestra bola. bbox: El boundingbox de nuestra bola. Por que razón BoundingBox y no BoundingSphere?, la colisión tenia problemas con el BoundingSphere, lo atribuí al tamaño de la pelotita. Con el BoundingBox fallaba mucho menos. tamañoventana: Lo usamos para la colisión de la pelota para lo lados de arriba y abajo de la ventana
Constructor
public Bola(Inicio init)
{
textura = init.Content.Load("disco");
posicion = new Vector2(init.Window.ClientBounds.Width / 2, init.Window.ClientBounds.Height / 2);
posicionIni = posicion;
vel = new Vector2(5, 5);
tamañoventana = new Vector2(init.Window.ClientBounds.Width, init.Window.ClientBounds.Height);}
Creo que no hay nada que aclarar.
Update
public void Update(BoundingBox player1, BoundingBox player2)
{
posicion += vel;
bbox = new BoundingBox(new Vector3(posicion, 0), new Vector3(posicion.X + textura.Width, posicion.Y + textura.Height, 0));
Colision(player1, player2);
}
El update de la bola pide los BoundingBox de las paletas, por eso en la clase Paleta.cs hicimos sus BoundingBox publicas. Primero le sumamos a su posición la velocidad de la bola, eso hará que se mueva. Creamos su BoundingBox y después llamamos a una función llamada Colisión y tomamos los dos BoundingBox como parámetro.
void Colision
private void Colision(BoundingBox player1, BoundingBox player2)
{
if (posicion.Y > tamañoventana.Y - textura.Height || posicion.Y < 0)
{
vel.Y *= -1;
}
 
Random rnd = new Random();
if (bbox.Intersects(player1) || bbox.Intersects(player2))
{
if (vel.X < 0)
{
vel.X = rnd.Next(2, 8);
}
else
{vel.X = rnd.Next(-8, -2);
}
 
if (vel.Y < 0)
{
vel.Y = rnd.Next(2, 8);
}
else
{vel.Y = rnd.Next(-8, -2);
}
}
}
El primer if corresponde a la colisión de cuando choca con una de los lado de arriba o abajo de nuestra ventana. Si choca arriba o abajo invertirá su velocidad a su valor contrario, de esta forma la pelota ira para el lado contrario por el que iba.
Luego viene la colisión contra las paletas. La función Random la utilizamos para crear un numero al azar y luego aplicarlo a la velocidad, esto es para que cuando choque con una paleta este se devuelva con una velocidad y orientación distinta. Si la velocidad es menor a 0, eso quiere decir que la pelota va hacia atrás, entonces al tocar con la paleta le asignamos un valor positivo al azar, entonces la pelota va hacia delante con una velocidad que varia cada vez que golpe. Lo mismo pasa al revez. Y por ultimo
Agregamos lo siguiente, las funciones las usaremos para el próximo(y ultimo) tutorial.
public void Draw(SpriteBatch sb)
{
sb.Draw(textura, posicion, Color.White);
}
 
public int SePaso(BoundingBox player1, BoundingBox player2)
{
if (posicion.X < player1.Min.X)
{
return 1;
}
else if (posicion.X > player2.Min.X)
{
return 2;
}
else
{
return 0;
}
}
 
public void Reset()
{
posicion = posicionIni;
vel = new Vector2(5, 5);
}
Iniciamos la pelotaA lo que teníamos antes, agregamos lo siguiente.
Bola bola;
Lo iniciamos.
bola = new Bola(this);
Ahora en el Update.
bola.Update(player1.bbox, player2.bbox);
Y en el Draw.
bola.Draw(spriteBatch);
Si todo nos salio bien, tendríamos nuestra pelota andando y chocando con las paletas, pero sin tener colisión contra los lados laterales de la ventana. Aca termina el tutorial para la Bola, en el proximo veremos el ultimo paso, que es el del Puntaje.
Bola.cs
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 MiJuego_Tutorial_9
{
 
public class Bola
{
Texture2D textura;
Vector2 posicion;
Vector2 posicionIni;
Vector2 vel;
BoundingBox bbox;
Vector2 tamañoventana;
 
public Bola(Inicio init)
{
textura = init.Content.Load< Texture >("disco");
posicion = new Vector2(init.Window.ClientBounds.Width / 2, init.Window.ClientBounds.Height / 2);
posicionIni = posicion;vel = new Vector2(5, 5);
tamañoventana = new Vector2(init.Window.ClientBounds.Width, init.Window.ClientBounds.Height);
}
 
public void Update(BoundingBox player1, BoundingBox player2)
{
posicion += vel;
bbox = new BoundingBox(new Vector3(posicion, 0), new Vector3(posicion.X + textura.Width, posicion.Y + textura.Height, 0));
Colision(player1, player2);
}
 
public void Draw(SpriteBatch sb)
{
sb.Draw(textura, posicion, Color.White);
}
 
private void Colision(BoundingBox player1, BoundingBox player2)
{
if (posicion.Y > tamañoventana.Y - textura.Height || posicion.Y < 0)
{
vel.Y *= -1;
}
 
Random rnd = new Random();
if (bbox.Intersects(player1) || bbox.Intersects(player2))
{
if (vel.X < 0)
{
vel.X = rnd.Next(2, 8);
}
else
{
vel.X = rnd.Next(-8, -2);
}
 
if (vel.Y < 0)
{
vel.Y = rnd.Next(2, 8);
}
else
{vel.Y = rnd.Next(-8, -2);
}
 
}
}
 
public int SePaso(BoundingBox player1, BoundingBox player2)
{
if (posicion.X < player1.Min.X)
{return 1;
}
else if (posicion.X > player2.Min.X)
{
return 2;
}
else
{
return 0;
}
}
 
public void Reset()
{
posicion = posicionIni;
vel = new Vector2(5, 5);
}
 
}}
Inicio.cs
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 MiJuego_Tutorial_9
{
public class Inicio : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
 
Paleta player1;
Paleta player2;
Bola bola;
Texture2D fondo;
 
public Inicio()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
Content.RootDirectory = "Content";
}
 
protected override void Initialize(){
 
base.Initialize();}
 
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
player1 = new Paleta(1, this);
player2 = new Paleta(2, this);
bola = new Bola(this);
fondo = Content.Load< Texture2D >("fondo");
}
 
protected override void UnloadContent(){
 
}
 
protected override void Update(GameTime gameTime)
{
bola.Update(player1.bbox, player2.bbox);
player1.Update();
player2.Update();
 
base.Update(gameTime);
}
 
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
 
spriteBatch.Begin();
spriteBatch.Draw(fondo, new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height), Color.White);
player1.Draw(spriteBatch);player2.Draw(spriteBatch);
bola.Draw(spriteBatch);
 
spriteBatch.End();
 
base.Draw(gameTime);
}
}
}