Box2dを使ってプルプルするタイヤみたいなものを作ってみる
(XcodeのiOS6 iPhone Simulatorで作っています。)
ポイント
・b2DistanceJointDefで物体を繋ぎ合わせる
・真ん中にハブをおいて、周りに丸を並べることで、タイヤっぽく
Box2d導入手順
次のアドレスからソースを取得
svn checkout http://box2d.googlecode.com/svn/trunk/ box2d-read-only
1. Box2Dをプロジェクトに組み込む
Xcodeメニューの File -> Add File
2. C++ で書く。Fileの拡張子を変更
Box2dを使うソースの拡張子を mm に
3. Box2Dを import できるように Search Pathを追加
Build Settings (All) の Search Pathsのなかの Header Search Paths
サンプルコード
#import “ViewController.h”
#import <Box2D/Box2D.h>
#import <QuartzCore/QuartzCore.h>
#define PTMRatio 16
@interface ViewController () {
b2World *world;
NSTimer *timer;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
[self createPhysicsWorld];
[self start];
}
– (void)createPhysicsWorld
{
CGSize screenSize = self.view.bounds.size;
b2Vec2 gravity;
gravity.Set(0.0f, –9.81f);
world = new b2World(gravity);
world->SetContinuousPhysics(true);
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0);
b2Body* groundBody = world->CreateBody(&groundBodyDef);
b2EdgeShape groundBox;
groundBox.Set(b2Vec2(0, 0), b2Vec2(screenSize.width/PTMRatio, 0));
groundBody->CreateFixture(&groundBox, 0);
groundBox.Set(b2Vec2(0,screenSize.height/PTMRatio), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox, 0);
groundBox.Set(b2Vec2(screenSize.width/PTMRatio, screenSize.height/PTMRatio), b2Vec2(screenSize.width/PTMRatio, 0));
groundBody->CreateFixture(&groundBox, 0);
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self addSoftCircles];
}
– (void)start
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
– (void)tick:(NSTimer*)sender
{
int32 velocityIteration = 8;
int32 positionIteration = 1;
world->Step(1.0f/60.0f, velocityIteration, positionIteration);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) {
if (b->GetUserData() != NULL) {
UIView *v = (__bridge UIView *)b->GetUserData();
CGPoint newCenter = CGPointMake(b->GetPosition().x * PTMRatio, self.view.bounds.size.height – b->GetPosition().y * PTMRatio);
v.center = newCenter;
}
}
}
– (void)addSoftCircles
{
b2Body** parts = (b2Body**)b2Alloc(sizeof(b2Body*) * 12);
for (int i=0; i<12; i++) {
float th = i * M_PI/6.0 + M_PI * 0.1;
float x = 50 * cos(th) + 160;
float y = 50 * sin(th) + 160;
UIView *ball = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
ball.center = CGPointMake(x,y);
ball.layer.cornerRadius = ball.bounds.size.width / 2.0;
ball.backgroundColor = [UIColor blueColor];
ball.alpha = 0.2;
ball.layer.borderWidth = 2.0;
[self.view addSubview:ball];
// Create ball body
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
CGPoint p = ball.center;
ballBodyDef.position.Set(p.x/PTMRatio, (460.0 – p.y)/PTMRatio);
ballBodyDef.userData = (__bridge void *)ball;
parts[i] = world->CreateBody(&ballBodyDef);
// Create circle shape
b2CircleShape circle;
circle.m_radius = ball.bounds.size.width/2.0/PTMRatio;
// Create shape definition and add to body
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 1.0f;
ballShapeDef.friction = 0.0f;
ballShapeDef.restitution = 0.5f;
parts[i]->CreateFixture(&ballShapeDef);
}
UIView *hub = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
hub.center = CGPointMake(160, 160);
hub.layer.cornerRadius = hub.bounds.size.width / 2.0;
hub.backgroundColor = [UIColor blueColor];
hub.alpha = 0.2;
hub.layer.borderWidth = 2.0;
[self.view addSubview:hub];
// Create ball body
b2BodyDef hubBodyDef;
hubBodyDef.type = b2_dynamicBody;
CGPoint p = hub.center;
hubBodyDef.position.Set(p.x/PTMRatio, (460.0 – p.y)/PTMRatio);
hubBodyDef.userData = (__bridge void *)hub;
b2Body* hubBody = world->CreateBody(&hubBodyDef);
// Create circle shape
b2CircleShape circle;
circle.m_radius = hub.bounds.size.width/2.0/PTMRatio;
// Create shape definition and add to body
b2FixtureDef hubShapeDef;
hubShapeDef.shape = &circle;
hubShapeDef.density = 1.0f;
hubShapeDef.friction = 0.0f;
hubShapeDef.restitution = 0.5f;
hubBody->CreateFixture(&hubShapeDef);
for (int i=0; i<12; i++) {
// 隣と繋ぐ
b2DistanceJointDef jointDef;
jointDef.Initialize(parts[i], parts[(i+1) % 6], parts[i]->GetPosition(), parts[(i+1)%6]->GetPosition());
jointDef.collideConnected = true;
jointDef.frequencyHz = 40.0f;
jointDef.dampingRatio = 0.5;
world->CreateJoint(&jointDef);
// 中央と繋ぐ
jointDef.Initialize(parts[i], hubBody, parts[i]->GetPosition(), hubBody->GetPosition());
jointDef.collideConnected = true;
jointDef.frequencyHz = 10.0f;
jointDef.dampingRatio = 0.5;
world->CreateJoint(&jointDef);
}
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end