iOS動畫中的物理知識應用之憤怒的小鳥-碰撞檢測,ios碰撞檢測
碰撞檢測
原始碼:https://github.com/Esdeath/07-13-
我相信搞iOS得人,多多少少都知道 彈球這個小遊戲。撞擊不同的點,就能改變其運動的軌跡。對於很多人來說,如果不知道思路可能覺得小球在螢幕中撞來撞去,碰到牆壁就改變運動方向似乎很難實現。
其實這個只需要一點點iOS繪圖基礎和動畫基礎,還要一點點物理知識就OK了。
1.速度和位移都是向量
在2D座標系中,速度和位移都能分解成在x軸和y軸上的分量
所以可以根據速度在Vx 和 Vy來描述物體的運動情況。介面每次重新整理單位時間,利用物體速度分量Vx與Vy的值來計算下次物體出現的位置:
- 下次X軸座標=Vx + 當前X軸座標
- 下次Y軸座標=Vy + 當前Y軸座標
2.碰撞的速度模型
假設物體撞到螢幕的底邊,這時候物體在X軸上的方向不變,y軸方向上速度取反,同理撞到螢幕頂邊也是。
物理模型:
同理,如果物體撞到左邊或者右邊:
3.代碼實現1.建立一個MRView添加到根View上。
2.添加CADisplayLink
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.結果展示
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。