iOSのサンプルとしてふわふわ動くサンタがプレゼントを配るコードのメモ
( Xcode の iOS6 Simulator で試しています。)
ポイント
・絵をフォントの絵文字で代用(サンタとかApple EmojiをUILabelに)
・PanGestureのEndedのtranslate と サンタの位置でプレゼントの動きを決定
指でピッピってプレゼントを配るサンタシューティングゲームのサンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController () {
CADisplayLink *timer;
}
@property (nonatomic, strong) UIView *santa;
@property (nonatomic, strong) NSMutableArray *houses;
@property (nonatomic, strong) NSMutableDictionary *presents;
@end
// Apple Emojiをマクロ定義してみる(ここだけブログ文字化けるから画像。。。)
@implementation ViewController
@synthesize santa, houses;
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
}
– (void)viewDidAppear:(BOOL)animated
{
[self loadData];
[self start];
}
– (void)viewDidDisappear:(BOOL)animated
{
[timer invalidate];
santa = nil;
timer = nil;
houses = nil;
}
– (void)start
{
timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateDisplay:)];
[timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
– (void)loadData
{
[self randomHouseCreate];
[self loadSanta];
self.presents = [[NSMutableDictionary alloc] init];
}
– (void)loadSanta
{
// 透明な枠
self.santa = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
self.santa.backgroundColor = [UIColor brownColor];
self.santa.layer.cornerRadius = 5.0;
UILabel *slable = [[UILabel alloc] initWithFrame:CGRectZero];
slable.text = Santa;
slable.backgroundColor = [UIColor clearColor];
[slable sizeToFit];
slable.userInteractionEnabled = YES;
[self.santa addSubview:slable];
[self.view addSubview:self.santa];
// 拡大
self.santa.transform = CGAffineTransformMakeScale(2.0, 2.0);
// 外側のViewの中心に座標をコンバート
slable.center = [self.santa convertPoint:self.santa.center fromView:self.view];
// add gesture
[slable addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panSanta:)]];
}
– (void)randomHouseCreate
{
self.houses = [[NSMutableArray alloc] init];
// 以下の範囲にばらまく
// x point : 画面全体
// y point : 0 ~ 2/3 * height
// margin 20 point
int margin = 20;
int xMax = self.view.frame.size.width – margin;
int yMax = self.view.frame.size.height * (2.0 / 3.0) – margin;
for (int i = 0; i < 7; i++) {
// margin ~ Max でランダム
int x = (arc4random() % (xMax – margin)) + margin;
int y = (arc4random() % (yMax – margin)) + margin;
// 家のフォント絵文字を配置
UILabel *h = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 30, 30)];
// see #define House
h.text = House;
h.layer.cornerRadius = 5.0;
h.backgroundColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.0 alpha:0.2];
[self.view addSubview:h];
[houses addObject:h];
}
}
– (void)updateDisplay:(CADisplayLink*)sender
{
static float lastTime = 0.0;
float timeDelta = 0.0;
if (lastTime == 0.0) {
lastTime = sender.timestamp;
} else {
timeDelta = sender.timestamp – lastTime;
lastTime = sender.timestamp;
}
// サンタの位置
// 縦の基本位置調整
self.santa.center = CGPointMake(self.santa.center.x, 350);
float x = self.santa.center.x + 10.0 * timeDelta;
float y = self.santa.center.y + 50.0 * sinf(x * 0.1);
self.santa.center = CGPointMake(x, y);
// プレゼント配布
for (NSNumber *index in self.presents.keyEnumerator) {
NSDictionary *p = [self.presents objectForKey:index];
UIView *present = [p objectForKey:@”view”];
CGPoint direction = [[p objectForKey:@”direction”] CGPointValue];
float px = present.center.x + direction.x * timeDelta;
float py = present.center.y + direction.y * timeDelta;
present.center = CGPointMake(px, py);
}
// 接触確認
[self collisionCheck];
}
– (void)panSanta:(UIPanGestureRecognizer*)gr
{
// 何回か、思ったが、Panの開始と、タッチした場所はずれるのでなんとかとれないものか。
// touchBeginを使うのも手。今回は、サンタの顔の中心
// if (gr.state == UIGestureRecognizerStateBegan) {
// startPoint = [gr locationInView:self.view];
// }
if (gr.state == UIGestureRecognizerStateEnded) {
// タッチ開始位置と方向を計算
NSValue *translate = [NSValue valueWithCGPoint:[gr translationInView:self.view]];
UILabel *present = [[UILabel alloc] initWithFrame:CGRectZero];
present.text = Present;
present.center = self.santa.center;
[present sizeToFit];
[self.view addSubview:present];
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:present, @”view”, translate, @”direction”, nil];
[self.presents setObject:dict forKey:[self counter]];
}
}
– (void)collisionCheck
{
// プレゼントと家の総当たりチェック
// 微小時間でかぶらせることもないと思うので、ヒットしたら戻す。
for (int i=0; i<[self.houses count]; i++) {
for (NSNumber *index in self.presents.keyEnumerator) {
UIView *house = [self.houses objectAtIndex:i];
NSDictionary *p = [self.presents objectForKey:index];
UIView *present = [p objectForKey:@”view”];
if(CGRectIntersectsRect(house.frame, present.frame)) {
// hit
// house : ライトを明るく、チェックリストから外す
house.backgroundColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.0 alpha:0.6];
[self.houses removeObject:house];
// present : View消す、チェックリストからも消す
[self.presents removeObjectForKey:index];
[present removeFromSuperview];
return;
}
}
}
}
– (NSNumber*)counter
{
static int number = 0;
number++;
return [NSNumber numberWithInt:number];
}
@end