UIAttachmentBehavior 不适用于可能会丢失的乒乓 AI

UIAttachmentBehavior not working for pong AI that can lose

所以我正在尝试实现一个基本的 pong AI,它很不错,但可以被打败。我试过 [UIView animateWithDuration...] UISnapBehavior 和 UIAttachmentBehavior。

animateWithDuration 没有正确更新碰撞检测,所以我得到了隐形墙

UISnapBehavior 还是太快了,不响应摩擦或阻力减速

UIAttachmentBehavior 似乎是我最好的选择,因为它适用于我的碰撞行为,如 Snap,但更灵活。我打算调整频率来影响速度。但是,我无法让它工作。欢迎所有建议,这里是代码:

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

[self startGame];
}

让一切顺利进行的基本方法

- (void)startGame {
[self createBall];
[self createPlayerPaddle];
[self createAIPaddle];
[self createCollisions];

// Remove rotation
self.paddleDynamicProperties = [[UIDynamicItemBehavior alloc] initWithItems:@[self.paddleView, self.paddleViewAI]];
self.paddleDynamicProperties.allowsRotation = NO;

//make heavy
self.paddleDynamicProperties.density = 1000.0f;

//make slow
self.paddleDynamicProperties.friction = 1000;

[self.animator addBehavior:self.paddleDynamicProperties];
}

我们将看看碰撞和 paddleViewAI

- (void)createCollisions {
self.collider = [[UICollisionBehavior alloc] initWithItems:@[self.ballView, self.paddleView, self.paddleViewAI]];
//self.collider.collisionDelegate = self.paddleView;
self.collider.collisionMode = UICollisionBehaviorModeEverything;
[self.collider addBoundaryWithIdentifier:@"left" fromPoint:CGPointMake(0, 0) toPoint:CGPointMake(0, self.view.frame.size.height)];
[self.collider addBoundaryWithIdentifier:@"right" fromPoint:CGPointMake(self.view.frame.size.width, 0) toPoint:CGPointMake(self.view.frame.size.width, self.view.frame.size.height)];
[self.animator addBehavior:self.collider];
}
- (void)createAIPaddle {
CGRect paddleRect = CGRectMake((self.view.frame.size.width / 2), 30, 100, 10);
self.paddleViewAI = [[UIView alloc] initWithFrame:paddleRect];
self.paddleViewAI.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.paddleViewAI];

//make AI work
//track location of ball
[self addObserver:self forKeyPath:@"self.ballView.center" options:NSKeyValueObservingOptionNew context:nil];
}

最后我在球移动时响应球位置的变化

-(void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString *,id> *)change context:(nullable void *)context {
if ([keyPath isEqualToString:@"self.ballView.center"]) {

    if (!CGRectContainsRect(self.view.frame, self.ballView.frame)) {
        [self createBall];
        [self createCollisions];
    }

    CGPoint location = self.ballView.center;

    //paddle respond to location of ball

    if (self.dxAI == 0) {
        self.dxAI = location.x - self.paddleViewAI.center.x;
    }
    //create offsets
    CGPoint newLocation = CGPointMake(location.x - self.dxAI, self.paddleViewAI.center.y);
    CGRect newRect = CGRectMake(newLocation.x - (self.paddleViewAI.frame.size.width / 2), self.paddleViewAI.frame.origin.y, self.paddleViewAI.frame.size.width, self.paddleViewAI.frame.size.height);


    //keep paddle inside view
    if (CGRectContainsRect(self.view.frame, newRect)) {
        //apply offsets

        if (self.attach != nil) {
            [self.animator removeBehavior:self.attach];
        }
        self.attach = [[UIAttachmentBehavior alloc] initWithItem:self.paddleViewAI attachedToAnchor:self.paddleViewAI.center];
        // the plan was adjust the frequency to affect speed so AI will only be able to keep up sometimes
        self.attach.frequency = 20;
        self.attach.damping = 1;
        [self.attach setAnchorPoint:newLocation];
        [self.animator addBehavior:self.attach];

    }
    //update animations
    [self.animator updateItemUsingCurrentState:self.paddleViewAI];
    }
}

我可以在最后一个方法中使用 UISnap、UIAttach 或 UIView animateWithDuration,但正如我提到的 none 非常有效。我对任何建议持开放态度,或者只是让 UIAttach 至少工作会很可爱。

好吧,我从来没有让 UIAttachmentBehavior 工作,但我想出了如何让我的 AI 好但不完美。我最终使用了 UIPushBehavior。如果球在左边,我将 AI 桨推到左边,如果它在右边,则相同。这样我就可以修改桨的推动幅度和阻力来创造我想要的效果。

if (self.pushAI != nil) {
        [self.animator removeBehavior:self.pushAI];
    }
    //keep paddle inside view
    if (CGRectContainsRect(self.view.frame, newRect)) {
        //apply offsets
        self.pushAI = [[UIPushBehavior alloc] initWithItems:@[self.paddleViewAI] mode:UIPushBehaviorModeInstantaneous];
        if (self.paddleViewAI.center.x < self.ballView.center.x) {
            [self.pushAI setAngle:0 magnitude:self.difficultyMagnitude];
            [self.animator addBehavior:self.pushAI];
        }
        if (self.paddleViewAI.center.x > self.ballView.center.x) {
            [self.pushAI setAngle:M_PI magnitude:self.difficultyMagnitude];
            [self.animator addBehavior:self.pushAI];
        }

    }
    //update animations
    [self.animator updateItemUsingCurrentState:self.paddleViewAI];