I have a function that processes data from a dynamic vector and turns it into a tiled map, and another function that scrolls around the map when the player moves. I'm not really sure how this is happening, but every row and column of tiles that is generated (which happens when they come into view of the player) sticks around on the borders of the screen when they are no longer in the view of the player. They are all stored in the same position, so basically all of the rows and columns that have been generated and that are no longer in view (ie, when the player moves away from them) are piled on top of one another on the outer edge of the screen. They should, at least, stick around OUT OF VIEW, but the "hidden" rows and columns are just barely visible - about two pixels of them stay on the edge of the screen.
This screenshot shows the "hidden" column on the left-hand side. There is a two-pixel-wide line of tiles that just shouldn't be there. The red arrows point out the places where this is visible, but they actually run up the whole side - the rest of them just blend in because they are the same color as the background.
When I run the program and I am in the position captured by the above screenshot, if I move up or down, the little rectangles get longer or shorter, respectively. This is because the "hidden" column is in a fixed position, but the visible tiles on the map move when I move the character. It's like the tiles on the map cover up the tiles in the hidden column until the map tiles move down, at which point the hidden column is uncovered.
The first column on the far left-hand side of the map is all water tiles, so it is solid blue. In the second screenshot above, I have moved all the way to the left of the map (thus generating the columns of tiles that had not been generated in the first screenshot) and then moved back to the right. If you look closely, you'll see a solid, two-pixel-wide line of blue - that is the first column of water tiles, covering up the rest of the "off-screen" tiles in the hidden column, and completely visible over the map tiles. I'm not sure why it is this way, but the top row of tiles on the map has the same effect - a solid blue line across the top of the screen.
In this screenshot I have reduced the number of visible tiles on the screen from (20, 15) to (18, 13). The highlighted row and column at the bottom-right are the hidden row and column on that side of the screen. With the original settings, these are completely off the screen and are not visible whatsoever. However, when the number of visible tiles on the screen in reduced, this hidden row/column is in clear view. Directly after I took this screenshot, I moved the player up and left one tile and took this:
As you can see, the row/column that I highlighted in the screenshot before this stayed in the same position, in what would normally be off-screen. (The reason for the misalignment of the row and column is that I first had to move up, which froze the bottom row, and then left, which then froze the right column.)
The row on the bottom and the column on the right are not important, because once I change the settings back to normal they are off-screen. However, this illustrates roughly what is happening with the hidden column on the left side, and the hidden row on the top. While they should be off-screen, as the bottom-right ones normally are, they are about two pixels further in than they should be, and so are just barely visible on the borders of the screen.
That is my dilemma. I just can't figure out how to make that stupid little border go away. For now, I'll just post all of my relevant code. Let me know if it's too much, or not enough, and I'll make changes as is necessary.
Main.h:
// STRUCTURES
struct TileProperties
{
bool bSolid; // true if the tile is solid
char* cName;
};
struct SysVars
{
static const int tileSize = 32;
static const int viewWidth = 18;
static const int viewHeight = 13;
int mapWidth;
int mapHeight;
}; extern SysVars System1;
// CURRENT MAP
extern std::vector<int> currentMap;
// FUNCTION PROTOTYPES
const TileProperties& GetTile(int iX, int iY);
void PlayerInit();
void MapInit();
Main.cpp:
#include <iostream>
#include <vector>
#include <string>
#include <DarkGDK.h>
#include "Main Header.h"
using namespace std;
SysVars System1;
std::vector<int> currentMap(System1.mapWidth * System1.mapHeight);
void DarkGDK (void)
{
dbSyncOn ();
dbSyncRate (60);
dbDisableEscapeKey ();
dbRandomize (dbTimer ());
System1.mapWidth = 30;
System1.mapHeight = 25;
int Super_Map[30 * 25] = {/* map array */};
int mapSize = sizeof Super_Map / sizeof *Super_Map;
currentMap.assign(Super_Map, Super_Map+mapSize);
PlayerInit();
while(LoopGDK())
{
if(dbEscapeKey())
break;
dbSync();
}
}
Player.cpp:
#include <DarkGDK.h>
#include "Main Header.h"
int viewX=32;
int viewY=32;
int usrX=0;
int usrY=0;
void PlayerInit ()
{
int usrImage = 10001;
int usrDir = 0; /* 0 NORTH *\
|* 1 WEST *|
|* 2 SOUTH *|
\* 3 EAST */
dbLoadImage ( "player.png", usrImage);
dbCreateAnimatedSprite ( usrImage, "player.png", 4, 4, usrImage);
while ( LoopGDK () )
{
// define simple variables to refer to elements of <struct SysVars System1>
int mH = System1.mapHeight;
int mW = System1.mapWidth;
int vH = System1.viewHeight;
int vW = System1.viewWidth;
dbSprite (usrImage, 320 + usrX, 240 + usrY, usrImage);
dbOffsetSprite (usrImage, 12, 28);
dbSetSpritePriority (usrImage, 2);
// STANDING STILL
if(!dbUpKey() && !dbRightKey() && !dbDownKey() && !dbLeftKey())
dbSetSpriteFrame(usrImage, (4 * usrDir) + 2);
// REMEMBER! The halfway-point on the viewscreen is (320, 240)
// NORTH
if(dbUpKey() && !dbRightKey() && !dbLeftKey())
{
if (usrDir != 0) dbSetSpriteFrame(usrImage, 1);
usrDir = 0;
if(!GetTile(viewX+usrX+316, viewY+usrY+234).bSolid && !GetTile(viewX+usrX+324, viewY+usrY+234).bSolid)
{
if(viewY > 0 && usrY == 0)
viewY-=2;
else if(viewY <= 0 && usrY > -236 || viewY + 480 >= mH * 32 && usrY > 0)
usrY-=2;
}
dbPlaySprite (usrImage, 1, 4, 150);
}
// WEST
if(dbLeftKey() && !dbUpKey() && !dbDownKey())
{
if (usrDir != 1) dbSetSpriteFrame(usrImage, 5);
usrDir = 1;
if(!GetTile(viewX+usrX+314, viewY+usrY+244).bSolid && !GetTile(viewX+usrX+314, viewY+usrY+236).bSolid)
{
if(viewX > 0 && usrX == 0)
viewX-=2;
else if(viewX <= 0 && usrX > -316 || viewX + 640 >= mW * 32 && usrX > 0)
usrX-=2;
}
dbPlaySprite (usrImage, 5, 8, 150);
}
// SOUTH
if(dbDownKey() && !dbRightKey() && !dbLeftKey())
{
if (usrDir != 2)
{
dbSetSpriteFrame(usrImage, 9);
usrDir = 2;
}
if(!GetTile(viewX+usrX+316, viewY+usrY+246).bSolid && !GetTile(viewX+usrX+324, viewY+usrY+246).bSolid)
{
if(viewY+480 < mH*32 && usrY == 0)
viewY+=2;
else if(viewY+480 >= mH*32 && viewY+usrY+244 < mH*32 || viewY == 0 && usrY < 0)
usrY+=2;
}
dbPlaySprite (usrImage, 9, 12, 150);
}
// EAST
if(dbRightKey() && !dbUpKey() && !dbDownKey())
{
if (usrDir != 3) dbSetSpriteFrame(usrImage, 13);
usrDir = 3;
if(!GetTile(viewX+usrX+326, viewY+usrY+244).bSolid && !GetTile(viewX+usrX+326, viewY+usrY+236).bSolid)
{
if(viewX+640 < mW*32 && usrX == 0)
viewX+=2;
else if(viewX+640 >= mW*32 && viewX+usrX+324 < mW*32 || viewX == 0 && usrX < 0)
usrX+=2;
}
dbPlaySprite (usrImage, 13, 16, 150);
}
MapInit();
dbSync();
}
}
MapLibrary.cpp:
#include <DarkGDK.h>
#include "Main Header.h"
extern int viewX;
extern int viewY;
TileProperties myTileset[5] = {
{ false, "event" },
{ false, "grass" },
{ true , "water" },
{ false, "snow" },
{ false, "sand" }};
const TileProperties& GetTile(int iX, int iY)
{
iX = iX / 32; iY = iY / 32; // convert pixel coordinates to tile coords
return myTileset[currentMap[(iY * System1.mapWidth) + iX]];
}
void MapInit ()
{
// load the main tileset image(s)
dbLoadImage ("tileset.png", 1);
// define simple variables to refer to elements of <struct SysVars System1>
int mW = System1.mapWidth;
int mH = System1.mapHeight;
int vW = System1.viewWidth;
int vH = System1.viewHeight;
// system coords refer to the (x,y) of the first visible tile in the (0,0) position
// calculated by dividing the pixel coords of the viewscreen by the tilesize, 32
int systemX = viewX/32;
int systemY = viewY/32;
// run through every tile in every row, in that order!
for(int H = systemY; H < systemY+vH+1; H++)
for(int W = systemX; W < systemX+vW+1; W++) // start at the first tile on the screen, end at the other side, and then some for scrolling
{
// tile sprite and ID
int tSprite = (H*mW)+W+1; // because sprite IDs start at 1,
int tID = (H*mW)+W; // and vector cells start at 0
dbSetSpritePriority(tSprite,0);
// make sure we don't go over the map size - otherwise it CRASHES
if(tSprite > currentMap.size()) break;
// first we draw the sprite, which is clipped and sized later
dbSprite (tSprite, W*32-viewX, H*32-viewY, 1);
/* There's some math here, to clip the tile from a tileset for use on the map. */
}
}
neguz