UIAccelerometer Sample Code

Vamos a ver en este ejemplo como utilizar los acelerometros que trae el iPhone para detectar la inclinación del mismo.

Crear un Proyecto OpenGL

Como siempre vamos a empezar desde 0 y es creando un proyecto en OpenGL Es, abrimos el XCode vamos a File > New Proyect y seleccionamos un proyecto “OpenGL ES Application“, pulsamos el botón choose y le damos el nombre que nos interese:

Nuestra Clase GL

Por ahora no vamos a aportar nada nuevo a nuestra clase GL para dibujar sprites, asi que os toca copiar los pasos que ya hicimos en nuestro capitulo Sprites en OpenGL os recuerdo que ahi solamente vamos a definir la clase GL.m vamos a agregar el Framework CoreGraphics.Framework, y vamos a añadir un nuevo archivo grafico a los resources del proyecto.

También deberemos copiar todas las modificaciones que hicimos a la clase EAGLView.m, los metodos inicializar, setupView, clearBuffer y swapBuffer que agregamos.

Implementando UIAcclerometer

Ahora viene la finalidad del proyecto … y realmente lo facil, enseguida veréis que no tiene ninguna dificultad:

Vamos a EAGLView.h

y dentro de la interfaz, añadimos estas variables:

 C |  copy code |? 
1
 
2
 GLuint texture; 
3
 GLfloat angle; 
4
 GLfloat angle2; 
5
 UILabel *label1, *label2, *label3;

Por un lado vemos que tenemos la textura que vamos a usar, un par de variables para guardar un angulo … y vemos 3 lables. Estas labels serán para poner texto en pantalla, algo que se sale un poco de la finalidad del ejemplo pero que es muy facil de implementar y nos ayudará a ver que está pasando realmente.

Ademas, que vamos a añadir estas Labels al proyecto sin pasar por el InterfaceBuilder, las ponemos a pelo, como los hombres de verdad

Seguimos en EAGLView.h y añadimos (ya fuera de la interfaz) estos métodos:

 C |  copy code |? 
1
 
2
 -(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration ; 
3
 -(UILabel *) newLabelWithOffset:(float)offset numberOfLines:(NSUInteger) lines;

Y ya está, por aqui todo está listo.

Abrimos el archivo EAGLView.m

En primer lugar vamos a ver como se implementan las labels, para ello tenemos el método newLabelWithOffset que crea una label en la posición indicada:

 C |  copy code |? 
01
 
02
 -(UILabel *) newLabelWithOffset:(float)offset numberOfLines:(NSUInteger) lines 
03
 { 
04
 float textHeight = 20.0; 
05
 UILabel *label =  [[UILabel alloc] initWithFrame:CGRectMake(self.frame.origin.x + 10.0, offset, self.frame.size.width - 20.0, textHeight * lines)]; 
06
 
07
 // Set the font size, text color, background color, and alignment. 
08
 label.font = [UIFont systemFontOfSize:18.0]; 
09
 label.textColor = [UIColor lightTextColor]; 
10
 label.backgroundColor = [UIColor clearColor]; 
11
 label.textAlignment = UITextAlignmentLeft; 
12
 
13
 // Set the number of lines 
14
 label.numberOfLines = lines; 
15
 // Set the linebreak mode if there is more than one line. 
16
 if (lines > 1) label.lineBreakMode = UILineBreakModeWordWrap; 
17
 
18
 // Initialize as an empty string 
19
 label.text = @""; 
20
 return label; 
21
 }

y dentro de nuestro metodo ‘initWithCoder‘ crearemos las 3 labels asi:

 C |  copy code |? 
01
 
02
 label1 = [self newLabelWithOffset:(self.frame.origin.y + 25) numberOfLines: 1]; 
03
 label1.text = @"Acceleration.x"; 
04
 [self addSubview:label1]; 
05
 
06
 label2 = [self newLabelWithOffset:(self.frame.origin.y + 45) numberOfLines: 1]; 
07
 label2.text = @"Acceleration.y"; 
08
 [self addSubview:label2]; 
09
 
10
 label3 = [self newLabelWithOffset:(self.frame.origin.y + 65) numberOfLines: 1]; 
11
 label3.text = @"Angulo"; 
12
 [self addSubview:label3];

UIAccelerometer

Aqui teneis todo el codigo necesario, en nuestro metodo inicializar inicializamos el acelerometro diciendole que delege sus eventos sobre esta clase, y debajo tenemos el metodo accelerometer implementado que es quien recibe los eventos.

 C |  copy code |? 
01
 
02
 -(void)inicializar 
03
 { 
04
 // Cargamos la unica textura que vamos a usar 
05
 texture1 = [GL loadTexture:@"4Sprites.png"]; 
06
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
07
 
08
 // Configure and start the accelerometer 
09
 [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 30)]; 
10
 [[UIAccelerometer sharedAccelerometer] setDelegate:self]; 
11
 
12
 } 
13
 
14
 - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
15
 { 
16
 float x = acceleration.x; 
17
 float y = acceleration.y; 
18
 
19
 angle = atan2(y, x); 
20
 angle *= 180.0/3.14159; 
21
 angle += 90; 
22
 
23
 label1.text = [NSString stringWithFormat:@"Acceleration.x = %4.4f ", x]; 
24
 label2.text = [NSString stringWithFormat:@"Acceleration.y = %4.4f ", y]; 
25
 label3.text = [NSString stringWithFormat:@"Angulo = %4.1f ",angle]; 
26
 
27
 float dif = angle2 - angle; 
28
 if(abs(dif)>180) dif+= 360; 
29
 angle2 -= dif * 0.5f; 
30
 
31
 }

En este método acceleratometer podéis ver como sacamos los valores X e Y de aceleración.. que realmente nos indican el coseno y el seno de la inclinación del dispositivo, y mediante un atan sabemos el angulo de inclinación … sólo son matemáticas.

Podéis ver como se meten estos valores en las 3 labels para poder verlos en pantalla, veréis como tanto x como y representan valores comprendidos entre 1 y -1 (propios del seno y coseno unitario de toda la vida).

Bueno a lo que vamos si os fijáis bien tengo una segunda variable llamada angle2 que no es mas que una interpolacion del angulo actual con el angulo anterior (queeee???) … si eso, los acerelometros tienen bastante variación, aunque dejemos el dispositivo quiero están fluctuando a lo loco .. y esto hace que el angulo no quede estable, mediante esta segunda variable solo intentamos suavizar esos cambios bruscos. El efecto es visible así que esperar a ejecutar y lo comprenderéis mejor.
Porque solo nos queda nuestro metodo draw!!!!

 C |  copy code |? 
01
 
02
 - (void)drawView 
03
 { 
04
 [self clearBuffer]; 
05
 glLoadIdentity(); 
06
 
07
 glPushMatrix(); 
08
 [GL setSprite:texture1 frame:0]; 
09
 glTranslatef(-80,0,0); 
10
 glRotatef(-angle,0,0,1); 
11
 [GL drawSprite:-64 y1:-64 x2:64 y2:64]; 
12
 glPopMatrix(); 
13
 
14
 glPushMatrix(); 
15
 [GL setSprite:texture1 frame:3]; 
16
 glTranslatef(80,0,0); 
17
 glRotatef(-angle2,0,0,1); 
18
 [GL drawSprite:-64 y1:-64 x2:64 y2:64]; 
19
 glPopMatrix(); 
20
 
21
 [self swapBuffer]; 
22
 }

Aquí podemos ver como dibujamos 2 sprites en pantalla, uno usando el angle que va un poco a lo loco, y otro mediante angle2, podéis girar el dispositivo y veréis como los 2 van juntitos … pero que nuestro sprite de la derecha parece mas cuerdo que el otro.
:)

  • Delicious
  • Twitter
  • Facebook
  • Meneame
  • WordPress
  • Digg
  • Gmail
  • Google Reader
  • Google Bookmarks
  • Slashdot
  • Share/Bookmark

One Comment

frocco  on May 4th, 2009

Buenas!
No tenes el .zip del proyecto????
Estoy aprendiendo OpenGL para Iphone y todavia me hace falta seguimiento :P

Abrazo grande y muy bueno el blog!!!

Leave a Comment