[Game]Planet Escape [wip]

Fun fact: “For negative a, the value of a >> b is implementation-defined”.

I agree.
One of my golden rules when programming is “express your intent”, which for operating on integers means:

  • If you intended to treat an integer as a string of bits, use bitwise operators.
  • If you intended to operate on an integer as if it were a number, use arithmetic operators.
    • Let the compiler decide when and where to replace arithmetic operators with bitwise operators.

I’d be happy to have a look at the code when you’re ready to post it all.

A few small tips:

  • Using int16_t for arguments and locals doesn’t actually give you any benefit over int because the processor is 32 bit.
  • drawBitmap has an overload that accepts a ‘frame’ parameter which you could use instead of your tile array. (In fact, I suspect you might already be trying to do this, if tiles is actually const uint8_t tiles[].)
  • You don’t need to create an instance of Pokitto::Core, you can just use static functions, e.g. gb.display.drawBitmap becomes Pokitto::Display::drawBitmap

Also, but your world drawing function can be greatly simplified:

void world_draw(int x, int y)
{
	// Precalculate and cache loop bounds
	const int hStart = (y / 8);
	const int hEnd = (hStart + 16);

	const int wStart = (x / 8);
	const int wEnd = (wStart + 16);

	// Precalculate and cache loop offset;
	const int xOff = x + (x % 8);
	const int yOff = y + (y % 8);

	for(int h = hStart; h < hEnd; ++h)
		for(int w = wStart; w < wEnd; ++w)
		{
			if((h < 0) || (h >= WORLD_SIZE))
				continue;
			
			const std::size_t width = (w < 0) ? (w + WORLD_SIZE) : (w % WORLD_SIZE);
			Pokitto::Display::drawBitmap((w - xOff), (h - yOff), &tiles[world[h][width] * 34]);			
		}
}

(I think that works, but I can’t guarantee that I haven’t broken something.)

Sorry, I didn’t mean that the code doesn’t contain the problem, I think I was just focusing on the wrong part. The working example I posted does still exhibit the visual error. I changed the step and draw functions so that now the error appears by simply tapping left or right.

void world_step(){
  if( gb.buttons.repeat(BTN_LEFT,1) ){
    vx = -1;
    if( vx < -VEL_MAX ) vx = -VEL_MAX;
  }else if( gb.buttons.repeat(BTN_RIGHT,1) ){
    vx = 1;
    if( vx > VEL_MAX ) vx = VEL_MAX;
  }
  
  camx += vx;    
}

void world_draw(int16_t x, int16_t y){
    int16_t w,h;
    for( h = (y/8); h < (y/8)+16; h++ ){
      for( w = (x/8); w < (x/8)+16; w++ ){
        if( h >=0 && h < WORLD_SIZE ){
          if( w < 0 )
            gb.display.drawBitmap( w*8-x, h*8-y, &tiles[world[h][w+WORLD_SIZE]*34]);
          else
            gb.display.drawBitmap( w*8-x, h*8-y, &tiles[world[h][w%WORLD_SIZE]*34]);
        }
      }
    }
}

Oops, I think I had assumed it was 16-bit. I had been considering the possibility of porting it to 16/8-bit systems, so I might keep it that way for now.

Thanks, I might try that.

I’ll also take a closer look at adding your improvements to the drawing function.

Glad you both like it! I might try to add saving soon, but I have to figure out how I want to set up the menu option for that first. I want to keep the menu simple and quick to use.

If VEL_MAX is (2) and -VEL_MAX is -(2) then those tests are redundant because you’re setting vx to -1 or 1, so it will never be -2 or 2 by the time you do the tests.

The compiler probably even figures that out and removes the tests itself.

In that case, consider using int_fast16_t.
That will let the compiler use a 32-bit value if it thinks it will be faster.

If you want to question any of my changes, feel free to do so.

Those comparisons were there from before I simplified the example. I wasn’t setting vx to 1 and -1 before, but this simplified version will show the graphical glitch on the pokitto more consistently. The code I have has some other artifacts that do nothing from the code I am actually using for the game, but that’s because I was simplifying the code to try to narrow down what’s causing the glitch.

I’m actually starting to wonder whether my code is the culprit, because the correct bitmaps are being drawn in the correct locations, even the ones affected by the glitch. The problem is with the drawn bitmaps themselves, and it appears to be caused by bitmaps drawn partway off the screen. Very strange!

I have an idea of what the problem might be but it will take some time for me to get to look at it

2 Likes

@wuuff : I found the bug, and it was quite subtle. And it was my mistake.

Source of issue:

In the screenmode that you are using (Mode 2 , 110x88 pixels 16 colors), two 4-bit “nibbles”, in other words two pixels are packed into one byte. Leftmost pixel is the high nibble (top 4 bits) and right pixel is the low 4 bits.

I had the routine drawing pixels on the target pixel like so: targetpixel |= (sourcepixel & 0xF)<<4;

Now, the problem comes, when the background is not 0x00. (In your case it was 0xCC)

If the sourcepixel is 0x4 and background pixel is 0xCC, then targetpixel becomes 0xCC | (0x4<<4) = 0xCC, ie. it does not change

Solution
The top nibble of the target pixel needs to be first ‘emptied’ with targetpixel &= 0x0F, so that the top nibble bits all get reset to zero!

I will push the fix into the repository in the afternoon

2 Likes

I’m glad to hear that I was accidentally able to help find a bug in the drawing code! That’s a surprising edge case. I guess nobody had tried drawing over just the right background color in this mode before.

2 Likes

Yep. You had the perfect case.

But this I think is just positive … in the end, the quality of the code improves.

I will be pushing the fix to the repo very soon

2 Likes

Thanks Jonne!

I really want this game to have all the help it can have. This and @drummyfish Demo3 really caught my attention.

2 Likes

@wuuff !!!

The bugfix has been pushed to the repo. Please try now.

Thanks, that was fast! I see the update on github, but not on Mbed. I have been using the online Mbed compiler because I never set up anything locally (besides for the simulator, but I never set up a project for this game with the simulator). Is using Mbed still recommended?

Oops! I will update that also. Just a minute!

It’s now also in mbed online ide

@wuuff : Right-Click on PokittoLib folder under your project in the project tree in your mbed online compiler, choose “update”

Your framerate will improve if you don’t use Mbed.

1 Like

I don’t know what the official line is, but personally I recommend PlatformIO with a compatible IDE,
such as VSCode or Atom.

It works better, and there’s no more glitches on the left, but at certain offsets there is still a weird artifact on the right side:

The glitch can also be seen using the sample code I posted earlier, although it’s much less colorful.

3 Likes

Ok! Is it visible all the tine or just at times?

Not all the time, the camera needs to at a certain offset like before.

1 Like

Try to manage, I’ll take another look later today

1 Like

No rush, it doesn’t really impact gameplay, and like @BigBadHodad said, it looks kind of like what old NES games did, which is kind of neat. Of course, I’ll still update the library when you do find a fix, but it’s not a big problem.