iOS 简单的操作杆旋转实现示例详解
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、效果实现</li><li>二、操作杆实现</li><li>三、发射子弹及碰撞检测</li><ul class="second_class_ul"><li>1、发射子弹</li><li>2、检测碰撞</li></ul><li>四、添加病毒及消灭动画</li><ul class="second_class_ul"><li>1、随机创建病毒</li><li>2、消灭动画</li></ul><li>五、思考与总结</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>一、效果实现</h2><div class="cros igoods"><div class="goodsin" data-img="https://img14.360buyimg.com/pop/jfs/t1/64278/26/13103/156838/5da59193Eaf77d6de/45a726d801b9a952.jpg" data-name="Flutter:从0到1构建大前端应用(博文视点出品)" data-owner="京东自营" data-price="39.5" data-tgid="38" data-url="https://union-click.jd.com/jdc?e=&p=JF8BAMkJK1olXwUAU11UD0sRBV8IGF8QWgIKXG4ZVxNJXF9RXh5UHw0cSgYYXBcIWDoXSQVJQwYBUFtaDEMfHDZNRwYlQwFdH1tDQT10CztKXQVrJVFlSl4UTkcbM2gNHF4dXwMBZF5eDkwXAmoIK2sVXDZQOobrvpOysnPcsdTA1ZEyVW5dD00UAGYOHFgVXgEAZF5VDHtUVypcWBhdbTYyV25tOEsnAF9WdVpGVQYLVQoIZhZFCjVPTxhRMwUHUF9eCk4QM20JGlkXbTY"></div></div>
<p>简单实现了一个消灭病毒的小效果,画面略显粗糙,多多见谅</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202212/2022122909090906.gif" /></p>
<p>控制球复位</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202212/2022122909090907.gif" /></p>
<p class="maodian"></p><h2>二、操作杆实现</h2>
<p>实现拖动小球,获取当前小球的旋转方向,将旋转的方向传递出去,旋转“坦克”进行攻击“病毒”。</p>
<div class="jb51code"><pre class="brush:cpp;">#import "DirectionOptionView.h"
@interface DirectionOptionView()
//方向指示器滚珠
@property(nonatomic,strong) UIView * ball;
@end
@implementation DirectionOptionView
- (instancetype)initWithFrame:(CGRect)frame changeDirectionBlock:(ChangeDirectionBlock)changeDirectionBlock
{
if (self = ) {
self.changeDirectionBlock = changeDirectionBlock;
;
;
}
return self;
}
//添加拖拽手势
- (void)addPan{
UIPanGestureRecognizer * pan = [ initWithTarget:self action: @selector(panAction:)];
;
}
- (void)panAction:(UIPanGestureRecognizer *)pan
{
switch (pan.state) {
case UIGestureRecognizerStateBegan:
{
CGPoint point = ;
self.ball.alpha = 1;
;
}
break;
case UIGestureRecognizerStateChanged:
{
CGPoint point = ;
;
}
break;
case UIGestureRecognizerStateEnded:
{
CGPoint point = ;
;
}
break;
default:
break;
}
}
//小球复位
- (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;
}];
}
//根据控制球位置获取当前旋转角度
- (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形式向外界暴露当前控制球相对于屏幕上方的角度
self.changeDirectionBlock(-rotation + M_PI);
self.ball.center = CGPointMake(x, y);
}
- (void)makeView{
//进行倒角
self.layer.masksToBounds = YES;
self.layer.cornerRadius = self.frame.size.width / 2.0;
self.backgroundColor = [ colorWithAlphaComponent:0.7];
//添加控制球
;
}
//控制球
- (UIView *)ball
{
if (!_ball) {
CGSize size = CGSizeMake(45, 45);
_ball = [ 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 = ;
}
return _ball;
}
@end
</pre></div>
<p class="maodian"></p><h2>三、发射子弹及碰撞检测</h2>
<p class="maodian"></p><h3>1、发射子弹</h3>
<div class="jb51code"><pre class="brush:cpp;">//根据当前角度,预判子弹动画的结束位置
- (NSArray *)prepareBulletPath
{
CGPoint center = self.center;
CGFloat maxLength = sqrt((.bounds.size.width * .bounds.size.width) + (.bounds.size.height * .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 = [ initWithFrame:CGRectMake((self.frame.size.width - bulletWidth) / 2.0, 0,bulletWidth,bulletWidth)];
view.points = ;
;
;
view.center = CGPointValue];
[UIView animateWithDuration:1 animations:^{
view.center = CGPointValue];
} completion:^(BOOL finished) {
;
;
}];
}
}
</pre></div>
<p><strong>fir</strong> 本身是一个定时器事件,在里面添加一些创建子弹的逻辑,位置移动还是用了最简单的 <strong>UIView</strong> 的 <strong>animateWithDuration</strong> 方法,但是注意这里面通过 <strong>frame</strong> 进行碰撞检测是获取不到,所以,添加了 <strong>CADisplayLink</strong> 屏幕刷新事件来检测子弹视图的 <strong>layer.presentationLayer.frame</strong>来进行与病毒的 <strong>frame</strong> 进行检测屏幕位置是否包含。</p>
<p class="maodian"></p><h3>2、检测碰撞</h3>
<p>bool CGRectIntersectsRect(CGRect rect1, CGRect rect2) 检测碰撞的方法</p>
<div class="jb51code"><pre class="brush:cpp;">//添加屏幕刷新事件监听
- (void)addScreenRefreshAction
{
self.displayLink = ;
forMode:NSRunLoopCommonModes];
}
- (void)update
{
[self.bulletArr enumerateObjectsUsingBlock:^(BulletView * bulletView, NSUInteger idx, BOOL * _Nonnull stop) {
[self.virusArr enumerateObjectsUsingBlock:^(VirusView * virusView, NSUInteger idx, BOOL * _Nonnull stop) {
//检测碰撞
if (CGRectIntersectsRect(bulletView.layer.presentationLayer.frame, virusView.frame)) {
;
;
;
if () {
;
;
}
}
}];
}];
if (!self.virusArr.count) {
;
}
}
</pre></div>
<p class="maodian"></p><h2>四、添加病毒及消灭动画</h2>
<p class="maodian"></p><h3>1、随机创建病毒</h3>
<div class="jb51code"><pre class="brush:cpp;">- (void)createVirusView
{
int width = arc4random() % 30 + 50;
int x = arc4random() % ([.bounds.size.width] integerValue] - width);
int y = arc4random() % ([.bounds.size.height / 2.0] integerValue]);
VirusView * virusView = [ initWithFrame:CGRectMake(x, y, width, width)];
;
;
}
</pre></div>
<p class="maodian"></p><h3>2、消灭动画</h3>
<p>添加了一点粒子效果,显示病毒消散动画</p>
<div class="jb51code"><pre class="brush:cpp;">- (void)fireExplode
{
CAEmitterLayer * emitter = ;
emitter.frame = self.frame;
;
emitter.renderMode = kCAEmitterLayerAdditive;
emitter.emitterPosition = CGPointMake(emitter.frame.size.width*0.5, emitter.frame.size.height*0.5);
CAEmitterCell *cell = [ init];
cell.contents = ( __bridge id).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;//缩放倍数
emitter.emitterCells = @;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
;
});
}
</pre></div>
<p class="maodian"></p><h2>五、思考与总结</h2>
<p>添加 <strong>UIView</strong> 的 <strong>animateWithDuration</strong> 方法后,这里用的是屏幕刷新检测,来获取当前控件的 <strong>layer.presentationLayer.frame</strong> 来检测碰撞,其他逻辑都相对简单。</p>
<p>以上就是iOS 简单的操作杆旋转实现示例详解的详细内容,更多关于iOS 操作杆旋转的资料请关注琼殿技术社区其它相关文章!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>iOS 断点上传文件的实现方法</li><li>iOS开发中以application/json上传文件实例详解</li><li>IOS开发教程之put上传文件的服务器的配置及实例分享</li><li>iOS内存管理Tagged Pointer使用原理详解</li><li>iOS 底层alloc init new 源码流程示例分析</li><li>iOS通过UIDocumentInteractionController实现应用间传文件</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]