Jump to content
  • Advertisement
Sign in to follow this  
rpg_code_master

tilemap trouble

This topic is 4857 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, I am having this weird bug with my tiles. The pixels seem to wrap 1px in both the x and the y coords. I have tried to fix this bug, but I just can't seem to figure out what it is. I think that it must be in the loading code, i'm not sure. I couldn't get a screen shot for some reason. Here is the project in question (9MB). Here is the most suspect code.
// FILE: TileMap.h by Richard Hughes. 30/11/2003
//
// DESC: This declares the CTileMap and assosiated classs

#pragma once

// INCLUDES
#include "MemoryManager.h"
#include "ErrorLogging.h"
#include "Graphics.h"
#include "Image.h"
#include "Util.h"
#include "FileInfo.h"

/*********************************************************************************************/
//
//	CLASS: tagTile
//
//	DESC: This is a tile
//
/*********************************************************************************************/

typedef struct tagTile : public IMemObject {
	tagTile( void )
	{
	}
	~tagTile( void )
	{
	}
	unsigned char* m_pData;    // the image data
	long           m_lWidth,   // the tiles width
		           m_lHeight;  // the tiles height
	unsigned long  m_dwFormat; // RGB RGBA
	unsigned long  m_dwInternalFormat; // RGB RGBA

	QUICK_SIZE;
}TILE, *LPTILE;

/*********************************************************************************************/
//
//	CLASS: CTileMap
//
//	DESC: This handles tilemaps. see doc for more info
//
/*********************************************************************************************/

class CTileMap : public IError {

	CPointer < TILE > m_Tiles;  // the tiles in the tilemap

public:
	CTileMap( void )
	{
	}
	~CTileMap( void )
	{
	}

	// this loads in a tile map directly
	ERROR_STRING Load( string strFName, int nHeight, int nWidth, long lTWidth, long lTHeight, 
					   int nHBorder, int nVBorder );

	// this loads certain tiles from a tilemap directly
	ERROR_STRING Load( string strFName, int nHeight, int nWidth, long lTWidth, long lTHeight, 
					   int nHBorder, int nVBorder, pint pList );

	// this loads in a tilemap directly via a tilemap file
	ERROR_STRING Load( string strFName );

	// this loads in a tilemap indirectly via a tilemap file
	ERROR_STRING Load( string strFName, pint pList, pstring pNames );

	// this returns a tile
	inline TILE& GetTile( int nIndex )
	{
		return ( m_Tiles[ nIndex ] );
	} // end GetTile

	QUICK_NAME( "CTileMap" );
	QUICK_SIZE;
}; // end CTileMap

// EOF: TileMap.h

// FILE: TileMap.cpp by Richard Hughes. 30/11/2003
//
// DESC: This defines the CTileMap class

// INCLUDES
#include "TileMap.h"

/*********************************************************************************************/
//
//	CLASS: CTileMap
//
//	DESC: This handles tilemaps. see doc for more info
//
/*********************************************************************************************/

// this loads in a tilemap
// it takes the tilemaps filename, the amount of cells heigh and wide, the height and the width of the tiles,
// and the horizontal and vertical border
// it returns the nessercary ERROR_STRING error
ERROR_STRING CTileMap::Load( string strFName, int nHeight, int nWidth, long lTWidth, long lTHeight, 
							 int nHBorder, int nVBorder )
{
	Enter( "Load_Direct" );


	int nBPP = 0; // the images BPP

	// load in the tilemap
	CImage Image;
	ERROR( Image.Load( strFName ) );

	// init the tiles
	m_Tiles.Init( nWidth*nHeight );

	// set the BPP
	nBPP = ( Image.GetFormat( ) == CF_RGB ) ? 3 : 4;

	// compute the tile area
	UCHAR *pSource, *pDest;    // pointers for saving
	long Width = lTWidth * nBPP;
	long Height = lTHeight * nBPP;
	long TileArea = Width*Height;

	/*
		extract the image data into the cells
	*/
	// get the image data
	unsigned char* p = Image.GetData( );
	pSource = Image.GetData( );

	// get the image width in bits ( RGB )
	long lImageWidth = Image.GetWidth( ) * nBPP;
	long l = 0;

	// loop thru and load in all of the cells
	for ( long idx = 0; idx < nWidth; idx++ )
		for ( long idy = 0; idy < nHeight; idy++ ) {
			l = idx+( idy*nWidth );

			// set the image stats
			m_Tiles[ l ].m_pData = new unsigned char[ TileArea ];
			memset( m_Tiles[ l ].m_pData, 0, sizeof ( unsigned char ) * TileArea );
			m_Tiles[ l ].m_lWidth = lTWidth;
			m_Tiles[ l ].m_lHeight = lTHeight;
			m_Tiles[ l ].m_dwFormat = Image.GetFormat( );
			m_Tiles[ l ].m_dwInternalFormat = Image.GetInternalFormat( );
			pDest = m_Tiles[ l ].m_pData;

			int cx = idx*Width;
			int cy = idy*lTHeight;

			// extract bitmap data
			pSource = Image.GetData( ) + cy*lImageWidth+cx;

			for ( int y = 0; y < lTHeight; y++ )
			{
				// copy over the first line of the tile
				memcpy( pDest, pSource, Width );

				// goto the next line
				pSource += lImageWidth;
				pDest += Width;
			} // end for
		} // end for

	RETURN_SUCCESS;
} // end CTileMap::Load
// FILE: 25DMap.h by Richard Hughes. 19/02/2005
//
// DESC: This file defines the 25DMap and assosiated classes

#ifndef __25DMap_h__
#define __25DMap_h__

// INCLUDES
#include <vector>
#include "ErrorLogging.h"
#include "Mesh.h"
#include "Tilemap.h"
#include "Animation.h"
#include "SpriteManager.h"

using namespace std;

/*********************************************************************************************/
//
//	CLASS: CTile
//
//	DESC: This is a tile
//
/*********************************************************************************************/

class CTile : public IError {
	
	char               m_strIdx[ MAX_STRING_LENGTH ]; // the tiles index
	CAnimation         m_Anim;   // this tiles animation
	int                m_nFrame; // the current animation frame
	CPointer < CQuad > m_pTiles; // the tile animations
	float              m_fX,     // the tiles x pos
		               m_fY;     // the tiles y pos
	int                m_nW,     // the tiles width
		               m_nH;     // the tiles height
	float              m_fSW,    // the scale width
		               m_fSH;    // the scale height

public:
	CTile( void )
	{
		m_nFrame = 0;
		m_fX = m_fY = 0.0f;
		m_nW = m_nH = 0;
		m_fSW = m_fSH = 1.0f;
	}
	~CTile( void )
	{
	}

	// this loads the tile
	ERROR_STRING Load( CPointer < CTileMap > pMap, int w, int h, string strFName );

//.....

#endif /* __25DMap_h__*/

// EOF: 25DMap.h

// FILE: 25DMap.cpp by Richard Hughes. 19/02/2005
//
// DESC: This file defines the 25DMap and assosiated classes

// INCLUDES
#include "25DMap.h"
#include "TexturePool.h"
#include "Texture.h"
#include "Sprite.h"

/*********************************************************************************************/
//
//	CLASS: CTile
//
//	DESC: This is a tile
//
/*********************************************************************************************/

// this loads the tile
// it takes the tilemap to load the tiles from, the tile dimentions and the tile file name
// it returns the necessary ERROR_STRING error
ERROR_STRING CTile::Load( CPointer < CTileMap > pMap, int w, int h, string strFName )
{
	Enter( "Load" );

	if ( !pMap )
		RETURN_POINTER_NULL( "pMap" );

	FILE*  fp      = NULL;  // the file pointer
	string str     = "";    // temp
	int    n       = 0;     // temp
	float  f       = 0.0f;  // temp
	bool   bKey    = false; // whether to use a color key for this tile
	int    r1      = 0;     // the min red component of the color key
	int    r2      = 0;     // the max red component of the color key
	int    g1      = 0;     // the min green component of the color key
	int    g2      = 0;     // the max green component of the color key
	int    b1      = 0;     // the min blue component of the color key
	int    b2      = 0;     // the max blue component of the color key
	int    nSize   = 0;     // the size of the animation
	pint   pAnim;           // the animation indexes
	pfloat pTimes;          // the frame times

	// set the tile dimentions
	m_nW = w; m_nH = h;

	// load in the tile file
	// open the file
	fp = fopen( strFName.data( ), "r" );
	if ( POINTER_NULL( fp ) )
		RETURN_NOT_OPENED( strFName );

	// read in the index
	fscanf( fp, "%s", m_strIdx );

	// read in the number of frames
	fscanf( fp, "%d", &nSize );

	// init the animations
	m_pTiles.Init( nSize );
	pAnim.Init( nSize );
	pTimes.Init( nSize );

	// read in the animations
	for ( int i = 0; i < nSize; i++ )
	{
		fscanf( fp, "%d", &n );
		fscanf( fp, "%f", &f );
		pAnim[ i ] = n;
		pTimes[ i ] = f;
	} // end for

	// read in the color key if there is one
	if ( fscanf( fp, "%d", &r1 ) != EOF &&
		 fscanf( fp, "%d", &r2 ) != EOF &&
		 fscanf( fp, "%d", &g1 ) != EOF &&
		 fscanf( fp, "%d", &g2 ) != EOF &&
		 fscanf( fp, "%d", &b1 ) != EOF &&
		 fscanf( fp, "%d", &b2 ) != EOF )
			bKey = true;

	// close the file
	fclose( fp );
	fflush( fp );
	fp = NULL;

	// load in the indexes
	for ( i = 0; i < nSize; i++ )
	{
		// setup the quad
		m_pTiles[ i ].Init( w,h, 0,0, VB_TEX2D_1 );

		// load in the tile
		str = strFName + ToString( " : %d", i );
		CTexturePool::GetSingleton( ).LoadTex( pMap->GetTile( *pAnim[ i ] ), str, bKey, r1,r2, g1,g2, b1,b2 );

		// attach tex
		CTexturePool::GetSingleton( ).AttachTex( &m_pTiles[ i ], str, false );

		// set the animation index
		pAnim[ i ] = i;
	} // end for

	// create the animation
	m_Anim.Set( pAnim, pTimes, 0, m_strIdx );
    
	RETURN_SUCCESS;
} // end CTile::Load
// EOF: 25DMap.cpp

NOTE: The code above has now been edited down to be more specific. Thanks, [Edited by - rpg_code_master on April 1, 2005 5:38:48 AM]

Share this post


Link to post
Share on other sites
Advertisement
That's quite a lot of code for us to look through! Perhaps you can narrow it down somewhat..?

Share this post


Link to post
Share on other sites
I just skimmed through your code. You seem to use OpenGL or something to render your tiles? I didn't quite get what you meant by "wrap 1px in both x an the y coords", but if it is what I think it is, then you could try to shrink your tiles' texture size 0.5 pixels from all edges.

So if your texture co-ordinates are (0, 0) to (32, 32) then make that (0.5, 0.5) to (31.5, 31.5).

Share this post


Link to post
Share on other sites
I have narrowed down the code and have also mustered up a screen shot.

If you notice, the tiles seem to have wrapped 1px in the x and y directions. Note the top left, the sand path has grass on the wrong side and the ship in the bottom right the decking is incorect etc... This incorectness is only 1px I believe.

Share this post


Link to post
Share on other sites
In that code I don't see any indication (a) of how you load the textures, (b) how you set up the rendering system, or (c) how you do the rendering. These are the areas that are likely to be the problem, not the (edited) samples above.

The only suggestion I can give without any information on your rendering system is that your texture mode might be set to 'wrap' when it needs to be set to 'clamp'. How to do that will all depend on how you're actually rendering those graphics.

Share this post


Link to post
Share on other sites
There are two questions:
- what is your tile drawing code ?
Do you draw textured quads using integer coordinates or floating point vertices coords ? What is the unit width and height of your quad in world coordinates ?
- what is your texture tile loading code ?
What is the unit size of a texture tile in pixel ? If you load from a big texture bitmap multiple texture tiles, how do you calculate starting and ending texture coordinates for each tile ?

Ghostly yours,
Red.

Share this post


Link to post
Share on other sites
Ah, yes! Read my post again. I'm sure that will fix this problem :)

Basically you want your texture co-ordinates to point to the middle of the pixels, not their edges. That's why you add/subtract 0.5 pixels from the its size. Note that you do not change the actual size of the tile.

Otherwise the colour of the pixel next to it will have an influence.

Share this post


Link to post
Share on other sites
I'm pretty sure that your getting these results from using linear filtering, switch to point filtering and it will look just as it does on your images. If you want to use linear filtering without these borders render everything to a texture and then use linear filtering on the render texture.

Share this post


Link to post
Share on other sites
Yes, I use linear filtering. Whats point filtering? How do I implement that in OpenGL?

The tile drawing code is simply rendering a quad. The texture coords for that are 0,0 0,1 1,1 1,0. If you would like to see the code, download the project. It's all self explanitory.

I'm not going to post anymore code because there is alot of code posted.

To get the tile data, I copy the pixels from the main loaded image. That code is posted in the tile loading code.

Share this post


Link to post
Share on other sites
Machinoid, I use 0.0,0.0 1.0,1.0 0.0,1.0 1.0,0.0 as texture coordinates because the quad does not know the size of the tile. How can I point to the middle of the pixels?

I tried 0.05 and 0.95, the produces better results but it squashes the tile.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!