I'm glad that this code does exactly what I wanted it to do...But I can't make sense of it although I wrote it from scratch myself. What I wanted to do was create an infinitely scrolling background.

What I figured I'd need to do was have it draw the entire background twice so that the second one comes in after the first one, and when the first one gets to the end it starts over behind the second one, and it would loop like this forever. However, after I wrote the code to make it scroll and tested it, it scrolls infinitely by just having the code draw the background once...

I have the function to draw the background like so...

void drawBackground(int xStart,int yStart,SDL_Rect *clip) {
  int x,y;  
  for(y=yStart;y<SCREENH;y=y+TILEH) {
    for(x=xStart;x<SCREENW;x=x+TILEW) {

And then I use the function like this to scroll the background...

bgX -= 1;
if(bgX==SCREENW) bgX=0;
bgY -= 1;
if(bgY==SCREENH) bgY=0;

drawBackground(bgX, bgY, bgClip);

It works perfectly...I just don't understand what makes it loop around with no gaps.

  • 2
    \$\begingroup\$ That is an interesting twist on "here"s my code where's the bug?". +1 :) \$\endgroup\$ Jan 12, 2013 at 10:38
  • \$\begingroup\$ Ha ha...Sometimes things go the opposite way and work when you don't expect them to. \$\endgroup\$
    – rzrscm
    Jan 12, 2013 at 11:04

2 Answers 2


There's actually a bug in your second code sample: assuming that SCREENW and SCREENH are positive, the if statements will never succeed and your bgX and bgY will just keep getting more and more negative. (Well, until they wrap around, anyway, which could take a while.)

Why does it still work, then? Well, you're drawing the tile repeatedly from bgX up to SCREENW and from bgY up to SCREENH. Presumably, your drawClip() function ignores attempts to draw outside the screen, so only the parts of the tiles that visible on the screen get drawn, and those parts are enough to cover the entire screen.

That said, if you left the code running for long enough, it would probably start to get slower as it wasted more and more time calling drawClip() for tiles that are entirely outside the screen.

So, how should you fix the bug, then? Well, bgX and bgY clearly must never be greater than zero, otherwise part of the screen would not be drawn. There's also no point in trying to draw tiles that are entirely outside the screen, which happens whenever bgX <= -TILEW or bgY <= -TILEH, so your code should look like this:

bgX -= speedX;
bgY -= speedY;

while (bgX > 0) bgX -= TILEW;
while (bgY > 0) bgY -= TILEH;
while (bgX <= -TILEW) bgX += TILEW;
while (bgY <= -TILEH) bgY += TILEH;

(Ps. I used while instead of if just to make sure that bgX and bgY end up in the valid range even in the unlikely case that the background movement speed exceeds one tile width/height per frame. It probably won't make any practical difference, but it's generally better to play it safe anyway. Of course, if you really were expecting such high movement speeds, you should rewrite this to use the % operator instead.)

  • \$\begingroup\$ Thanks for the nfo...I fixed that bug with some modifications of my own and I can see the performance difference. Now that I know what's going on in my code, hopefully I can better optimize it. \$\endgroup\$
    – rzrscm
    Jan 13, 2013 at 5:35

I'll explain it in one dimension only (the same is true for the other one):


This will start on the left border of the screen (or a bit outside depending on your bgX offset). It will then loop till the new drawing position is outside the screen (i.e. passed the right border of the screen; once the full line is drawn).

Just to note: you shouldn't wrap your offsets based on screen width/height (as these might not necessarily be multiples of your tile width/height). Usually you'd use the tile width/height so wrapping isn't noticeable and you don't draw too much outside the visible area.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .