棒人間 Stick Personに背泳ぎをさせるサンプルです。
今日は、東京の3月にしては暑かったのでプールものです。
最高気温は25度らしいです。
サンプルアプリは、指でタッチしたコース上を、stick person が
手足をバタバタさせながら、プールを泳いでいくように
作ってみました。
環境
XcodeのiOS6 iPhone Simulatorで動かしています。
ポイント
手のストロークには、楕円の式、x = a * cos, y = b * cos を利用、
手を下から上に上げるときは、円軌道ではなく
直線になるように、if 条件で制御を追加しています。
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface StickPerson : UIView
{
CGPoint head, neck, hip;
CGPoint sholderR, sholderL, elbowR, elbowL, handR, handL;
CGPoint kneeR, kneeL, footR, footL;
NSTimer *timer;
float lastTime;
}
– (void)swim;
@end
@implementation StickPerson
– (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
CGSize size = self.bounds.size;
head = CGPointMake(size.width*0.5, size.height*0.2);
neck = CGPointMake(size.width*0.5, size.height*0.3);
hip = CGPointMake(size.width*0.5, size.height*0.6);
sholderR = CGPointMake(size.width*0.5, size.height*0.3);
elbowR = CGPointMake(size.width*0.4, size.height*0.45);
handR = CGPointMake(size.width*0.3, size.height*0.6);
kneeR = CGPointMake(size.width*0.45, size.height*0.85);
footR = CGPointMake(size.width*0.45, size.height);
sholderL = CGPointMake(size.width*0.5, size.height*0.3);
elbowL = CGPointMake(size.width*0.6, size.height*0.45);
handL = CGPointMake(size.width*0.7, size.height*0.6);
kneeL = CGPointMake(size.width*0.55, size.height*0.85);
footL = CGPointMake(size.width*0.55, size.height);
}
return self;
}
– (void)swim
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f/60.0f target:self selector:@selector(turnHand:) userInfo:nil repeats:YES];
}
– (void)turnHand:(NSTimer*)sender
{
lastTime += 4*sender.timeInterval;
CGSize size = self.bounds.size;
{
CGPoint c = CGPointMake(size.width*0.45, size.height*0.3);
float x = size.width*0.2 * 0.4 * cos(-lastTime) + c.x;
if (x > size.width*0.45) {
x = size.width*0.45;
}
float y = size.height*0.2 * 0.5 * sin(-lastTime) + c.y;
elbowR = CGPointMake(x, y);
}
{
CGPoint c = CGPointMake(size.width*0.45, size.height*0.3);
float x = size.width*0.2 * cos(-lastTime) + c.x;
if (x > size.width*0.45) {
x = size.width*0.45;
}
float y = size.height*0.25 * sin(-lastTime) + c.y;
handR = CGPointMake(x, y);
}
{
CGPoint c = CGPointMake(size.width*0.55, size.height*0.3);
float x = size.width*0.2 * 0.4 * cos(lastTime) + c.x;
if (x < size.width*0.55) {
x = size.width*0.55;
}
float y = size.height*0.2 * 0.5 * sin(lastTime) + c.y;
elbowL = CGPointMake(x, y);
}
{
CGPoint c = CGPointMake(size.width*0.55, size.height*0.3);
float x = size.width*0.2 * cos(lastTime) + c.x;
if (x < size.width*0.55) {
x = size.width*0.55;
}
float y = size.height*0.25 * sin(lastTime) + c.y;
handL = CGPointMake(x, y);
}
{
CGPoint c = kneeR;
float y = size.height*0.3 * sin(4*lastTime) + c.y;
if (y < size.height*0.75) {
y = size.height*0.75;
}
footR = CGPointMake(c.x, y);
}
{
CGPoint c = kneeL;
float y = size.height*0.3 * sin(4*lastTime + M_PI) + c.y;
if (y < size.height*0.75) {
y = size.height*0.75;
}
footL = CGPointMake(c.x, y);
}
[self setNeedsDisplay];
}
– (void)drawRect:(CGRect)rect
{
CGSize size = self.bounds.size;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx, size.width*0.07);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineJoin(ctx, kCGLineJoinMiter);
CGContextMoveToPoint(ctx, head.x, head.y);
CGContextAddArc(ctx, head.x, head.y, size.width*0.1, 0, 2.0*M_PI, NO);
CGContextFillPath(ctx);
[[UIColor whiteColor] setFill];
CGContextAddArc(ctx, head.x + size.width*0.04, head.y, size.width*0.02, 0, 2.0*M_PI, NO);
CGContextAddArc(ctx, head.x – size.width*0.04, head.y, size.width*0.02, 0, 2.0*M_PI, NO);
CGContextAddRect(ctx, CGRectMake(head.x – size.width*0.03, head.y + size.height*0.05, size.width*0.05, size.width*0.02));
CGContextFillPath(ctx);
[[UIColor blackColor] setFill];
CGContextMoveToPoint(ctx, neck.x, neck.y);
CGContextAddLineToPoint(ctx, sholderR.x, sholderR.y);
CGContextAddLineToPoint(ctx, elbowR.x, elbowR.y);
CGContextMoveToPoint(ctx, elbowR.x, elbowR.y);
CGContextAddLineToPoint(ctx, handR.x, handR.y);
CGContextMoveToPoint(ctx, neck.x, neck.y);
CGContextAddLineToPoint(ctx, sholderL.x, sholderL.y);
CGContextAddLineToPoint(ctx, elbowL.x, elbowL.y);
CGContextAddLineToPoint(ctx, handL.x, handL.y);
CGContextMoveToPoint(ctx, neck.x, neck.y);
CGContextAddLineToPoint(ctx, hip.x, hip.y);
CGContextAddLineToPoint(ctx, kneeR.x, kneeR.y);
CGContextAddLineToPoint(ctx, footR.x, footR.y);
CGContextMoveToPoint(ctx, hip.x, hip.y);
CGContextAddLineToPoint(ctx, kneeL.x, kneeL.y);
CGContextAddLineToPoint(ctx, footL.x, footL.y);
CGContextStrokePath(ctx);
}
@end
@interface ViewController () {
NSTimer *timer;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
[self createPool];
[self startTimer];
}
– (void)createPool
{
self.view.backgroundColor = [UIColor whiteColor];
UIView *water = [[UIView alloc] initWithFrame:self.view.bounds];
water.backgroundColor = [UIColor colorWithRed:0 green:0.7 blue:1 alpha:0.9];
[self.view addSubview:water];
UIView *bartop = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)];
bartop.backgroundColor = [UIColor whiteColor];
bartop.layer.shadowRadius = 4.0;
bartop.layer.shadowOpacity = 1.0;
bartop.layer.shadowOffset = CGSizeMake(2, 4);
bartop.layer.shadowColor = [UIColor blackColor].CGColor;
[self.view addSubview:bartop];
for (int i=1; i<5; i++) {
UILabel *num = [[UILabel alloc] initWithFrame:CGRectMake(i*70 –30, 10, 40, 40)];
num.text = [NSString stringWithFormat:@”%d”, i];
num.textAlignment = 1;
[self.view addSubview:num];
UIView *lineA = [[UIView alloc] initWithFrame:CGRectMake(i*70 –15, 80, 10, 400)];
lineA.backgroundColor = [UIColor blackColor];
[self.view insertSubview:lineA belowSubview:water];
UIView *lineB = [[UIView alloc] initWithFrame:CGRectMake(i*70 –30, 80, 40, 10)];
lineB.backgroundColor = [UIColor blackColor];
[self.view insertSubview:lineB belowSubview:water];
}
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInView:self.view];
StickPerson *sp = [[StickPerson alloc] initWithFrame:CGRectMake(p.x – 35, 480, 80, 80)];
[self.view addSubview:sp];
[sp swim];
[UIView animateWithDuration:6.0 animations:^{
sp.center = CGPointMake(sp.center.x, 100);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.2 animations:^{
sp.alpha = 0;
} completion:^(BOOL finished) {
[sp removeFromSuperview];
}];
}];
}
– (void)startTimer
{
timer = [NSTimer scheduledTimerWithTimeInterval:5.0f/60.0f target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
– (void)tick:(NSTimer*)sender
{
for (UIView *v in self.view.subviews) {
if ([v isKindOfClass:[StickPerson class]]) {
UIView *white = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
white.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.6];
float x = arc4random() % 40 + 20;
float y = arc4random() % 10 + 70;
white.center = CGPointMake(x, y);
[v addSubview:white];
[UIView animateWithDuration:0.5 animations:^{
white.alpha = 0;
} completion:^(BOOL finished) {
[white removeFromSuperview];
}];
}
}
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end