gergonzalez
Nuestro primer videojuego para iPhone – II
Escrito por gergonzalez | Noviembre 23, 2009 | Casos de Estudio | Comentarios 0
Ya estamos de vuelta con nuestro caso de estudio sobre la creación de un videojuego, después de implementar la interfaz gráfica en el post anterior, hoy vamos a ver como darle un poco de vida mediante la implementación del Game Loop y de la interacción con el usuario.
Game Loop
El Game Loop, o bucle de juego (¡qué difícil es adaptar términos al castellano!), es una de las partes más importantes de un videojuego, se podría decir que es el corazón de nuestro juego, siendo cada iteración del bucle como un latido, y al igual que a nosotros nos es imposible vivir sin un corazón, a un videojuego le sería imposible existir sin su Game Loop.
Hay infinidad de técnicas para implementar el Game Loop, queda en manos del programador y de las características de la plataforma en la que se trabaja la elección de este. Para este ejemplo no hemos entrado a analizar el grado de optimización de los recursos de nuestro iPhone, simplemente nos hemos limitado a que fuera sencillo y funcional.
Bueno, pues vamos a ir completando nuestro código anterior con el fin de implementar nuestro Game Loop, para ello en el header de nuestra clase iPingPongViewController.h declararemos una nueva variable instanciada que llamaremos ballVelocity, la cual no es más que una estructura del tipo CGPoint que contendrá un par de coordenadas que usaremos para definir la velocidad de nuestra pelota durante la ejecución, y también una variable del tipo BOOL y una etiqueta que usaremos para evitar que el juego empiece a ejecutarse nada más cargarse:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #import <UIKit/UIKit.h> @interface iPingPongViewController : UIViewController { UIView *player1; UIView *player2; UIView *ball; UILabel *player1Score; UILabel *player2Score; UILabel *startLabel;//New CGPoint ballVelocity;//New BOOL gameRunning;//New } @property(nonatomic, retain) UIView *ball; @property(nonatomic, retain) UIView *player1; @property(nonatomic, retain) UIView *player2; @property(nonatomic, retain) UILabel *player1Score; @property(nonatomic, retain) UILabel *player2Score; @property(nonatomic, retain) UILabel *startLabel;//New @property (nonatomic) CGPoint ballVelocity;//New @end |
El siguiente paso consistirá en abrir iPingPongViewController.m y, al igual que para implementar nuestra interfaz, sobrecargaremos el método loadView para inicializar nuestras nuevas variables y crearemos una instancia de NSTimer que llamará a nuestro evento gameLoop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | //New #define kBallSpeedX 3 #define kBallSpeedY 2 #define kFPS 0.01 #import "iPingPongViewController.h" @implementation iPingPongViewController @synthesize ball, player1, player2, player1Score, player2Score; @synthesize startLabel, ballVelocity;//New // Implement loadView to create a view hierarchy programmatically, // without using a nib. - (void)loadView { //Create the main view and assign a black color to background CGRect backgroundFrame = [[UIScreen mainScreen] applicationFrame]; ... //New //Tap to Start Label startLabel = [[UILabel alloc] initWithFrame: CGRectMake(self.view.center.x-50, 200, 100, 15)]; startLabel.font = [UIFont fontWithName:@"Helvetica" size:12]; startLabel.text = @"TAP TO START GAME"; startLabel.textColor = [UIColor whiteColor]; startLabel.backgroundColor = [UIColor blackColor]; [self.view addSubview:startLabel]; //Game start Paused gameRunning = NO; ballVelocity = CGPointMake(kBallSpeedX, kBallSpeedY); [NSTimer scheduledTimerWithTimeInterval:kFPS target:self selector:@selector(gameLoop) userInfo:nil repeats:YES]; } -(void)gameLoop{ if (gameRunning) { ball.center = CGPointMake(ball.center.x + ballVelocity.x, ball.center.y + ballVelocity.y); } else { if (startLabel.hidden) { startLabel.hidden = NO; } } } ... - (void)dealloc { [player1 release]; [player2 release]; [ball release]; [player1Score release]; [player2Score release]; [startLabel release];//New [super dealloc]; } @end |
En el código superior vemos como primeramente nos hemos definido una serie de constantes que representan la velocidad de la pelota y la cantidad de frames por segundo (FPS), o lo que es lo mismo, el tiempo en milisegundos que nuestro timer tardará en llamar al Game Loop. Ya en loadView hemos inicializado la nueva etiqueta, el estado del juego, la velocidad de la pelota y, como hemos dicho antes, hemos creado una instancia de NSTimer que ejecutará nuestro Game Loop cada x tiempo en función a la constante kFPS que hayamos elegido.
Después hemos creado un nuevo método llamado gameLoop en el cual, por ahora, simplemente comprobamos el estado del juego mediante gameRunning y en caso de ser positivo cambiamos la posición de la variable ball sumándole la velocidad de la pelota en la coodenada correspondiente, de esta manera implementamos el movimiento de la pelota en función del tiempo.
Si simulamos no pasa nada, veremos nuestra interfaz anterior más una etiqueta que nos incita a tocar la pantalla, pero al hacerlo no ocurre nada, vamos a solucionarlo.
Control
Una de principales características del dispositivo iPhone es la carencia de un teclado físico, esta carencia es suplida por una interfaz táctil que nos permite registrar cada uno de los toques que se producen en la pantalla del terminal. Con estas características decidimos que la mejor manera de implementar nuestra interacción con el usuario es mediante el movimiento de nuestra paleta a la par que nuestro dedo, sin perder su posición con respecto al eje y, pero sí en x.
Entonces, para implementar un control como el descrito, abrimos de nuevo iPingPongViewController.m y copiamos en el lugar correspondiente los siguientes métodos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ... - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; } //New - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if(!gameRunning) { startLabel.hidden = YES; gameRunning = YES; } else if(gameRunning) { [self touchesMoved:touches withEvent:event]; } } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [[event allTouches] anyObject]; CGPoint location = [touch locationInView:self.view]; player1.center = CGPointMake(location.x, player1.center.y);; } - (void)dealloc { ... |
Como se observa, hemos sobrecargado touchesBegan para hacer que el juego empiece cuando se pulse por primera vez la pantalla, para ello simplemente testeamos el estado del juego y en caso de estar pausado lo ponemos en estado de ejecución y ocultamos la etiqueta startLabel.
En lo que se refiere al control del juego propiamente dicho, hemos decidido hacerlo lo más sencillo posible, simplemente con la sobrecarga de touchesMoved asignamos a la vista player1 las coordenadas en x que obtenemos del toque del dedo en la vista principal, manteniendo constante la coordenada con respecto a y.
En esta ocasión, al simular, veremos como nuestra pelota se mueve hasta desaparecer de pantalla, es normal, no hay límites que produzcan un cambio en su dirección y velocidad. Lo que si observaremos es como si movemos el dedo por la pantalla nuestra raqueta se mueve por el eje x al igual que nuestro dedo.
Pues por hoy ya es suficiente, más adelante implementaremos la detección de colisiones y una sencilla inteligencia artificial para nuestro oponente.
Puede que te interese también:
-

- Hola, me llamo Germán González Rodríguez, soy ingeniero de teleco. Toda mi experiencia laboral ha estado ligada al diseño web, aunque en la actualidad dedico mis esfuerzos a la programación para iPhone. Más...
-
Más Leídos
-
Blogroll
- App cultura Iphone Iphone Developer Program iPod iPod Touch iTunes Keynote Mac Personal Programación SDK videojuegos









Comentarios