iOSアニメの実戦釣り小ゲームの実例コード
前言
最近は釣りゲームを書いていますが、自分は普段ゲームをしたことがありません。このようなゲームはcocos 2 dなどで実現すると思っていましたが、実はアニメは素晴らしい効果を実現することができます。まず効果図を見てください。
コンダクタンス
まず、私達は思考図を見てみます。このゲームは主に4つの大きな塊に分けられています。その中で魚の実現が一番複雑です。
コンダクタンス
プロジェクト構造
準備工作
まず必要な図を用意します。この魚は写真のセットです。画像のサイズが固定されていて、フレームごとに位置が変化しています。だから上下に動く魚のように見えます。
枚の写真
フックモジュール
アニメーションを振る
フックの振り幅は[M_]です。PI/4.0、-M_PI/4.0(垂直下は0度、時計回りは正)、ここではタイマを利用して角度の変更を行い、タイマー用のCADisplayLinkは画面のリフレッシュ率と一致するタイマーです。カードがないと、毎秒の更新回数は60回、本Demoの多くのタイムマシンはすべてCADisplayLinkです。以下はフックの主なコードです。(ポイント:1、アンカーポイントを設定してから、frameをリセットします。2、角度を変えて、3、回転)。ここでblockを定義して、アングルをFishingViewインターフェースに戻して、釣り針を池に落とす位置を計算します。
魚のモジュールはUImageViewから継承されているクラスです。
魚のモジュールは3種類の初期化方式を提供しています。釣りができる魚、釣れない魚(使わなくてもいいです)、釣れた魚の3種類があります。
魚の移動方法は二つあります。エニュメレート・定義を使って、左から右へ、右から左へ。
魚の種類は6種類ありますが、列挙で定義されています。
ダイナミック魚のロード方法
提供している写真は全部頭が左にあるので、左から右に行くとイメージが反転します。
魚が釣れるかどうかは通知で情報を伝えるもので、釣りができます。釣りができない状態です。
釣りができます。釣り針が池に沈むと釣りの知らせを受けます。今は釣りができます。釣り針の確率などから釣り糸がかかると判断したら、魚を回転させてから、釣りアニメーションを実行します。アニメーションが終わったら、プロキシを実行します。
釣られた魚の初期化方法
これはインターフェイスを実現しました。VCに書いていますが、後で抽出できます。すべて抽出しました。呼び出し時はとても簡単です。正常なViewのように初期化してからメインViewに追加すればいいです。vieDidDisplaarで資源を解放してください。
釣り針を初期化する
フックの振れ角度はプロキシによって本インターフェースに伝えられます。
アニメが始まって、総金貨が10個減った。
インターネット動画が開始されました。釣り糸不可のお知らせを送ります。釣り針状態は釣り糸状態です。
魚を捕まえた場合(魚モジュールの代行が実行するかどうかを判断します)、金貨アニメーションと増分アニメーションを実行します。
フック動画が終了したら、魚釣りができるという通知を魚モジュールに送り、フック座標を伝えて、釣り針のタイマーをオンにします。
ネットアニメーションが終わったら、フックの状態を変えて、いくつかのViewを削除して、フックは引き続き振ります。
釣られた魚を作って、釣り針にかけると、釣り針と一緒に釣りアニメーションができます。
魚の背景を簡単に作成してクリックジェスチャーを追加します。
3.魚を初期化する
forサイクルを通して、いくつかの魚を作ることができます。
タイマーが破壊されないと循環参照になりますので、メモリが漏れてしまいます。手動で彼を除去しなければなりません。また、アニメーションは代理を実行して、終了後は終了位置に留まります。また、リリースされないので、手動で資源を解放します。
これで、本ゲームはもう完成しました。書くことが多くて、混乱しています。何か悪いところがあったら、叱正を歓迎します。皆さんに助けてほしいです。本demo住所【https://github.com/Ccalary/FishingGame】
最近は釣りゲームを書いていますが、自分は普段ゲームをしたことがありません。このようなゲームはcocos 2 dなどで実現すると思っていましたが、実はアニメは素晴らしい効果を実現することができます。まず効果図を見てください。
コンダクタンス
まず、私達は思考図を見てみます。このゲームは主に4つの大きな塊に分けられています。その中で魚の実現が一番複雑です。
コンダクタンス
プロジェクト構造
準備工作
まず必要な図を用意します。この魚は写真のセットです。画像のサイズが固定されていて、フレームごとに位置が変化しています。だから上下に動く魚のように見えます。
枚の写真
フックモジュール
アニメーションを振る
フックの振り幅は[M_]です。PI/4.0、-M_PI/4.0(垂直下は0度、時計回りは正)、ここではタイマを利用して角度の変更を行い、タイマー用のCADisplayLinkは画面のリフレッシュ率と一致するタイマーです。カードがないと、毎秒の更新回数は60回、本Demoの多くのタイムマシンはすべてCADisplayLinkです。以下はフックの主なコードです。(ポイント:1、アンカーポイントを設定してから、frameをリセットします。2、角度を変えて、3、回転)。ここでblockを定義して、アングルをFishingViewインターフェースに戻して、釣り針を池に落とす位置を計算します。
@property (nonatomic, strong) CADisplayLink *linkTimer;
@property (nonatomic, assign) BOOL isReduce;//
@property (nonatomic, assign) CGFloat angle;//
- (void)initView{
[self setAnchorPoint:CGPointMake(0.5, 0) forView:self];
UIImageView *gouImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - 35 , 30, 35)];
gouImageView.image = [UIImage imageNamed:@"fish_catcher_tong"];
[self addSubview:gouImageView];
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake((self.frame.size.width - 3)/2.0, 0, 3, self.frame.size.height - 35)];
lineView.backgroundColor = HEXCOLOR(0x9e664a);
[self addSubview:lineView];
//
_linkTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(hookMove)];
// link
[_linkTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
// frame
- (void) setAnchorPoint:(CGPoint)anchorpoint forView:(UIView *)view{
CGRect oldFrame = view.frame;
view.layer.anchorPoint = anchorpoint;
view.frame = oldFrame;
}
#pragma mark -
- (void)hookMove{
if (self.isReduce){
_angle-=1.8*cos(1.5*_angle)*0.01;// , cos ,
if (_angle < -M_PI/180*45){
self.isReduce = NO;
}
}else {
_angle+=1.8*cos(1.5*_angle)*0.01;
if (_angle > M_PI/180*45){
self.isReduce = YES;
}
}
if (self.angleBlock){
self.angleBlock(_angle);
}
// DLog(@" %f",_angle);
//
self.transform = CGAffineTransformMakeRotation(_angle);
}
魚のモジュール魚のモジュールはUImageViewから継承されているクラスです。
魚のモジュールは3種類の初期化方式を提供しています。釣りができる魚、釣れない魚(使わなくてもいいです)、釣れた魚の3種類があります。
魚の移動方法は二つあります。エニュメレート・定義を使って、左から右へ、右から左へ。
魚の種類は6種類ありますが、列挙で定義されています。
typedef NS_ENUM(NSInteger, FishModelImageViewType){
FishModelImageViewTypeXHY = 0, //
FishModelImageViewTypeSBY = 1, //
FishModelImageViewTypeHSY = 2, //
FishModelImageViewTypeBWY = 3, //
FishModelImageViewTypeSHY = 4, //
FishModelImageViewTypeSY = 5, //
};
釣った魚の代理店を提供します。
FishModelImageViewDelegate
// - -
- (void)catchTheFishWithType:(FishModelImageViewType)type
andDirection:(FishModelImageViewDirection)dir
andWinCount:(int)count;
1、ダイナミックな魚ダイナミック魚のロード方法
// UIImageView
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 55, 55)];
// , xhy1,xhy2,xhy3..., , ,duration
imageView.image = [UIImage animatedImageNamed:@"xhy" duration:1];
[self.view addSubview:imageView];
初期化は魚の大きさによって動きの速度が違っていますので、アニメの時とは違っています。
// git
- (void)initViewWithType:(FishModelImageViewType)type andDuration:(double)time{
self.fishType = type;
switch (type) {
case FishModelImageViewTypeXHY://
self.duration = 6.0;
self.frame = CGRectMake(-100, 0, 35, 40); //
self.image = [UIImage animatedImageNamed:@"xhy" duration:time];
break;
case FishModelImageViewTypeSBY://
self.duration = 7.0;
self.frame = CGRectMake(-100, 0, 50, 50);
self.image = [UIImage animatedImageNamed:@"sby" duration:time];
break;
case FishModelImageViewTypeHSY://
self.duration = 8.0;
self.frame = CGRectMake(-100, 0, 50, 40);
self.image = [UIImage animatedImageNamed:@"hsy" duration:time];
break;
case FishModelImageViewTypeBWY://
self.duration = 8.5;
self.frame = CGRectMake(-100, 0, 65, 53);
self.image = [UIImage animatedImageNamed:@"bwy" duration:time];
break;
case FishModelImageViewTypeSHY://
self.duration = 9.0;
self.frame = CGRectMake(-100, 0, 55, 55);
self.image = [UIImage animatedImageNamed:@"shy" duration:time];
break;
case FishModelImageViewTypeSY://
self.duration = 11.0;
self.frame = CGRectMake(-200, 0, 145, 90);
self.image = [UIImage animatedImageNamed:@"sy" duration:time];
break;
}
}
2、動く魚提供している写真は全部頭が左にあるので、左から右に行くとイメージが反転します。
魚が釣れるかどうかは通知で情報を伝えるもので、釣りができます。釣りができない状態です。
釣りができます。釣り針が池に沈むと釣りの知らせを受けます。今は釣りができます。釣り針の確率などから釣り糸がかかると判断したら、魚を回転させてから、釣りアニメーションを実行します。アニメーションが終わったら、プロキシを実行します。
//
- (instancetype)initCanCatchFishWithType:(FishModelImageViewType)type andDirection:(FishModelImageViewDirection)dir{
if (self = [super init]){
self.direction = dir;
[self initViewWithType:type andDuration:1];
if (dir == FishModelImageViewFromLeft){// ,
self.transform = CGAffineTransformMakeScale(-1, 1); //
}
[self initFishView];
}
return self;
}
#pragma mark - ( )
- (void)initFishView{
//
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationCanCatch:) name:NotificationFishHookStop object:nil];
//
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationCannotCatch) name:NotificationFishHookMove object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeTimer) name:NotificationRemoveFishModelTimer object:nil];
//
_linkTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(fishMove)];
// link( )
[_linkTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
_offsetX = ScreenWidth;
_offsetY = 100;
_fishWidth = self.frame.size.width;
//Y
_randomRange = (int) (YuTangHeight - self.frame.size.height - OffSetYRange);
self.speed = (ScreenWidth + _fishWidth)/self.duration;//
self.changeX = self.speed/60.0;// 60
DLog(@" :%f, :%f", self.speed,self.changeX);
}
魚移動動画とインターネット動画
- (void)fishMove{
if (self.direction == FishModelImageViewFromLeft){//
if (_offsetX > ScreenWidth + _fishWidth){
_offsetY = arc4random()%_randomRange + OffSetYRange;
_offsetX = - _fishWidth - _offsetY;
}
_offsetX+=self.changeX;
self.frame = [self resetFrameOrigin:CGPointMake(_offsetX, _offsetY)];
if ([self fishCanBeCatchedWithOffsetX:_offsetX + _fishWidth]){
NSLog(@" :%ld",(long)self.fishType);
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, -1, 1);//
transform = CGAffineTransformRotate(transform, M_PI_2);// 90
self.transform = transform;
self.frame = [self resetFrameOrigin:CGPointMake(ScreenWidth*2, 0)];
[self fishCatchedMoveUpWithOffsetX:_offsetX + _fishWidth];
_offsetX = ScreenWidth + _fishWidth + 1;//
_linkTimer.paused = YES;//
}
}else {//
if (_offsetX < -_fishWidth){
_offsetY = arc4random()%_randomRange + OffSetYRange;
_offsetX = ScreenWidth + _offsetY;
}
_offsetX-=self.changeX;
self.frame = [self resetFrameOrigin:CGPointMake(_offsetX, _offsetY)];
if ([self fishCanBeCatchedWithOffsetX:_offsetX]){
NSLog(@" :%ld",(long)self.fishType);
self.transform = CGAffineTransformMakeRotation(M_PI_2);
self.frame = [self resetFrameOrigin:CGPointMake(ScreenWidth*2, 0)];
[self fishCatchedMoveUpWithOffsetX:_offsetX];
_offsetX = -_fishWidth-1;//
_linkTimer.paused = YES;//
}
}
}
魚がかかる確率と勝つ金貨の個数
// ( )
- (BOOL)fishCanBeCatchedWithOffsetX:(CGFloat)offsetX{
if (!self.isCanCatch) return NO;
if (fabs(offsetX - self.hookX) > self.changeX/2.0) return NO; //
int random = arc4random()%100; //[0,99]
DLog(@"random:%d", random);
switch (self.fishType) {
case FishModelImageViewTypeXHY:// 80% 2
if (random < 80){
self.moneyCount = 2;
return YES;
}
break;
case FishModelImageViewTypeSBY:// 50% 5
if (random < 50) {
self.moneyCount = 5;
return YES;
}
break;
case FishModelImageViewTypeHSY:// 30% 10
if (random < 30) {
self.moneyCount = 10;
return YES;
}
break;
case FishModelImageViewTypeBWY:// 15% 20
if (random < 15) {
self.moneyCount = 20;
return YES;
}
break;
case FishModelImageViewTypeSHY:// 5% 50
if (random < 5) {
self.moneyCount = 50;
return YES;
}
break;
case FishModelImageViewTypeSY:// 1% 100
if (random < 1) {
self.moneyCount = 100;
return YES;
}
break;
}
self.moneyCount = 0;
return NO;
}
3.釣られた魚釣られた魚の初期化方法
//
- (instancetype)initCatchedFishWithType:(FishModelImageViewType)type andDirection:(FishModelImageViewDirection)dir{
if (self = [super init]){
self.direction = dir;
[self initViewWithType:type andDuration:0.5];
// x,y , 30 ,85
self.x = (30 - self.width)/2.0;
self.y = 85 - 6;
if (dir == FishModelImageViewFromLeft){// ,
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, -1, 1);//
transform = CGAffineTransformRotate(transform, M_PI_2);// 90
self.transform = transform;
}else {
self.transform = CGAffineTransformMakeRotation(M_PI_2);
}
}
return self;
}
魚が捕まると、食いアニメーションが実行されます。
//
- (void)fishCatchedMoveUpWithOffsetX:(CGFloat) offsetX{
// 45
//
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"position"];
ani.duration = 0.7;
if (self.fishType == FishModelImageViewTypeSY){// ,
ani.fromValue = [NSValue valueWithCGPoint:CGPointMake(offsetX,45 + _fishWidth/2.0)];
ani.toValue = [NSValue valueWithCGPoint:CGPointMake(_hookX, 45 + _fishWidth/2.0)];
}else {
ani.fromValue = [NSValue valueWithCGPoint:CGPointMake(offsetX, (_offsetY < 60) ? 45 + _fishWidth/2.0 : _offsetY)];//
ani.toValue = [NSValue valueWithCGPoint:CGPointMake(_hookX, 45 + _fishWidth/2.0)];
}
ani.delegate = self;
//
[ani setValue:kFishCatchedMoveUpValue forKey:kFishCatchedMoveUpKey];
[self.layer addAnimation:ani forKey:kFishCatchedMoveUpKey];
}
魚の上流動画が終わったら、反転した魚をリセットして、代理で釣った魚を代理で渡すようにします。
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (flag){
if ([[anim valueForKey:kFishCatchedMoveUpKey] isEqualToString:kFishCatchedMoveUpValue]){//
if (self.direction == FishModelImageViewFromLeft){
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, -1, 1);//
transform = CGAffineTransformRotate(transform, 0);// 90
self.transform = transform;
}else {
self.transform = CGAffineTransformMakeRotation(0);
}
if ([self.delegate respondsToSelector:@selector(catchTheFishWithType:andDirection:andWinCount:)]){
[self.delegate catchTheFishWithType:self.fishType andDirection:self.direction andWinCount:self.moneyCount];
}
}
}
}
釣りViewこれはインターフェイスを実現しました。VCに書いていますが、後で抽出できます。すべて抽出しました。呼び出し時はとても簡単です。正常なViewのように初期化してからメインViewに追加すればいいです。vieDidDisplaarで資源を解放してください。
- (void)viewDidLoad {
[super viewDidLoad];
_fishView = [[FishingView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_fishView];
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[_fishView removeFishViewResource];
}
1.釣り針を初期化する釣り針を初期化する
フックの振れ角度はプロキシによって本インターフェースに伝えられます。
#pragma mark -
- (void)initHookView{
_fishHookView = [[FishHookView alloc] initWithFrame:CGRectMake((ScreenWidth - 30)/2.0, 5, 30, 85)];
__weak typeof (self) weakSelf = self;
_fishHookView.angleBlock = ^(CGFloat angle) {
weakSelf.angle = angle;
};
[self addSubview:_fishHookView];
UIImageView *yuGanImageView = [[UIImageView alloc] initWithFrame:CGRectMake(ScreenWidth/2.0 - 2, 0, ScreenWidth/2.0, 50)];
yuGanImageView.image = [UIImage imageNamed:@"fish_gan_tong"];
[self addSubview:yuGanImageView];
}
フックアニメーション:魚の池をクリックしてジェスチャーを追加しました。クリックして釣り針の動きを実行して、釣り針の動きを一時停止します。動画が終わったら、高速魚のモジュールが引っかかることができます。そして釣り針の底の中心座標を過去に伝えます。釣り糸はCAShape Layerで描いて、strook Endアニメーションを実行します。
//
- (void)fishBtnAction{
if (self.fishHookState != FishHookStateShake) return; //
[self.fishHookView hookTimerPause];//
double degree = _angle*180/M_PI;//
double rate = tan(_angle);//
DLog(@"degree:%f---rate:%f",degree,rate);
// x , , y
_lineOffsetX = ScreenWidth/2.0 - (FishLineHeigth)*rate;
// xy
_hookBottomX = ScreenWidth/2.0 - (FishLineHeigth + FishHookHeight)*rate;
_hookBottomY = FishLineHeigth + FishHookHeight;
//
double aniDuration = [self hookOutOfRiver] ? 0.5 : 1;
//
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(ScreenWidth/2.0 ,5)];
[path addLineToPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
//
_linePathLayer = [CAShapeLayer layer];
_linePathLayer.frame = self.bounds;
_linePathLayer.path = path.CGPath;
_linePathLayer.strokeColor = [HEXCOLOR(0x9e664a) CGColor];
_linePathLayer.fillColor = nil;
_linePathLayer.lineWidth = 3.0f;
_linePathLayer.lineJoin = kCALineJoinBevel;
[self.layer addSublayer:_linePathLayer];
//
CAKeyframeAnimation *ani = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
ani.duration = aniDuration;
ani.values = @[@0,@0.8,@1];
ani.keyTimes = @[@0,@0.6,@1];
ani.delegate = self;
[ani setValue:kLineDownAnimationValue forKey:kLineDownAnimationKey];
[_linePathLayer addAnimation:ani forKey:kLineDownAnimationKey];
//
_hookAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//
CGFloat tempOffsetX = ScreenWidth/2.0 - (FishLineHeigth*0.8)*rate;
NSValue *p1 = [NSValue valueWithCGPoint:CGPointMake(ScreenWidth/2.0 ,5)];
NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(tempOffsetX, FishLineHeigth*0.8)];
NSValue *p3 = [NSValue valueWithCGPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
_hookAnimation.duration = aniDuration;
_hookAnimation.values = @[p1,p2,p3];
_hookAnimation.keyTimes = @[@0,@0.7,@1];//
//
_hookAnimation.removedOnCompletion = NO;
_hookAnimation.fillMode=kCAFillModeForwards;
[_fishHookView.layer addAnimation:_hookAnimation forKey:@"goukey"];
}
釣り動作:フック動画が終了したらタイマーが開き、この方法を実行します。カウントダウンは最後の一秒の時に魚がかからないようにします。タイマーが0の時に魚釣り不可のお知らせを送ります。魚モジュールが釣れなくなりました。そして、インターネット動画を実行します。
//
- (void)hookStop:(NSTimer *)timer{
_stopDuration-=1;
//
if (_stopDuration == 1){
//
self.fishHookState = FishHookStateUp;
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationFishHookMove object:nil];
}
if (_stopDuration <= 0){
//
[timer setFireDate:[NSDate distantFuture]];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
[path addLineToPoint:CGPointMake(ScreenWidth/2.0 ,5)];
_linePathLayer.path = path.CGPath;
//
double aniDuration = [self hookOutOfRiver] ? 0.5 : 1;
//
CABasicAnimation *ani = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
ani.duration = aniDuration;
ani.fromValue = [NSNumber numberWithFloat:0];
ani.toValue = [NSNumber numberWithFloat:1];
ani.delegate = self;
ani.removedOnCompletion = NO;
ani.fillMode=kCAFillModeForwards;
[ani setValue:kLineUpAnimationValue forKey:kLineUpAnimationKey];
[_linePathLayer addAnimation:ani forKey:kLineUpAnimationKey];
[_fishHookView.layer removeAllAnimations];
NSValue *p1 = [NSValue valueWithCGPoint:CGPointMake(ScreenWidth/2.0 ,5)];
NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(_lineOffsetX, FishLineHeigth)];
_hookAnimation.duration = aniDuration;
_hookAnimation.values = @[p2,p1];
_hookAnimation.keyTimes = @[@0,@1];
[_fishHookView.layer addAnimation:_hookAnimation forKey:@"goukey"];
}
}
金貨アニメ&増分アニメアニメが始まって、総金貨が10個減った。
インターネット動画が開始されました。釣り糸不可のお知らせを送ります。釣り針状態は釣り糸状態です。
魚を捕まえた場合(魚モジュールの代行が実行するかどうかを判断します)、金貨アニメーションと増分アニメーションを実行します。
フック動画が終了したら、魚釣りができるという通知を魚モジュールに送り、フック座標を伝えて、釣り針のタイマーをオンにします。
ネットアニメーションが終わったら、フックの状態を変えて、いくつかのViewを削除して、フックは引き続き振ります。
#pragma mark - CAAnimationDelegate
//
- (void)animationDidStart:(CAAnimation *)anim{
//
if ([[anim valueForKey:kLineDownAnimationKey] isEqualToString:kLineDownAnimationValue]){
self.fishHookState = FishHookStateDown;//
//
self.moneyLabel.text = [NSString stringWithFormat:@"%d", _totalMoney-=10];
self.winMoney = 0;
}else if ([[anim valueForKey:kLineUpAnimationKey] isEqualToString:kLineUpAnimationValue]){//
self.fishHookState = FishHookStateUp;//
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationFishHookMove object:nil];
}
if (self.isCatched){//
HHShootButton *button = [[HHShootButton alloc] initWithFrame:CGRectMake(_lineOffsetX, 0, 10, 10) andEndPoint:CGPointMake(10, 200)];
button.setting.iconImage = [UIImage imageNamed:@"coin"];
button.setting.animationType = ShootButtonAnimationTypeLine;
[self.bgImageView addSubview:button];
[self bringSubviewToFront:button];
[button startAnimation];
HHWinMoneyLabel *winLabel = [[HHWinMoneyLabel alloc] initWithFrame:CGRectMake(_lineOffsetX - 100/2, ScreenFullHeight - FishSeaHeight, 100, 30)];
winLabel.text = [NSString stringWithFormat:@"+%d",_winMoney];
[self addSubview:winLabel];
self.isCatched = !self.isCatched;
//
self.moneyLabel.text = [NSString stringWithFormat:@"%d", _totalMoney+=self.winMoney];
}
}
//
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (flag){
if ([[anim valueForKey:kLineDownAnimationKey] isEqualToString:kLineDownAnimationValue]){//
self.fishHookState = FishHookStateStop;//
//
NSDictionary *dic = @{@"offsetX":[NSString stringWithFormat:@"%.2f",_hookBottomX],@"offsetY":[NSString stringWithFormat:@"%.2f",_hookBottomY]};
// ,
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationFishHookStop object:nil userInfo:dic];
_stopDuration = [self hookOutOfRiver] ? 1 : arc4random()%3 + 3; // [3,5), 1s
//
[_fishTimer setFireDate:[NSDate distantPast]];
}else if ([[anim valueForKey:kLineUpAnimationKey] isEqualToString:kLineUpAnimationValue]){//
self.fishHookState = FishHookStateShake;//
[_linePathLayer removeFromSuperlayer];
[_fishHookView hoolTimerGoOn];//
_catchedHeight = 0;
//
[self removeTheCatchedFishes];
}
}
}
魚モジュールの代理方法釣られた魚を作って、釣り針にかけると、釣り針と一緒に釣りアニメーションができます。
#pragma mark - FishModelImageViewDelegate
- (void)catchTheFishWithType:(FishModelImageViewType)type andDirection:(FishModelImageViewDirection)dir andWinCount:(int)count{
self.isCatched = YES;
FishModelImageView *fishImageView = [[FishModelImageView alloc] initCatchedFishWithType:type andDirection:dir];
[self.fishHookView addSubview:fishImageView];
fishImageView.y = fishImageView.y + _catchedHeight;
_catchedHeight += 8;// y
//
self.winMoney += count;
}
2.池を初期化する魚の背景を簡単に作成してクリックジェスチャーを追加します。
3.魚を初期化する
forサイクルを通して、いくつかの魚を作ることができます。
//
for (int i = 0; i < 8; i++){
FishModelImageView *model1 = [[FishModelImageView alloc] initCanCatchFishWithType:FishModelImageViewTypeXHY andDirection: (i%2 == 0) ? FishModelImageViewFromRight : FishModelImageViewFromLeft];
model1.delegate = self;
[self.bgImageView addSubview:model1];
}
4.リソースの削除タイマーが破壊されないと循環参照になりますので、メモリが漏れてしまいます。手動で彼を除去しなければなりません。また、アニメーションは代理を実行して、終了後は終了位置に留まります。また、リリースされないので、手動で資源を解放します。
- (void)removeFishViewResource{
//
_linePathLayer = nil;
//
[_fishTimer invalidate];
_fishTimer = nil;
//
[self.fishHookView hoolTimerInvalidate];
//
[[NSNotificationCenter defaultCenter] postNotificationName:NotificationRemoveFishModelTimer object:nil];
}
締め括りをつけるこれで、本ゲームはもう完成しました。書くことが多くて、混乱しています。何か悪いところがあったら、叱正を歓迎します。皆さんに助けてほしいです。本demo住所【https://github.com/Ccalary/FishingGame】