iPhone積み上げタワー

棒をゴールラインまで積み上げていく単純ゲームを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