Box2D: Un motore fisico opensource multipiattaforma

Post on 28-Nov-2014

2.481 views 1 download

description

 

Transcript of Box2D: Un motore fisico opensource multipiattaforma

Box2D: Un motore fisico opensource multipiattaforma

Maurizio Moriconi

CTO presso MobilesoftMobile Developer

Co-founder Pixmapbrothers

Ubuntu member

bugman79 on Twitter

Box2D

Motore fisico 2d

Opensource (licenza zlib)Creato da Erin Catto

(Blizzard Entertainment)Scritto in C++ Multi piattaforma

Usato da molti giochi tra cui:Angry BirdsRolandoCrayon Physics Deluxe

Alcune risorse

Sito ufficiale: http://www.box2d.org/

Codice sorgente: http://code.google.com/p/box2d/

Documentazione online:http://www.box2d.org/manual.html

Forum ufficiale: http://box2d.org/forum/

LIVE: Installazione su iOS

Motore Fisico

Può essere visto come un sistema di animazione (videogiochi)

Permette il mapping tra “sprite” ed oggetti fisici

Oggetto fisico: rigid bodies (corpi rigidi)

- Dynamic (Dinamici)

- Static (Statici)

Motore Fisico in Box2D

World

Definisce la gravità (gravity)

Muove i corpi (step)

Intercetta le collisioni (contact listener)

Contiene i vari bodies (corpi fisici)

Motore Fisico in Box2D

BodyPosition / Rotation

Density / Mass (Densità / Massa)Friction (Attrito nel contatto)Restitution (Fattore di rimbalzo)

Contengono un puntatore void per dati aggiuntivi (User Data)

Possono avere uno o più Fixture

Motore Fisico in Box2D

ShapeArea di un bodyPuò essere un cerchio, un rettangolo o un poligonoSono usati per gestire le collisioni tra corpi

FixtureCollega una Shape con un BodyCollision Filtering (permette di decidere se uno shape deve collidere o

meno)Aggiunge al body le proprietà fisiche:

• Density• Friction• Restitution

Motore Fisico in Box2D

JointConnettono più corpiLimitano il loro movimento in vari modi:

Motore Fisico in Box2D

Le animazioni dei corpi dinamici avvengono tramite:

Force (Forze)

Impulse (Impulsi)

Torque (Momento di torsione)

Unità di misura

MKS (meters-kilogram-second)

Box2D lavora con i numeri in virgola mobile!!!

Ottimizzato per lavorare bene con oggetti che si muovono tra 0.1 e 10 metri

Gli oggetti statici possono essere grandi sopra i 50 metri senza problemi.

Box2D usa i radianti per gli angoli.

Per iniziare, Conquest the World!b2Vec2 gravity(0.0f, -10.0f);

bool doSleep = true;

b2World world(gravity, doSleep);

b2Vec2 : vettore a 2 dimensioni (in questo caso la gravità)

doSleep: un body fermo può passare allo stato sleepun body in sleep non richiede alcun calcolo nella simulazione

fisicaun body torna attivo appena “toccato” o su richiesta (awake)

Creazione di un body

1. Definire un body con una posizione

2. Usare l'oggetto world per creare un body

3. Definire uno shape

4. Definire la fixture con lo shape aggiungendo friction, density...

5. Creare la fixture sul body

Body statici: Ground Box

1. Definire un body con una posizioneb2BodyDef groundBodyDef;

groundBodyDef.position.Set(0.0f, -10.0f);

2. Usare l'oggetto world per creare un bodyb2Body* groundBody = world.CreateBody(&groundBodyDef);

Di base un body è creato come statico: – Non fa collisione con altri body statici– È inamovibile– statico per Box2D → Massa = 0

Body statici: Ground Box

3. Definire uno shapeb2PolygonShape groundBox;

groundBox.SetAsBox(50.0f, 10.0f);

In questo caso un PolygonShape

SetAsBox prende come parametri le grandezze / 2

Quindi nell'esempio il box è 100x20 (metri si suppone)

5. Creare la fixture sul bodygroundBody->CreateFixture(&groundBox,0);

L'oggetto b2Shape “è dentro” la fixture!!!

Body Dinamici

1. Definire un bodyb2BodyDef bodyDef;

bodyDef.type = b2_dynamicBody;

bodyDef.position.Set(0.0f, 4.0f);

In questo caso si specifica che è Dinamico!

2. Usare l'oggetto world per creare un bodyb2Body* body = world.CreateBody(&bodyDef);

Body Dinamici

3. Definire uno shapeb2PolygonShape dynamicBox;

dynamicBox.SetAsBox(1.0f, 1.0f);

4. Definire la fixture con lo shape aggiungendo friction, density...

b2FixtureDef fixtureDef;

fixtureDef.shape = &dynamicBox;

fixtureDef.density = 1.0f;

fixtureDef.friction = 0.3f;

Definiamo la fixture con densità pari a 1 e attrito pari a 0.3

5. Creare la fixture sul bodybody->CreateFixture(&fixtureDef);

Simulating the World!

float32 timeStep = 1.0f / 60.0f;

int32 velocityIterations = 6;

int32 positionIterations = 2;

world.Step(timeStep, velocityIterations, positionIterations);

Time Step 60Hz (1/60 di secondo)

Iterator Sono i cicli in cui Box2d itera per calcolare posizione e velocitàUn valore di 10 è suggeritoDa decidere come compromesso tra velocità e precisione

LIVE: Hello Box2D

Rendering

Il motore fisico da solo non basta...

Mappare oggetti fisici ad oggetti “reali”

1) UIKit

2) OpenGL ES

3) Altro...

Rendering con UIKit

Physics 101 – UIKit app with Box2D for Gravity

http://www.cocoanetics.com/2010/05/physics-101-uikit-app-with-box2d-for-gravity/

Rendering con UIKit

1) Gestione di un sistema di coordinate Box2d → UIKit e viceversa

2) Creare rappresentazione fisica per ogni view

3) Impostare un timer per :Muovere il motore fisicoAggiornare posizione ed angolo delle nostre view

Sistema di coordinate

Posizione di partenza (0,0)UiKit in alto a sinistraBox2d in basso a sinistra

Unità di misura: Pixel vs Metri!!

#define PTM_RATIO 16

16 pixel equivalgono ad 1 metro

Rappresentazione fisica

DimensioniCGPoint boxDimensions = CGPointMake(

physicalView.bounds.size.width/PTM_RATIO/2.0,physicalView.bounds.size.height/PTM_RATIO/2.0 );

PosizioneCGPoint p = physicalView.center;

bodyDef.position.Set(

p.x/PTM_RATIO,

(480.0 – p.y)/PTM_RATIO );

UserData bodyDef.userData = physicalView;

Timer e Step

tickTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

Quindi un timer che chiama la funzione tick all'infinito.

Mentre i parametri per l'iterator sono:

int32 velocityIterations = 8;

int32 positionIterations = 1;

world->Step(1.0f/60.0f, velocityIterations, positionIterations);

for(b2Body* b=world->GetBodyList(); b; b=b->GetNext())

{

if (b->GetUserData() != NULL)

{

UIView *oneView = (UIView *)b->GetUserData();

CGPoint newCenter = CGPointMake(

b->GetPosition().x * PTM_RATIO,

self.view.bounds.size.height - b->GetPosition().y * PTM_RATIO);

oneView.center = newCenter;

CGAffineTransform transform = CGAffineTransformMakeRotation(- b->GetAngle());

oneView.transform = transform;

}

}

LIVE: Rendering con UIKit

Debug Draw

Classe da utilizzare per debug

Creare una classe che estende b2DebugDraw:class DebugDraw : public b2DebugDraw

{

public:

void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);

void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);

void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);

void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);

….

};

Debug Draw

Attivare i flags:

m_world->SetDebugDraw(&m_debugDraw);

int32 flags = 0;

flags += 1 * b2DebugDraw::e_shapeBit;

flags += 1 * b2DebugDraw::e_jointBit;

flags += 1 * b2DebugDraw::e_coreShapeBit;

flags += 1 * b2DebugDraw::e_aabbBit;

flags += 1 * b2DebugDraw::e_obbBit;

flags += 1 * b2DebugDraw::e_pairBit;

flags += 1 * b2DebugDraw::e_centerOfMassBit;

m_debugDraw.SetFlags(flags);

LIVE: Esempi vari

Altre caratteristiche

Gestione dei contatti (Contact Listener)Applicazione di forze, impulsiJoint

Provare il TestBed !!!

Cocos 2D

Progetto opensourceScritto in Objective-CIntegra i motori fisici Box2D e ChipmunkUsa OpenGL ES 1.0Supporto per videogiochi:

Suono e musicaSistema particellareTile Map e parallasseText renderingGestione menùGestione highscore….

Altre piattaforme???

- C# : Box2DX, Box2D.XNA,

- JAVA : Jbox2D

- Delphi: Box2D Delphi

- Javascript : Box2DJS, box2dweb

- FLASH : Box2DFlash

- DS : Box2D for DS

The End