是否有更有效的方式来绘制国际象棋棋盘?

时间:2013-12-30 13:33:29

标签: ios graphics

以下是我在我的应用程序中绘制棋盘的方法。除了使用静态图像之外,还有更有效或更明智的方法吗?

- (void)drawRect:(CGRect)rect {
    int verticalOffset = 40;
    int horizontalOffset = 0;
    int squareSize = 40;
    NSString *nextSquareColour = @"light";

    CGContextRef context = UIGraphicsGetCurrentContext();

    for (int i = 1; i <= 64; i++) {
        // define square position
        CGRect square = {horizontalOffset, verticalOffset, squareSize, squareSize};

        // set square to be light or dark in colour
        if ([nextSquareColour isEqualToString:@"dark"]) {
            // dark square
            CGContextSetRGBFillColor(context, 0.05, 0.05, 0.05, 0.80);
            nextSquareColour = @"light";
        } else {
            // light square
            CGContextSetRGBFillColor(context, 0.95, 0.95, 0.95, 0.80);
            nextSquareColour = @"dark";
        }
        CGContextSetStrokeColorWithColor(context, [UIColor
                                                   clearColor].CGColor);
        CGContextFillRect(context, square);
        CGContextStrokeRect(context, square);

        // set up colour and position of next square
        horizontalOffset = horizontalOffset + squareSize;
        if (i % 8 == 0) {
            verticalOffset = verticalOffset + squareSize;
            horizontalOffset = 0;
            nextSquareColour = @"dark";
        }
        if (i % 16 == 0) {
            nextSquareColour = @"light";
        }

    } // end for-loop



}

5 个答案:

答案 0 :(得分:1)

如果您只想填充纯色的方形单元格,则可以对每个单元格使用UIViewCALayer。为每个视图(图层)设置适当的背景,并将它们添加到superview(超级图层)。这将比绘制电路板消耗更少的内存。

其他选项是使用CAReplicatorLayer。但我认为第一种选择没有任何好处。

答案 1 :(得分:1)

除了UI之外,您要多次比较字符串。你可以通过以下方式避免它:

for(int row = 0; row < 8; row++)
{
     for(int column = 0; column < 8; column++)
     {
          CGRect square = {horizontalOffset  + (column * squareSize),
               verticalOffset + (row * squareSize),
               squareSize,
               squareSize};

          if((row + column) % 2 == 0)
               CGContextSetRGBFillColor(context, 0.05, 0.05, 0.05, 0.80);
          else
               CGContextSetRGBFillColor(context, 0.95, 0.95, 0.95, 0.80);

          CGContextSetStrokeColorWithColor(context, [UIColor
                                                     clearColor].CGColor);
          CGContextFillRect(context, square);
          CGContextStrokeRect(context, square);

     }
}

答案 2 :(得分:1)

除非导致视图在有限的时间间隔内重绘太多次,否则不应出现性能问题。从它的外观(棋盘)看,你的情况不应该发生。

你可以避免的一件事是绘制两种方形颜色。例如,您可以将深色设置为背景,并仅绘制浅色方块。 这是一个小课程:(颜色,大小和起始位置可设置)

@interface ChessView : UIView

@property (nonatomic, strong) UIColor *lightSquareColor; // default is 0.95f 0.95f 0.95f 0.8f

@property (nonatomic, strong) UIColor *darkSquareColor; // default is 0.05f 0.05f 0.05f 0.8f

@property (nonatomic) CGFloat squareSize; // default is 40.0f

@property (nonatomic) CGPoint boardOrigin; // default is {0.0f, 0.0f}

@end 


@implementation ChessView

@synthesize lightSquareColor = _lightSquareColor;
@synthesize darkSquareColor = _darkSquareColor;

#pragma mark - UIView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self baseInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self baseInit];
    }
    return self;
}

- (void)baseInit
{
    self.squareSize = 40.0f;
    self.boardOrigin = CGPointZero;
}

- (void)drawRect:(CGRect)rect
{
    CGFloat verticalOffset = self.boardOrigin.y;
    CGFloat horizontalOffset = self.boardOrigin.x;
    CGFloat squareSize = self.squareSize;

    CGContextRef context = UIGraphicsGetCurrentContext();
    // draw background with dark color
    [self.darkSquareColor setFill];
    CGContextFillRect(context, CGRectMake(horizontalOffset, verticalOffset, squareSize * 8.0f, squareSize * 8.0f));

    // Create a path and add light squares to it
    CGMutablePathRef path = CGPathCreateMutable();
    for (int i = 1; i <= 32; i++) {
        CGRect square = {horizontalOffset, verticalOffset, squareSize, squareSize};
        CGPathAddRect(path, NULL, square);

        horizontalOffset = horizontalOffset + 2.0f * squareSize;
        if (i % 4 == 0) {
            verticalOffset = verticalOffset + self.squareSize;
            horizontalOffset = i % 8 == 0 ? 0.0f : squareSize;
        }
    }
    [self.lightSquareColor setFill];
    CGContextAddPath(context, path);
    CGPathRelease(path);
    CGContextFillPath(context);
}

#pragma mark - Colors

- (UIColor *)lightSquareColor
{
    if (!_lightSquareColor) {
        _lightSquareColor = [UIColor colorWithRed:0.95f
                                            green:0.95f
                                             blue:0.95f
                                            alpha:0.8f];
    }
    return _lightSquareColor;
}

- (UIColor *)darkSquareColor
{
    if (!_darkSquareColor) {
        _darkSquareColor = [UIColor colorWithRed:0.05f
                                           green:0.05f
                                            blue:0.05f
                                           alpha:0.8f];
    }
    return _darkSquareColor;
}

- (void)setLightSquareColor:(UIColor *)lightSquareColor
{
    if (![_lightSquareColor isEqual:lightSquareColor]) {
        _lightSquareColor = lightSquareColor;
        [self setNeedsDisplay];
    }
}

- (void)setDarkSquareColor:(UIColor *)darkSquareColor
{
    if (![_darkSquareColor isEqual:darkSquareColor]) {
        _darkSquareColor = darkSquareColor;
        [self setNeedsDisplay];
    }
}

#pragma mark - Metrics

- (void)setBoardOrigin:(CGPoint)boardOrigin
{
    if (!CGPointEqualToPoint(_boardOrigin, boardOrigin)) {
        _boardOrigin = boardOrigin;
        [self setNeedsDisplay];
    }
}

- (void)setSquareSize:(CGFloat)squareSize
{
    if (_squareSize != squareSize) {
        _squareSize = squareSize;
        [self setNeedsDisplay];
    }
}

@end

答案 3 :(得分:1)

您可以使用直线破折号来简化整个事情。但我没有检查是否更高效。 类似的东西:

- (void)drawRect:(CGRect)rect {
    int verticalOffset = 40;
    int horizontalOffset = 0;
    int squareSize = 40;

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGFloat dashes[2] = { squareSize, squareSize};
    CGRect boardRect = {horizontalOffset, verticalOffset, squareSize * 8, squareSize * 8};
    CGFloat halfSquareSize = squareSize * .5;

    // Fill board with light color
    CGContextSetRGBFillColor(context, 0.95, 0.95, 0.95, 0.80);
    CGContextFillRect(context, boardRect);

    // Draw dark squares only by using line dashes
    CGContextSetRGBFillColor(context, 0.05, 0.05, 0.05, 0.80);
    CGContextSetLineWidth(context, squareSize);

    for (int i = 0; i < 8; i++)
    {
        if ((i & 0x1) == 0)
        {
            CGContextSetLineDash(context, squareSize, dashes, 2);
        }
        else
        {
            CGContextSetLineDash(context, 0, dashes, 2);
        }

        CGContextMoveToPoint(context, horizontalOffset, verticalOffset + i * squareSize + halfSquareSize);
        CGContextAddLineToPoint(context, horizontalOffset + 8 * squareSize, verticalOffset + i * squareSize + halfSquareSize);

        CGContextDrawPath(context, kCGPathFillStroke);
    }
}

答案 4 :(得分:0)

为什么不只有一张包含整个棋盘的黎明前图像