Catapum Parte 2: Accelerometer

En nuestro primer juego intentamos tocar un poco en todos los campos para poder llegar a hacer un juego, es un ejemplo bastante sencillo de implementar y podemos ver como cocos2d nos va a agilizar enormemente todo el proceso. Pero ahora vamos a ver como sobre el mismo juego podemos incluir cosas nuevas, y vamos a empezar por cambiar el control del joystick por los acelerometros.

No nos vamos a poder librar del joystick completamente ya que va a seguir siendo necesario para los botones pero quitaremos el stick y pasaremos a mover nuestra nave inclinando nuestro dispositivo. Como ya sabemos nuestro iPhone tiene 3 acelerometros que nos van a dar en todo momento la inclinacion en cada uno de los ejes. Lo primero que tenemos que tener presente a la hora de trabaja con un acelerometros es saber sobre que plano vamos a calcular la inclinación, en nuestro caso queremos el angulo XY por lo que deberemos calcular la arcotangente de estos 2 valores para saber el angulo de inclinación

No os asusteis mucho por como suenta, porque sobre codigo esto solo es una instrucción:

 C |  copy code |? 
1
 
2
 float angle = atan2(y, x) * 180.0f / 3.14159f; 
3
 

Esto nos dará como resultado un angulo que nos indicará en que dirección está apuntando nuestro dispositivo, en esta imagen podeis ver ese angulo representado de forma grafica:

Es decir .. si mantenemos nuestro dispositivo en horizontal este nos dará 180 grados, si giramos hacia la derecha nos dará -90 grados y si giramos a la izquierda nos dará 90 grados. Realmente es una faena que nos encontremos justo en el angulo donde cambiamos de signo y probablemente se hubiera solucionado haciendo el atan2(-y,x) .. pero tampoco es mi intención esquivar los problemas, y si nos va a dar los ángulos así no es ningún problema.

Modificar el Joystick

Empezaremos por quitar el Stick y configurar los 2 botones, también vamos a quitar completamente los sprites del joystick, nisiquiera dejaremos los botones, lo que haremos será dividir la pantalla en 2 areas, toda la mitad izquierda de la pantalla será el botón A y toda la mitad derecha será el botón B

 C |  copy code |? 
01
 
02
 -(void) BuildJoystick 
03
 { 
04
 // creamos el objeto joystick 
05
 joystick = [[Joystick alloc] init]; 
06
 
07
 // solo tenemos 2 botones, que cubren cada mitad de pantalla 
08
 // solo existe la difinición del boton, no hay sprite grafico 
09
 [joystick addButton:@"A" rect:CGRectMake(  0, 0, 240,320)]; 
10
 [joystick addButton:@"B" rect:CGRectMake(240, 0,240,320)]; 
11
 
12
 // el delay 
13
 [joystick setDelayFor:@"A" delay:0.5f]; 
14
 [joystick setDelayFor:@"B" delay:0.5f]; 
15
 }

Capturar el angulo de inclinación

Empezamos por ir a nuestro método ‘init’ y decirle al cocos2d que queremos controlar los eventos del acelerometro.

 C |  copy code |? 
1
 
2
 // enable accelerometer 
3
 self.isAccelerometerEnabled = YES; 
4
 

A partir de este momento empezaremos a recibir eventos en nuestro metodo accelerometer.
Very important: Este método SOLO se llama cuando se produce algún cambio en la inclinación del dispositivo, lo que significa que NO es un buen lugar donde tomar decisiones, limitaros únicamente a guardar el angulo de inclinación del dispositivo. Y que sea otro método, que se ejecute de forma constante, el que transforme ese angulo en movimiento

Definimos de forma global la variable angleX

 C |  copy code |? 
01
 
02
 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
03
 { 
04
 // Sacamos el angulo de la inclinacion 
05
 float angle = atan2(acceleration.y, acceleration.x) * 180.0/3.14159; 
06
 
07
 // controlamos los limites de donde no queremos salir 
08
 if(angle < 90 && angle > 0) angle = 90; 
09
 if(angle >-90 && angle < 0) angle =-90; 
10
 
11
 // y a partir de ese angulo sacamos el seno 
12
 angleX = sin(angle * 3.1415 / 180) * -100; 
13
 }

A continuación vamos a seguir usando nuestro metodo ‘updateJoystick’ para mover la nave y también para seguir leyendo los clicks sobre los botones A y B.

En este método podéis ver como se usa el valor de angleX para incrementarselo al vector velocity, esto significa que mientras tengamos el dispositivo inclinado estaremos moviéndonos en una dirección. Del mismo modo recordar que este metodo se llama mediante un scheduler de cocos2d … asi que no podemos saber cada cuanto tiempo nos llama y por tanto debemos multiplicar el valor del angleX por el delta.

 C |  copy code |? 
01
 
02
 -(void) updateJoystick: (ccTime) delta 
03
 { 
04
 CGPoint newPosition; 
05
 
06
 //incrementamos nuestro vector velocidad con la inclinacion que nos 
07
 // dejo el acelerometro 
08
 velocity.x += angleX * delta; 
09
 // no hay desplazamiento en Y 
10
 
11
 // esto nos añade la resistencia necesaria para frenar el avion 
12
 // si dejamos de pulsar el joystick 
13
 velocity.x *= .9f; 
14
 velocity.y *= .9f; 
15
 
16
 // calculamos la nueva posicion 
17
 newPosition.x = player.position.x + velocity.x; 
18
 newPosition.y = player.position.y + velocity.y; 
19
 
20
 // y una vez mas controlamos los limites para no salir de la pantalla 
21
 int sizex = player.contentSize.width / 2; 
22
 int sizey = player.contentSize.height / 2; 
23
 CGSize winSize = [[CCDirector sharedDirector] winSize]; 
24
 
25
 if(newPosition.x < sizex   ) newPosition.x = sizex; 
26
 if(newPosition.x > winSize.width -sizex) newPosition.x = winSize.width-sizex; 
27
 if(newPosition.y < sizey   ) newPosition.y = sizey; 
28
 if(newPosition.y > winSize.height -sizey) newPosition.y = winSize.height -sizey; 
29
 
30
 // ya está ... el player se mueve 
31
 [player setPosition:newPosition]; 
32
 
33
 int cx = winSize.width/2; 
34
 int cy = winSize.height/2; 
35
 
36
 background.position = ccp(cx + (cx-player.position.x), cy + (cy-player.position.y)); 
37
 
38
 if([joystick isDown:@"A"]) 
39
 [self PlayerShoot]; 
40
 
41
 if([joystick isDown:@"B"]) 
42
 { 
43
 [self PlayerShoot]; 
44
 [self PlayerShoot]; 
45
 } 
46
 
47
 }

Autorotate

No hemos hecho muchos cambios para usar los acelorometros, pero debemos tener en cuenta que por defecto cocos2d crea un proyecto con el rotate de la pnatalla activado, es decir que si damos la vuelta a nuestro dispositivo no rota la pantalla para tener siempre el juego en la horientación correcta. Para este juego estamos calculando el angulo de inclunación, y os recuerdo que habiamos ignorado la parte 90-90 de la rotación. Asi que debemos anular el autorotate del dispositivo:

Para ello vamos al archivo GameConfig.h y cambiamos este define para poner el valor kGameAutorotationNone

 C |  copy code |? 
1
 
2
 // 
3
 // Define here the type of autorotation that you want for your game 
4
 // 
5
 #define GAME_AUTOROTATION kGameAutorotationNone 
6
 

Desde os podeis descargar el proyecto completo
 Catapum v2-accelerometer.zip (1.9 Mb)

FIN!!!!!!

2 Comments

alejandro  on June 13th, 2011

Hice todo bien lo pruebo funciona pero no me deja ir para arriba se queda abajo del todo Como se soluciona?

neofar  on June 14th, 2011

Es que en este ejemplo no se mueve arriba ni abajo, solo se usa el acelerometro para movernos a los lados … de hecho esta parte del código te debería haber dado alguna pista:

velocity.x += angleX * delta;
// no hay desplazamiento en Y

Leave a Comment