ひらがなの「さしすせそ」、カタカナの「サシスセソ」一緒はどれだ?というのを子供に覚えてもらうための単純なiPhoneアプリを作ってみます。さかなにはひらがなを書いておいて、魚をタッチするとカタカナが横から出てくるので、同じものを選びましょう。
動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。
ポイント
船、釣り人、釣り竿、魚はUIBezierPathをつかって、三角形、四角形の組み合わせで描いてみました。ゲームスタート時にランダムで魚にひらがなを表示するようにしています。
サンプルコード
#import “ViewController.h”
#import <QuartzCore/QuartzCore.h>
@interface ViewController () {
UIView *fish;
NSString *hiragana;
UIView *katakanaBox;
UIView *fisingRod;
CGPoint rodTop, rodGrip;
NSArray *hiraganaArr;
NSArray *katakanaArr;
}
@end
@implementation ViewController
– (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self createBackground];
[self createFishingRod];
[self createButton];
[self createKatakanaBox];
}
– (void)createBackground
{
//
// sea
//
UIView *sea = [[UIView alloc] initWithFrame:CGRectMake(0, 400, 320, 168)];
[self.view addSubview:sea];
UIBezierPath *wavePath = [UIBezierPath bezierPath];
[wavePath moveToPoint:CGPointMake(0, 0)];
for (int i=0; i<320; i++) {
float x = i * 1.0;
float y = 10 * sin(M_PI/60.0 * i);
[wavePath addLineToPoint:CGPointMake(x, y)];
}
[wavePath addLineToPoint:CGPointMake(320, 168)];
[wavePath addLineToPoint:CGPointMake(0, 168)];
[wavePath closePath];
CAShapeLayer *wavesl = [[CAShapeLayer alloc] init];
wavesl.fillColor = [self color:1].CGColor;
wavesl.path = wavePath.CGPath;
[sea.layer addSublayer:wavesl];
//
// ship
//
UIView *ship = [[UIView alloc] initWithFrame:CGRectMake(0, 320, 180, 100)];
[self.view insertSubview:ship belowSubview:sea];
UIBezierPath *shippath = [UIBezierPath bezierPath];
[shippath moveToPoint:CGPointMake(0, 0)];
[shippath addLineToPoint:CGPointMake(100/1.618, 0)];
[shippath addLineToPoint:CGPointMake(100/1.618, 100 – 100/1.618)];
[shippath addLineToPoint:CGPointMake(100, 100 – 100/1.618)];
[shippath addLineToPoint:CGPointMake(100/1.618, 100)];
[shippath addLineToPoint:CGPointMake(0, 100)];
[shippath closePath];
[shippath appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 40, 30)]];
CAShapeLayer *shipcl = [[CAShapeLayer alloc] init];
shipcl.fillColor = [self color:2].CGColor;
shipcl.path = shippath.CGPath;
shipcl.fillRule = kCAFillRuleEvenOdd;
[ship.layer addSublayer:shipcl];
// Angler(釣り人)
UIView *angler = [[UIView alloc] initWithFrame:CGRectMake(12, 14, 26, 26)];
[ship addSubview:angler];
UIBezierPath *anglerP = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 26, 13)];
[anglerP moveToPoint:CGPointMake(13, 8)];
[anglerP addLineToPoint:CGPointMake(26, 26)];
[anglerP addLineToPoint:CGPointMake(0, 26)];
[anglerP closePath];
CAShapeLayer *anglerCL = [[CAShapeLayer alloc] init];
anglerCL.fillColor = [self color:0].CGColor;
anglerCL.path = anglerP.CGPath;
[angler.layer addSublayer:anglerCL];
}
– (void)createFishingRod
{
rodTop = CGPointMake(220, 180);
rodGrip = CGPointMake(40, 360);
fisingRod = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:fisingRod];
CAShapeLayer *rodCL = [[CAShapeLayer alloc] init];
rodCL.fillColor = [self color:0].CGColor;
[fisingRod.layer addSublayer:rodCL];
[self updateFishingRod];
}
– (void)updateFishingRod
{
CGPoint cp = CGPointMake(100, 100);
UIBezierPath *rodP = [UIBezierPath bezierPath];
[rodP moveToPoint:rodGrip];
[rodP addQuadCurveToPoint:rodTop controlPoint:cp];
[rodP addLineToPoint:CGPointMake(rodTop.x, rodTop.y – 2)];
[rodP addQuadCurveToPoint:CGPointMake(rodGrip.x, rodGrip.y – 10) controlPoint:cp];
[rodP closePath];
[rodP appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(rodTop.x, rodTop.y, 1, 240)]];
CAShapeLayer *sl = [fisingRod.layer.sublayers objectAtIndex:0];
sl.path = rodP.CGPath;
}
– (void)createButton
{
// fish
fish = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, 70)];
fish.center = CGPointMake(rodTop.x, 450);
[self.view addSubview:fish];
UIBezierPath *fPath = [UIBezierPath bezierPath];
[fPath moveToPoint:CGPointMake(30, 0)];
[fPath addLineToPoint:CGPointMake(60, 30)];
[fPath addLineToPoint:CGPointMake(10, 70)];
[fPath addLineToPoint:CGPointMake(50, 70)];
[fPath addLineToPoint:CGPointMake(0, 30)];
[fPath closePath];
CAShapeLayer *fSlayer = [[CAShapeLayer alloc] init];
fSlayer.fillColor = [self color:3].CGColor;
fSlayer.path = fPath.CGPath;
[fish.layer addSublayer:fSlayer];
// hiragana
hiraganaArr = [@”さ し す せ そ“ componentsSeparatedByString:@” “];
hiragana = [hiraganaArr objectAtIndex:arc4random() % [hiraganaArr count]];
UILabel *hiraganaL = [[UILabel alloc] initWithFrame:CGRectMake(15, 15, 30, 30)];
hiraganaL.backgroundColor = [UIColor clearColor];
hiraganaL.text = hiragana;
hiraganaL.font = [UIFont boldSystemFontOfSize:30];
hiraganaL.textAlignment = NSTextAlignmentCenter;
hiraganaL.textColor = [self color:0];
[fish addSubview:hiraganaL];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hook)];
[fish addGestureRecognizer:tap];
}
– (void)hook
{
[UIView animateWithDuration:0.2 animations:^{
// down
rodTop = CGPointMake(rodTop.x, rodTop.y + 10);
[self updateFishingRod];
fish.transform = CGAffineTransformMakeTranslation(0, 20);
} completion:^(BOOL finished) {
// jump
rodTop = CGPointMake(rodTop.x, rodTop.y – 10);
[self updateFishingRod];
[UIView animateWithDuration:0.5 animations:^{
CGAffineTransform t = CGAffineTransformMakeTranslation(-50, –350);
fish.transform = CGAffineTransformRotate(t, M_PI);
katakanaBox.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
// fall
[UIView animateWithDuration:6.0 animations:^{
fish.transform = CGAffineTransformMakeTranslation(0, 100);
} completion:^(BOOL finished) {
// restart
[self restart];
}];
}];
}];
}
– (void)createKatakanaBox
{
katakanaBox = [[UIView alloc] initWithFrame:CGRectMake(20, 440, 280, 80)];
katakanaBox.backgroundColor = [self color:4];
[self.view addSubview:katakanaBox];
katakanaArr = [@”サ シ ス セ ソ“ componentsSeparatedByString:@” “];
for (int i=0; i<5; i++) {
UILabel *katakana = [[UILabel alloc] initWithFrame:CGRectMake(50 * i + 15 , 15, 50, 50)];
katakana.layer.cornerRadius = 25;
katakana.text = [katakanaArr objectAtIndex:i];
katakana.font = [UIFont boldSystemFontOfSize:30];
katakana.textAlignment = NSTextAlignmentCenter;
[katakanaBox addSubview:katakana];
katakana.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(checkfish:)];
[katakana addGestureRecognizer:tap];
}
katakanaBox.transform = CGAffineTransformMakeTranslation(-400, 0);
}
– (void)checkfish:(UITapGestureRecognizer*)gr
{
gr.view.backgroundColor = [self color:3];
[self performSelector:@selector(removeHighLight:) withObject:gr.view afterDelay:0.3];
UILabel *katakanaL = (UILabel*)gr.view;
NSString *katakana = katakanaL.text;
int hiraganaIndex = [hiraganaArr indexOfObject:hiragana];
int katakanaIndex = [katakanaArr indexOfObject:katakana];
if (hiraganaIndex == katakanaIndex) {
UILabel *ok = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
ok.text = @”OK”;
ok.textColor = [self color:1];
ok.font = [UIFont boldSystemFontOfSize:50];
ok.center = CGPointMake(160, 200);
ok.backgroundColor = [UIColor clearColor];
ok.alpha = 0;
[self.view addSubview:ok];
[UIView animateWithDuration:1.0 animations:^{
fish.center = CGPointMake(-200, –200);
ok.alpha = 0.8;
} completion:^(BOOL finished) {
// restart
[self performSelector:@selector(restart) withObject:nil afterDelay:0.5];
}];
}
}
– (void)restart
{
self.view.layer.sublayers = nil;
fish = nil;
katakanaBox = nil;
fisingRod = nil;
hiraganaArr = nil;
katakanaArr = nil;
[self createBackground];
[self createFishingRod];
[self createButton];
[self createKatakanaBox];
}
– (void)removeHighLight:(UIView *)v
{
v.backgroundColor = [UIColor whiteColor];
}
#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(0x2E2D33);
case 1:
return UIColorHex(0x40E2E1);
case 2:
return UIColorHex(0x90CC3A);
case 3:
return UIColorHex(0xD13351);
case 4:
return UIColorHex(0xEBC434);
default:
break;
}
return nil;
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end