在学习了
UIDynamic
之后突发奇想,能不能在iOS UIKit框架下,利用物理仿真API写出一个小游戏,于是尝试着写了一下,虽然还存在一些问题,但游戏整体已经实现,并且可以玩耍,步骤详解以后贴出,现将代码贴在这里,方便记录.
// ViewController.m
// FlayppyBird
//
// Created by wsh on 2017/1/26.
// Copyright © 2017年 wsh. All rights reserved.
//
#import "ViewController.h"
#import "AppDelegate.h"
#define KScreenWidth [UIScreen mainScreen].bounds.size.width
#define KScreenHeight [UIScreen mainScreen].bounds.size.height
#define KWidth bounds.size.width
#define KHeight bounds.size.height
@interface ViewController ()
@property (weak, nonatomic) UIImageView *bird;
@property (weak, nonatomic) IBOutlet UIImageView *cloud;
@property (weak, nonatomic) IBOutlet UIImageView *bottom;
/** <#注释#> */
@property (nonatomic, strong) NSTimer *timer1;
@property (nonatomic, strong) NSTimer *timer2;
@property (nonatomic, strong) NSTimer *timer3;
/** <#注释#> */
@property (nonatomic, weak) UILabel *label;
/** <#注释#> */
@property (nonatomic, strong) UIImageView *imageView2;
/** <#注释#> */
@property (nonatomic, strong) UIImageView *imageView;
/** <#注释#> */
@property (nonatomic, strong) UIImageView *huishou1;
/** <#注释#> */
@property (nonatomic, strong) UIImageView *huishou2;
/** bottom */
@property (nonatomic, strong) UIImageView *bottom1;
/** cloud */
@property (nonatomic, strong) UIImageView *cloud1;
/** 上部管子 */
@property (nonatomic, strong) UIImageView *topPiller;
/** 物理仿真器 */
@property (nonatomic, strong) UIDynamicAnimator *animater;
/** 记录点击的时间 */
@property (nonatomic, strong) NSDate *firstDate;
@property (nonatomic, strong) UIDynamicBehavior *beh;
/** <#注释#> */
@property (nonatomic, strong) CALayer *layer;
@end
static CGFloat pillerWidth = 100;
static NSInteger score = 0;
//难度,也就是两个水管中间距离
static NSInteger distance = 200;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBarHidden = YES;
self.cloud1 = self.cloud;
self.bottom1 = self.bottom;
[self setupBird];
[self setupPillers];
[self setupBg];
[self setupCloud];
[self setupScoreLabel];
}
#pragma mark -
#pragma mark - 小鸟
-(void)setupBird {
UIImageView *birdView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 68 * 0.8, 48 * 0.8)];
birdView.center = self.view.center;
//播放动画图片
UIImage *b1 = [UIImage imageNamed:@"bird-1"];
UIImage *b2 = [UIImage imageNamed:@"bird-2"];
UIImage *b3 = [UIImage imageNamed:@"bird-3"];
UIImage *b4 = [UIImage imageNamed:@"bird-4"];
birdView.animationImages = @[b1,b2,b3,b4];
//动画间隔
birdView.animationDuration = 1;
birdView.animationRepeatCount = MAXFLOAT;
//开始动画
[birdView startAnimating];
//添加
[self.view addSubview:birdView];
self.bird = birdView;
}
#pragma mark -
#pragma mark - 给小鸟加重力/推力
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//记录两次点击间隔
NSDate *currentTime = [NSDate date];
NSTimeInterval timeInterval = [currentTime timeIntervalSinceDate:self.firstDate];
//NSLog(@"%f",timeInterval);
self.firstDate = currentTime;
//创建物理仿真器
self.animater = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
//推动行为(持续推动)
UIPushBehavior *push = [[UIPushBehavior alloc]initWithItems:@[self.bird] mode:UIPushBehaviorModeInstantaneous];
//设置推动的方向和推力的大小
push.angle = - M_PI_2 ;
// push.magnitude = 10;
if (timeInterval) {
push.magnitude = 1.8 - timeInterval;
if (push.magnitude < 0 ) {
push.magnitude = 0;
}
}
//重力行为
UIGravityBehavior * gravity = [[UIGravityBehavior alloc]initWithItems:@[self.bird]];
gravity.magnitude = 1.5;
//碰撞行为
UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.bird]];
//collision.translatesReferenceBoundsIntoBoundary = YES;
collision.collisionMode = UICollisionBehaviorModeEverything;
//添加一条直线作为碰撞边界
CGFloat x = KScreenWidth;
CGFloat y = 480;
//NSLog(@"%f,%f",x,y);
[collision addBoundaryWithIdentifier:@"bottomID" fromPoint:CGPointMake(0, y) toPoint:CGPointMake(x, y)];
//动力行为项
UIDynamicItemBehavior *item = [[UIDynamicItemBehavior alloc]initWithItems:@[self.bird]];
item.elasticity = 0.5;
//item.friction = 0.5;
//添加行为
[self.animater addBehavior:push];
[self.animater addBehavior:collision];
[self.animater addBehavior:gravity];
[self.animater addBehavior:item];
collision.collisionDelegate = self;
//小鸡旋转
[UIView animateWithDuration:1 animations:^{
[self.bird setTransform:CGAffineTransformMakeRotation(M_PI_4)];
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 animations:^{
[self.bird setTransform:CGAffineTransformMakeRotation(- M_PI_4)];;
}];
}];
}
#pragma mark --
#pragma mark - 设置水管 以及动画
-(void)setupPillers{
// NSTimer *timer = [NSTimer timerWithTimeInterval:10 repeats:YES block:^(NSTimer * _Nonnull timer) {
//
// [self creatPiller];
//
//
//
// UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.bird,self.imageView]];
// UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.imageView.frame];
// [collision addBoundaryWithIdentifier:@"b1" forPath:path];
// [self.animater addBehavior:collision];
//
//
//
//
//
// [UIView animateKeyframesWithDuration:9 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
// [self.imageView setTransform:CGAffineTransformMakeTranslation(-KScreenWidth - 100 , 0)];
// self.layer = self.imageView.layer;
//
// } completion:^(BOOL finished) {
//
// nil;
// }];
//
// }];
// [[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
// [timer fire];
//
//
//
//
// [self creatPiller];
//
//
// NSTimer *timer1 = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) {
//
// CALayer *layer1 = [CALayer layer];
// layer1.frame = self.imageView.frame;
// NSLog(@"%f",layer1.frame.size.width);
// [self.view.layer addSublayer:layer1];
//
// CABasicAnimation *animation = [CABasicAnimation animation];
//
// animation.keyPath = @"position";
// animation.toValue = [NSValue valueWithCGPoint:CGPointMake(-pillerWidth, self.imageView.center.y)];
// animation.duration = 4;
// animation.repeatCount = MAXFLOAT;
// [layer1 addAnimation:animation forKey:nil];
// }];
// [[NSRunLoop mainRunLoop]addTimer:timer1 forMode:NSDefaultRunLoopMode];
// [timer1 fire];
// //使用核心动画
// CALayer *layer = self.imageView.layer;
// CALayer *layer2 = self.imageView2.layer;
// CABasicAnimation *animation = [CABasicAnimation animation];
//
// animation.keyPath = @"position";
// animation.toValue = [NSValue valueWithCGPoint:CGPointMake(-pillerWidth, self.imageView.center.y)];
// animation.duration = 4;
// animation.repeatCount = MAXFLOAT;
// [layer addAnimation:animation forKey:nil];
//
//
// CABasicAnimation *animation2 = [CABasicAnimation animation];
// animation2.keyPath = @"position";
// animation2.toValue = [NSValue valueWithCGPoint:CGPointMake(-pillerWidth, self.imageView2.center.y)];
// animation2.duration = 4;
// animation2.repeatCount = MAXFLOAT;
// [layer2 addAnimation:animation2 forKey:nil];
//
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [layer2 addAnimation:animation2 forKey:nil];
// [layer addAnimation:animation forKey:nil];
// });
//
// NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
//
//
// NSLog(@"%f",layer.presentationLayer.frame.origin.x);
// UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.bird]];
// UIBezierPath *path = [UIBezierPath bezierPathWithRect:layer.presentationLayer.frame];
// UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:layer2.presentationLayer.frame];
// [collision addBoundaryWithIdentifier:@"b1" forPath:path];
// [collision addBoundaryWithIdentifier:@"b2" forPath:path2];
//
// collision.collisionDelegate = self;
// [self.animater addBehavior:collision];
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self.animater removeBehavior:collision];
// });
// }];
//
// [[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
// [timer fire];
// //
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// for (UIImageView *pile in self.view.subviews) {
// if ((pile.bounds.size.width == pillerWidth) && pile.frame.origin.x < 0 ) {
// [pile removeFromSuperview];
// }
// }
//
// });
[self creatPiller];
NSTimer *timer2 = [NSTimer timerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
CGRect frame = self.imageView.frame;
CGRect frame2 = self.imageView2.frame;
frame.origin.x -= 1.5 ;
frame2.origin.x -= 1.5 ;
self.imageView.frame = frame;
self.imageView2.frame = frame2;
if (self.imageView.center.x < self.view.center.x) {
self.huishou1 = self.imageView;
self.huishou2 = self.imageView2;
self.label.text = [NSString stringWithFormat:@"%ld",++score];
[UIView animateWithDuration:(KScreenWidth / (2 * 1.5)) * 0.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.imageView setTransform:CGAffineTransformMakeTranslation(-(KScreenWidth / 2 + pillerWidth/2 ), 0)];
[self.imageView2 setTransform:CGAffineTransformMakeTranslation(-(KScreenWidth / 2 + pillerWidth/2 ), 0)];
} completion:^(BOOL finished) {
// [self.huishou2 removeFromSuperview];
// [self.huishou1 removeFromSuperview];
}];
[self creatPiller];
}
UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.bird]];
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.imageView.frame];
[collision addBoundaryWithIdentifier:@"b1" forPath:path];
UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:self.imageView2.frame];
[collision addBoundaryWithIdentifier:@"b2" forPath:path2];
collision.collisionDelegate = self;
[self.animater addBehavior:collision];
self.beh = collision;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.animater removeBehavior:collision];
});
}];
[[NSRunLoop mainRunLoop]addTimer:timer2 forMode:NSDefaultRunLoopMode];
[timer2 fire];
self.timer2 = timer2;
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
for (UIImageView *pile in self.view.subviews) {
if ((pile.bounds.size.width == pillerWidth) && pile.frame.origin.x < 0 ) {
[pile removeFromSuperview];
}
}
});
}
#pragma mark --
#pragma mark - 创建得分Label
-(void)setupScoreLabel {
UILabel *label = [[UILabel alloc]init];
label.text = [NSString stringWithFormat:@"%ld",score];
label.textColor = [UIColor redColor];
label.font = [UIFont systemFontOfSize:50];
label.center = CGPointMake(self.view.center.x, self.view.center.y - 200) ;
label.bounds = CGRectMake(0, 0, KScreenWidth, KScreenHeight);
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
self.label = label;
}
#pragma mark --
#pragma mark - 创建水管
-(void)creatPiller {
//添加图片在最右边
UIImageView * topPiller = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"PipeDown"]];
UIImageView * bottomPiller = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"PipeUp"]];
CGFloat TopPillerHeight = arc4random_uniform(200)+ 100;
topPiller.frame = CGRectMake(KScreenWidth, 0, pillerWidth, TopPillerHeight);
//
CGFloat downY = TopPillerHeight + distance;
CGFloat downH = 480 - downY;
bottomPiller.frame = CGRectMake(KScreenWidth, downY, pillerWidth, downH);
[self.view addSubview:bottomPiller];
[self.view addSubview:topPiller];
self.imageView = bottomPiller;
self.imageView2 = topPiller;
}
-(void)setupBg{
//self.bottom.hidden = YES;
UIImageView *bottom1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"land"]];
bottom1.frame = CGRectMake(KScreenWidth, 480, KScreenWidth, 187);
[self.view addSubview:bottom1];
//平移动画
[UIView animateWithDuration:8 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.bottom1 setTransform:CGAffineTransformTranslate(self.bottom1.transform, -KScreenWidth, 0)];
[bottom1 setTransform:CGAffineTransformMakeTranslation(- KScreenWidth, 0)];
} completion:^(BOOL finished) {
[self.bottom1 removeFromSuperview];
self.bottom1 = bottom1;
UIImageView *bottom2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"land"]];
bottom2.frame = CGRectMake(KScreenWidth, 480, KScreenWidth, 187);
[self.view addSubview:bottom2];
[UIView animateWithDuration:8 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.bottom1 setTransform:CGAffineTransformTranslate(self.bottom1.transform, -KScreenWidth, 0)];
[bottom2 setTransform:CGAffineTransformMakeTranslation(- KScreenWidth, 0)];
} completion:^(BOOL finished) {
[self.bottom1 removeFromSuperview];
self.bottom1 = bottom2;
[self setupBg];
}];
}];
}
-(void)setupCloud{
UIImageView *cloud = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"sky"]];
cloud.frame = CGRectMake(KScreenWidth, 265, KScreenWidth, 215);
[self.view insertSubview:cloud belowSubview:self.bird];
//平移动画
[UIView animateWithDuration:8 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.cloud1 setTransform:CGAffineTransformTranslate(self.cloud1.transform, -KScreenWidth, 0)];
[cloud setTransform:CGAffineTransformMakeTranslation(- KScreenWidth, 0)];
} completion:^(BOOL finished) {
[self.cloud1 removeFromSuperview];
self.cloud1 = cloud;
UIImageView *cloud2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"sky"]];
cloud2.frame = CGRectMake(KScreenWidth, 265, KScreenWidth, 215);
[self.view insertSubview:cloud2 belowSubview:self.bird];
[UIView animateWithDuration:8 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.cloud1 setTransform:CGAffineTransformTranslate(self.cloud1.transform, -KScreenWidth, 0)];
[cloud2 setTransform:CGAffineTransformMakeTranslation(- KScreenWidth, 0)];
} completion:^(BOOL finished) {
[self.cloud1 removeFromSuperview];
self.cloud1 = cloud2;
[self setupCloud];
}];
}];
}
#pragma mark --
#pragma mark - 碰撞检测
-(void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id)item withBoundaryIdentifier:(id)identifier atPoint:(CGPoint)p {
//self.bird.backgroundColor = [UIColor redColor];
self.label.text = [NSString stringWithFormat:@"0"];
[self.timer2 invalidate];
self.timer2 = nil;
for (UIImageView *pill in self.view.subviews) {
if (pill.bounds.size.width == pillerWidth) {
[pill performSelector:@selector(removeFromSuperview)];
}
}
// [self.animater removeAllBehaviors];
// self.animater = nil;
NSString *lala = [NSString stringWithFormat:@"您一共得了 %lu 分 ,再接再厉哦!",score];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"失败" message:lala preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *act1 = [UIAlertAction actionWithTitle:@"再来一局" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
score = 0 ;
[self.bird removeFromSuperview];
[self setupBird];
[self setupPillers];
//[self.animater removeBehavior:self.beh];
//self.animater = nil;
} ];
// [act1 setValue:green forKey:@"_titleTextColor"];
UIAlertAction *act2 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
[self exitApplication];
} ];
[alert addAction:act1];
[alert addAction:act2];
[self presentViewController:alert animated:YES completion:nil];
// UIViewController *vc = [[UIViewController alloc]init];
// UINavigationController *nac = [[UINavigationController alloc]initWithRootViewController:vc];
// vc.view.backgroundColor = [UIColor whiteColor];
// UILabel *label = [[UILabel alloc]init];
// label.text = [NSString stringWithFormat:@"您一共得了 %lu 分 ,再接再厉哦!",score];
// label.numberOfLines = 0;
// label.textColor = [UIColor redColor];
// label.font = [UIFont systemFontOfSize:50];
// label.center = CGPointMake(self.view.center.x, self.view.center.y - 200) ;
// label.bounds = CGRectMake(0, 0, KScreenWidth, KScreenHeight);
// label.textAlignment = NSTextAlignmentCenter;
// [vc.view addSubview:label];
// [self.navigationController pushViewController:vc animated:YES];
}
-(void)dealloc {
NSLog(@"销毁");
}
- (void)exitApplication {
AppDelegate *app = [UIApplication sharedApplication].delegate;
UIWindow *window = app.window;
[UIView animateWithDuration:1.0f animations:^{
window.alpha = 0;
window.frame = CGRectMake(0, window.bounds.size.width, 0, 0);
} completion:^(BOOL finished) {
exit(0);
}];
//exit(0);
}
@end