在网格中移动对象

时间:2013-12-26 23:41:47

标签: ios objective-c cocoa-touch

我正试图让这些盒子在网格中自由移动,但仍然尊重这些简单的规则:

  1. 一个盒子一次只能朝一个方向移动。
  2. 框不能重叠或突破网格。
  3. 现在他们从一个细胞跳到另一个细胞,现在我让它们自由移动?如果在X轴上通过触摸移动一个点,则该框也应仅移动一个点 - 而不仅仅是动画到下一个网格。

    然后在touchesEnded / touchesCanceled上,我可以将框捕捉到最近的网格。

    感谢。

    Grid with boxes

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        if (![self canMove])
            return;
    
        UITouch *touch = [touches anyObject];
        CGPoint location = [touch locationInView:self.superview];
    
        CGPoint cell = [self.grid getCellFromLocation:location];
        BOOL allowMove = [self canMoveTo:cell.x y:cell.y];
    
        if (allowMove) {
            CGRect rect = [self.grid getCellRect:self.grid.gridView x:cell.x y:cell.y];
    
            [self moved:cell.x y:cell.y];
            self.frame = rect;
        }
    }
    

2 个答案:

答案 0 :(得分:0)

你的代码不是最好的实现那种漂亮的动画,但这对你来说可能是一个可能的解决方案,但是对我来说它看起来有点难看,但是这个小扩展会为你提供一个你可以在以后确定的想法任何时候。

如此。


将其添加到 Box.h 文件中:

@interface Box : UIView {
    BOOL _isAnimationInProgress;
}

而不是这一行:

@interface Box : UIView

并使用这些更改覆盖 Box.m

- (id)initWithType:(NSInteger)type x:(NSInteger)x y:(NSInteger)y grid:(Grid*)grid {
    _isAnimationInProgress = FALSE;

    // (...)

}

以下-touches...方法应如下所示:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (![self canMove])
        return;

    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.superview];

    CGPoint cell = [self.grid getCellFromLocation:location];
    BOOL allowMove = [self canMoveTo:cell.x y:cell.y];

    if (allowMove && _isAnimationInProgress == FALSE) {
        _isAnimationInProgress = TRUE;

        didMove = YES;
        CGRect rect = [self.grid getCellRect:self.grid.gridView x:cell.x y:cell.y];

        [UIView animateWithDuration:0.3f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            if (CGRectContainsPoint(rect, location)) {
                [self moved:cell.x y:cell.y];
                self.frame = rect;
            }
        } completion:^(BOOL finished) {
            _isAnimationInProgress = FALSE;
        }];
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    _isAnimationInProgress = FALSE;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    _isAnimationInProgress = FALSE;
}

注意:这是我用你的代码结构做的最好的。

答案 1 :(得分:0)

这就是我最终做的事情,这使得盒子一次向一个方向移动,然后允许它在网格单元内部时改变方向。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.superview];

    CGPoint offset = CGPointMake(self.center.x + location.x - self.lastLocation.x, self.center.y + location.y - self.lastLocation.y);
    CGPoint closestCenter = [self closestCenter:offset]; // Finds the closest grid cell center
    CGRect rect = CGRectMake(offset.x - (self.size.width / 2), offset.y - (self.size.height / 2), self.size.width, self.size.height);

    if (fabsf(closestCenter.x - offset.x) < fabsf(closestCenter.y - offset.y)) {
        offset.x = closestCenter.x;
    }
    else {
        offset.y = closestCenter.y;
    }

    if ([self collisionLeftRight:rect]) { // Check collision against left/right side
        offset.x = self.center.x;
    }

    if ([self collisionTopBottom:rect]) { // Check collision against top/bottom side
        offset.y = self.center.y;
    }

    self.lastLocation = location;
    self.center = offset;
}