画面をタッチして、入れ替え、回転であそぶパズル
(XcodeのiOS6 iPhone Simulatorで試しています。)
ポイント
・パネルを二つタップすると入れ替え
・同じパネルをタップすると回転
・タッチしたパネルに色を重ねるために、UIViewでBlendModeMultiply
サンプルコード
ViewController.m
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface Piece : UIView
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIColor *overlay;
@end
@implementation Piece
@synthesize image, overlay;
– (void)setOverlay:(UIColor *)aOverlay
{
overlay = aOverlay;
[self setNeedsDisplay];
}
– (void) drawRect:(CGRect)area
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// CGContextDrawImageを使うと上下反転してしまうからこっちに。
[self.image drawInRect:self.bounds];
CGContextSetBlendMode (context, kCGBlendModeMultiply);
CGContextSetFillColor(context, CGColorGetComponents(overlay.CGColor));
CGContextFillRect (context, self.bounds);
CGContextRestoreGState(context);
}
@end
@interface ViewController () {
Piece *onePiece;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor blackColor]];
UIImage *resized = [self resize:[UIImage imageNamed:@”rocket.jpg”] scaledToSize:CGSizeMake(320, 320)];
onePiece = [[Piece alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
onePiece.image = resized;
onePiece.overlay = [UIColor clearColor];
[self.view addSubview:onePiece];
// レイヤーのマスクで丸角
CAShapeLayer * shapeLayer = [CAShapeLayer layer];
shapeLayer.backgroundColor = [UIColor clearColor].CGColor;
shapeLayer.path = [UIBezierPath bezierPathWithRoundedRect:onePiece.bounds byRoundingCorners: UIRectCornerAllCorners cornerRadii:CGSizeMake(20.0, 20.0)].CGPath;
onePiece.layer.masksToBounds = YES;
onePiece.layer.mask = shapeLayer;
shapeLayer.frame = onePiece.layer.bounds;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startTap:)];
[onePiece addGestureRecognizer:tap];
}
– (void)startTap:(UITapGestureRecognizer*)gr
{
// 元の絵を上に小さく表示
[UIView animateWithDuration:0.5 animations:^{
onePiece.transform = CGAffineTransformMakeScale(0.25, 0.25);
onePiece.center = CGPointMake(160, 50);
}];
// 4×4に分割する
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++) {
[self createPiece:CGRectMake(i*80, j*80, 80, 80) image:onePiece.image];
}
}
// シャッフルして動かす
// 配列の中身をランダムに入れ替え
NSMutableArray *array = [[NSMutableArray alloc] init];
for (UIView *v in self.view.subviews) {
if (v.tag == 1) {
[array addObject:v];
}
}
int count = [array count];
for (int i = count – 1; i > 0; i–) {
int randomNum = arc4random() % i;
[array exchangeObjectAtIndex:i withObjectAtIndex:randomNum];
}
// シャッフル後の位置に動かす
for (int i=0; i<[array count]; i++) {
float x = 80 * (i / 4) + 40;
float y = 80 * (i % 4) + 140;
[UIView animateWithDuration:0.3 delay:0.1 * i options:UIViewAnimationCurveEaseIn animations:^{
UIView *v = [array objectAtIndex:i];
// 場所
v.center = CGPointMake(x, y);
// 回転
float angle = (arc4random() % 4) * 0.5 * M_PI;
v.transform = CGAffineTransformMakeRotation(angle);
} completion:^(BOOL finished) {}];
}
}
#pragma mark – image util
– (UIImage *)resize:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
– (void)createPiece:(CGRect)rect image:(UIImage*)origin
{
CGImageRef imageRef = CGImageCreateWithImageInRect([origin CGImage], rect);
Piece *piece = [[Piece alloc] initWithFrame:rect];
// 表示位置を少し下げる
piece.center = CGPointMake(piece.center.x, piece.center.y + 100);
piece.image = [UIImage imageWithCGImage:imageRef];
piece.overlay = [UIColor clearColor];
piece.layer.borderColor = [UIColor blackColor].CGColor;
piece.layer.borderWidth = 2.0;
piece.tag = 1;
[self.view addSubview:piece];
// こっちはlayer.cornerRadiusで丸角
piece.layer.cornerRadius = 10.0;
piece.layer.masksToBounds = YES;
CGImageRelease(imageRef);
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapPanel:)];
[piece addGestureRecognizer:tap];
}
– (void)tapPanel:(UITapGestureRecognizer*)gr
{
static Piece *firstTap;
UIColor *color = [UIColor colorWithRed:0 green:0 blue:1.0 alpha:0.5];
Piece *piece = (Piece*)gr.view;
if (!firstTap) {
firstTap = piece;
piece.overlay = color;
return;
}
if (firstTap == gr.view) {
[UIView animateWithDuration:0.3 animations:^{
piece.transform = CGAffineTransformRotate(gr.view.transform, M_PI * 0.5);
} completion:^(BOOL finished) {
firstTap.overlay = [UIColor clearColor];
piece.overlay = [UIColor clearColor];
firstTap = nil;
}];
} else {
CGPoint p1 = firstTap.center;
CGPoint p2 = piece.center;
piece.overlay = color;
[UIView animateWithDuration:0.3 animations:^{
firstTap.center = p2;
piece.center = p1;
} completion:^(BOOL finished) {
firstTap.overlay = [UIColor clearColor];
piece.overlay = [UIColor clearColor];
firstTap = nil;
}];
}
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end