Continuando con la serie de artículos sobre el motor de física 2D, Chipmunk, veremos los conceptos básicos de este y su implementación en una aplicación para el iPhone. En el post anterior solo hemos creado un proyecto en Xcode, agregado dos imágenes y vinculado las librerías de Chipmunk al proyecto, pero como habrán observado no hemos utilizado aún el motor de física.

Conceptos Básicos

Los principales conceptos que debemos tener en cuenta para la implementación del motor de física son:

  • Space: Es la unidad de simulación básica que contiene todos los objetos creados, es decir, es el entorno donde interactúan los objetos. En él se establecen las reglas generales que afectan a todos los objetos de la simulación como por ejemplo la gravedad.
  • Body: Son cuerpos rígidos que contienen las propiedades físicas de un objeto como: masa, posición, rotación, velocidad, etc. No poseen forma (shape) por si mismos y por lo tanto no colisionan con otros cuerpos.
  • Shape: Son las diferentes partes de un cuerpo (body), es decir, con los shape le damos forma a los cuerpos permitiendo la colisión entre ellos. Existen tres tipos de shapes : circular, segmentado y poligonal.
  • Constraints: Permiten conectar dos cuerpos de diferentes formas.
  • Forces: Son vectores (x,y) utilizados para interactúar con los objetos creados en el entorno de simulación. No es recomendable modificar directamente las propiedades de los objetos (posición, velocidad, etc), para realizar esto se deben utilizar las funciones que asignan estos vectores a los objetos.

Continuando la implementación en Xcode

Tomando como base el proyecto creado en el post anterior, prosigamos con la implementación de las librerías de Chipmunk:

1. Incluir en ViewController.h el archivo de cabecera “chipmunk.h”, un objeto de la clase cpSpace y las tres funciones que utilizaremos para iniciar e implementar Chipmunk

#import <UIKit/UIKit.h>

#import "chipmunk.h"

@interface EquilibrioChipmunkViewController : UIViewController
{

UIImageView *barra;

UIImageView *esfera;

cpSpace *space;

}

- (void)configurarChipmunk;

- (void)delta:(NSTimer *)timer;

void updateShape(void *ptr, void* unused);

@end

2. Realizar el llamado de “(void)configurarChipmunk” en la función “(void)viewDidLoad”

- (void)viewDidLoad
{

[super viewDidLoad];

barra = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"barra.png"]];

barra.center = CGPointMake(160, 350);

esfera = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"esfera.png"]];

esfera.center = CGPointMake(160, 230);

[self.view addSubview:barra];

[self.view addSubview:esfera];

[self.view setBackgroundColor:[UIColor whiteColor]];

[self configurarChipmunk];

}

3. Implementar las tres funciones declaradas anteriormente


- (void)delta:(NSTimer *)timer {

// Actualiza información del Space

cpSpaceStep(space, 1.0f/60.0f);

// Actualiza información de los Shapes definidos

cpSpaceHashEach(space->activeShapes, &updateShape, nil);

}

void updateShape(void *ptr, void* unused) {

cpShape *shape = (cpShape*)ptr;

// Validación del Shape recibido

if(shape == nil || shape->body == nil || shape->data == nil) {

NSLog(@"Invalido shape revisar ...");

return;

}

// Actualiza la posición del Shape

if([(UIView *)shape->data isKindOfClass:[UIView class]]) {

[(UIView *)shape->data setCenter:CGPointMake(shape->body->p.x, 480 - shape->body->p.y)];

}

else

NSLog(@"Shape actualizado fuera de la función : updateShape ");

}

4. Definir Body y Shape de un objeto dinámico circular en la función “(void)configurarChipmunk”

- (void)configurarChipmunk {

// Inicia el motor de fisica 2D Chipmunk

cpInitChipmunk();

// Crea un nuevo Space

space = cpSpaceNew();

// Define la dirección y magnitud de la gravedad en el Space

space->gravity = cpv(0, -100);

// Implementa el NSTimer encargado de realizar las animaciones

[NSTimer scheduledTimerWithTimeInterval:1.0f/60.0f target:self selector:@selector(delta:) userInfo:nil repeats:YES];

// Crea un Body con masa 50 y momento INFINITY

cpBody *esferaBody = cpBodyNew(50.0f, INFINITY);

// Establece posición inicial

esferaBody->p = cpv(160, 250);

// Agrega el Body al Space

cpSpaceAddBody(space, esferaBody);

// Crea un Shape tipo Circle con radio 15 asociado al Body "esferaBody"

cpShape *esferaShape = cpCircleShapeNew(esferaBody, 15.0f, cpvzero);

esferaShape->e = 0.5f; // Elasticidad

esferaShape->u = 0.8f; // Fricción

esferaShape->data = esfera; // Asocia Shape con UIImageView

esferaShape->collision_type = 1; // Las colisiones son agrupadas por tipo

// Agrega el Shape al Space

cpSpaceAddShape(space, esferaShape);

}

5. Compilar y ejecutar

Si hemos hecho todo bien al final se vera mal, la esfera caerá en dirección de la gravedad definida y no encontrará obstáculos en el espacio. En el siguiente artículo definiremos un objeto estático (madera) e implementaremos el acelerómetro en nuestra aplicación.

Repositorio en GitHub : MDW-Guia-iOS11-Chipmunk2