「まる、さんかく、しかく」を引っぱるとビョーンとのびます。
ゆびを離すと、飛んでいくので、同じ形の的に当ててみましょう。
というようなゲームのサンプルを作ってみました。
環境
XcodeのiOS6 iPhone Simulatorで動かしています。
ポイント
touchesMovedで引っぱった方向にあわせて、
transformで図形を回転させ、UIViewのcenterからの距離
y方向を調整することで、引っぱった感じを出してみました。
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController () {
UIView *selected;
NSTimer *timer;
NSTimer *checkTimer;
CGPoint points[3];
NSMutableArray *holes;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [self colors:0];
[self createUI];
[self startCheck];
}
– (UIColor*)colors:(int)i
{
float rgb[5][3] = {
{ 9.0/255.0, 33.0/255.0, 64.0/255.0}
,{242.0/255.0, 199.0/255.0, 119.0/255.0}
,{242.0/255.0, 71.0/255.0, 56.0/255.0}
,{7.0/255.0, 242.0/255.0, 0.0/255.0}
,{ 2.0/255.0, 73.0/255.0, 89.0/255.0}
};
return [UIColor colorWithRed:rgb[i][0] green:rgb[i][1] blue:rgb[i][2] alpha:1.0];
}
– (void)createUI
{
// create holes
holes = [[NSMutableArray alloc] init];
for (int i=0; i<3; i++) {
UIView *h = [self createRandomFigure];
h.center = CGPointMake(i*100 + 60, 60);
[self.view addSubview:h];
h.backgroundColor = [UIColor clearColor];
CAShapeLayer *l = [h.layer.sublayers objectAtIndex:0];
l.fillColor = [UIColor whiteColor].CGColor;
[holes addObject:h];
}
// create figure
UIView *v = [self createRandomFigure];
v.center = self.view.center;
[self.view addSubview:v];
}
– (UIView*)createRandomFigure
{
int rand = arc4random() % 3;
UIView *figure = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
figure.backgroundColor = [UIColor clearColor];
UIBezierPath *path = [[UIBezierPath alloc] init];
switch (rand) {
case 0: // triangle
figure.tag = 1;
[path moveToPoint:CGPointMake(0, 40)];
[path addLineToPoint:CGPointMake(20, 0)];
[path addLineToPoint:CGPointMake(40, 40)];
break;
case 1: // rect
figure.tag = 2;
[path appendPath:[UIBezierPath bezierPathWithRect:figure.bounds]];
break;
case 2: // circle
figure.tag = 3;
[path appendPath:[UIBezierPath bezierPathWithOvalInRect:figure.bounds]];
break;
default:
break;
}
CAShapeLayer *sl = [[CAShapeLayer alloc] initWithLayer:figure.layer];
sl.path = path.CGPath;
sl.fillColor = [self colors:figure.tag].CGColor;
[figure.layer addSublayer:sl];
return figure;
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (selected) {
[self touchesCancelled:touches withEvent:event];
return;
}
CGPoint p = [[touches anyObject] locationInView:self.view];
for (UIView *v in self.view.subviews) {
if (CGRectContainsPoint(v.frame, p)) {
selected = v;
}
}
}
– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!selected) {
return;
}
CGPoint p = [[touches anyObject] locationInView:selected];
CGPoint center = CGPointMake(20, 20);
float distance = hypot(p.x – center.x, p.y – center.y);
points[0] = CGPointMake(center.x, center.y – distance);
points[1] = CGPointMake(0, 40);
points[2] = CGPointMake(40, 40);
UIBezierPath *path = [[UIBezierPath alloc] init];
switch (selected.tag) {
case 1:
[path moveToPoint:points[0]];
[path addLineToPoint:points[1]];
[path addLineToPoint:points[2]];
break;
case 2:
[path moveToPoint:CGPointMake(points[0].x + 10, points[0].y)];
[path addLineToPoint:CGPointMake(points[0].x – 10, points[0].y)];
[path addLineToPoint:points[1]];
[path addLineToPoint:points[2]];
break;
case 3:
[path addArcWithCenter:points[0] radius:10 startAngle:M_PI endAngle:0 clockwise:YES];
[path addArcWithCenter:CGPointMake(20, 20) radius:20 startAngle:0 endAngle:M_PI clockwise:YES];
break;
default:
break;
}
CAShapeLayer *sl = [selected.layer.sublayers lastObject];
sl.path = path.CGPath;
float angle = atan2f(p.y – center.y, p.x – center.x) + M_PI/2.0;
selected.transform = CGAffineTransformRotate(selected.transform, angle);
}
– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!selected) {
return;
}
[self start:selected];
selected.userInteractionEnabled = NO;
CGPoint p = [[touches anyObject] locationInView:self.view];
CGPoint velocity = CGPointMake(selected.center.x – p.x, selected.center.y – p.y);
[UIView animateWithDuration:1.0 animations:^{
selected.center = CGPointMake(velocity.x * 5 + selected.center.x, velocity.y * 5 + selected.center.y);
} completion:^(BOOL finished) {
if (finished) {
[selected removeFromSuperview];
selected = nil;
}
UIView *v = [self createRandomFigure];
v.center = self.view.center;
[self.view addSubview:v];
}];
}
– (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[selected removeFromSuperview];
selected = nil;
[super touchesCancelled:touches withEvent:event];
}
– (void)start:(UIView*)v
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:v repeats:YES];
}
– (void)tick:(NSTimer*)sender
{
float newY = points[0].y – (points[0].y – 20) * 0.1;
points[0] = CGPointMake(20, newY);
UIBezierPath *path = [[UIBezierPath alloc] init];
float w;
switch (selected.tag) {
case 1:
[path moveToPoint:points[0]];
[path addLineToPoint:points[1]];
[path addLineToPoint:points[2]];
break;
case 2:
w = 10 + 10 * (300 + points[0].y) / 300.0;
[path moveToPoint:CGPointMake(points[0].x + w, points[0].y)];
[path addLineToPoint:CGPointMake(points[0].x – w, points[0].y)];
[path addLineToPoint:points[1]];
[path addLineToPoint:points[2]];
break;
case 3:
w = 10 + 10 * (100 + points[0].y) / 100.0;
[path addArcWithCenter:CGPointMake(points[0].x, points[0].y + 20) radius:w startAngle:M_PI endAngle:0 clockwise:YES];
[path addArcWithCenter:CGPointMake(20, 20) radius:20 startAngle:0 endAngle:M_PI clockwise:YES];
break;
default:
break;
}
CAShapeLayer *sl = [selected.layer.sublayers lastObject];
sl.path = path.CGPath;
if (points[0].y >= 0.1) {
[timer invalidate];
}
}
– (void)startCheck
{
checkTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(check) userInfo:nil repeats:YES];
}
– (void)check
{
// goal check
[self performSelectorOnMainThread:@selector(next) withObject:nil waitUntilDone:NO];
static BOOL checking;
if(selected && !checking) {
for (UIView *v in holes) {
CGRect r = [selected.layer.presentationLayer frame];
if (CGRectIntersectsRect(v.frame, r)) {
checking = TRUE;
[selected.layer removeAllAnimations];
selected.frame = r;
if (v.tag == selected.tag) {
// collect figure
[UIView animateWithDuration:0.5 animations:^{
selected.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.2 animations:^{
selected.frame = v.frame;
selected = nil;
[holes removeObject:v];
}];
checking = FALSE;
}];
} else {
// different figure
[UIView animateWithDuration:0.5 animations:^{
selected.center = CGPointMake(500, 300);
} completion:^(BOOL finished) {
[selected removeFromSuperview];
selected = nil;
checking = FALSE;
}];
}
}
}
}
}
– (void)next
{
if ([holes count] == 0) {
// next
for (UIView *v in self.view.subviews) {
v.tag = 10;
[UIView animateWithDuration:0.5 animations:^{
v.alpha = 0.3;
} completion:^(BOOL finished) {
[v removeFromSuperview];
}];
}
[self createUI];
for (UIView *v in self.view.subviews) {
if (v.tag != 10) {
v.center = CGPointMake(v.center.x + 320, v.center.y);
[UIView animateWithDuration:0.5 animations:^{
v.center = CGPointMake(v.center.x – 320, v.center.y);
}];
}
}
}
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end