今日はあみだくじをiPhoneアプリで作ってみます。グリッド状に基準となる点を決めておいて、そこにランダムに線を描いていきます。
動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。
ポイント
データ構造を思いつくまま作ってしまいました。いつにも増してガリガリ描いてしまっています。(※いつか、イケテルあみだデータ構造を知りたい。)縦に6本線を引いた後、ランダムで横線を引いています。横線の中心点を保持しています。タッチすると、タイマーでマーカーが動いていく感じにして、タイマーの左右50pt以内に横棒の中心点があった場合、タイマーを一時停止して横に動かしています。
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController () {
UIView *amida;
CGPoint point[36];
BOOL bar[20]; // bar[0] : point[6] to point[7] …
CGPoint barPoint[20];
int goal;
UIView *selected;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [self color:2];
[self createGrid];
[self createGoal];
[self createStartButton];
}
– (void)createGrid
{
amida = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:amida];
for (int i=0; i<36; i++) {
float x = 50 * (i % 6) + 35;
float y = 70 * (i / 6) + 35;
point[i] = CGPointMake(x, y);
}
for (int i=0; i<20; i++) {
if (arc4random()%3) {
bar[i] = YES;
} else {
bar[i] = NO;
barPoint[i] = CGPointZero;
}
}
UIBezierPath *path = [UIBezierPath bezierPath];
// vertical line
for (int i=0; i<6; i++) {
[path moveToPoint:point[i]];
[path addLineToPoint:point[i + 30]];
}
for (int i=0; i<20; i++) {
if (bar[i]) {
int col = i % 5;
int row = i / 5 + 1;
CGPoint s = point[col + row * 6];
CGPoint e = point[col + row * 6 + 1];
// 線が一直線にならないようにずらす
if (col % 2) {
[path moveToPoint:s];
[path addLineToPoint:e];
barPoint[i] = CGPointMake((s.x + e.x) / 2.0, s.y);
} else {
[path moveToPoint:CGPointMake(s.x, s.y – 35)];
[path addLineToPoint:CGPointMake(e.x, e.y – 35)];
barPoint[i] = CGPointMake((s.x + e.x) / 2.0, s.y – 35);
}
}
}
CAShapeLayer *sl = [[CAShapeLayer alloc] init];
sl.strokeColor = [self color:0].CGColor;
sl.fillColor = [UIColor clearColor].CGColor;
sl.lineWidth = 15;
sl.path = path.CGPath;
sl.shadowOpacity = 0.7;
sl.shadowRadius = 4.0;
sl.shadowOffset = CGSizeMake(3, 3);
[amida.layer addSublayer:sl];
}
– (void)createGoal
{
goal = arc4random() % 6;
UIView *mark = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
mark.center = point[goal];
mark.backgroundColor = [self color:1];
mark.layer.shadowOpacity = 0.7;
mark.layer.shadowRadius = 4.0;
mark.layer.shadowOffset = CGSizeMake(3, 3);
[amida addSubview:mark];
}
– (void)createStartButton
{
for (int i= 30; i<36; i++) {
UIView *mark = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
mark.center = point[i];
mark.backgroundColor = [self color:4];
mark.layer.cornerRadius = 20;
mark.layer.shadowOpacity = 0.7;
mark.layer.shadowRadius = 4.0;
mark.layer.shadowOffset = CGSizeMake(3, 3);
mark.tag = i;
[amida addSubview:mark];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(start:)];
[mark addGestureRecognizer:tap];
}
}
– (void)start:(UITapGestureRecognizer*)gr
{
selected = gr.view;
[NSTimer scheduledTimerWithTimeInterval:2.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
– (void)tick:(NSTimer*)sender
{
for (int i=0; i<20; i++) {
// check light
if (CGRectContainsPoint(CGRectMake(selected.center.x, selected.center.y, 50, 1), barPoint[i])) {
[sender invalidate];
[UIView animateWithDuration:0.5 animations:^{
selected.center = CGPointMake(selected.center.x + 50, selected.center.y);
} completion:^(BOOL finished) {
selected.center = CGPointMake(selected.center.x, selected.center.y – 2);
// continue
[NSTimer scheduledTimerWithTimeInterval:2.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}];
return;
}
// check left
if (CGRectContainsPoint(CGRectMake(selected.center.x – 50, selected.center.y, 50, 1), barPoint[i])) {
[sender invalidate];
[UIView animateWithDuration:0.5 animations:^{
selected.center = CGPointMake(selected.center.x – 50, selected.center.y);
} completion:^(BOOL finished) {
selected.center = CGPointMake(selected.center.x, selected.center.y – 2);
// continue
[NSTimer scheduledTimerWithTimeInterval:2.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}];
return;
}
}
// up!!
selected.center = CGPointMake(selected.center.x, selected.center.y – 1);
if (selected.center.y == 10) {
[sender invalidate];
// restart
for (UIView *v in self.view.subviews) {
[v removeFromSuperview];
[self createGrid];
[self createGoal];
[self createStartButton];
}
}
}
#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(0xF88D00);
case 1:
return UIColorHex(0xED4500);
case 2:
return UIColorHex(0xFCFBE5);
case 3:
return UIColorHex(0xD9224C);
case 4:
return UIColorHex(0xBBD400);
default:
break;
}
return nil;
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end