Using frame buffering to solidify tft displayed objects

Status
Not open for further replies.
Actually the frame buffer is one size. But if memory serves me, if you set a clipping rectangle to some boundary of the screen, it will only update that portion of the screen.

At one point I was going to update the library to keep a bounding rectangle for the "dirty rectangle", but never got around to it. As I did not need it.
 
Still keying in the camera stuff but I did a small experiment of changing the player movement speed to 10 this doubled the speed of travel with in the boundary to a less annoying speed. But yea the problem besides the flashing of the character is that when the player hits the boundary and the camera starts to scroll, it scrolls at only one column or row of pixels at a time. Believe to not the tilemap doesn't flash and is smooth when scrolled it's just slow.

Yea my theory that planting a bitmap on top of another bitmap is gonna cause flicker because the code doesn't know what the dominant bit map should be is proving to be true. Tilemap is called first so it's the dominant image being displayed and stays solid while the second image is flashed. I was thinking a bitmap image with white and transparent pixels that could be displayed under the player at all times. But we would still be calling secondary and third part bitmaps to the same area which is the problem.

You idea sounds good but I wouldn't know how to implement it.

Edit::::

With the screen buffer on and the tile map off the player bitmap remains solid as it should. So it definitely needs some kind of mask that can clear just the pixels under the given Sprite and clear pixels around that. As far as trails go, you can't see them under the tile map
 
Last edited:
The way to have flicker free images is to never have a pixel on the screen that is incorrect. Here incorrect means that it is not part of the final image the user should see. If you draw just the background to the screen there is a period of time that the user will see the background without the sprite on top.

I think the correct way to use the frame buffer would be to turn it on in setup() and leave it on. All writes ( even your background ) go to the frame buffer. Write the background first. You then write your sprites on top of the background in the frame buffer. When the image ( in memory ) is complete you call the function that transfers the frame buffer to the screen. If you do this it will not flicker and I think you will get maybe 20 frames a second?
 
If I were writing this, I think I would try the following combination of page flipping and a variation of dirty scanlines. The idea here is the only screen writes that are necessary are performed since that seems to be the slow part of the process. You have 4 bits per pixel, so 8 pixels will fit in a 32 bit unsigned integer.

Set up two arrays of 32 bit integers - you can make these double subscripted if you like. They would each need to be 240*320/8 in total size.

Basic page flipping:
You write your image in 4 bpp format to one of the memory arrays. When it is complete with the background and sprites on top, you call a function that writes that out to the screen via palette map lookups.
The next frame of your animation gets written to the 2nd array in 4bpp format. When it is complete you call the function that writes that out to your screen via palette map lookups. You then repeat.

A variation of that is to always write to array number 1 and display that. Then copy all of array 1 to array 2. This keeps the functions simpler and more straight forward. Lets go with that method.

Well that is a lot of work and it didn't gain a thing. So enter the dirty scanline part.

You write your image to array number 1. During the write to screen function, you xor the entry in array number 1 with the corresponding entry in array number 2. Only if the result is not zero do you actually write those 8 nibbles to the screen. ( and you could narrow that down to just the pixels that change, but I think a 32x32 bit xor is going to be very fast without all the masking and shifting that would be needed to get just the pixels that changed ). When all the dirty parts have been written to the screen, you do the copy from array number 1 to array number 2. And then repeat.

This would be very fast I think and accommodates all the features of your system of sprites on top of a background where the background is bigger than the screen size. It will slow down a bit when you scroll the background, but still would be very fast.
 
Again if it were me, I would probably do lots of things. But again it all starts out with understanding exactly what you expect on the screen and sort of a logical flow chart showing how all of the updates happen and how the interact. That is what things are logically on top of other things...

And again this may have to be done logically for several different types of information. And again setup logical test setups for them. Then see if there are ways to optimize the screen updates. Example if your code starts off doing something like: tft.fillScreen()... Dirty bits or rectangles is not going to help as they are all dirty. Also understanding that there is overhead with starting up new drawing area. That is why Opaque text which updates every bit in the rectangle is a lot faster than Transparent which only a portion of the bits.

Example: if the logical operation is to move a sprite from one location to the next one. In most cases, I would think the two location would be pretty close to each other... Maybe a pixel or two in either or both directions?

What happens if you simply set a clipping rectangle for the union of those two rectangles? I am pretty sure there is code in the updateScreen method that will only output that portion of the display. So just before you call updateScreen, turn on the clipRectangle... Probably just before the call as to allow the rest of FB to be updated if your calls are outside this range. and then turn it off after the call to updateScreen?

But again this all starts with you understanding each of your operations and know exactly what effect you are expecting
 
You idea sounds good but I wouldn't know how to implement it.

Hey DuhJoker, perhaps I am a bit over zealous in proposing ideas. Here is what I think you should do:

1) enable the framebuffer in setup(). Do not disable it anywhere.
2) remove your framebuffer code in your direction 2 routine.
3) do not add a updateScreen yet.
4) run the program. If anything writes to the screen you need to find that and change it to write to the framebuffer. So if your tile maps show, you will need to look at your drawTilemap function and change it to write to the framebuffer.
5) When all is blank, add one updateScreen in your loop at the end of all the drawing of objects.

You should now have a basic system that will not flash and flicker. You can then look at speeding it up with the rectangle clipping.

One thing you should correct is to put your button down, up, left, right, and your player direction up,down,left,right into one big if, if else, if else ..... as the way I see it would work now is that your direction sprite will over write your walking sprite and the walking sprites will not show.
 
Looks I gained a new user over the weekend. Lol that's two! But two is better than zero!

I was able to add camera speed to the camera controls and the character moves a lot better when he hits the boundary. Far less annoying!!! And a lot smoother. It can be sped up down as well. So say I want to immatate deep sand I can set the camera and character speed for those tiles.

I'm still reading all that you've written. I've been translating characters into bit code but I hope to try your suggestion at some point tonight. I'm hoping this works.

I am curious though as to why the character moves ultrafast with put tiles but I have to set the character speed to 5x that of no tiles or he walks incredibly slow. I've tried this with and with out using collision with the same results.

I also killed the all in one library today over the seperate libraries.
 
Last edited:
Ok moved every thing back to the new laptop. Updated the github libraries and deleted the all in one. Then I ran my sketch.
When I compile it every thing shows up with the frameBuffer turned on in the set up. So how exactly do I write the tilemap to the frame buffer?
 
All right. I have enough character sprites for now. I would like to figure this out so I quit bugging you guys.:p

I don't mean to be dense but what does writing a function actually entail. As it stands I followed rcarrs post and placed the frameBuffer in the set up and removed the stuff in the player direction. But every thing shows up.
 
Sorry that was my fault. I know the basics of how to write a function, well sometimes. Any way what I meant was that I put the frameBuffer que in the set up function but how do I write the functions into the frame buffer. Rcarrs 4th step in post #81.

I mean all the functions I'm using have frame buffer code written into the function on the cpp side. Most of the functions do. Or they use a helper that has the FB code written into it.
 
Last edited:
I have company for a couple of days and won't be much help. I suggest you search your program for any updateScreen function calls. Make sure they are all commented out.

Once you enable the framebuffer, all the writes should go there. If not, then you would need to follow the functions called and see if the program is using something that writes the screen that does not have the use framebuffer code. I would expect maybe fillscreen will write to the screen and that is ok, but most functions should be framebuffer enabled.

I just signed up on github. I see your library there but not your main program that has setup(), loop(), bitmaps, tilemaps, spritemaps. How do I find that part of your work?
 
I would like both if you can do it in lay terms. I understand. I still have a ton of work to do and things to figure out for the game. We'll get it figured out eventually. I went ahead and posted the project on github as the Dune demo for the GameR-Iot if you still want to look it over.

I've made a few changes mostly the camera and more player sprites. Almost done with the mains. Have 11 more then some generic characters. I lost all my monster sprites when the beast crashed a month or so back so now I get to remake those. Then a desert backdrop to display the monsters on. Might try those on SD since they don't need to move or any thing.
 
Last edited:
As a quick guess, you have this.

Code:
uint8_t use_fb = 0;
......
tft.useFrameBuffer(use_fb);
uint32_t start_time = millis(); 
use_fb = !use_fb;
Try
Code:
 uint8_t use_fb = 1;
.......
  tft.useFrameBuffer(use_fb);
  uint32_t start_time = millis(); 
  // use_fb = !use_fb;

The difference being we are going to call useFrameBuffer with a True value instead of False. Might not make any difference but worth a try.
 
Well I was going by the example but I get what you mean. Good news every one!!!!

It worked and now the screen only shows black. So what next please.

Edit:::::


Ok I added tft.updateScreen(); to the end of the void loop and now it's solid!!!!! Thank you thank you thank you!!!!!!!! Happy happy joy joy happy joy joy HAPPY HAPPY!


So nice!!! It even stopped flashing the tilemap when it scrolled. Still has an after image flash of the character when moved but only when moving fast. I'm extremely happy with it.

https://youtu.be/RkjMWnHrJNM

Edit:::

Humour in programming..... The other day I was working hard on my game and trying to fix every thing and I was asked what I wanted to eat from a certain restaraunt and I replied with some else if statements. Not even realizing what I was doing. Lol


Edit::::

Also with the frame buffer working the character isn't forcibly moving so I can set it and the camera back down to 2 pixel rows and columns per movement.
 
Last edited:
Only 3 things left to fix. Collision, titlescreen and popup. But as I need collision to be able to move onto the next aspect of the game which is having the player touch a tile and the map changes for like towns or dungeons or what ever. I have the change map code but im having trouble with the collision period.

ive been trying to fix this just as long as the buffer but figured id wait til I was completely stuck. The first thing to note is that the collide functions have not been altered. they were written for 16x16 bitmaps as I understand.

Code:
  void        drawBitmapTM(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *bitmap, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh,  uint16_t color);
	boolean     getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y);

	void        drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, const uint16_t * palette);
	void        drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, const uint16_t * palette);

	typedef struct {       //line 171 "Public Variables   - ADD by Summoner123
		int x;                    //X coordinate                 - ADD by Summoner123
		int y;                    //Y coordinate                 - ADD by Summoner123
		const byte *spritecol;    //Sprite of object             - ADD by Summoner123
	}object;
	object solid[60];         // Matriz were saved a Sprite, X and Y cordinates of all tiles on the screen - ADD by Summoner123

	byte numcolision = 0;     //count of solid objects indacat how many tiles drawed on the screen - ADD by Summoner123

	bool flagcollision = true;

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
//////////////-----------------------------Collision--------------------------//////////////
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////

	boolean collidePointRect(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t w, int16_t h);
	boolean collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1, int16_t x2, int16_t y2, int16_t w2, int16_t h2);
	boolean collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2);

and here is the cpp stuff
Code:
void GrafxT3::writeRect4BPPtm(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, const uint16_t * palette )
{
	dw += dx;
	dh += dy;{
//	int32_t largest = 0;
//	int32_t largesty = 0;
		int16_t drawX = x;
				int16_t drawY = y;

				if (drawX >= dx && drawX < dw && drawY >= dy && drawY < dh){
	// Simply call through our helper
	writeRectNBPP(x, y, w, h,  4, pixels, palette );
        }
    }
}

boolean GrafxT3::getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y){
	return pgm_read_byte(bitmap + 2 + y * ((pgm_read_byte(bitmap) + 7) / 8) + (x >> 3)) & (B10000000 >> (x % 8));
}

void GrafxT3::drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, const uint16_t * palette){
	drawTilemap(x, y, tilemap, spritesheet, 0, 0, GrafxT3_TFTHEIGHT, GrafxT3_TFTWIDTH, palette);
}
void GrafxT3::drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, const uint16_t * palette){
	uint16_t tilemap_width = pgm_read_byte(tilemap);
	uint16_t tilemap_height = pgm_read_byte(tilemap + 1);
	uint16_t tile_width = pgm_read_byte(tilemap + 2);
	uint16_t tile_height = pgm_read_byte(tilemap + 3);
	tilemap += 4; // now the first tiyleis at tilemap
	uint16_t ddw = dw + dx;
	uint16_t ddh = dh + dy;
	uint16_t maxDdx = (dw - x + tile_width - 1) / tile_width;
	uint16_t maxDdy = (dh - y + tile_height - 1) / tile_height;
	if (tilemap_width < maxDdx){
		maxDdx = tilemap_width;
	}
	if (tilemap_height < maxDdy){
		maxDdy = tilemap_height;
	}
	int16_t startDdx = (-x) / tile_width;
	int16_t startDdy = (-y) / tile_height;
	if (startDdx < 0){
		startDdx = 0;
	}
	if (startDdy < 0){
		startDdy = 0;
	}
	if (flagcollision)numcolision = 0;                                 //Line 735 - clear numcolision - ADD by Summoner123

	for (uint16_t ddy = startDdy; ddy < maxDdy; ddy++){
		for (uint16_t ddx = startDdx; ddx < maxDdx; ddx++){
			int16_t drawX = ddx*tile_width + x + dx;
			int16_t drawY = ddy*tile_height + y + dy;
			uint16_t tile = pgm_read_byte(tilemap + ddy*tilemap_width + ddx);
			if (drawX >= dx && drawY >= dy && drawX <= (ddw - tile_width) && drawY <= (ddh - tile_height)){
				writeRectNBPP(drawX, drawY,tile_width, tile_height, 4, spritesheet[tile], palette );

				if (flagcollision){
					solid[numcolision].x = drawX;                     //Save X coordinate      - ADD by Summoner123
					solid[numcolision].y = drawY;                     //Save Y coordinate      - ADD by Summoner123
					solid[numcolision].spritecol = spritesheet[tile]; //Save Sprite of tile    - ADD by Summoner123
					numcolision++;                                    //Increment numcolision  - ADD by Summoner123
				}
			}
			else{ // we need to draw a partial bitmap
				writeRect4BPPtm(drawX, drawY, tile_width, tile_height, spritesheet[tile], dx, dy, dw, dh, palette);
			}
		}
	}
}

ok so now I have a function in my sketch that allows you to name the sprites you want solid as seen here....

Code:
#include <GrafxT3.h>
#include <SPIN.h>
#include "SPI.h"
#include <Bounce.h>
#include "bitmaps.h"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#define TFT_DC  9
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
uint8_t use_fb = 1;
uint8_t use_clip_rect = 0;
uint8_t use_set_origin = 0;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
GrafxT3 tft = GrafxT3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
 int player_x = 240;
 int player_y = 320;
 int player_direction = 2;
 int x=-0,y=0;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Camera offset
int cameraX = -160;  /////starting position X 0f camera on tilemap
int cameraY = -120;  /////starting position Y of camera on tilemap

// Camera speed in pixels per update
int cameraXSpeed = 2;
int cameraYSpeed = 2;

// Camera offset boundaries
const int cameraXMin = -2080;
const int cameraXMax = 0;
const int cameraYMin = -2144;
const int cameraYMax = 0;

// Player offset boundaries
const int playerXMin = 80;
const int playerXMax = 240;
const int playerYMin = 80;
const int playerYMax = 160;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////Pixel Color Includes////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
uint16_t palette[16];  // Should probably be 256, but I don't use many colors...
uint16_t pixel_data[2500];

//Extra integers for color palette
int a = 0xa; int b = 0xb; int c = 0xc; 
int d = 0xd; int e = 0xe; int f = 0xf;

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////Button assignments//////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////dpad + select buttons
const int buttonUp = 33; //up button
Bounce ButtonUp = Bounce(buttonUp, 10);  // 10 ms debounce
const int buttonDown = 38; //down_button
Bounce ButtonDown = Bounce(buttonDown, 10);  // 10 ms debounce
const int buttonLeft = 35; //left button
Bounce ButtonLeft = Bounce(buttonLeft, 10);  // 10 ms debounce
const int buttonRight = 17; //right button
Bounce ButtonRight = Bounce(buttonRight, 10);  // 10 ms debounce
const int buttonS = 21; //select button
Bounce ButtonS = Bounce(buttonS, 10);  // 10 ms debounce

//////action + start buttons
const int buttonX = 32; // X button up
Bounce ButtonX = Bounce(buttonX, 10);  // 10 ms debounce
const int buttonY = 26; // Y button left
Bounce ButtonY = Bounce(buttonY, 10);  // 10 ms debounce
const int buttonA = 21; // A button right
Bounce ButtonA = Bounce(buttonA, 10);  // 10 ms debounce
const int buttonB = 28; // B buttun down
Bounce ButtonB = Bounce(buttonB, 10);  // 10 ms debounce
const int buttonT = 4; // Start button
Bounce ButtonT = Bounce(buttonT, 10);  // 10 ms debounce

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////Set-up//////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void setup() {
  while (!Serial && (millis() < 4000)) ;
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(BLACK);
  //tft.setFrameRate(60);
  tft.persistence = false;
   pinMode(buttonUp, INPUT_PULLUP);
   pinMode(buttonDown, INPUT_PULLUP);
   pinMode(buttonLeft, INPUT_PULLUP);
   pinMode(buttonRight, INPUT_PULLUP);
   pinMode(buttonS, INPUT_PULLUP);
   pinMode(buttonX, INPUT_PULLUP);
   pinMode(buttonY, INPUT_PULLUP);
   pinMode(buttonA, INPUT_PULLUP);
   pinMode(buttonB, INPUT_PULLUP);
   pinMode(buttonT, INPUT_PULLUP); 
 
   tft.useFrameBuffer(use_fb);
     uint32_t start_time = millis(); 
//       use_fb = !use_fb;
 
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////Loop////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void loop(void) {
   //updates the GameRIot (the display, the sound, the buttons, everyyhing)
  //returns true when it's time to render a new frame (20 times/second)
//   if(tft.updateAll()){

///////////////////////////////////////////////////////////////////////////////
////////////////////////////////camera controls////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Clamp cameraX
if(cameraX < cameraXMin)
{
  cameraX = cameraXMin;
}
else if(cameraX > cameraXMax)
{
   cameraX = cameraXMax;
}

// Clamp cameraY
if(cameraY < cameraYMin)
{
  cameraY = cameraYMin;
}
else if(cameraY > cameraYMax)
{
   cameraY = cameraYMax;  
}

// Check if player is beyond X boundary
if(player_x < playerXMin)
{
  cameraX += cameraXSpeed;
  if(cameraX > cameraXMin && cameraX < cameraXMax)
  {
    player_x = playerXMin;
  }
}
else if(player_x > playerXMax)
{
  cameraX -= cameraXSpeed;
  if(cameraX > cameraXMin && cameraX < cameraXMax)
  {
    player_x = playerXMax;
  }
}

// Check if player is beyond Y boundary
if(player_y < playerYMin)
{
  cameraY += cameraYSpeed;
  if(cameraY > cameraYMin && cameraY < cameraYMax)
  {
    player_y = playerYMin;
  }
}
else if(player_y > playerYMax)
{
  cameraY -= cameraYSpeed;
  if(cameraY > cameraYMin && cameraY < cameraYMax)
  {
    player_y = playerYMax;
  }
}
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////Palette////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 palette[0] = 0;
       palette[1] = BLACK;
             palette[2] = BLUE;
                   palette[3] = BROWN;
                         palette[4] = DARKGREEN;
                              palette[5] = GREY;
                                    palette[6] = PINK;
                                          palette[7] = RED;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////                                                
                                           palette[8] = LIGHTBROWN;
                                     palette[9] = GREEN;
                               palette[a]= DARKGREY;
                         palette[b] = LIGHTGREY;
                   palette[c] = YELLOW; 
             palette[d] = PURPLE; 
       palette[e] = WHITE;
 palette[f] = NAVY;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////Tilemap/////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

tft.drawTilemap(cameraX, cameraY, dune_demo, spritesheet, palette);
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////Buttons/////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////  
       if (ButtonUp.update());
               if (ButtonDown.update());
                       if (ButtonLeft.update());
                             if (ButtonRight.update());
                                       if (ButtonA.update());
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
                                       ButtonUp.rebounce(10);
                               ButtonDown.rebounce(10);
                       ButtonLeft.rebounce(10);
            ButtonRight.rebounce(10);
     ButtonA.rebounce(10);
///////////////////////////////////////////////////////////////////////////////
//////////////////////////Down/////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
 if (ButtonUp.fallingEdge()){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearw,palette);
     player_direction = 1;
     player_y -= 2;
     if(checkcolision())
     {
      player_y += 2;} 
     }
     if(player_y <= 32){
        player_y = 32;}
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////Up///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 if (ButtonDown.fallingEdge()){
   tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontw,palette);
   player_direction = 2;
   player_y += 2;
    if(checkcolision())
    {
    player_y -=2;}
    }
    if(player_y >= 216){
       player_y = 216;}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////Left////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 if (ButtonLeft.fallingEdge()){
   tft.writeRectNBPP(player_x, player_y,16,16,4,paulleftw,palette);
   player_direction = 3;
   player_x -= 2;
   if(checkcolision())
   {
      player_x += 2;}  
   }
   if(player_x >= 288){
      player_x = 288;}
//////////////////////////////////////////////////////////////////////////////
////////////////////////////Right////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (ButtonRight.fallingEdge()){
  tft.writeRectNBPP(player_x, player_y,16,16,4,paulrightw,palette);
  player_direction = 4;
  player_x += 2;
  if(checkcolision())
  {
    player_x -= 2;}
  }
            if(player_x <= 32){
              player_x = 32;}
///////////////////////////////////////////////////////////////////////////////     
//////////////////////////////PLAYER DIRECTION/////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
if (player_direction == 1){
  tft.writeRectNBPP(player_x, player_y,16,16,4,paulrear,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 2){
   tft.writeRectNBPP(player_x, player_y,16,16,4,paulfront,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 3){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleft,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 4){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulright,palette);
        }
       tft.updateScreen(); 
     }
//}
/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////collision/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
   bool checkcolision() { // Transformed it into a function 
    uint16_t i;  
     for(i=0; i < tft.numcolision + 1; i++)
   {
    if(tft.collideRectRect(player_x, player_y,16,16,tft.solid[i].x,tft.solid[i].y,16,16))
{
     if(tft.solid[i].spritecol == blank_tile)return false; //Do nothing because it's floor - this line not needed
else if(tft.solid[i].spritecol == cave)return true;
else if(tft.solid[i].spritecol == grass)return false;
else if(tft.solid[i].spritecol == grassbl)return false;
else if(tft.solid[i].spritecol == grassbr)return false;
else if(tft.solid[i].spritecol == grasstl)return false;
else if(tft.solid[i].spritecol == grasstr)return false;
else if(tft.solid[i].spritecol == rock){tft.fillScreen(PURPLE); return true;} //Return True if character have touched the wall
else if(tft.solid[i].spritecol == rockbl)return true;
else if(tft.solid[i].spritecol == rockbr)return true;
else if(tft.solid[i].spritecol == rocktl)return true;
else if(tft.solid[i].spritecol == rocktr)return true;
else if(tft.solid[i].spritecol == sand)return false;
else if(tft.solid[i].spritecol == seitch)return true;
else if(tft.solid[i].spritecol == stairsl)return true;
else if(tft.solid[i].spritecol == stairsr)return true;
else if(tft.solid[i].spritecol == tree)return false;
   }
}
return false; // Return false if don't touch anything
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

I put a return to to fill the screen purple when it hits a rock but nothing happens. Every now and then it happens but it acts more like glitch meaning I have to go back and forth a few times maybe and before the flash happens.

My cable is starting to get wonky so I cant seem to get it to do serial monitor. But I can use print commands on screen or other display functions.

oh and here is the original sketch....

Code:
const byte *spritesheet[] = {bush, port_noir, rock_terrain_master, rock_valley_ne, 
rock_valley_nw, rock_valley_se, rock_valley_sw, turtle_rock, void_tile, water_left_bottom,
water_left_middle, water_left_top, water_right_bottom, water_right_middle, water_right_top, 
water_middle_bottom, water_middle_middle, water_middle_top, steps, dead_tree, dungeon_left_bottom,
dungeon_left_top, dungeon_right_bottom, dungeon_right_top, statue, bridge, grave_marker, dungeon_middle,}; 

const byte sever_front_black[] PROGMEM = {8,8,0x39,0x7d,0x01,0x01,0xfe,0x01,0x7c,0x46};
const byte sever_front_grey[] PROGMEM = {8,8,0x82,0x82,0xd6,0x7c,0x01,0xa8,0x00,0x00,};
const byte sever_left_black[] PROGMEM = {8,8,0x9f,0xbe,0x80,0x82,0x7f,0x00,0x3e,0x62,};
const byte sever_left_grey[] PROGMEM = {8,8,0x00,0x00,0x17,0x3c,0x00,0x95,0x00,0x00,};
const byte sever_rear_black[] PROGMEM = {8,8,0x9c,0xbe,0xbe,0x80,0x7f,0x88,0x3e,0x62,};
const byte sever_rear_grey[] PROGMEM = {8,8,0x41,0x41,0x7f,0x3e,0x80,0x15,0x00,0x00,};
const byte sever_right_black[] PROGMEM = {8,8,0xf9,0x7d,0x01,0x41,0xfe,0x00,0x7c,0x46,};
const byte sever_right_grey[] PROGMEM = {8,8,0x00,0x00,0xe8,0x3c,0x00,0xa9,0x00,0x00,};

* int player_x = 70;
* int player_y = 40;
* int player_direction = 0;

int x=0,y=0;

int camerax = -20 ;
int cameray = -10 ;
int xmax = -68;

void setup() {
* gb.begin();
* gb.titleScreen(F("test"));
* gb.setFrameRate(62);
* gb.display.persistence = false;
}

/////////PLAYER_MOVEMENT\\\\\\\\\

void loop() {
* if(gb.update()){
* * if (gb.buttons.repeat(BTN_RIGHT,1));//{x--;}
* * if (gb.buttons.repeat(BTN_LEFT,1));//{x++;}
* * if (gb.buttons.repeat(BTN_DOWN,1));//{y--;}
* * if (gb.buttons.repeat(BTN_UP,1));//{y++;} 
* * *
//////camera controls
if(player_x > 59 && camerax <* 0 && camerax* > -52){player_x = 59;camerax--;}* *
//value 59 equals player position on right when camera will start to follow 
//value 0 and -52 equals camera boundary positions
else* if(player_x < 15 && camerax <* 0 && camerax* > -52){player_x = 15;camerax++;}
//value 15 equals player position on left when camera will start to follow 
//value 0 and -52 equals camera boundary positions
else* if(player_x > 59 && camerax <= 0 && camerax >= -52)camerax--;
else* if(player_x < 15 && camerax <= 0 && camerax >= -52)camerax++;* *
* 
* 
* * * if(player_y > 28 && cameray < 0 && cameray >* -40){player_y = 28;cameray--;}
//value 28 equals player position on right when camera will start to follow 
//value 0 and -40 equals camera boundary positions
else* if(player_y < 15 && cameray < 0 && cameray >* -40){player_y = 15;cameray++;}
//value 15 equals player position on left when camera will start to follow 
//value 0 and -40 equals camera boundary positions
else* if(player_y > 28 && cameray <= 0 && cameray >= -40)cameray--;
else* if(player_y < 15 && cameray <= 0 && cameray >= -40)cameray++;* 

* * * if(camerax > 0)camerax= 0;
else* if(camerax < -52) camerax = -52;
//value 0 and -52 equals camera boundary positions 
* * * if(cameray > 0)cameray= 0;* *
else* if(cameray < -40) cameray = -40;
//value 0 and -40 equals camera boundary positions
* 
*
* * *gb.display.drawTilemap(camerax,cameray,room_1_1,spritesheet);

*if(gb.buttons.repeat(BTN_UP,1)){
* * * *gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_rear_black);
* * * *}
* * gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_rear_grey);
* * }
* * * player_direction = 1;
* * * player_y = player_y - 1;
* * * if(checkcolision())player_y++;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }

* * * 
* * if(player_y <= 0){
* * * player_y = 0;}



* * if(gb.buttons.repeat(BTN_DOWN,1)){
* * * gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_front_black);
* * }
* * *gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_front_grey);
* * } 
* * * player_direction = 2;
* * * player_y = player_y + 1;
* * * if(checkcolision())player_y--;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }
* * * 
* * if(player_y >= 40){
* * * player_y = 40;}
* 


* * if(gb.buttons.repeat(BTN_RIGHT,1)){
* * * *gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_right_black);
* * }
* * *gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_right_grey);
* * }
* * * player_direction = 3;
* * * player_x = player_x + 1;
* * * if(checkcolision())player_x--;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }
* * * 
* * * 
* * if(player_x >= 77){
* * * player_x = 77;}


* * if(gb.buttons.repeat(BTN_LEFT,1)){
* * * *gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_left_black);
* * }
* * gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_left_grey);
* * }
* * * player_direction = 4;
* * * player_x = player_x - 1;
* * * 
* * * if(checkcolision())player_x++;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }
* * * 
* * if(player_x <= -2){
* * * player_x = -2;}
* * * 
* * * ////////////PLAYER DIRECTION/////////////

*if (player_direction == 1){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_rear_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_rear_grey);
* * * * }
*}
* * * 
* * * else if (player_direction == 2){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_grey);
* * * * }
* * * }
else if (player_direction == 3){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_left_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_left_grey);
* * * * }
}
* * * else if (player_direction == 4){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_right_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_right_grey);
* * * * }
* * * }
* * * else {* gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_grey);
* * * * }
* * * }
} 
* 
}
* * *bool checkcolision() // Transformed it into a function
* *{
* * uint16_t i;
* * *for(i=0; i < gb.display.numcolision + 1; i++)
* *{
* * if(gb.collideRectRect(player_x,player_y,8,8,gb.display.solid[i].x,gb.display.solid[i].y,8,8))
* * {
* * * * * if(gb.display.solid[i].spritecol == void_tile); //Do nothing because it's floor - This line not needed
* * * * * if(gb.display.solid[i].spritecol == bush)return true;
else* * * if(gb.display.solid[i].spritecol == port_noir)return true; 
else* * * if(gb.display.solid[i].spritecol == rock_terrain_master){gb.popup(F(" ""Rock"" "),1); return true;} //Return True if character have touched the wall
else* * * if(gb.display.solid[i].spritecol == rock_valley_ne)return true;
else* * * if(gb.display.solid[i].spritecol == rock_valley_nw)return true;
else* * * if(gb.display.solid[i].spritecol == rock_valley_se)return true;
else* * * if(gb.display.solid[i].spritecol == rock_valley_sw)return true;
else* * * if(gb.display.solid[i].spritecol == turtle_rock)return true;
else* * * if(gb.display.solid[i].spritecol == water_left_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == water_left_middle)return true;
else* * * if(gb.display.solid[i].spritecol == water_left_top)return true;
else* * * if(gb.display.solid[i].spritecol == water_right_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == water_right_middle)return true;
else* * * if(gb.display.solid[i].spritecol == water_right_top)return true;
else* * * if(gb.display.solid[i].spritecol == water_middle_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == water_middle_middle)return true;
else* * * if(gb.display.solid[i].spritecol == water_middle_top)return true;
else* * * if(gb.display.solid[i].spritecol == steps)return true;
else* * * if(gb.display.solid[i].spritecol == dead_tree)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_left_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_left_top)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_right_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_right_top)return true;
else* * * if(gb.display.solid[i].spritecol == statue)return true;
else* * * if(gb.display.solid[i].spritecol == bridge)return true;
* 
* * * }
* *}
* * return false; // Return false if don't touch anything
* * * *
}
 
All right guys...... Check out this video.........

https://youtu.be/MzJgTL08zP0

As you can see from the code in my last post that I put a return to flash a purple screen if he hits a "rock". It works but only sporadically after making the character play in the rocky area.

What could be causing this?
 
You need a new cable so you can print out some stuff.

Code:
   bool checkcolision() { // Transformed it into a function 
    uint16_t i;  
     for(i=0; i < tft.numcolision + 1; i++)    // [COLOR="#00FF00"]what is the value of numcolision when you get here?[/COLOR]
   {                                                    // [COLOR="#FFA500"]why is there a +1?   is that correct?[/COLOR]
    if(tft.collideRectRect(player_x, player_y,16,16,tft.solid[i].x,tft.solid[i].y,16,16))   [COLOR="#FFA07A"]// how many times do you get a collide Rectangle
{                                                                                                              // how many times should you get a collide rectangle[/COLOR]
     if(tft.solid[i].spritecol == blank_tile)return false; //Do nothing because it's floor - this line not needed
else if(tft.solid[i].spritecol == cave)return true;
else if(tft.solid[i].spritecol == grass)return false;      // [COLOR="#FFA07A"]what are the values stored in spritcol and do they match rock?[/COLOR]
else if(tft.solid[i].spritecol == grassbl)return false;
else if(tft.solid[i].spritecol == grassbr)return false;
else if(tft.solid[i].spritecol == grasstl)return false;
else if(tft.solid[i].spritecol == grasstr)return false;
else if(tft.solid[i].spritecol == rock){tft.fillScreen(PURPLE); return true;} //Return True if character have touched the wall
else if(tft.solid[i].spritecol == rockbl)return true;
else if(tft.solid[i].spritecol == rockbr)return true;
else if(tft.solid[i].spritecol == rocktl)return true;
else if(tft.solid[i].spritecol == rocktr)return true;
else if(tft.solid[i].spritecol == sand)return false;
else if(tft.solid[i].spritecol == seitch)return true;
else if(tft.solid[i].spritecol == stairsl)return true;
else if(tft.solid[i].spritecol == stairsr)return true;
else if(tft.solid[i].spritecol == tree)return false;
   }
}
return false; // Return false if don't touch anything
}

Code:
object solid[60];         // Matriz were saved a Sprite, X and Y cordinates of all tiles on the screen - ADD by Summoner123

Is this left over from the nokia display? How many tiles fit on the screen now?
 
The matriz is definitely from the nokia library. But here's the thing..... 84x48=4,032 divide that by 16 you get 252. 8 and its 504.

I am working on ngetting a new cable. I live pretty far from the local general goods and grocery stores.

This is a link to a gamebuino simulator on line. only problem is that its set up for the nokia display, but you can take the working example below and compile it to get your hex and load it. You can get a better idea of what every thing is doing. you can also use popup as seen in the example to print returns on screen.

http://simbuino4web.ppl-pilot.com/

Code:
#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;



const byte room_1_1[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,8,8,2,2,2,2,2,2,
2,2,2,2,2,1,4,8,8,2,2,2,2,2,2,
2,2,2,2,4,8,8,8,8,2,2,2,2,2,2,
2,2,2,4,8,8,8,8,8,2,2,2,2,2,2,
2,2,4,8,8,8,8,8,8,3,2,2,2,2,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
2,2,8,8,8,8,8,8,8,8,8,8,8,2,2,
2,2,8,8,8,8,8,8,8,8,8,8,8,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};

const byte room_1_2[] PROGMEM = {15,9,
8,8,
2,0,8,0,8,0,8,8,8,0,8,0,8,0,2,
2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
4,8,8,8,8,0,8,8,8,0,8,0,8,0,8,
8,0,8,0,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,0,8,8,8,0,8,0,8,0,8,
8,0,8,0,8,8,8,8,8,8,8,8,8,8,8,
6,8,8,8,8,0,8,8,8,0,8,0,8,0,8,
2,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,2};

const byte room_1_3[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,2,2,2,8,8,8,8,8,8,8,8,3,2,2,
8,3,2,2,8,8,8,8,8,8,8,8,8,2,2,
8,8,3,2,8,8,8,8,7,8,8,8,8,3,2,
8,8,8,8,8,8,8,7,8,7,8,8,8,8,8,
8,8,8,8,8,8,8,8,7,8,8,8,8,5,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,2,2,
8,8,5,2,6,8,8,8,8,8,8,8,5,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};

const byte room_1_4[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,4,3,2,2,2,2,2,
2,2,2,2,2,2,2,4,8,8,8,8,3,2,2,
2,2,2,2,4,8,8,8,8,8,8,8,8,2,2,
3,4,3,4,8,8,8,8,8,8,8,8,8,2,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
5,6,5,6,8,8,8,8,8,8,8,8,8,2,2,
2,2,2,2,6,8,8,8,8,8,8,8,8,2,2,
2,2,2,2,2,2,2,6,8,8,8,8,8,2,2,
2,2,2,2,2,2,2,2,6,5,2,2,2,2,2};

const byte room_1_5 [] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,8,8,8,0,
2,4,8,8,8,8,8,8,8,8,8,8,8,8,8,
4,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,11,17,17,17,17,17,17,17,
6,8,8,8,8,8,8,11,16,16,16,16,16,16,16,
2,2,2,6,8,8,8,10,16,16,16,16,16,16,16,
2,2,2,2,2,2,2,10,16,16,16,16,16,16,16};

const byte room_1_6[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16};

const byte room_1_7[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16};

const byte room_1_8[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,
8,8,3,2,4,3,4,3,4,3,2,4,3,2,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16};

const byte room_1_9[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,8,8,8,10,16,16,16,16,
4,3,2,4,3,2,4,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16};


const byte room_2_1[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,4,8,8,8,8,8,8,2,8,8,8,3,2,
2,4,8,8,7,8,7,8,8,8,8,7,8,8,3,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,7,8,7,8,8,8,8,7,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
2,6,8,8,7,8,7,8,8,8,8,7,8,8,5,
2,2,6,8,8,8,8,8,8,2,8,8,8,5,2,
2,2,2,2,2,2,2,8,8,2,2,2,2,2,2};

const byte room_2_2[] PROGMEM = {15,9,
8,8,
2,0,8,0,8,0,8,8,8,0,8,0,8,8,0,
2,0,8,8,8,8,8,8,8,8,8,8,8,8,2,
4,8,8,8,0,8,8,8,8,0,8,8,0,8,8,
8,8,0,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,0,8,0,8,8,0,8,0,8,8,8,
8,8,0,8,8,8,8,8,8,8,8,8,8,8,8,
6,8,8,8,0,8,8,8,8,0,8,8,0,8,8,
2,0,8,8,8,8,8,8,8,8,8,8,8,8,2,
2,0,8,0,8,0,8,8,8,0,8,0,8,8,0};

const byte rooom_2_3[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,0,8,8,8,11,16,16,16,
0,0,8,8,8,8,8,8,8,8,8,10,16,16,16,
0,8,8,8,8,8,0,8,8,0,8,10,16,16,16,
8,8,8,0,8,8,8,8,8,8,8,10,16,16,16,
8,8,8,8,8,8,0,8,8,8,8,9,15,15,15,
8,8,8,0,8,8,8,8,8,8,8,8,8,8,8,
0,8,8,8,8,8,0,8,8,8,8,8,8,8,8,
0,0,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_2_4[] PROGMEM = {15,9,
8,8,
16,16,16,14,8,8,8,0,0,0,8,0,0,8,0,
16,16,16,14,8,8,8,0,0,0,8,0,0,8,0,
16,16,16,14,8,8,8,8,8,8,8,8,8,8,8,
15,15,15,12,8,8,8,0,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_2_5[] PROGMEM = {15,9,
8,8,
0,8,0,8,8,8,0,8,0,8,0,8,8,8,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,0,8,8,8,8,
8,8,0,8,8,8,0,8,0,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,0,8,8,8,0,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
0,0,0,0,0,0,0,0,0,0,0,8,8,8,0};

const byte room_2_6[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,8,0,0,0,0,8,0,0,0,
0,0,0,0,0,0,0,8,0,0,8,8,8,8,8,8,
0,0,0,0,0,0,0,8,0,8,8,8,8,0,0,0,
8,8,8,8,8,8,8,8,0,8,8,8,8,0,0,0,
8,8,8,8,8,8,8,8,0,8,8,8,8,0,0,0,
8,8,8,8,8,8,8,8,0,8,8,8,8,0,0,0,
0,0,0,0,0,0,0,0,0,8,8,8,8,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,8,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_2_7[] PROGMEM = {15,9,
8,8,
0,0,0,8,0,0,0,0,0,0,0,0,0,8,0,0,
8,8,8,8,8,8,8,8,8,8,8,0,8,8,0,0,
0,0,8,8,0,0,0,0,0,0,0,0,0,8,0,0,
0,0,8,8,0,0,0,0,0,0,0,0,0,8,8,8,
0,0,8,8,0,0,0,0,0,0,0,0,0,8,8,8,
0,0,8,8,0,0,0,0,0,0,0,0,0,8,8,8,
0,0,8,8,0,0,0,0,0,0,0,0,0,0,0,0,
8,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_2_8[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,4,8,8,8,8,8,3,2,2,2,4,8,3,2,
2,8,8,8,8,8,8,8,3,2,4,8,8,8,2,
8,8,8,8,0,8,8,8,8,8,8,8,0,8,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,
2,8,8,8,0,8,8,8,8,8,8,8,0,8,2,
2,8,8,8,8,8,8,8,5,2,6,8,8,8,2,
2,6,8,8,8,8,8,5,2,2,2,6,8,5,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};

const byte room_2_9[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,8,8,8,10,16,16,16,16,
2,2,2,2,2,2,4,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
8,8,8,8,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,2,2,2,6,8,8,8,10,16,16,16,16,
2,2,2,2,2,2,2,8,8,8,10,16,16,16,16};

const byte room_3_1[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,0,8,0,8,8,8,0,8,0,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,0,8,0,8,0,8,0,8,0,8,0,8,0,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,0,8,0,8,8,8,0,8,0,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_3_2[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,8,8,8,0,0,0,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,8,0,8,8,8,0,8,8,8,0,8,0,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,8,0,8,8,8,0,8,8,8,0,8,0,8,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,8,0,8,8,8,0,8,8,8,0,8,0,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,8,0,8,0,8,0,8,8,8,0,8,0,8,0};

const byte room_3_3[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,8,8,8,0,0,0,0,0,
0,0,8,8,8,0,0,8,8,8,0,0,0,0,0,
0,0,8,8,8,0,0,8,8,8,0,0,0,0,0,
0,0,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,8,7,8,8,8,8,8,8,8,8,8,8,8,
0,0,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,8,8,8,0,0,8,8,8,0,0,0,0,0,
0,0,8,8,8,0,0,8,8,8,0,0,0,0,0,
0,0,0,0,0,0,0,8,8,8,0,0,0,0,0};

const byte room_3_4[] PROGMEM ={15,9,
8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
17,17,17,14,8,8,8,8,8,8,8,8,8,8,8,
16,16,16,13,8,8,8,8,8,8,8,8,8,8,8,
16,16,16,13,8,8,8,0,0,0,8,0,0,8,0,
16,16,16,13,8,8,8,0,0,0,8,0,0,8,0};

const byte room_3_5[] PROGMEM = {15,9,
8,8,
0,8,0,8,8,8,0,8,0,8,0,8,8,8,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,0,8,8,8,0,8,0,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,0,8,8,8,8,
8,8,0,8,8,8,0,8,0,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,0,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,8,0,8,8,8,0,8,0,8,0,8,8,8,0};

const byte room_3_6[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,0,0,
0,0,0,0,0,0,0,0,0,0,0,8,8,0,0,
0,0,0,0,0,0,0,0,0,0,0,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,
8,8,8,8,8,8,8,0,0,0,0,8,0,0,0,
0,0,0,0,0,0,8,0,0,0,0,8,0,0,0};

const byte room_3_7[] PROGMEM = {15,9,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0};

const byte room_3_8[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,4,8,8,8,8,8,3,2,2,2,4,8,3,2,
2,8,8,8,8,8,8,8,3,2,4,8,8,8,2,
8,8,8,8,0,8,8,8,8,8,8,8,0,8,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,
8,8,8,8,0,8,8,8,8,8,8,8,0,8,2,
2,8,8,8,8,8,8,8,5,2,6,8,8,8,2,
2,6,8,8,8,8,8,5,2,2,2,6,8,5,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};

const byte room_3_9[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,8,8,8,8,10,16,16,16,16,
2,2,2,2,2,4,8,8,8,8,10,16,16,16,16,
2,2,2,2,4,8,8,8,8,8,10,16,16,16,16,
2,2,2,4,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,8,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,8,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,6,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,2,6,8,8,8,8,8,10,16,16,16,16,
2,2,2,2,2,8,8,8,8,8,10,16,16,16,16};


const byte room_4_1[] PROGMEM = {15,9,
8,8,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_4_2[] PROGMEM = {15,9,
8,8,
16,16,16,16,16,16,13,8,8,8,0,0,0,0,0,
16,16,16,16,16,16,13,8,8,8,8,8,8,0,0,
16,16,16,16,16,16,13,8,8,8,8,8,8,0,0,
15,15,15,15,15,15,12,8,8,8,8,8,8,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,0,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,0,0,
0,8,8,8,8,8,8,8,8,8,8,8,8,0,0,
0,0,0,0,0,0,0,8,8,8,0,0,0,0,0};

const byte room_4_3[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,4,8,8,8,8,8,8,8,8,8,8,8,3,2,
2,8,8,8,8,8,8,8,8,8,8,8,8,8,2,
2,8,0,8,8,11,17,17,17,14,8,8,0,8,2,
2,8,8,8,8,10,16,16,16,13,8,8,8,8,2,
2,8,0,8,8,9,15,15,15,12,8,8,0,8,2,
2,8,8,8,8,8,8,8,8,8,8,8,8,8,2,
2,6,8,8,8,8,8,8,8,8,8,8,8,5,2,
2,2,2,2,2,2,2,8,8,8,2,2,2,2,2};

const byte room_4_4[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,2,8,8,8,2,2,2,2,2,
2,2,4,8,8,8,8,8,8,8,8,8,3,2,2,
2,4,8,8,8,8,8,8,8,8,8,8,8,3,2,
8,8,8,8,0,8,8,8,8,8,0,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,0,8,8,8,8,8,0,8,8,8,8,
2,6,8,8,8,8,8,8,8,8,8,8,8,5,2,
2,2,6,8,8,8,8,8,8,8,8,8,5,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};

const byte room_4_5[] PROGMEM ={15,9,
8,8,
0,0,0,0,0,0,0,0,0,0,0,8,8,8,0,
0,8,8,8,8,8,8,8,8,8,0,8,8,8,0,
0,8,8,8,8,0,8,8,8,8,0,8,8,8,0,
8,8,8,8,8,8,8,0,8,8,0,8,8,8,0,
8,8,0,8,8,0,8,8,8,8,0,8,8,8,0,
8,8,8,8,8,8,8,0,8,8,0,8,8,8,0,
0,8,8,8,8,0,8,8,8,8,0,8,8,8,0,
0,8,8,8,8,8,8,8,8,8,0,8,8,8,0,
0,8,0,8,8,8,0,8,0,8,0,8,8,8,0};

const byte room_4_6[] PROGMEM = {15,9,
8,8,
2,2,4,3,2,2,18,2,2,2,4,3,2,2,2,
2,4,8,8,3,2,18,2,2,2,8,8,8,2,2,
2,8,8,8,8,2,18,2,2,4,8,8,8,2,2,
4,8,8,8,8,3,18,2,2,4,8,8,8,2,2,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
6,8,8,8,8,8,8,8,8,8,8,8,8,2,2,
2,8,8,8,8,8,8,8,8,8,8,8,8,2,2,
2,8,8,8,8,8,8,8,8,8,8,8,8,2,2,
2,6,5,2,2,6,5,2,2,2,6,5,2,2,2};

const byte room_4_7[] PROGMEM = {15,9,
8,8,
0,8,0,8,0,8,0,8,8,8,0,8,0,8,0,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
0,8,8,8,8,8,0,8,8,8,0,8,8,8,0,
8,8,0,8,0,8,8,8,0,8,8,8,0,8,8,
8,8,8,8,8,8,0,8,8,8,0,8,8,8,8,
8,8,0,8,0,8,8,8,0,8,8,8,0,8,8,
0,8,8,8,8,8,0,8,8,8,0,8,8,8,0,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
0,0,0,8,0,0,0,0,0,0,0,0,8,0,0};

const byte room_4_8[] PROGMEM = {15,9,
8,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,8,8,8,8,8,8,8,8,8,8,8,0,0,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,0,8,8,8,8,8,0,8,8,8,0,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
8,8,8,8,0,8,8,8,8,8,0,8,8,8,0,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,0,
0,0,8,8,8,8,8,8,8,8,8,8,8,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

const byte room_4_9[] PROGMEM = {15,9,
8,8,
2,2,2,2,2,2,8,8,8,8,10,16,16,16,16,
2,2,2,2,2,4,8,8,8,8,10,16,16,16,16,
2,2,2,2,4,8,8,8,8,8,10,16,16,16,16,
2,2,2,4,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,8,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,8,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,6,8,8,8,8,8,8,10,16,16,16,16,
2,2,2,2,6,8,8,8,8,8,10,16,16,16,16,
2,2,2,2,2,8,8,8,8,8,10,16,16,16,16};

const byte bush[] PROGMEM = {B00101100,B01010010,B10001001,B01000010,B10010001,B01001010,B00100100,B01111110,};
const byte port_noir[] PROGMEM = {B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,};
const byte rock_terrain_master[] PROGMEM = {B01001101,B10100100,B10010001,B01001010,B10010000,B01100101,B10001001,B01011010,};
const byte rock_valley_ne[] PROGMEM = {B10101010,B10010101,B01000100,B00101001,B00110010,B00001010,B00000100,B00000011,};
const byte rock_valley_nw[] PROGMEM = {B01010101,B10101001,B00100010,B10010100,B01001100,B01010000,B00100000,B11000000,};
const byte rock_valley_se[] PROGMEM = {B00000011,B00000100,B0011001,B00010010,B00101001,B01000110,B10110001,B10001010,};
const byte rock_valley_sw[] PROGMEM = {B11000000,B00100000,B10011000,B01001000,B10010100,B01100010,B10001101,B01010001,};
const byte turtle_rock[] PROGMEM = {B01101100,B10110010,B11010001,B01010101,B01010010,B10011001,B10000001,B11111110,};
const byte void_tile[] PROGMEM = {B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,};
const byte water_left_bottom[] PROGMEM = {B10001111,B10000000,B11110000,B10000000,B10001111,B10000000,B11110000,B11111111,};
const byte water_left_middle[] PROGMEM = {B10001111,B10000000,B11110000,B10000000,B10001111,B10000000,B11110000,B10000000,};
const byte water_left_top[] PROGMEM = {B11111111,B10000000,B11110000,B10001111,B10000000,B10000000,B11110000,B10000000,};
const byte water_right_bottom[] PROGMEM = {B1110001,B00000001,B0000111,B00000001,B11110001,B00000001,B00001111,B11111111,};
const byte water_right_middle[] PROGMEM = {B11110001,B00000001,B00001111,B00000001,B11110001,B00000001,B00001111,B00000001,};
const byte water_right_top[] PROGMEM = {B11111111,B00000001,B00001111,B00000001,B11110001,B00000001,B00001111,B00000001,};
const byte water_middle_bottom[] PROGMEM = {B11110000,B00000000,B00001111,B00000000,B11110000,B00000000,B00001111,B11111111,};
const byte water_middle_middle[] PROGMEM = {B11110000,B00000000,B00001111,B00000000,B11110000,B00000000,B00001111,B00000000,};
const byte water_middle_top[] PROGMEM = {B11111111,B00000000,B11110000,B00000000,B00001111,B00000000,B11110000,B00000000,};
const byte steps[] PROGMEM = {B10000001,B01111110,B10000001,B01111110,B10000001,B01111110,B10000001,B01111110,};
const byte dead_tree[] PROGMEM = {B10101001,B01010110,B01001001,B10101010,B01011010,B00111100,B00011000,B00011000,};
const byte dungeon_left_bottom[] = {B11111111,B10001111,B01001111,B11111111,B10001111,B01001111,B11111111,B10001111,};
const byte dungeon_left_top[] = {B00010001,B00101110,B00101010,B00101110,B01000000,B01000001,B10010010,B10001000,};
const byte dungeon_right_bottom[] = {B11111111,B11110001,B11110010,B11111111,B11110001,B11110010,B11111111,B11110001,};
const byte dungeon_right_top[] = {B10001000,B01110100,B01010100,B01110100,B00000010,B10000010,B01001001,B00010001,};
const byte statue[] = {B10111010,B11000110,B01101100,B11101110,B11111110,B11111110,B01101100,B01101100,};
const byte bridge[] = {B01110111,B10001000,B10101010,B10001000,B10001000,B10101010,B10001000,B01110111,};
const byte grave_marker[] PROGMEM = {B00011000,B00111100,B01100110,B0100010,B01100110,B01100110,B00111100,B11111111,};
const byte dungeon_middle[] = {B10000001,B01000010,B00111100,B00000000,B00000000,B10011001,B00011000,B01000010,};
const byte sand[] PROGMEM = {B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,};

const byte *spritesheet[] = {bush, port_noir, rock_terrain_master, rock_valley_ne, 
rock_valley_nw, rock_valley_se, rock_valley_sw, turtle_rock, void_tile, water_left_bottom,
water_left_middle, water_left_top, water_right_bottom, water_right_middle, water_right_top, 
water_middle_bottom, water_middle_middle, water_middle_top, steps, dead_tree, dungeon_left_bottom,
dungeon_left_top, dungeon_right_bottom, dungeon_right_top, statue, bridge, grave_marker, dungeon_middle,}; 

const byte sever_front_black[] PROGMEM = {8,8,0x39,0x7d,0x01,0x01,0xfe,0x01,0x7c,0x46};
const byte sever_front_grey[] PROGMEM = {8,8,0x82,0x82,0xd6,0x7c,0x01,0xa8,0x00,0x00,};
const byte sever_left_black[] PROGMEM = {8,8,0x9f,0xbe,0x80,0x82,0x7f,0x00,0x3e,0x62,};
const byte sever_left_grey[] PROGMEM = {8,8,0x00,0x00,0x17,0x3c,0x00,0x95,0x00,0x00,};
const byte sever_rear_black[] PROGMEM = {8,8,0x9c,0xbe,0xbe,0x80,0x7f,0x88,0x3e,0x62,};
const byte sever_rear_grey[] PROGMEM = {8,8,0x41,0x41,0x7f,0x3e,0x80,0x15,0x00,0x00,};
const byte sever_right_black[] PROGMEM = {8,8,0xf9,0x7d,0x01,0x41,0xfe,0x00,0x7c,0x46,};
const byte sever_right_grey[] PROGMEM = {8,8,0x00,0x00,0xe8,0x3c,0x00,0xa9,0x00,0x00,};

* int player_x = 70;
* int player_y = 40;
* int player_direction = 0;

int x=0,y=0;

int camerax = -20 ;
int cameray = -10 ;
int xmax = -68;

void setup() {
* gb.begin();
* gb.titleScreen(F("test"));
* gb.setFrameRate(62);
* gb.display.persistence = false;
}

/////////PLAYER_MOVEMENT\\\\\\\\\

void loop() {
* if(gb.update()){
* * if (gb.buttons.repeat(BTN_RIGHT,1));//{x--;}
* * if (gb.buttons.repeat(BTN_LEFT,1));//{x++;}
* * if (gb.buttons.repeat(BTN_DOWN,1));//{y--;}
* * if (gb.buttons.repeat(BTN_UP,1));//{y++;} 
* * *
//////camera controls
if(player_x > 59 && camerax <* 0 && camerax* > -52){player_x = 59;camerax--;}* *
//value 59 equals player position on right when camera will start to follow 
//value 0 and -52 equals camera boundary positions
else* if(player_x < 15 && camerax <* 0 && camerax* > -52){player_x = 15;camerax++;}
//value 15 equals player position on left when camera will start to follow 
//value 0 and -52 equals camera boundary positions
else* if(player_x > 59 && camerax <= 0 && camerax >= -52)camerax--;
else* if(player_x < 15 && camerax <= 0 && camerax >= -52)camerax++;* *
* 
* 
* * * if(player_y > 28 && cameray < 0 && cameray >* -40){player_y = 28;cameray--;}
//value 28 equals player position on right when camera will start to follow 
//value 0 and -40 equals camera boundary positions
else* if(player_y < 15 && cameray < 0 && cameray >* -40){player_y = 15;cameray++;}
//value 15 equals player position on left when camera will start to follow 
//value 0 and -40 equals camera boundary positions
else* if(player_y > 28 && cameray <= 0 && cameray >= -40)cameray--;
else* if(player_y < 15 && cameray <= 0 && cameray >= -40)cameray++;* 

* * * if(camerax > 0)camerax= 0;
else* if(camerax < -52) camerax = -52;
//value 0 and -52 equals camera boundary positions 
* * * if(cameray > 0)cameray= 0;* *
else* if(cameray < -40) cameray = -40;
//value 0 and -40 equals camera boundary positions
* 
*
* * *gb.display.drawTilemap(camerax,cameray,room_1_1,spritesheet);

*if(gb.buttons.repeat(BTN_UP,1)){
* * * *gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_rear_black);
* * * *}
* * gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_rear_grey);
* * }
* * * player_direction = 1;
* * * player_y = player_y - 1;
* * * if(checkcolision())player_y++;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }

* * * 
* * if(player_y <= 0){
* * * player_y = 0;}



* * if(gb.buttons.repeat(BTN_DOWN,1)){
* * * gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_front_black);
* * }
* * *gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_front_grey);
* * } 
* * * player_direction = 2;
* * * player_y = player_y + 1;
* * * if(checkcolision())player_y--;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }
* * * 
* * if(player_y >= 40){
* * * player_y = 40;}
* 


* * if(gb.buttons.repeat(BTN_RIGHT,1)){
* * * *gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_right_black);
* * }
* * *gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_right_grey);
* * }
* * * player_direction = 3;
* * * player_x = player_x + 1;
* * * if(checkcolision())player_x--;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }
* * * 
* * * 
* * if(player_x >= 77){
* * * player_x = 77;}


* * if(gb.buttons.repeat(BTN_LEFT,1)){
* * * *gb.display.setColor(BLACK);{
* * gb.display.drawBitmap(player_x,player_y,sever_left_black);
* * }
* * gb.display.setColor(GRAY);{
* * gb.display.drawBitmap(player_x,player_y,sever_left_grey);
* * }
* * * player_direction = 4;
* * * player_x = player_x - 1;
* * * 
* * * if(checkcolision())player_x++;* // ADD by Summoner123 - If have colision on the new position regreat one Pixel
* * * }
* * * 
* * if(player_x <= -2){
* * * player_x = -2;}
* * * 
* * * ////////////PLAYER DIRECTION/////////////

*if (player_direction == 1){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_rear_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_rear_grey);
* * * * }
*}
* * * 
* * * else if (player_direction == 2){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_grey);
* * * * }
* * * }
else if (player_direction == 3){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_left_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_left_grey);
* * * * }
}
* * * else if (player_direction == 4){
* * * * gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_right_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_right_grey);
* * * * }
* * * }
* * * else {* gb.display.setColor(BLACK);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_black);
* * * }
* * * * gb.display.setColor(GRAY);{
* * * * gb.display.drawBitmap(player_x,player_y,sever_front_grey);
* * * * }
* * * }
} 
* 
}
* * *bool checkcolision() // Transformed it into a function
* *{
* * uint16_t i;
* * *for(i=0; i < gb.display.numcolision + 1; i++)
* *{
* * if(gb.collideRectRect(player_x,player_y,8,8,gb.display.solid[i].x,gb.display.solid[i].y,8,8))
* * {
* * * * * if(gb.display.solid[i].spritecol == void_tile); //Do nothing because it's floor - This line not needed
* * * * * if(gb.display.solid[i].spritecol == bush)return true;
else* * * if(gb.display.solid[i].spritecol == port_noir)return true; 
else* * * if(gb.display.solid[i].spritecol == rock_terrain_master)return true;//{gb.popup(F(" ""Rock"" "),1); return true;} //Return True if character have touched the wall
else* * * if(gb.display.solid[i].spritecol == rock_valley_ne)return true;
else* * * if(gb.display.solid[i].spritecol == rock_valley_nw)return true;
else* * * if(gb.display.solid[i].spritecol == rock_valley_se)return true;
else* * * if(gb.display.solid[i].spritecol == rock_valley_sw)return true;
else* * * if(gb.display.solid[i].spritecol == turtle_rock)return true;
else* * * if(gb.display.solid[i].spritecol == water_left_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == water_left_middle)return true;
else* * * if(gb.display.solid[i].spritecol == water_left_top)return true;
else* * * if(gb.display.solid[i].spritecol == water_right_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == water_right_middle)return true;
else* * * if(gb.display.solid[i].spritecol == water_right_top)return true;
else* * * if(gb.display.solid[i].spritecol == water_middle_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == water_middle_middle)return true;
else* * * if(gb.display.solid[i].spritecol == water_middle_top)return true;
else* * * if(gb.display.solid[i].spritecol == steps)return true;
else* * * if(gb.display.solid[i].spritecol == dead_tree)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_left_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_left_top)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_right_bottom)return true;
else* * * if(gb.display.solid[i].spritecol == dungeon_right_top)return true;
else* * * if(gb.display.solid[i].spritecol == statue)return true;
else* * * if(gb.display.solid[i].spritecol == bridge)return true;
* 
* * * }
* *}
* * return false; // Return false if don't touch anything
* * * *
}


note the collision functions in the library were placed as is from the original and is set up for 16bit graphics

http://gamebuino.com/wiki/index.php?title=Gb.collideRectRect

Oops getting hex now
 
Last edited:
Hi,
I haven't been following very closely but I think KurtE and defragster were helping you with converting some 8 bit dimensions to 16 bit. Aren't the original tiles 8x8? 84 x 48 screen with 8x8 tiles -> 48/8 is 6 tiles down by 84/8 == 10.5 tiles across. I would expect the dimension for solid[] as 60 is 6x10 but I could be wrong. But if I am correct, you have a 320 x 240 screen with 16x16 tiles. So 240/16 is 15 tiles down by 320/16 == 20 across. 15 * 20 is 300 tiles on the screen. So it it works the way I think it does, you have a buffer overflow with the array solid[]. And you could verify that by printing out the value of tft.numcolision when you enter the collision function.
That +1 in the for loop just looks like an off by one error to me, but I have not verified that to be true.

For the future when you feel like optimizing some functions, I think the whole collision algorithm is too complicated if it works the way I think it does. It seems to me you could add/subtract the camera coordinates with the player coordinates, divide by 16 and directly compute the tile map index you are on top of. I believe you would need to check 1, 2 or 4 tiles for a collision depending upon if you are directly on top of a tile or offset in the x and/or y directions.
 
ok so I tried making what you talked about 300 instead of 60 but no luck there. Its still working half assed. I haven't touched the algorithm. I ledt that part of the code untouched.

also tried this.....

Code:
bool checkcolision(void) // Transformed it into a function 
{
  for(uint16_t i=0; i < tft.numcolision + 1; i++)
  {
    if(tft.collideRectRect(player_x, player_y,16,16,tft.solid[i].x,tft.solid[i].y,16,16))
    {
      if(tft.solid[i].spritecol == cave) return true;
      else if(tft.solid[i].spritecol == rockbl) return true;
      else if(tft.solid[i].spritecol == rockbr) return true;
      else if(tft.solid[i].spritecol == rocktl) return true;
      else if(tft.solid[i].spritecol == rocktr) return true;
      else if(tft.solid[i].spritecol == seitch) return true;
      else if(tft.solid[i].spritecol == stairsl) return true;
      else if(tft.solid[i].spritecol == stairsr) return true;
    }
  }
  return false; // Return false if don't touch anything
}

This might be one of those ridiculous instances where the fix is something being overlooked. Lets look at some c file stuff. First we have the original function that allows us to use the tilemap.......
Code:
void GrafxT3::drawBitmapTM(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *bitmap, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, uint16_t color) {
	int16_t i, j, byteWidth = (w + 7) / 8;
	dw += dx;
	dh += dy;
//	int32_t largest = 0;
//	int32_t largesty = 0;
	for (j = 0; j < h; j++) {
		for (i = 0; i < w; i++) {
			if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (B10000000 >> (i % 8))) { ///////is tile map using this to read pixels for collision???
				int16_t drawX = x + i;
				int16_t drawY = y + j;

				if (drawX >= dx && drawX < dw && drawY >= dy && drawY < dh){
					drawPixel(drawX, drawY, color);
				}
			}
		}
	}
}

now lets look at the rest of the functions for tilemap.....
Code:
boolean GrafxT3::getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y){
	return pgm_read_byte(bitmap + 2 + y * ((pgm_read_byte(bitmap) + 7) / 8) + (x >> 3)) & (B10000000 >> (x % 8));
}

void GrafxT3::drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, const uint16_t * palette){
	drawTilemap(x, y, tilemap, spritesheet, 0, 0, GrafxT3_TFTHEIGHT, GrafxT3_TFTWIDTH, palette);
}
void GrafxT3::drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, const uint16_t * palette){
	uint16_t tilemap_width = pgm_read_byte(tilemap);
	uint16_t tilemap_height = pgm_read_byte(tilemap + 1);
	uint16_t tile_width = pgm_read_byte(tilemap + 2);
	uint16_t tile_height = pgm_read_byte(tilemap + 3);
	tilemap += 4; // now the first tiyleis at tilemap
	uint16_t ddw = dw + dx;
	uint16_t ddh = dh + dy;
	uint16_t maxDdx = (dw - x + tile_width - 1) / tile_width;
	uint16_t maxDdy = (dh - y + tile_height - 1) / tile_height;
	if (tilemap_width < maxDdx){
		maxDdx = tilemap_width;
	}
	if (tilemap_height < maxDdy){
		maxDdy = tilemap_height;
	}
	int16_t startDdx = (-x) / tile_width;
	int16_t startDdy = (-y) / tile_height;
	if (startDdx < 0){
		startDdx = 0;
	}
	if (startDdy < 0){
		startDdy = 0;
	}
	if (flagcollision)numcolision = 0;                                 //Line 735 - clear numcolision - ADD by Summoner123

	for (uint16_t ddy = startDdy; ddy < maxDdy; ddy++){
		for (uint16_t ddx = startDdx; ddx < maxDdx; ddx++){
			int16_t drawX = ddx*tile_width + x + dx;
			int16_t drawY = ddy*tile_height + y + dy;
			uint16_t tile = pgm_read_byte(tilemap + ddy*tilemap_width + ddx);
			if (drawX >= dx && drawY >= dy && drawX <= (ddw - tile_width) && drawY <= (ddh - tile_height)){
				writeRectNBPP(drawX, drawY,tile_width, tile_height, 4, spritesheet[tile], palette );

				if (flagcollision){
					solid[numcolision].x = drawX;                     //Save X coordinate      - ADD by Summoner123
					solid[numcolision].y = drawY;                     //Save Y coordinate      - ADD by Summoner123
					solid[numcolision].spritecol = spritesheet[tile]; //Save Sprite of tile    - ADD by Summoner123
					numcolision++;                                    //Increment numcolision  - ADD by Summoner123
				}
			}
			else{ // we need to draw a partial bitmap
				writeRect4BPPtm(drawX, drawY, tile_width, tile_height, spritesheet[tile], dx, dy, dw, dh, palette);
			}
		}
	}
}

You can see where I changed every thing so it utilizes the writerect functions. Now lets look at my helper function for the tilemap...

Code:
void GrafxT3::writeRect4BPPtm(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, const uint16_t * palette )
{
	dw += dx;
	dh += dy;{
	int16_t largest = 0;
	int16_t largesty = 0;
		int16_t drawX = x;
				int16_t drawY = y;

				if (drawX >= dx && drawX < dw && drawY >= dy && drawY < dh){
	// Simply call through our helper
	writeRectNBPP(x, y, w, h,  4, pixels, palette );
        }
    }
}

the only real difference I see is the pgm read byte. could this be the problem????
 
You need to print out some stuff in your function checkcolision() to see where it is failing. See my other post. Does tft.numcolision have a reasonable value? If it is zero, then you aren't checking anything. Does (tft.collideRectRect() find some matches? I would expect up to 4 each time you call the function. Do the values stored in solid.x, solid.y and solid.sprintcol look reasonable? Print them out and see. Print out the value for rock ( which appears to be the address in memory of the sprite ). Do the values stored in solid.sprintcol look like they are even close?

This will print values out at your frame rate. You will want to print out some extra messages to mark the begin and end of a set of data.
 
Ok just back from town with a new cord. Just tell me what to print and where. I changed the 60 to 300. I also changed the byte nu collision to = 3 since it gets a plus one in the sketch.

but look at this...
Code:
void GrafxT3::drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, const uint16_t * palette){
	drawTilemap(x, y, tilemap, spritesheet, 0, 0, GrafxT3_TFTHEIGHT, GrafxT3_TFTWIDTH, palette);
}
void GrafxT3::drawTilemap(int x, int y, const uint8_t *tilemap, const uint8_t **spritesheet, uint16_t dx, uint16_t dy, uint16_t dw, uint16_t dh, const uint16_t * palette){
	uint16_t tilemap_width = pgm_read_byte(tilemap);
	uint16_t tilemap_height = pgm_read_byte(tilemap + 1);
	uint16_t tile_width = pgm_read_byte(tilemap + 2);
	uint16_t tile_height = pgm_read_byte(tilemap + 3);
	tilemap += 4; // now the first tiyleis at tilemap
	uint16_t ddw = dw + dx;
	uint16_t ddh = dh + dy;
	uint16_t maxDdx = (dw - x + tile_width - 1) / tile_width;
	uint16_t maxDdy = (dh - y + tile_height - 1) / tile_height;
	if (tilemap_width < maxDdx){
		maxDdx = tilemap_width;
	}
	if (tilemap_height < maxDdy){
		maxDdy = tilemap_height;
	}
	int16_t startDdx = (-x) / tile_width;
	int16_t startDdy = (-y) / tile_height;
	if (startDdx < 0){
		startDdx = 0;
	}
	if (startDdy < 0){
		startDdy = 0;
	}
	if (flagcollision)numcolision = 0;                                  //Line 735 - clear numcolision - ADD by Summoner123

	for (uint16_t ddy = startDdy; ddy < maxDdy; ddy++){
		for (uint16_t ddx = startDdx; ddx < maxDdx; ddx++){
			int16_t drawX = ddx*tile_width + x + dx;
			int16_t drawY = ddy*tile_height + y + dy;
			uint16_t tile = pgm_read_byte(tilemap + ddy*tilemap_width + ddx);
			if (drawX >= dx && drawY >= dy && drawX <= (ddw - tile_width) && drawY <= (ddh - tile_height)){
				writeRectNBPP(drawX, drawY,tile_width, tile_height, 4, spritesheet[tile], palette );

				if (flagcollision){
					solid[numcolision].x = drawX;                     //Save X coordinate      - ADD by Summoner123
					solid[numcolision].y = drawY;                     //Save Y coordinate      - ADD by Summoner123
					solid[numcolision].spritecol = spritesheet[tile]; //Save Sprite of tile    - ADD by Summoner123
					numcolision++;                                    //Increment numcolision  - ADD by Summoner123
				}
			}
			else{ // we need to draw a partial bitmap
				writeRect4BPPtm(drawX, drawY, tile_width, tile_height, spritesheet[tile], dx, dy, dw, dh, palette);
			}
		}
	}
}

do I need to change the code with the line 735 comment?

other wise I changed the .h to this.....

Code:
typedef struct {       //line 171 "Public Variables   - ADD by Summoner123
		int x;                    //X coordinate                 - ADD by Summoner123
		int y;                    //Y coordinate                 - ADD by Summoner123
		const byte *spritecol;    //Sprite of object             - ADD by Summoner123
	}object;
	object solid[300];         // Matriz were saved a Sprite, X and Y cordinates of all tiles on the screen - ADD by Summoner123

	byte numcolision = 3;     //count of solid objects indacat how many tiles drawed on the screen - ADD by Summoner123

	bool flagcollision = true;

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
//////////////-----------------------------Collision--------------------------//////////////
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////

	boolean collidePointRect(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t w, int16_t h);
	boolean collideRectRect(int32_t x1, int32_t y1, int32_t w1, int32_t h1, int32_t x2, int32_t y2, int32_t w2, int32_t h2);
	boolean collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2);
 
Last edited:
Ok so I set up my sketch again to print colors when ever a tile is hit. I then went around the map the best I could looking for a collision. Here's the thing. The one collision o get is always in the same place at the top of the screen left corner. And it only reacts from direction the left. So say you started all the way left of the collision tile that's working and walk to that tile nothing. But if you start right of it and walk left toward the tile it will collide. Up and down are the same. You can only hit it from the left.

So only one tile period is being collided with.

I included a newer example that buses the collision in the same way but with other stuff the collision stuff is the bottom.....


View attachment connect_maps_inventory.zip

you can load the included hex files into this simulator....

http://simbuino4web.ppl-pilot.com/


Edit::: ok I rechecked and I'm getting more collisions in the bottom corners but nothing at the top right corner.
 
Last edited:
Status
Not open for further replies.
Back
Top