iOS牛顿摆 小球撞击 物理学仿真模拟

                        **第一次写博客有点激动呢**

iOS牛顿摆 小球撞击 物理学仿真模拟_第1张图片
使用 UIDynamic 的方法就不叙述了
这里先讲一下 牛顿摆是经过计算的一个公式才能达到理想状态 由于我不知道公式 所以做出来不能完美的达成 一个小球落下来另一个小球飞起来

接下来直接上代码 代码中的描述还是很详细的

#import "ViewController.h"
#import "ContentView.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    ContentView *view =[[ContentView alloc]initWithFrame:self.view.bounds];
    view.backgroundColor=[UIColor blueColor];
    [self.view addSubview:view];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

#import "ContentView.h"
#import "BallsView.h"
@interface ContentView(){
    UIDynamicAnimator *_animator;//仿真模拟器
    NSMutableArray *_arrayBalls;
    CGPoint _centers[100];//可变的小球中心坐标
    UISnapBehavior *_snapB;
    UIAttachmentBehavior *attachement1;
}
@end

static CGFloat radius=20;//小球半径
static CGFloat attachmentLenth=500;//链接长度
@implementation ContentView
-(id)initWithFrame:(CGRect)frame{
    if (self=[super initWithFrame:frame]) {
        //初始化仿真模拟器
        _animator=[[UIDynamicAnimator alloc]initWithReferenceView:self];

        //初始化所有仿真元素 就是小球
        [self creatBalls];

        //添加小球的行为元素
        [self addBehavior];

        //利用 drawRect 方法绘制小球和锚点的连线

        //使用 touchBegan方法判断我们要抓住的小球 用 touchMove的方法使我们的小球随着手指滑动 使用 touchEnd 方法移除 snap 行为释放小球

    }
    return  self;
}

static int b;
-(void)addBehavior{

    //这样的方法要经常使用 可以避免程序的崩溃
    if (!_arrayBalls.count) {
        return;
    }

    //仿真元素的行为描述
    UIDynamicItemBehavior *itemBehavior=[[UIDynamicItemBehavior alloc]initWithItems:_arrayBalls];
    itemBehavior.elasticity=1.00001;//弹性
    itemBehavior.resistance=.01;//阻尼
    itemBehavior.density=1000;//密度
    itemBehavior.allowsRotation=NO;//禁止旋转
    [_animator addBehavior:itemBehavior];


    //因为我们的小球都需要重力行为直接添加上就可以了
    UIGravityBehavior *gravityB=[[UIGravityBehavior alloc]initWithItems:_arrayBalls];
    gravityB.magnitude=10;//重力加速度

    [_animator addBehavior:gravityB];

    //添加碰撞行为
    UICollisionBehavior *collisionB=[[UICollisionBehavior alloc]initWithItems:_arrayBalls];
    [_animator addBehavior:collisionB];

    //添加链接行为 链接行为是将两个点相连
    for (int i=0; i<_arrayBalls.count; i++) {
        UIAttachmentBehavior *attachmentB=[[UIAttachmentBehavior alloc]initWithItem:_arrayBalls[i] attachedToAnchor:_centers[i]];
        attachmentB.length=attachmentLenth;
        attachmentB.damping=0;
        attachmentB.frequency=0;
        [_animator addBehavior:attachmentB];

    }

}

-(void)creatBalls{
    _arrayBalls=[[NSMutableArray alloc]initWithCapacity:1];
    //计算小球中心的坐标
    for (int i=0; i<6; i++) {
        CGPoint p=CGPointMake(60+i*2*radius+i*3, 30);
        _centers[i]=p;
    }

    for (int i=0; i<6; i++) {
        //这里创建一个小球的 view
        BallsView *ball=[[BallsView alloc]initWithFrame:CGRectMake(0, 0, 2*radius, 2*radius) withRadius:radius];

        //在这里确定小球的初始位置
        ball.center=_centers[i];

        //这里添加的 kvo 方法作用是当监听到小球的中心变化时 执行 setNeedDisplay 方法 走了这方法后 就会重新绘制contentView
        [ball addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:nil];
        [self addSubview:ball];
        [_arrayBalls addObject:ball];
    }

}

- (void)drawRect:(CGRect)rect {
    //绘图第一点 获取上下文
    CGContextRef context=UIGraphicsGetCurrentContext();

    //绘制连接线
    for (int i=0; i<6; i++) {
        UIView *view=_arrayBalls[i];
        CGContextMoveToPoint(context, _centers[i].x, _centers[i].y);
        CGContextAddLineToPoint(context,view.center.x, view.center.y);

    }
    CGContextStrokePath(context);


}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    [self setNeedsDisplay];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UITouch *touch=[touches anyObject];
    for (int i=0; i<6; i++) {
        UIView *view=_arrayBalls[i];
        CGPoint point=[touch locationInView:view];
        if ([view pointInside:point withEvent:nil]) {
            //NSLog(@"%d",i);
            b=i;
        }
    }
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    if (_snapB==nil) {
        UITouch *touch=[touches anyObject];
        CGPoint point=[touch locationInView:self];
        _snapB=[[UISnapBehavior alloc]initWithItem:_arrayBalls[b] snapToPoint:point];
        //NSLog(@"%d",b);
        [_animator addBehavior:_snapB];
    }else{
        [_animator removeBehavior:_snapB];
        _snapB=nil;
    }

}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [_animator removeBehavior:_snapB];
}
@end
#import <UIKit/UIKit.h>

@interface BallsView : UIView
-(id)initWithFrame:(CGRect)frame withRadius:(CGFloat)radius;
@end
#import "BallsView.h"

@implementation BallsView

-(id)initWithFrame:(CGRect)frame withRadius:(CGFloat)radius{
    if (self =[super initWithFrame:frame]) {

        //初始化小球的属性
        self.layer.cornerRadius=radius; 
        self.layer.borderColor=[UIColor greenColor].CGColor;
        self.layer.borderWidth=2;
        self.backgroundColor=[UIColor yellowColor];
        self.layer.shadowColor=[UIColor blackColor].CGColor;
        self.layer.shadowRadius=.5;

    }
    return self;
}

@end

你可能感兴趣的:(ios,博客)