C++ SDL switch not working properly

Started by
2 comments, last by rip-off 10 years, 10 months ago

Can anyone spot an error in this small code section?, when I separate it up and manual enter the coords for .x and .y it works fine, but as the clipboard size is likely to grow by quite a bit, I wanted to automate the loading process.

The error I am getting is that when Blit-ing a clip that's loaded in the for loop - its coming up blank. my loaded graphic (clipboard) has 7 images across and 4 images down, each image is 30 pixels across.

anyway the code :


void Player1::Set_CLips()
{
	int i,n;
	
	for (i=0; i < totalFrames; i++)
	{
		  switch(i)
        {
		  case 0: case 1: case 2: case 3: case 4: case 5: case 6:
		  	  CLip[i].x = (i * 30);
			  CLip[i].y = 0;
			  CLip[i].h = 30;
			  CLip[i].y = 30;
			  break;
		  case 7:case 8:case 9:case 10:case 11:case 12:case 13:
			n = i-7;
			  CLip[i].x = (n * 30);
			  CLip[i].y = 31;
			  CLip[i].h = 30;
			  CLip[i].y = 30;
			 break;
		  case 14:case 15:case 16: case 17:case 18:case 19:case 20:
			  n = i - 14;
			  CLip[i].x = (n * 30);
			  CLip[i].y = 61;
			  CLip[i].h = 30;
			  CLip[i].y = 30;
			  break;
		  case 21:case 22:case 23:case 24:case 25:case 26:case 27:
			  n = i - 21;
			  CLip[i].x = (n * 30);
			  CLip[i].y = 91;
			  CLip[i].h = 30;
			  CLip[i].y = 30;
			 break;    
		}
	}


}
Advertisement

You have CLip.y twice, not sure if that is your problem but you should fix that.

Crusable, you sir are a genius with the eyesight of the hawk, I have been looking at that code for hours and couldn't see the wood for the trees.. lol, yes, that was a stupid error on my part.. should have been .w for width .

Cheers buddy.

There is another way of doing this. Let us make an example program that shows what you're trying to achieve (corrected with Crusable's fix, and one or two stylistic changes):

#include <iostream>
 
struct Rect {
    int x, y, w, h;
};
 
int main()
{
    const int totalFrames = 28;
    Rect Clip[totalFrames];
    
    for (int i = 0; i < totalFrames; i++)
    {
        int n;
        switch(i)
        {
          case 0: case 1: case 2: case 3: case 4: case 5: case 6:
              Clip[i].x = (i * 30);
              Clip[i].y = 0;
              Clip[i].h = 30;
              Clip[i].w = 30;
              break;
          case 7:case 8:case 9:case 10:case 11:case 12:case 13:
              n = i-7;
              Clip[i].x = (n * 30);
              Clip[i].y = 31;
              Clip[i].h = 30;
              Clip[i].w = 30;
             break;
          case 14:case 15:case 16: case 17:case 18:case 19:case 20:
              n = i - 14;
              Clip[i].x = (n * 30);
              Clip[i].y = 61;
              Clip[i].h = 30;
              Clip[i].w = 30;
              break;
          case 21:case 22:case 23:case 24:case 25:case 26:case 27:
              n = i - 21;
              Clip[i].x = (n * 30);
              Clip[i].y = 91;
              Clip[i].h = 30;
              Clip[i].w = 30;
             break;    
        }
    }
    
    for(int i = 0 ; i < totalFrames ; ++i) {
        const Rect &rect = Clip[i];
        std::cout << i << ":\t" << rect.x << ", " << rect.y << ", " << rect.w << ", " << rect.h << std::endl;
    }
}
Note that loop variables should be declared in the loop. I've also moved "n" inside the loop, there is more we could with "n" but this suffices as a starting point.
Running this program produces some "reference" output:

0: 0, 0, 30, 30
1: 30, 0, 30, 30
2: 60, 0, 30, 30
3: 90, 0, 30, 30
4: 120, 0, 30, 30
5: 150, 0, 30, 30
6: 180, 0, 30, 30
7: 0, 31, 30, 30
8: 30, 31, 30, 30
9: 60, 31, 30, 30
10: 90, 31, 30, 30
11: 120, 31, 30, 30
12: 150, 31, 30, 30
13: 180, 31, 30, 30
14: 0, 61, 30, 30
15: 30, 61, 30, 30
16: 60, 61, 30, 30
17: 90, 61, 30, 30
18: 120, 61, 30, 30
19: 150, 61, 30, 30
20: 180, 61, 30, 30
21: 0, 91, 30, 30
22: 30, 91, 30, 30
23: 60, 91, 30, 30
24: 90, 91, 30, 30
25: 120, 91, 30, 30
26: 150, 91, 30, 30
27: 180, 91, 30, 30
There are some patterns here we can exploit. The first obvious pattern is that the width and height are contant regardless of the index. So we can quickly move them out of the switch:

for (int i = 0; i < totalFrames; i++)
{
    Clip[i].h = 30;
    Clip[i].w = 30;
    
    int n;
    switch(i)
    {
      case 0: case 1: case 2: case 3: case 4: case 5: case 6:
          Clip[i].x = (i * 30);
          Clip[i].y = 0;
          break;
      case 7:case 8:case 9:case 10:case 11:case 12:case 13:
          n = i-7;
          Clip[i].x = (n * 30);
          Clip[i].y = 31;
         break;
      case 14:case 15:case 16: case 17:case 18:case 19:case 20:
          n = i - 14;
          Clip[i].x = (n * 30);
          Clip[i].y = 61;
          break;
      case 21:case 22:case 23:case 24:case 25:case 26:case 27:
          n = i - 21;
          Clip[i].x = (n * 30);
          Clip[i].y = 91;
         break;    
    }
}
What about X? We can compute this by taking the remainder of i and 7 using the modulus operator, and multiplying this result by 30:

 
for (int i = 0; i < totalFrames; i++)
{
    Clip[i].x = (i % 7) * 30;
 
    Clip[i].h = 30;
    Clip[i].w = 30;
    
    switch(i)
    {
      case 0: case 1: case 2: case 3: case 4: case 5: case 6:
          Clip[i].y = 0;
          break;
      case 7:case 8:case 9:case 10:case 11:case 12:case 13:
          Clip[i].y = 31;
         break;
      case 14:case 15:case 16: case 17:case 18:case 19:case 20:
          Clip[i].y = 61;
          break;
      case 21:case 22:case 23:case 24:case 25:case 26:case 27:
          Clip[i].y = 91;
         break;    
    }
}
Note that "n" is no longer needed, but you can store the modulus result in a temporary if you find that easier to read.
Y is a little trickier, because you have a slightly unusual pattern. If the first 7 cases had y = 1, it would be very easy: simply divide i by 7 and multiply by 30, and add one. However, Y starts at 0 for the first 7. I actually think this is probably a mistake, you probably intend y to start at 1, or that the others should all be reduced by one, but let us go with the original for the time being.
We can handle by conditionally reducing Y for the first few iterations:

for (int i = 0; i < totalFrames; i++)
{
    Clip[i].x = (i % 7) * 30;
    Clip[i].y = (i / 7) * 30;

    if(i >= 7) {
        Clip[i].y += 1;
    }

    Clip[i].h = 30;
    Clip[i].w = 30;
}
We could combine this into a single expression, but this is difficult to understand:

 
for (int i = 0; i < totalFrames; i++)
{
    Clip[i].x = (i % 7) * 30;
    Clip[i].y = (i >= 7) + ((i / 7) * 30);
    Clip[i].h = 30;
    Clip[i].w = 30;
}
In any case,we might also consider is naming some of these constants:

const int CLIP_SIZE = 30;
const int FRAMES_PER_ROW = 7;
 
// ...
 
for (int i = 0; i < totalFrames; i++)
{
    Clip[i].x = (i % FRAMES_PER_ROW) * CLIP_SIZE;
    Clip[i].y = (i / FRAMES_PER_ROW) * CLIP_SIZE;

    Clip[i].y = (i / FRAMES_PER_ROW) * 30;

    if(i >= FRAMES_PER_ROW) {
        Clip[i].y += 1;
    }


    Clip[i].h = CLIP_SIZE;
    Clip[i].w = CLIP_SIZE;
}
Another thing we can do is use a reference to make the code easier to read:

for (int i=0; i < totalFrames; i++)
{
    Rect &rect = Clip[i]
    rect.x = (i % FRAMES_PER_ROW) * CLIP_SIZE;

    rect.y = (i / FRAMES_PER_ROW) * CLIP_SIZE;

    if(i >= FRAMES_PER_ROW) {
        rect.y += 1;
    }


    rect.h = Clip_SIZE;
    rect.w = Clip_SIZE;
}
Putting this all together, we get the following example program:


#include <iostream>
 
struct Rect {
    int x, y, w, h;
};
 
int main()
{
    const int CLIP_SIZE = 30;
    const int FRAMES_PER_ROW = 7;
    const int TOTAL_FRAMES = FRAMES_PER_ROW * 4;
    
    Rect Clip[TOTAL_FRAMES];
    
    for (int i=0; i < TOTAL_FRAMES; i++)
    {
        Rect &rect = Clip[i];
        rect.x = (i % FRAMES_PER_ROW) * CLIP_SIZE;
        rect.y = (i / FRAMES_PER_ROW) * CLIP_SIZE;
        if(i >= FRAMES_PER_ROW) {
            rect.y += 1;
        }
        rect.h = CLIP_SIZE;
        rect.w = CLIP_SIZE;
    }
    
    for(int i = 0 ; i < TOTAL_FRAMES ; ++i) {
        const Rect &rect = Clip[i];
        std::cout << i << ":\t" << rect.x << ", " << rect.y << ", " << rect.w << ", " << rect.h << std::endl;
    }
}

If you run this, you'll get identical output to the original, so we know it is still doing the same thing!

This topic is closed to new replies.

Advertisement