明天ios中实现staggeringBeauty的效果(四)

明天ios中实现staggeringBeauty的效果(四)

好吧。。。过了两天再回来。。
今天讲的是用户的交互,先在 CMSpringyRopeLayer.h中加上外调的函数,之后会在CMSpringyRopeView中调用

- (void)touchBeganAtLocation:(CGPoint)location;
- (void)touchMovedAtLocation:(CGPoint)location;
- (void)touchEndedAtLocation:(CGPoint)location;
- (void)touchCancelledAtLocation:(CGPoint)location;

然后跳的CMSpringyRopeLayer.m来实现上面这三个函数

#pragma mark - Handle touches

- (void)touchBeganAtLocation:(CGPoint)location
{
    //if (CGPointDistance(location, self.handleParticle.center) <= 40.0f) {
    [self moveHandleToLocation:location];
    self.isDragging = YES;
    //}
}

- (void)touchMovedAtLocation:(CGPoint)location
{
    if (self.isDragging) {
    [self moveHandleToLocation:location];
    }
}

- (void)touchEndedAtLocation:(CGPoint)location
{
    if (self.isDragging) {
    [self moveHandleToLocation:location];
    //self.isDragging = NO;

    }
}

- (void)touchCancelledAtLocation:(__unused CGPoint)location
{
    if (self.isDragging) {
    //self.isDragging = NO;
    }
}

#pragma mark - Move Handle

- (void)moveHandleToLocation:(CGPoint)location
{
    CGFloat angle=atan2(location.y,location.x-CGRectGetMidX(self.bounds));

    location.x=CGRectGetMidX(self.bounds)+cos(angle)*_rope_length*1.5;
    location.y=CGRectGetHeight(self.bounds)-sin(angle)*_rope_length/5;


    self.addGravite=cos(angle)*0.5;

    self.handleParticle.center = location;
    self.handleSpringBehavior.anchorPoint = location;

    [self.animator updateItemUsingCurrentState:self.handleParticle];
}

其中的handleParticle这里使用的第2个Particle点,上一篇的- (void)generateParticles 函数中的一句:
self.handleParticle = [particles objectAtIndex:1];
可以得,当然这个是个人调试定出来的,可以通过调试根据个人喜好来决定。。。其实应该把数值用 static CGFloat const ****去先定义好,然后以后改就直接在上面去修改,方便去看去参考,所以之前就说代码没有重构好,先不放上来。好吧先姑且看着吧。
上面的- (void)touchBeganAtLocation:(CGPoint)location;
- (void)touchMovedAtLocation:(CGPoint)location;
- (void)touchEndedAtLocation:(CGPoint)location;
- (void)touchCancelledAtLocation:(CGPoint)location;
函数与苹果自带的那几个东西,是不是很像对,你猜的没错就是在那几个东西里分别去调用。给自己一个赞吧。

#pragma mark - Handle touches

- (void)touchesBegan:(NSSet *)touches withEvent:(__unused UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint position = [touch locationInView:self];
    [self.springyRopeLayer touchBeganAtLocation:position];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(__unused UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint position = [touch locationInView:self];
    [self.springyRopeLayer touchMovedAtLocation:position];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(__unused UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint position = [touch locationInView:self];
    [self.springyRopeLayer touchEndedAtLocation:position];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(__unused UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint position = [touch locationInView:self];
    [self.springyRopeLayer touchCancelledAtLocation:position];
}

当然了,你得先在#import “CMSpringyRopeLayer.h”,这个就再提一下。。虽然大家都应该知道。

现在来讲一下update的实现吧,当用户做了操作之后当然要update一下,要做一个反馈,一般update都是每隔一段时间然后重新去加载。
这里有一点特别,如果你看的仔细的话,在init中有那么两句

    __weak CMSpringyRopeLayer *weakSelf = self;
    _gravityBehavior.action = ^{
        __strong CMSpringyRopeLayer *strongSelf = weakSelf;
        [strongSelf drawFrame];
    };

把_gravityBehavior(重力)与drawFrame(重绘)联系在了一起,为什么这样做,我想应该是为了方便,先来看一下重绘吧。

#pragma mark - Draw Frame

- (void)drawFrame
{
    //if (self.motionManager.isDeviceMotionActive) {
        //CMAcceleration gravity = self.motionManager.deviceMotion.gravity;
    //由stress的值来决定重力的大小
        CGVector gravityVector = CGVectorMake((float)self.addGravite, (float)-0.5);
    if (self.stress>stressNumber) {
          gravityVector = CGVectorMake((float)self.addGravite, (float)-2.5);
    }else{
         gravityVector = CGVectorMake((float)self.addGravite, (float)-0.5);
    }
        gravityVector = [self vector:gravityVector rotatedToInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
        self.gravityBehavior.gravityDirection = gravityVector;
   // }

    [self setNeedsDisplay];      // draw layer

    /* FPS */
    if (self.fpsLabel) {
    double curr_time = CACurrentMediaTime();
    if (curr_time - self.fps_prev_time >= 0.2) {
        double delta = (curr_time - self.fps_prev_time) / self.fps_count;
        self.fpsLabel.text = [NSString stringWithFormat:@"%0.0f fps", 1.0/delta];
        self.fps_prev_time = curr_time;
        self.fps_count = 1;
    }
    else {
        self.fps_count++;
    }
    }

    //set the supports points



    CGFloat targetStress=0;

    double bend=-0.15;

    NSUInteger particlesMaxIndex = [self.particles count];

    //调整 support1,support2

    for (NSUInteger i=1; i<particlesMaxIndex; i++)  {
//        CMSpringyRopeParticle *particle=self.particles[i];
//        if (particle.center.x<CGRectGetMinX(self.bounds)) {
//            particle.center=CGPointMake(CGRectGetMinX(self.bounds)+50, particle.center.y) ;
//        }else if(particle.center.x>CGRectGetMaxX(self.bounds)){
//            particle.center=CGPointMake(CGRectGetMaxX(self.bounds)-50, particle.center.y) ;
//        }
//        
        CMSpringyRopeParticle *support2=self.supports2[i];
        CMSpringyRopeParticle *curPartice=self.particles[i];

        CMSpringyRopeParticle *prePartice=self.particles[i-1];

      double angle=atan2(curPartice.center.y-prePartice.center.y, curPartice.center.x-prePartice.center.x);

        CGFloat support2x=curPartice.center.x-cos(angle+i*bend)*CMSpringyRopeLength/9 ;
        CGFloat support2y=curPartice.center.y-sin(angle+i*bend)*CMSpringyRopeLength /9;
        support2.center=CGPointMake(support2x, support2y);


        CMSpringyRopeParticle *support1=self.supports1[i];


        CGFloat support1x=curPartice.center.x-cos(angle+3.14)*CMSpringyRopeLength/9 ;
        CGFloat support1y=curPartice.center.y-sin(angle+3.14)*CMSpringyRopeLength /9;
        support1.center=CGPointMake(support1x, support1y);


        CGFloat length=(curPartice.center.x-prePartice.center.x)*(curPartice.center.x-prePartice.center.x)/200;

        if (i>1) {
            targetStress+=length;
        }


    }
    self.stress+=(targetStress-self.stress*0.1)*0.1;



}


#pragma mark - CALayer methods

- (void)drawInContext:(CGContextRef)ctx
{
    if (!CGSizeEqualToSize(self.bounds.size, self.lastSize)) {
    self.gravityScale = 1.0f * CGRectGetHeight(self.frame) / 320.0f;
        self.lastSize = self.bounds.size;
    }





    CGMutablePathRef path = CGPathCreateMutable();

    CGPoint anchorPoint = self.anchorSpringBehavior.anchorPoint;
    CGPathMoveToPoint(path, NULL, anchorPoint.x, anchorPoint.y);
    for (NSUInteger i=0; i<[self.particles count]; i++) {
    CMSpringyRopeParticle *p = [self.particles objectAtIndex:i];
    CGPathAddLineToPoint(path, NULL, p.center.x, p.center.y);
    }


    UIGraphicsPushContext(ctx);



    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:path];
    bezierPath = smoothedPath(bezierPath, 8);
    bezierPath.lineWidth=110;

    bezierPath.lineCapStyle=kCGLineCapRound;
    bezierPath.lineJoinStyle = kCGLineJoinRound;



    if (self.smoothed) {

        bezierPath.lineWidth=110;
        bezierPath.lineJoinStyle = kCGLineJoinRound;
        bezierPath.lineCapStyle=kCGLineCapRound;

        //[bezierPath fill];
    }

    if (self.stress>stressNumber) {
        NSLog(@"rilegoule");
      [[UIColor colorWithRed:1 green:0 blue:0.1 alpha:0.9]setStroke];
    }



    [bezierPath stroke];

    UIGraphicsPopContext();

    CGPathRelease(path);

    // Draw handle
    CGPoint handlePoint = self.handleParticle.center;
    CGContextAddEllipseInRect(ctx, CGRectMake(handlePoint.x-CMSpringyRopeHandleRadius, handlePoint.y-CMSpringyRopeHandleRadius, CMSpringyRopeHandleRadius*2, CMSpringyRopeHandleRadius*2));
    CGContextStrokePath(ctx);


    [self addEyes:ctx];

}

一般的在代码中已经写了注释,这里提一下上面的
[self setNeedsDisplay]; // draw layer
是调用- (void)drawInContext:(CGContextRef)ctx的标志千万不要忘了
而[self addEyes:ctx];是加那对色咪咪的眼睛,

#pragma mark - add eyes
-(void)addEyesBig:(CGContextRef)ctx{
    CGFloat eyeToeyelength=40;
    UIView *view1=self.particles[[self.particles count]-1];
    UIView *view2=self.particles[[self.particles count]-2];
    CGFloat angle=atan2(view2.center.y-view1.center.y, view2.center.x-view1.center.x)+90;
    CGPoint eyeLeft=CGPointMake(view2.center.x+cos(angle)*eyeToeyelength/2+5, view2.center.y+sin(angle)*eyeToeyelength/6-20);
    CGPoint eyeRight=CGPointMake(view2.center.x-cos(angle)*eyeToeyelength/2+5, view2.center.y-sin(angle)*eyeToeyelength/6-20);


   // CGContextAddRect(ctx, CGRectMake(eyeLeft.x, eyeLeft.y+5, 20, 2));
    CGContextAddEllipseInRect(ctx, CGRectMake(eyeLeft.x, eyeLeft.y, 15, 15));
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
    // CGContextRotateCTM(ctx,angle*M_PI/90);


    //CGContextAddRect(ctx, CGRectMake(eyeRight.x, eyeRight.y+5, 20, 2));
    CGContextAddEllipseInRect(ctx, CGRectMake(eyeRight.x, eyeRight.y, 15, 15));
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);

    CGContextRotateCTM(ctx,angle*M_PI/180);

    CGContextFillPath(ctx);

}

-(void)addEyesSmall:(CGContextRef)ctx{
    CGFloat eyeToeyelength=40;
    UIView *view1=self.particles[[self.particles count]-1];
    UIView *view2=self.particles[[self.particles count]-2];
    CGFloat angle=atan2(view2.center.y-view1.center.y, view2.center.x-view1.center.x)+90;
    CGPoint eyeLeft=CGPointMake(view2.center.x+cos(angle)*eyeToeyelength/2+5, view2.center.y+sin(angle)*eyeToeyelength/6-20);
    CGPoint eyeRight=CGPointMake(view2.center.x-cos(angle)*eyeToeyelength/2+5, view2.center.y-sin(angle)*eyeToeyelength/6-20);


    CGContextAddRect(ctx, CGRectMake(eyeLeft.x, eyeLeft.y+5, 15, 2));
    //CGContextAddEllipseInRect(ctx, CGRectMake(eyeLeft.x, eyeLeft.y, 10, 10));
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
    // CGContextRotateCTM(ctx,angle*M_PI/90);


    CGContextAddRect(ctx, CGRectMake(eyeRight.x, eyeRight.y+5, 15, 2));
    //CGContextAddEllipseInRect(ctx, CGRectMake(eyeRight.x, eyeRight.y, 10, 10));
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);

    CGContextRotateCTM(ctx,angle*M_PI/180);

    CGContextFillPath(ctx);
}


-(void)addEyesshape:(CGContextRef)ctx{
    CGFloat eyeToeyelength=40;
    UIView *view1=self.particles[[self.particles count]-1];
    UIView *view2=self.particles[[self.particles count]-2];
    CGFloat angle=atan2(view2.center.y-view1.center.y, view2.center.x-view1.center.x)+90;
    CGPoint eyeLeft=CGPointMake(view2.center.x+cos(angle)*eyeToeyelength/2+5, view2.center.y+sin(angle)*eyeToeyelength/6-20);
    CGPoint eyeRight=CGPointMake(view2.center.x-cos(angle)*eyeToeyelength/2+5, view2.center.y-sin(angle)*eyeToeyelength/6-20);


    CGContextAddRect(ctx, CGRectMake(eyeLeft.x, eyeLeft.y+5, 15, 2));
    CGContextAddRect(ctx, CGRectMake(eyeLeft.x+7.5, eyeLeft.y-2.5, 2, 15));
    //CGContextAddEllipseInRect(ctx, CGRectMake(eyeLeft.x, eyeLeft.y, 10, 10));
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
    // CGContextRotateCTM(ctx,angle*M_PI/90);


    CGContextAddRect(ctx, CGRectMake(eyeRight.x, eyeRight.y+5, 15, 2));
     CGContextAddRect(ctx, CGRectMake(eyeRight.x+7.5, eyeRight.y-2.5, 2, 15));
    //CGContextAddEllipseInRect(ctx, CGRectMake(eyeRight.x, eyeRight.y, 10, 10));
    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);

    CGContextRotateCTM(ctx,angle*M_PI/180);

    CGContextFillPath(ctx);

}

-(void)addEyes:(CGContextRef)ctx{


    if (self.stress>stressNumber) {
        [self addEyesshape:ctx];
    }else{
    self.eyesNumber+=1;
    int i=self.eyesNumber;
    if (i==509||i==510|| i==524||i==525||i==538||i==539||i==548||i==549) {
        [self addEyesSmall:ctx];
    }else if((i>510&&i<524)||(i>538&&i<548)){

    }
    else{
        [self addEyesBig:ctx];

    }

    if (self.eyesNumber>1000) {
        self.eyesNumber=0;
    }
    }
}

所以就是这样, staggeringBeauty那个魔性的晃动就是这样模仿出来了,然后在下一篇会完全按照,traer.js去做,不使用苹果自带的物理模型,当然。。。不一定会做。。也许就简单的把代码重构后打包上来分享了。。。因为最近在做另一款游戏也比较忙。。。见谅。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值