iOS 簡(jiǎn)單的操作桿旋轉(zhuǎn)實(shí)現(xiàn)示例詳解
一、效果實(shí)現(xiàn)
簡(jiǎn)單實(shí)現(xiàn)了一個(gè)消滅病毒的小效果,畫面略顯粗糙,多多見諒
控制球復(fù)位
二、操作桿實(shí)現(xiàn)
實(shí)現(xiàn)拖動(dòng)小球,獲取當(dāng)前小球的旋轉(zhuǎn)方向,將旋轉(zhuǎn)的方向傳遞出去,旋轉(zhuǎn)“坦克”進(jìn)行攻擊“病毒”。
#import "DirectionOptionView.h" @interface DirectionOptionView() //方向指示器滾珠 @property(nonatomic,strong) UIView * ball; @end @implementation DirectionOptionView - (instancetype)initWithFrame:(CGRect)frame changeDirectionBlock:(ChangeDirectionBlock)changeDirectionBlock { if (self = [super initWithFrame:frame]) { self.changeDirectionBlock = changeDirectionBlock; [self makeView]; [self addPan]; } return self; } //添加拖拽手勢(shì) - (void)addPan{ UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector(panAction:)]; [self addGestureRecognizer:pan]; } - (void)panAction:(UIPanGestureRecognizer *)pan { switch (pan.state) { case UIGestureRecognizerStateBegan: { CGPoint point = [pan locationInView:**self**]; self.ball.alpha = 1; [self moveWithPoint:point]; } break; case UIGestureRecognizerStateChanged: { CGPoint point = [pan locationInView:self]; [self moveWithPoint:point]; } break; case UIGestureRecognizerStateEnded: { CGPoint point = [pan locationInView:self]; [self resetBallPositionWithEndPoint:point]; } break; default: break; } } //小球復(fù)位 - (void)resetBallPositionWithEndPoint:(CGPoint)point { self.changeDirectionBlock(0); [UIView animateWithDuration:0.2 animations:^{ self.ball.center = CGPointMake((self.frame.size.width / 2.0), (self.frame.size.height / 2.0)); self.ball.alpha = 0.4; }]; } //根據(jù)控制球位置獲取當(dāng)前旋轉(zhuǎn)角度 - (void)moveWithPoint:(CGPoint)point { CGFloat distanceCircle = (self.ball.frame.size.width / 2.0); CGFloat x = point.x; CGFloat y = point.y; CGFloat dx = x - self.frame.size.width / 2.0; CGFloat dy = y - self.frame.size.height / 2.0; CGFloat rotation = atan2(dx,dy); CGFloat r = self.frame.size.width / 2.0; CGFloat rx = (r - distanceCircle) * sin(rotation) + r; CGFloat ry = (r - distanceCircle) * cos(rotation) + r; //防止控制球越界 if ((sqrt((dx * dx) + (dy * dy))) > (r - distanceCircle)) { x = rx; y = ry; } //用block形式向外界暴露當(dāng)前控制球相對(duì)于屏幕上方的角度 self.changeDirectionBlock(-rotation + M_PI); self.ball.center = CGPointMake(x, y); } - (void)makeView{ //進(jìn)行倒角 self.layer.masksToBounds = YES; self.layer.cornerRadius = self.frame.size.width / 2.0; self.backgroundColor = [[UIColor groupTableViewBackgroundColor] colorWithAlphaComponent:0.7]; //添加控制球 [self addSubview:self.ball]; } //控制球 - (UIView *)ball { if (!_ball) { CGSize size = CGSizeMake(45, 45); _ball = [[UIView alloc] initWithFrame:CGRectMake((self.frame.size.width - size.width) / 2.0, (self.frame.size.height - size.height) / 2.0, size.width, size.height)]; _ball.alpha = 0.4; _ball.layer.masksToBounds = YES; _ball.layer.cornerRadius = _ball.frame.size.width / 2.0; _ball.backgroundColor = [UIColor lightGrayColor]; } return _ball; } @end
三、發(fā)射子彈及碰撞檢測(cè)
1、發(fā)射子彈
//根據(jù)當(dāng)前角度,預(yù)判子彈動(dòng)畫的結(jié)束位置 - (NSArray *)prepareBulletPath { CGPoint center = self.center; CGFloat maxLength = sqrt(([UIScreen mainScreen].bounds.size.width * [UIScreen mainScreen].bounds.size.width) + ([UIScreen mainScreen].bounds.size.height * [UIScreen mainScreen].bounds.size.height)); CGFloat endY = sin(self.angle - M_PI / 2.0) * maxLength + center.y; CGFloat endX = cos(self.angle - M_PI / 2.0) * maxLength + center.x; CGPoint endPoint = CGPointMake(endX, endY); return @[@(center),@(endPoint)]; } - (void)fir { CGFloat bulletWidth = 10; BulletView * lastBulletView = self.bulletArr.count > 0 ? self.bulletArr.lastObject : nil; if (!lastBulletView) { BulletView * view = [[BulletView alloc] initWithFrame:CGRectMake((self.frame.size.width - bulletWidth) / 2.0, 0,bulletWidth,bulletWidth)]; view.points = [self prepareBulletPath]; [self.superview insertSubview:view belowSubview:self]; [self.bulletArr addObject:view]; view.center = [view.points[0] CGPointValue]; [UIView animateWithDuration:1 animations:^{ view.center = [view.points[1] CGPointValue]; } completion:^(BOOL finished) { [view removeFromSuperview]; [self.bulletArr removeObject:view]; }]; } }
fir 本身是一個(gè)定時(shí)器事件,在里面添加一些創(chuàng)建子彈的邏輯,位置移動(dòng)還是用了最簡(jiǎn)單的 UIView 的 animateWithDuration 方法,但是注意這里面通過(guò) frame 進(jìn)行碰撞檢測(cè)是獲取不到,所以,添加了 CADisplayLink 屏幕刷新事件來(lái)檢測(cè)子彈視圖的 layer.presentationLayer.frame來(lái)進(jìn)行與病毒的 frame 進(jìn)行檢測(cè)屏幕位置是否包含。
2、檢測(cè)碰撞
bool CGRectIntersectsRect(CGRect rect1, CGRect rect2) 檢測(cè)碰撞的方法
//添加屏幕刷新事件監(jiān)聽 - (void)addScreenRefreshAction { self.displayLink = [CADisplayLink displayLinkWithTarget:self selector: @selector(update)]; [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; } - (void)update { [self.bulletArr enumerateObjectsUsingBlock:^(BulletView * bulletView, NSUInteger idx, BOOL * _Nonnull stop) { [self.virusArr enumerateObjectsUsingBlock:^(VirusView * virusView, NSUInteger idx, BOOL * _Nonnull stop) { //檢測(cè)碰撞 if (CGRectIntersectsRect(bulletView.layer.presentationLayer.frame, virusView.frame)) { [bulletView removeFromSuperview]; [self.bulletArr removeObject:bulletView]; [virusView attacked]; if ([virusView isDie]) { [virusView removeFromSuperview]; [self.virusArr removeObject:virusView]; } } }]; }]; if (!self.virusArr.count) { [self createVirusView]; } }
四、添加病毒及消滅動(dòng)畫
1、隨機(jī)創(chuàng)建病毒
- (void)createVirusView { int width = arc4random() % 30 + 50; int x = arc4random() % ([[NSNumber numberWithFloat:[UIScreen mainScreen].bounds.size.width] integerValue] - width); int y = arc4random() % ([[NSNumber numberWithFloat:[UIScreen mainScreen].bounds.size.height / 2.0] integerValue]); VirusView * virusView = [[VirusView alloc] initWithFrame:CGRectMake(x, y, width, width)]; [self.superview addSubview:virusView]; [self.virusArr addObject:virusView]; }
2、消滅動(dòng)畫
添加了一點(diǎn)粒子效果,顯示病毒消散動(dòng)畫
- (void)fireExplode { CAEmitterLayer * emitter = [CAEmitterLayer layer]; emitter.frame = self.frame; [self.superview.layer addSublayer:emitter]; emitter.renderMode = kCAEmitterLayerAdditive; emitter.emitterPosition = CGPointMake(emitter.frame.size.width*0.5, emitter.frame.size.height*0.5); CAEmitterCell *cell = [[CAEmitterCell alloc] init]; cell.contents = ( __bridge id)[UIImage imageNamed:@"v4"].CGImage; cell.birthRate = 1;//出生率 cell.lifetime = 0.7;//生命周期 cell.emissionLongitude = - M_PI_2; cell.emissionRange = M_PI_2; cell.alphaSpeed = -0.2; cell.velocity = 10;//速度 cell.scale = 0.15;//縮放倍數(shù) emitter.emitterCells = @[cell]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [emitter removeFromSuperlayer]; }); }
五、思考與總結(jié)
添加 UIView 的 animateWithDuration 方法后,這里用的是屏幕刷新檢測(cè),來(lái)獲取當(dāng)前控件的 layer.presentationLayer.frame 來(lái)檢測(cè)碰撞,其他邏輯都相對(duì)簡(jiǎn)單。
以上就是iOS 簡(jiǎn)單的操作桿旋轉(zhuǎn)實(shí)現(xiàn)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于iOS 操作桿旋轉(zhuǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
iOS 開發(fā)中 NavigationController經(jīng)常出現(xiàn)的問(wèn)題原因分析
這篇文章主要介紹了iOS 開發(fā)中 NavigationController經(jīng)常出現(xiàn)的問(wèn)題原因分析的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09iOS仿網(wǎng)易新聞滾動(dòng)導(dǎo)航條效果
這篇文章主要為大家詳細(xì)介紹了iOS仿網(wǎng)易新聞滾動(dòng)導(dǎo)航條效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05iOS下PDF文件的瀏覽和涂鴉效果的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了iOS下PDF文件的瀏覽和涂鴉效果的簡(jiǎn)單實(shí)現(xiàn),代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-10-10IOS textField限制字節(jié)長(zhǎng)度
這篇文章主要介紹了IOS textField限制字節(jié)長(zhǎng)度的相關(guān)資料,需要的朋友可以參考下2016-02-02在iOS開發(fā)的Quartz2D使用中實(shí)現(xiàn)圖片剪切和截屏功能
這篇文章主要介紹了在iOS開發(fā)的Quartz2D使用中實(shí)現(xiàn)圖片剪切和截屏功能的方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-12-12使用AVFoundation實(shí)現(xiàn)視頻錄制詳解
這篇文章主要介紹了使用AVFoundation實(shí)現(xiàn)視頻錄制詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09