ブルドーザーをタッチして、砂山を崩す。
崩した砂をそのまま道路に空いた穴に落としましょう。
ただそれだけの簡単、子供向けアプリのサンプルです。
ポイント
砂同士の衝突判定は、簡素に右側が当たっていたら、左に少しずらす
左が当たっていたら、右に、下が当たっていたら停止といった感じに
NSTimerのなかで判定しています。
砂とブルドーザーのシャベル部分が当たったかどうかの判定は、
UIBezierPathのCGPathContainsPointを使って判定してみました。
環境
今回つくったiPhoneアプリサンプルは、
XcodeのiOS6 iPhone Simulatorで動かしています。
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController () {
UIView *bulldozer;
UIView *blade;
CAShapeLayer *bladeLayer;
NSTimer *timer;
NSMutableArray *sand;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
[self createBulldozer];
[self createGround];
[self createSand];
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
static BOOL lock;
if (!lock) {
lock = YES;
[self startTimer];
}
}
– (void)createBulldozer
{
bulldozer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
bulldozer.center = CGPointMake(260, 300);
bulldozer.backgroundColor = [UIColor clearColor];
UIView *body = [[UIView alloc] initWithFrame:CGRectMake(30, 50, 70, 40)];
body.backgroundColor = [UIColor yellowColor];
[bulldozer addSubview:body];
blade = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 30, 50)];
blade.backgroundColor = [UIColor clearColor];
[bulldozer addSubview:blade];
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(0, 0)];
[path addArcWithCenter:CGPointMake(0, 25) radius:25 startAngle:-M_PI*0.5 endAngle:M_PI*0.5 clockwise:YES];
bladeLayer = [[CAShapeLayer alloc] initWithLayer:blade.layer];
bladeLayer.path = path.CGPath;
bladeLayer.fillColor = [UIColor clearColor].CGColor;
bladeLayer.strokeColor = [UIColor yellowColor].CGColor;
bladeLayer.lineWidth = 5.0;
[blade.layer addSublayer:bladeLayer];
UIView *tireF = [[UIView alloc] initWithFrame:CGRectMake(30, 80, 30, 30)];
tireF.backgroundColor = [UIColor whiteColor];
tireF.layer.borderColor = [UIColor blackColor].CGColor;
tireF.layer.borderWidth = 10;
tireF.layer.cornerRadius = 15;
[bulldozer addSubview:tireF];
UIView *tireR = [[UIView alloc] initWithFrame:CGRectMake(70, 80, 30, 30)];
tireR.backgroundColor = [UIColor whiteColor];
tireR.layer.borderColor = [UIColor blackColor].CGColor;
tireR.layer.borderWidth = 10;
tireR.layer.cornerRadius = 15;
[bulldozer addSubview:tireR];
UIView *cockpit = [[UIView alloc] initWithFrame:CGRectMake(50, 10, 40, 40)];
cockpit.layer.borderWidth = 5;
cockpit.layer.borderColor = [UIColor blackColor].CGColor;
[bulldozer addSubview:cockpit];
UIView *driver = [[UIView alloc] initWithFrame:CGRectMake(55, 25, 20, 20)];
driver.backgroundColor = [UIColor blackColor];
driver.layer.cornerRadius = 10;
[bulldozer addSubview:driver];
[self.view addSubview:bulldozer];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
[bulldozer addGestureRecognizer:tap];
}
– (void)tap
{
bulldozer.tag = 10;
}
– (void)createSand
{
sand = [[NSMutableArray alloc] init];
for (int i=0; i<80; i++) {
float x = arc4random() % 50 + 100;
float y = arc4random() % 50;
UIView *s = [[UIView alloc] initWithFrame:CGRectMake(x + 10, y, 5, 5)];
s.backgroundColor = [UIColor brownColor];
s.tag = 1;
[self.view addSubview:s];
[sand addObject:s];
}
}
– (void)createGround
{
UIView *ground = [[UIView alloc] initWithFrame:CGRectMake(0, 350, 320, 130)];
ground.backgroundColor = [UIColor brownColor];
[self.view addSubview:ground];
UIView *hole = [[UIView alloc] initWithFrame:CGRectMake(50, 350, 50, 50)];
hole.backgroundColor = [UIColor blackColor];
[self.view addSubview:hole];
}
– (void)startTimer
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
– (void)tick:(NSTimer*)sender
{
float velocity = 1;
for (UIView *v1 in sand) {
for (UIView *v2 in sand) {
if (v2 == v1) {
continue;
}
CGPoint o = v1.frame.origin;
CGSize s = v1.frame.size;
CGRect right = CGRectMake(o.x + s.width, o.y, 1, s.height);
CGRect left = CGRectMake(o.x, o.y, 1, s.height);
CGRect bottom = CGRectMake(o.x, o.y+s.height, s.width, 1);
if(CGRectIntersectsRect(right, v2.frame)) {
v1.center = CGPointMake(v1.center.x – 1, v1.center.y);
} else if(CGRectIntersectsRect(left, v2.frame)) {
v1.center = CGPointMake(v1.center.x + 1, v1.center.y);
}
if (CGRectIntersectsRect(bottom, v2.frame)) {
v1.tag = 2;
}
}
if (v1.center.x > 50 && v1.center.x < 100 && v1.center.y < 400 && v1.tag != 2) {
// hole
v1.center = CGPointMake(v1.center.x, v1.center.y + 1);
} else if (v1.center.y < 350 && v1.tag != 2) {
// ground
v1.center = CGPointMake(v1.center.x, v1.center.y + 1);
} else {
v1.tag = 1;
}
}
if (bulldozer.tag == 10) {
bulldozer.center = CGPointMake(bulldozer.center.x-velocity, bulldozer.center.y);
for (UIView *s in sand) {
CGPoint cp = [self.view convertPoint:s.center toView:blade];
cp = CGPointMake(cp.x + 1, cp.y – 1);
if (CGPathContainsPoint(bladeLayer.path, 0, cp, YES)) {
s.center = CGPointMake(s.center.x – 1, s.center.y);
}
}
}
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end