• iOS动画中的物理知识应用之愤慨的小鸟-碰撞检測


    碰撞检測


    源码:https://github.com/Esdeath/collsion


    我相信搞iOS得人。多多少少都知道 弹球这个小游戏。

    撞击不同的点,就能改变其运动的轨迹。对于非常多人来说,假设不知道思路可能认为小球在屏幕中撞来撞去,碰到墙壁就改变运动方向似乎非常难实现。
    事实上这个仅仅须要一点点iOS画图基础和动画基础,还要一点点物理知识就OK了。


    这里写图片描写叙述

    1.速度和位移都是矢量

    在2D坐标系中,速度和位移都能分解成在x轴和y轴上的分量
    这里写图片描写叙述
    所以能够依据速度在Vx 和 Vy来描写叙述物体的运动情况。

    界面每次刷新单位时间。利用物体速度分量Vx与Vy的值来计算下次物体出现的位置:

    • 下次X轴坐标=Vx + 当前X轴坐标
    • 下次Y轴坐标=Vy + 当前Y轴坐标

    2.碰撞的速度模型

    这里写图片描写叙述
    假设物体撞到屏幕的底边,这时候物体在X轴上的方向不变。y轴方向上速度取反,同理撞到屏幕顶边也是。
    物理模型:

    • Vx = Vx
    • Vy = - Vy

    同理,假设物体撞到左边或者右边:

    • Vx = - Vx
    • Vy = Vy

    3.代码实现

    1.新建一个MRView加入到根View上。

    这里写图片描写叙述

    CADisplayLink是一个能让我们以和屏幕刷新率同样的频率将内容画到屏幕上的定时器。

    我们在应用中创建一个新的 CADisplayLink 对象,把它加入到一个runloop中,并给它提供一个 target 和selector 在屏幕刷新的时候调用。

    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    3.设置成员属性

    //小鸟图片
    @property (nonatomic,strong) UIImage *imageBird;
    //小鸟的位置
    @property (nonatomic,assign) CGFloat birdX;
    @property (nonatomic,assign) CGFloat birdY;
    //小鸟的速度
    @property (nonatomic,assign) CGFloat birdSpeedX;
    @property (nonatomic,assign) CGFloat birdSpeedY;

    4.初始化

    这里要注意,要设置从xib,storyboard,还有代码中初始化都必须引用到。

    CADisplayLink中调用setNeedsDisplay用来不停的重绘。

    //从xib或者storyboard初始化调用
    - (void)awakeFromNib
    {
        [self setUpBird];
    }
    //从代码初始化调用这个
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setUpBird];
        }
    
        return self;
    }
    
    -(void)setUpBird
    {
        self.backgroundColor = [UIColor blackColor];
    
        CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
        [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
        self.imageBird = [UIImage imageNamed:@"QQ20150714-1"];
        //设置初始位置
        self.birdX = 1;
        self.birdY = 1;
        //设置初始速度
        self.birdSpeedX = 5;
        self.birdSpeedY = 5;
    }

    5.画图

    主要是推断好。小鸟碰撞四周的时候速度反向

    - (void)drawRect:(CGRect)rect
    {
        [self.imageBird drawInRect:CGRectMake(self.birdX , self.birdY, IMAGEWIDTH, IMAGEHEIGHT)];
    
        if (self.birdX < 0 || (self.birdX > SCREENWIDTH - IMAGEWIDTH) )
        {
            self.birdSpeedX = -self.birdSpeedX;
        }
    
        if (self.birdY < 0 || (self.birdY > SCREENHEIGHT - IMAGEHEIGHT) )
        {
            self.birdSpeedY = -self.birdSpeedY;
        }
    
        self.birdX += self.birdSpeedX;
        self.birdY += self.birdSpeedY;
    }

    6.完整的代码

    这里MRView是self.view的子控件。

    全然覆盖self.view

    #import "MRView.h"
    
    #define SCREENHEIGHT   [UIScreen mainScreen].bounds.size.height
    #define SCREENWIDTH    [UIScreen mainScreen].bounds.size.width
    
    #define IMAGEWIDTH  50
    #define IMAGEHEIGHT 50
    
    @interface MRView()
    
    @property (nonatomic,strong) UIImage *imageBird;
    //小鸟的位置
    @property (nonatomic,assign) CGFloat birdX;
    @property (nonatomic,assign) CGFloat birdY;
    //小鸟的速度
    @property (nonatomic,assign) CGFloat birdSpeedX;
    @property (nonatomic,assign) CGFloat birdSpeedY;
    
    @end
    
    @implementation MRView
    - (void)awakeFromNib
    {
        [self setUpBird];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setUpBird];
        }
    
        return self;
    }
    
    -(void)setUpBird
    {
        self.backgroundColor = [UIColor blackColor];
    
        CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
        [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
        self.imageBird = [UIImage imageNamed:@"QQ20150714-1"];
        //设置初始位置
        self.birdX = 1;
        self.birdY = 1;
        //设置初始速度
        self.birdSpeedX = 5;
        self.birdSpeedY = 5;
    }
    
    - (void)drawRect:(CGRect)rect
    {
        [self.imageBird drawInRect:CGRectMake(self.birdX , self.birdY, IMAGEWIDTH, IMAGEHEIGHT)];
    
        if (self.birdX < 0 || (self.birdX > SCREENWIDTH - IMAGEWIDTH) )
        {
            self.birdSpeedX = -self.birdSpeedX;
        }
    
        if (self.birdY < 0 || (self.birdY > SCREENHEIGHT - IMAGEHEIGHT) )
        {
            self.birdSpeedY = -self.birdSpeedY;
        }
    
        self.birdX += self.birdSpeedX;
        self.birdY += self.birdSpeedY;
    }
    
    @end

    7.结果展示

    这里写图片描写叙述

    这里写图片描写叙述

    这里写图片描写叙述

    这里写图片描写叙述

    这里写图片描写叙述

  • 相关阅读:
    Ajax 传递json字符串到客户端时报 Internal server error
    Java 判断字符串的存储长度
    5个数组Array方法: indexOf、filter、forEach、map、reduce使用实例
    databales详解(一)
    JQuery总结
    《JavaScript 高级程序设计》总结
    ASP.NET MVC中controller和view相互传值的方式
    Jquery tmpl详解
    @section script{}的使用
    messager(消息窗口)
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6762410.html
Copyright © 2020-2023  润新知