Cocos2d: Moving background on update: offsett issue
- by mm24
working with Objective C, iOS and Cocos2d I am developing a vertical scrolling shooter game for iPhone (retina display models with 640 width x 960 height pixel resolution).
My basic algorithm works as following:
I create two instances of an image that has exactly 640 width x 960
height pixel of resolution, which we will call imageA and imageB
I then set the two imags with exactly 480.0f of offset from each other, as
the screenSize of a CCScene is set by default to 480.0f.
At each update method call I move the two images by the same value. I make sure that their offsett stays to 480.0f
However when running the game I see a 1 pixel height line between the two images. This literally bugs me and would like to adjust this.
What am I doing wrong?
This is a zoom in on the background when the "offsett line" is visible. The white line you can see divides the two background images and is not meant to exist as both images are completely black :):
If I change the yPositionOfSecondElement value to 479.0f until the first loop the two images overlap correctly, but as soon as the loop starts the two images starts having an offsett of -1.0f.
Here is the initialization code:
-(void) init
{
//...
screenHeight = 480.0f;
yPositionOfSecondElement= screenHeight;//I tried subtracting an offsett of -1 but eventually the image would go wrong again
yPositionOfFirstElement = 0.0f;
loopedBackgroundImageInstanceA = [BackgroundLoopedImage loopImageForLevel:levelName];
loopedBackgroundImageInstanceA.anchorPoint = CGPointMake(0.5f, 0.0f);
loopedBackgroundImageInstanceA.position = CGPointMake(160.0f, yPositionOfFirstElement);
[node addChild:loopedBackgroundImageInstanceA z:zLevelBackground];
//loopedBackgroundImageInstanceA.color= ccRED;
loopedBackgroundImageInstanceB = [BackgroundLoopedImage loopImageForLevel:levelName];
loopedBackgroundImageInstanceB.anchorPoint = CGPointMake(0.5f, 0.0f);
loopedBackgroundImageInstanceB.position = CGPointMake(160.0f, yPositionOfSecondElement);
[node addChild:loopedBackgroundImageInstanceB z:zLevelBackground];
//....
}
And here is the move code called at each update:
-(void) moveBackgroundSprites:(BackgroundLoopedImage*)imageA :(BackgroundLoopedImage*)imageB :(ccTime)delta
{
isEligibleToMove=false;
//This is done to avoid rounding errors
float yStep = delta * [GameController sharedGameController].currentBackgroundSpeed;
NSString* formattedNumber = [NSString stringWithFormat:@"%.02f", yStep];
yStep = atof([formattedNumber UTF8String]);
//First should adjust position of images
[self adjustPosition:imageA :imageB];
//The can get the actual image position
CGPoint posA = imageA.position;
CGPoint posB = imageB.position;
//Here could verify if the checksum is equal to the required difference (should be 479.0f)
if (![self verifyCheckSum:posA :posB]) {
CCLOG(@"does not comply A");
}
//At this stage can compute the hypotetical new position
CGPoint newPosA = CGPointMake(posA.x, posA.y - yStep);
CGPoint newPosB = CGPointMake(posB.x, posB.y - yStep);
// Reposition stripes when they're out of bounds
if (newPosA.y <= -yPositionOfSecondElement)
{
newPosA.y = yPositionOfSecondElement;
[imageA shuffle];
if (timeElapsed>=endTime && hasReachedEndLevel==FALSE) {
hasReachedEndLevel=TRUE;
shouldMoveImageEnd=TRUE;
}
}
else if (newPosB.y <= -yPositionOfSecondElement)
{
newPosB.y = yPositionOfSecondElement;
[imageB shuffle];
if (timeElapsed>=endTime && hasReachedEndLevel==FALSE) {
hasReachedEndLevel=TRUE;
shouldMoveImageEnd=TRUE;
}
}
//Here should verify that the check sum is equal to 479.0f
if (![self verifyCheckSum:posA :posB]) {
CCLOG(@"does not comply B");
}
imageA.position = newPosA;
imageB.position = newPosB;
//Here could verify that the check sum is equal to 479.0f
if (![self verifyCheckSum:posA :posB]) {
CCLOG(@"does not comply C");
}
isEligibleToMove=true;
}
-(BOOL) verifyCheckSum:(CGPoint)posA :(CGPoint)posB
{
BOOL comply = false;
float sum = 0.0f;
if (posA.y > posB.y) {
sum = posA.y - posB.y;
}
else if (posB.y > posA.y){
sum = posB.y - posA.y;
}
else{
return false;
}
if (sum!=yPositionOfSecondElement) {
comply= false;
}
else{
comply=true;
}
return comply;
}
And here is what happens on the update:
if(shouldMoveImageA && shouldMoveImageB)
{
if (isEligibleToMove) {
[self moveBackgroundSprites:loopedBackgroundImageInstanceA :loopedBackgroundImageInstanceB :delta];
}
Forget about shouldMoveImageA and shouldMoveImageB, this is just for when the background reaches the end of level, this works.