1. B L A D I M I R D I A Z C A M P O S
E I S I
Adicionar mas componentes
2. Agenda
Hasta ahora se ha creado un sprite que rebota en los
bordes de la pantalla
Ahora vamos a crear un sprite para golpear el queso
que ha sido puesto en pantalla.
En esta sesión, vamos a buscar la mejor manera para
manejar múltiples sprites en un juego, controlar la
posición del sprite, detectar colisiones entre los dos
objetos.
3. Información del sprite Cheese
Esta es toda la información que se requiere para
presentar el queso en la pantalla.
Se incluye la textura, tamaño y velocidad del sprite
Texture2D cheeseTexture;
Rectangle cheeseRectangle;
float cheeseWidthFactor = 0.05f;
float cheeseX;
float cheeseXSpeed;
float cheeseY;
float cheeseYSpeed;
float cheeseTicksToCrossScreen = 200.0f;
4. Crear el sprite Bread
Para crear el sprite, declaramos un conjunto de
variables con la información relativa a él.
Cada variable es similar a las declaradas para el
sprite cheese
Texture2D breadTexture;
Rectangle breadRectangle;
float breadWidthFactor = 0.05f;
float breadX;
float breadXSpeed;
float breadY;
float breadYSpeed;
float breadTicksToCrossScreen = 200.0f;
5. Variables y Diseño
Desde le punto de vista del diseño, no es correcto
declarar otro conjunto de variables con
características similares.
Aunque desde el punto de vista técnico esto debiera trabajar,
desde el punto de vista programación, este conjunto de
variables no es una buena opción.
En lugar de usar una convención que la palabra al
inicio del nombre de la variable tenga relación con el
sprite, es mejor aun que podamos agruparlas
C# provee un mecanismo llamado estructura para
colocar juntos elementos relacionados.
6. Las estructuras
Un struct es una construcción de C# que contiene
juntos métodos y datos.
Las estructuras son buenas para almacenar “grupos
de datos”.
El framework XNA y el sistema de librerías de C#
utiliza las estructuras.
Un valor DateTime es del tipo struct
Un valor Color es del tipo struct.
Ahora lo aplicamos para crear la estructura de un
sprite
7. Información del sprite cheese
El tipo GameSpriteStruct se ha creado para juntar
todos los campos de datos que este tipo necesita
struct GameSpriteStruct
{
public Texture2D SpriteTexture;
public Rectangle SpriteRectangle;
public float X;
public float Y;
public float XSpeed;
public float YSpeed;
public float WidthFactor;
public float TicksToCrossScreen;
}
8. Crear las variables
Se adiciona un nuevo tipo a todos los disponibles en
el programa.
Una vez declarada la estructura GameSpriteStruct.
Creamos las variables de este tipo.
Cada variable que se declara contiene todos los
campos de la struct que han sido declarados.
GameSpriteStruct cheese;
GameSpriteStruct bread;
9. Acceder a los campos de la estructura
Un programa puede acceder a los campos en una
estructura, dando el nombre de la variable seguido
por el nombre del campo que es requerido.
Las sentencias mostradas configuran las texturas
tanto para él queso como para él pan.
Esto trabaja porque estos campos han sido
declarados como públicos en la declaración de
GameSpriteStruct
cheese.SpriteTexture =
Content.Load<Texture2D>("Images/Cheese");
bread.SpriteTexture =
Content.Load<Texture2D>("Images/Bread");
10. Modificadores de este acceso
Los campos en GaemSpriteStruct son todos públicos.
Esto hace que puedan ser utilizados en cualquier
parte del código.
struct GameSpriteStruct
{
public Texture2D SpriteTexture;
public Rectangle SpriteRectangle;
public float X;
public float Y;
public float XSpeed;
public float YSpeed;
public float WidthFactor;
public float TicksToCrossScreen;
}
11. Campos públicos y privados
Los campos que no serán utilizados fuera de la
estructura deberán ser declarados como privados.
Es decir que serán procesados solamente por las
llamadas de métodos públicos.
struct BankAccount
{
private float bankBalance;
public void PayInFunds ( float amount)
{
}
public void WithDrawFunds (float amount)
{
}
}
12. Escalar los Sprites
Ahora podemos adicionar sentencias para el método
ScaleSprites para configurar tanto el queso como el
pan.
El pan se hace más largo que el queso y se habilitó un
movimiento un poco más rápido.
La velocidad relativa que el pan y el queso, es algo
que trabajaremos luego con
bread.WidthFactor = 0.15f;
bread.TicksToCrossScreen = 120.0f;
// rest of calculations here
14. controlar el Sprite con un Thumbstick
Se va a utilizar el
Thumbstick izquierdo para
controlar el movimiento del
pan alrededor de la pantalla.
El thumbstick provee valores
flotantes en el rango de -1 a 1
en las direcciones de X y Y.
Los valores son obtenidos
desde la variable
GamepadState.
15. Movimiento del Sprite Bread
La velocidad del bread es multiplicada por la
posición del thumbstick.
Cuanto más rápido se mueva el thumbstick, más
rápido se moverá el pan.
GamePadState gamePad1 = GamePad.GetState(PlayerIndex.One);
bread.X = bread.X +
(bread.XSpeed * pad1.ThumbSticks.Left.X);
bread.Y = bread.Y –
(bread.YSpeed * gamePad1.ThumbSticks.Left.Y);
bread.SpriteRectangle.X = (int)bread.X;
bread.SpriteRectangle.Y = (int)bread.Y;
17. Mejorando el diseño del programa
En este momento, el programa funciona, pero algún
código todavía está un poco desordenado.
El método scaleSprite está un poco desordenado,
conteniendo sentencias que configuran diferentes
partes delsprite.
Es fácilperder algunos ajustes y que el sprite no se
comporte de la manera correcta.
Una manera para mejorar esto debe de ser escribir
un método que dados un conjunto de parámetros
configuren un sprite
18. La cabecera del método
Los parámetros dados son la configuración inicial del
sprite.
Los valores de configuración son calculados y
utilizados para configurar el sprite.
void setupSprite(
GameSpriteStruct sprite,
float widthFactor,
float ticksToCrossScreen,
float initialX,
float initialY)
{
// sets the values of the sprite in here
}
20. La llamada del método
Este método llamado dos veces, para configurar cada
uno de los sprites.
Los valores son los que previamente han sido
utilizados
void setupSprites()
{
setupSprite(cheese, 0.05f, 200.0f ,
minDisplayX, minDisplayY);
setupSprite(bread, 0.15f, 120.0f,
displayWidth / 2, displayHeight / 2);
}
21. Otra forma
Esta llamada trabaja exactamente de la misma
manera que la anterior.
Sin embargo, se han adicionado comentarios para
hacer más claro y lo que cada parámetro realiza.
Este formato es mucho más claro
setupSprite(
cheese, // sprite to set up
0.05f, // width factor (a 20th)
200.0f, // ticks to cross the screen
minDisplayX, // starting X position
minDisplayY); // starting Y position
23. La llamada del método
No hay nada extraño con este método.
No hay nada raro con los valores que está
utilizándose para la llamada.
Desafortunadamente, el problema es que no se está
utilizando los parámetros de la manera correcta
setupSprite(
cheese, // sprite to set up
0.05f, // width factor (a 20th)
200.0f, // ticks to cross the screen
minDisplayX, // starting X position
minDisplayY); // starting Y position
24. Paso de parámetros por valor
Al parámetros que son pasados dentro del método
setupSprite.
Todas son pasadas por valor
Y es esto lo que causa el problema
void setupSprite(
GameSpriteStruct sprite,
float widthFactor,
float ticksToCrossScreen,
float initialX,
float initialY)
{
// sets the values of the sprite in here
}
25. Paso de parámetros por valor
Cuando un parámetro es pasado por Valor, éste le
dice a C# que envió una copia del Valor dentro del
método que está siendo llamado.
El método entonces trabajará como una copia.
Esto significa que setupSprite trabajará sobre una
copia de la estructura dada, no con el original.
Por lo que los cambios de la variable cheese nunca se
haran, los cambios se hacen en la copia, lo que
significa que esta variable nunca será configurada
26. Paso de parámetros por referencia
Le podemos decir al compilador que deseamos pasar
el sprite como una referencia utilizando la palabra
ref.
Ahora los métodos se pasan por referencia en los
parámetros, no una copia
void setupSprite(
ref GameSpriteStruct sprite,
float widthFactor,
float ticksToCrossScreen,
float initialX,
float initialY)
{
// sets the values of the sprite in here
}
27. Suministrar una llamada por referencia
Si le decimos al compilador que un está siendo
pasado por referencia, se puede dar una referencia
en la llamada también.
Esto es realizado colocando la palabra ref antes de la
variable en la llamada del método.
Es posible pasar cualquier otro tipo de variable por
referencia
setupSprite(
ref cheese, // reference to the sprite to set up
0.05f, // width factor (a 20th)
200.0f, // ticks to cross the screen
minDisplayX, // starting X position
minDisplayY); // starting Y position
29. Hacer que el pan golpee el queso
Cuando el pan golpear el queso, este debe de rebotar
en la pantalla..
Podemos hacer que el queso rebote, revirtiendo la
dirección de la velocidad en y.
Pero debemos saber cuando los dos sprite colisionan.
El programa de detectar cuando un jugador costear
el queso con el pan
30. Colisiones y rectángulos
Una simple detección de colisión puede ser
implementada, detectando cuando ambos
rectángulos se interceptan.
El tipo Rectangle proveer una manera fácil de hacer
esto
31. Usando el método
Un Valor Rectangle provee el método Intersects.
Se necesita de otro Rectangle para probar la
intersección.
El método retorna verdadero si ambos Rectangle se
interceptan
Podemos utilizar esto para nuestro propósito
if (cheese.SpriteRectangle.Intersects(bread.SpriteRectangle))
{
cheese.YSpeed = cheese.YSpeed * -1;
}
33. Resumen
Una estructura dentro del compilador es una manera de
juntar campos relacionados.
Los miembros de una estructura pueden ser privados
(utilizables solamente por los métodos de la estructura) o
públicos (utilizados por todos).
Las variables del tipo estructura son administradas por
Valor.
Los parámetros son usualmente pasados por Valor.
Si un método necesita cambiar valores de parámetros
éstos deben ser pasados por referencia.
La clase rectángulo tiene un método que es utilizado para
detectar cuando dos objetos colisionan
34. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien
35. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien
36. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien
37. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien
38. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien
39. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien
40. Verdadero o falso
Una estructura puede contener métodos y campos de
datos.
Una estructura es administrada por Valor.
Los campos privados de una estructura no pueden ser
cambiados.
Los parámetros son típicamente pasados a los métodos
por Valor.
Su método de cambiar los valores de los parámetros,
estos métodos debe ser pasados por referencia.
El thumbatick del gamepad retorna un Valor de entre
cero y cien