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
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


@raywenderlich
Cocos 2d
cocos2d-central
libgdx
libgdx-users
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?