1
votes

Being new to the obj-c language and Sprite kit I'm having difficulties positioning a rectangle in a grid...

There's an offset in the rectangles I create - if I manage to get the code to position a rectangle in a chosen field another rectangle will be offset...

I have tried several different approches and I can get it to work using JavaFX. What am I doing wrong?

The photo below shows my problem clearly.

enter image description here

My code is rather simple and can be seen here:

#import "MyScene.h"

@implementation MyScene

const int ROWS = 10;

-(id)initWithSize:(CGSize)size {    
if (self = [super initWithSize:size]) {
    /* Setup your scene here */

    self.backgroundColor = [SKColor darkGrayColor];

    [self createBoardWithRows:ROWS];

    [self createBoxPositionX:1 positionY:1];
    [self createBoxPositionX:3 positionY:3];
    [self createBoxPositionX:5 positionY:5];

}
return self;
}

-(void) createBoardWithRows: (int) rows{

for (int i = 1; i < rows; i++){

    //Horisontal lines
    int yPos = self.size.height/rows * i;

    SKShapeNode *lineH = [SKShapeNode node];
    CGMutablePathRef pathToDraw = CGPathCreateMutable();

    CGPathMoveToPoint(pathToDraw, NULL, 0, yPos);
    CGPathAddLineToPoint(pathToDraw, NULL, self.size.width, yPos);

    lineH.path = pathToDraw;
    lineH.lineWidth = 1.0;
    [lineH setStrokeColor:[UIColor blackColor]];


    //Vertical Lines
    int xPos = self.size.width/rows * i;

    SKShapeNode *lineV = [SKShapeNode node];

    CGPathMoveToPoint(pathToDraw, NULL, xPos, 0);
    CGPathAddLineToPoint(pathToDraw, NULL, xPos, self.size.height);

    lineV.path = pathToDraw;
    lineV.lineWidth = 1.0;
    [lineV setStrokeColor:[UIColor blackColor]];

    //Add lines
    [self addChild:lineH];
    [self addChild:lineV];
}
}

-(void) createBoxPositionX:(int) fieldIndexX positionY:(int) fieldIndexY{

int width = self.size.width/ROWS;
int height = self.size.height/ROWS;

int x = (width * fieldIndexX);
int y = (height * fieldIndexY);

CGRect box = CGRectMake(x, y, width, height);

SKShapeNode *shapeNode = [[SKShapeNode alloc] init];
shapeNode.path = [UIBezierPath bezierPathWithRect:box].CGPath;
shapeNode.fillColor = SKColor.yellowColor;
//Stroke settings
shapeNode.strokeColor = [SKColor clearColor];
shapeNode.lineWidth = 0;
[self addChild:shapeNode];

//Alternative rectangle
//SKSpriteNode spriteNodeWithColor:CGSize:
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
}

-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}

@end

2
It almost seems like you're not taking into account the line width of the border in each box - so when you create the yellow boxes they are displaced by the number of points equivalent to the number of "borders". - KerrM

2 Answers

3
votes

It almost seems like you're not taking into account the line width of the border in each box - so when you create the yellow boxes they are displaced by the number of points equivalent to the number of "borders".

To fix this, change these two lines:

int x = (width * fieldIndexX);
int y = (height * fieldIndexY);

to:

int x = (width * fieldIndexX) + fieldIndexX;
int y = (height * fieldIndexY) + fieldIndexY;
0
votes

If you are getting 1 pixel shifts into any direction it might be anchor point issue. By default it is 0.5,0.5 - at center of the sprite. So if your sprite has even length for example 4, the middle can fall on either 2 or 3 and you will get 1 pixel off positioning.

The fix for this is clear, set the anchor point of node to 0,0, like so:

node.anchorPoint = CGPointMake(0,0);

What this does is that the sprite is pinned to it parent with lower left corner instead of center. Since the lower left corner always starts at 0,0 pixel you will have correct positions regardless of pixel count of your nodes.

But you will have to adjust the nodes position to accomodate this change.

Hope this helps.