棒をゴールラインまで積み上げていく単純ゲームをiPhoneアプリで描いてみます。
動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。
サンプルコード
#import “ViewController.h”
#import <Box2D/Box2D.h>
#import <QuartzCore/QuartzCore.h>
#define PixelToMeterRatio 16.0
#define screen CGSizeMake(568, 300)
@interface ViewController () {
b2World *world;
b2Body *slopeBody;
NSTimer *timer;
CGPoint slopeTop;
UIView *goalLine;
UILabel *timeLabel;
float counter;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [self color:0];
[self createWorld];
[self createGoalLine];
counter = 3.0f;
[self start];
}
– (void)createWorld
{
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(screen.width/PixelToMeterRatio, 0));
groundBody->CreateFixture(&groundBox, 0);
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self.view];
// ボタンがある場所をクリックした場合はスキップ
if (CGRectContainsPoint(CGRectMake(270, 0, 50, 150), p)) {
[self touchesCancelled:touches withEvent:event];
return;
}
// ボールのときはタッチした場所にボールを生成
[self addHappy:p];
}
– (void)createGoalLine
{
goalLine = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 320, 10)];
goalLine.backgroundColor = [self color:3];
[self.view addSubview:goalLine];
timeLabel = [[UILabel alloc] init];
timeLabel.backgroundColor = [UIColor clearColor];
timeLabel.font = [UIFont systemFontOfSize:40];
timeLabel.textColor = [self color:4];
timeLabel.text = @”3.00″;
[timeLabel sizeToFit];
timeLabel.center = CGPointMake(160, 80);
[self.view addSubview:timeLabel];
}
– (void)start
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
// タイマーで時間を進める
– (void)tick:(NSTimer*)sender
{
int32 velocityIterations = 8;
int32 positionIterations = 1;
world->Step(1.0f/60.0f, velocityIterations, positionIterations);
BOOL goal = NO;
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
UIView *v = (__bridge UIView *) b->GetUserData();
float x = b->GetPosition().x * PixelToMeterRatio;
float y = self.view.bounds.size.height – b->GetPosition().y * PixelToMeterRatio;
CGPoint newCenter = CGPointMake(x,y);
v.center = newCenter;
v.transform = CGAffineTransformMakeRotation(-b->GetAngle());
// goal line check
if (CGRectIntersectsRect(v.frame, goalLine.frame)) {
goal = YES;
}
}
}
// goal line check
if (goal) {
counter -= sender.timeInterval;
} else {
counter = 3.0f;
}
timeLabel.text = [NSString stringWithFormat:@”%.2f”, counter];
if (counter < 0) {
[timer invalidate];
timeLabel.text = @”Clear”;
[timeLabel sizeToFit];
}
}
– (void)addHappy:(CGPoint)point
{
UIView *ball = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 50)];
ball.center = point;
ball.backgroundColor = [self color:2];
[self.view addSubview:ball];
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
CGPoint dimensions = CGPointMake(ball.bounds.size.width/PixelToMeterRatio/2.0, ball.bounds.size.height/PixelToMeterRatio/2.0);
bodyDef.position.Set(ball.center.x/PixelToMeterRatio, (568-ball.center.y)/PixelToMeterRatio);
bodyDef.userData = (__bridge void *)ball;
b2Body *body = world->CreateBody(&bodyDef);
b2PolygonShape box;
box.SetAsBox(dimensions.x, dimensions.y);
b2FixtureDef fixtureDef;
fixtureDef.shape = &box;
fixtureDef.density = 10.0f; // 密度
fixtureDef.friction = 1.0f; // 摩擦
fixtureDef.restitution = 0.1f; // 反発
body->CreateFixture(&fixtureDef);
body->SetType(b2_dynamicBody);
}
#define UIColorHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
– (UIColor*)color:(int)i
{
switch (i) {
case 0:
return UIColorHex(0x323738);
case 1:
return UIColorHex(0xFFF6EA);
case 2:
return UIColorHex(0xF28D00);
case 3:
return UIColorHex(0xF03909);
case 4:
return UIColorHex(0xCC1900);
default:
break;
}
return nil;
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end