当前位置: 代码网 > it编程>App开发>苹果IOS > iOS 简单的操作杆旋转实现示例详解

iOS 简单的操作杆旋转实现示例详解

2024年05月18日 苹果IOS 我要评论
一、效果实现简单实现了一个消灭病毒的小效果,画面略显粗糙,多多见谅控制球复位二、操作杆实现实现拖动小球,获取当前小球的旋转方向,将旋转的方向传递出去,旋转“坦克”进行攻击&ld

一、效果实现

简单实现了一个消灭病毒的小效果,画面略显粗糙,多多见谅

控制球复位

二、操作杆实现

实现拖动小球,获取当前小球的旋转方向,将旋转的方向传递出去,旋转“坦克”进行攻击“病毒”。

#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;
}
//添加拖拽手势
- (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;
    }
}
//小球复位
- (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 = [[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

三、发射子弹及碰撞检测

1、发射子弹

//根据当前角度,预判子弹动画的结束位置
- (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 本身是一个定时器事件,在里面添加一些创建子弹的逻辑,位置移动还是用了最简单的 uiviewanimatewithduration 方法,但是注意这里面通过 frame 进行碰撞检测是获取不到,所以,添加了 cadisplaylink 屏幕刷新事件来检测子弹视图的 layer.presentationlayer.frame来进行与病毒的 frame 进行检测屏幕位置是否包含。

2、检测碰撞

bool cgrectintersectsrect(cgrect rect1, cgrect rect2) 检测碰撞的方法

//添加屏幕刷新事件监听
- (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) {
            //检测碰撞
            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];
    }
}

四、添加病毒及消灭动画

1、随机创建病毒

- (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、消灭动画

添加了一点粒子效果,显示病毒消散动画

- (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;//缩放倍数
    emitter.emittercells = @[cell];
    dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(0.6 * nsec_per_sec)), dispatch_get_main_queue(), ^{
        [emitter removefromsuperlayer];
    });
}

五、思考与总结

添加 uiviewanimatewithduration 方法后,这里用的是屏幕刷新检测,来获取当前控件的 layer.presentationlayer.frame 来检测碰撞,其他逻辑都相对简单。

以上就是ios 简单的操作杆旋转实现示例详解的详细内容,更多关于ios 操作杆旋转的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com