欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

【ios】UIDynamic物理模拟实现物理碰撞

程序员文章站 2022-05-23 21:18:54
一、需求:请实现下图所示的动画(物理碰撞)     二、上面引入过uidynamic 可以实现碰撞的物理效果动画,how to start ? 在工程中导入uikit,从he...

一、需求:请实现下图所示的动画(物理碰撞)

 

【ios】UIDynamic物理模拟实现物理碰撞

 

二、上面引入过uidynamic 可以实现碰撞的物理效果动画,how to start ?

在工程中导入uikit,从headers 找一些uidynamic,发现了uidynamicanimator.h,uidynamicbehavior,uidynamicitembehavior

既然是要动画效果 那就应该是uidynamicanimator.h

到uidynamicanimator.h 头文件去查看注释

// when you initialize a dynamic animator with this method, you should only associates views with your behaviors.

// the behaviors (and their dynamic items) that you add to the animator employ the reference view’s coordinate system.

- (instancetype)initwithreferenceview:(uiview *)view ns_designated_initializer;

大概意思是使用这个初始化方法的时候,需要为你的试图关联behaviors

what’s the behaviors ? jump into defination 然而还不是很懂,uidynamicbehavior,那就查看api (注意文档中的如下描述)。

this parent class, uidynamicbehavior, is inherited by the primitive dynamic behavior classes uiattachmentbehavior, uicollisionbehavior, uigravitybehavior, uidynamicitembehavior, uipushbehavior, and uisnapbehavior.

文档中提到uidynamicbehavior的父类,那么uidynamicbehavior父类(dynamic 行为相关类)描述什么行为呢?

uiattachmentbehavior:附着行为

uicollisionbehavior:碰撞行为

uigravitybehavior:重力行为

uidynamicitembehavior:动态元素行为

uipushbehavior:推行为

uisnapbehavior:吸附行为

上述的各种行为可单独使用,也可以组合使用更复杂的动画效果。

解决方案的思路就引导到这边,也就可以实现上述需求。dynamic 行为相关类的属性可自行研究。

三、解决方案。

上述需求的解决方案(我这边用的是6sp的模拟器奥,因为在设置floor的y坐标是600)

既然是球落地效果,必然有两个模拟对象:floor,basketball

1.创建uidynamicanimator 对象

self.animator = [[uidynamicanimator alloc] initwithreferenceview:self.view];

2.刚刚在api 看到了初始化uidynamicanimator需要关联一个或者多个行为

nsarray *animatorobjects = @[self.imagev1];

// 刚刚在api 看到了初始化uidynamicanimator需要关联一个或者多个行为

self.gravitybehav = [[uigravitybehavior alloc] initwithitems:animatorobjects];

self.colision = [[uicollisionbehavior alloc] initwithitems:animatorobjects];

3.如果你想监听碰撞的状态,可以设置一下代理

self.colision.collisiondelegate = self;

4.设置碰撞边界

[self.colision addboundarywithidentifier:@"boundaryline" frompoint:cgpointmake(0, 600) topoint:cgpointmake(screenwith, 600)];

5.设置动态行为参数

// 设置动态行为参数

uidynamicitembehavior *itembehavior = [[uidynamicitembehavior alloc] initwithitems:animatorobjects];

// 设置弹性

[itembehavior setelasticity:0.5];

6.行为创建了,别忘了给animator添加上

[self.animator addbehavior:self.gravitybehav];

[self.animator addbehavior:self.colision];

[self.animator addbehavior:itembehavior];

三、下面代码只能说功能实现

ps:以下代码不符合代码书写规范

//

// viewcontroller.m

// dynamicanimation

//

// created by jeversonjee on 16/5/27.

// copyright © 2016年 jeversonjee. all rights reserved.

//

#import "viewcontroller.h"

#define screenwith [uiscreen mainscreen].bounds.size.width

#define screenheight [uiscreen mainscreen].bounds.size.height

@interface viewcontroller ()

@property (nonatomic, strong) uidynamicanimator *animator;

@property (nonatomic, strong) uigravitybehavior *gravitybehav;

@property (nonatomic, strong) uicollisionbehavior *colision;

@property (nonatomic, strong) uiimageview *imagev1;

@property (nonatomic, strong) uiimageview *imagev2;

@end

@implementation viewcontroller

- (void)viewdidload {

[super viewdidload];

// do any additional setup after loading the view, typically from a nib.

[self jjcollisionbehav];

}

- (void)jjcollisionbehav {

// 创建碰撞需要的对象

[self jjcreateball];

[self jjcreatefloor];

// 创建uidynamicanimator 对象

self.animator = [[uidynamicanimator alloc] initwithreferenceview:self.view];

nsarray *animatorobjects = @[self.imagev1];

// 刚刚在api 看到了初始化uidynamicanimator需要关联一个或者多个行为

self.gravitybehav = [[uigravitybehavior alloc] initwithitems:animatorobjects];

self.colision = [[uicollisionbehavior alloc] initwithitems:animatorobjects];

// 这里设置代理是为了监听碰撞状态的,可以去了解一下代理方法

self.colision.collisiondelegate = self;

// 设置碰撞边界

[self.colision addboundarywithidentifier:@"boundaryline" frompoint:cgpointmake(0, 600) topoint:cgpointmake(screenwith, 600)];

// 设置动态行为参数

uidynamicitembehavior *itembehavior = [[uidynamicitembehavior alloc] initwithitems:animatorobjects];

// 设置弹性

[itembehavior setelasticity:0.5];

// 创建了行为需要animator添加

[self.animator addbehavior:self.gravitybehav];

[self.animator addbehavior:self.colision];

[self.animator addbehavior:itembehavior];

}

-(void)collisionbehavior:(uicollisionbehavior *)behavior endedcontactforitem:(id)item withboundaryidentifier:(id)identifier {

nslog(@"collisionbehavior=%@", item);

nsstring *identifierstr = [nsstring stringwithformat:@"%@", identifier];

nslog(@"s=%@", identifier);

if ( [identifierstr isequaltostring:@"boundaryline"] ) {

[self.imagev2 setbackgroundcolor:[uicolor graycolor]];

[uiview animatewithduration:2 animations:^(void){

[self.imagev2 setbackgroundcolor:[uicolor graycolor]];

}];

}

}

-(void)jjcreateball {

_imagev1 = [[uiimageview alloc] initwithimage:[uiimage imagenamed:@"basketball"]];

_imagev1.frame = cgrectmake(100, 100, 60, 60);

[self.view addsubview:_imagev1];

}

- (void)jjcreatefloor {

_imagev2 = [[uiimageview alloc] init];

[_imagev2 setbackgroundcolor:[uicolor graycolor]];

_imagev2.frame = cgrectmake(0, 600, screenwith, screenheight - 400);

[self.view addsubview:_imagev2];

}

-(void)didreceivememorywarning {

[super didreceivememorywarning];

// dispose of any resources that can be recreated.

}

@end