[SDL] loading up tiles from an image

Started by
5 comments, last by econobeing 17 years, 6 months ago
i'm trying to load up the positions (top left pixel) of tiles, and save them in a vector, but it seems that the function to load them up doesn't work like i want it to. i'm trying to load them up left to right, then proceed to the next row and do it again. but it doesn't work how i want it to, i've re-written the functions twice now, and each time i get different results, but not what i want. here's my header:
#include <string>
#include <vector>

#include <SDL.h>
#include <SDL_image.h>

#ifndef _MAPS_H_
#define _MAPS_H_

struct tile{
	Uint16 tileSize;
	Uint16 sourceX;
	Uint16 sourceY;
	Uint16 drawX;
	Uint16 drawY;
	SDL_Surface* sourceImg;
};//struct tile

class tileMap{
	public:
		//data members
		SDL_Surface* sourceImg;
		std::vector<tile> map;
		std::vector<tile> tiles;
		//functions
		tileMap();
		tileMap(const char filename[],Uint16 tileSize,Uint8 gutter_size);
		tileMap(SDL_Surface* source_image,Uint16 tileSize,Uint8 gutter_size);
		void initMap(Uint16 map_width,Uint16 map_height);
		void drawMap(SDL_Surface* dest,int startX,int startY);
		Uint16 getTotalTiles();
		Uint16 getTileSize();
		Uint8 getGutterSize();
		Uint16 getMapWidth();
		Uint16 getMapHeight();
	private:
		//data members
		Uint16 totalTiles;
		Uint16 mapWidth;
		Uint16 mapHeight;
		Uint16 tileSize;
		Uint8 gutterSize;
		//functions
		void loadTiles();
};


#endif // _MAPS_H_

here's my .cpp file:
#include <string>
#include <vector>

#include <SDL.h>
#include <SDL_image.h>

#include "maps.h"

using namespace std;

tileMap::tileMap(){
	this->sourceImg = NULL;
}//tileMap::tileMap()

tileMap::tileMap(const char fileName[],Uint16 tile_size,Uint8 gutter_size){
	//fill out class info
	this->sourceImg = NULL;
	this->sourceImg = IMG_Load(fileName);
	this->tileSize = tile_size;
	this->totalTiles = ((sourceImg->w / this->tileSize) + (sourceImg->h / this->tileSize));
	this->gutterSize = gutter_size;

	//load the tiles
	if(this->sourceImg != NULL)
		this->loadTiles();
}//tileManager::tileManager(const char filename[],Uint16 tileWidth,Uint16 tileHeight)

tileMap::tileMap(SDL_Surface* source_image,Uint16 tile_size,Uint8 gutter_size){
	//fill out class info
	this->sourceImg = source_image;
	this->tileSize = tile_size;
	this->totalTiles = ((sourceImg->w / this->tileSize) + (sourceImg->h / this->tileSize));
	this->gutterSize = gutter_size;
}//tileMap(SDL_Surface* source_image,Uint16 tileSize,Uint8 gutter_size)

void tileMap::loadTiles(){
	this->tiles.clear();
	//for each row of tiles
	for(int rowIter = this->gutterSize ; rowIter < (this->sourceImg->w / (this->tileSize + this->gutterSize)) ; rowIter += (this->tileSize + this->gutterSize)){
		//for each column of tiles(per row)
		for(int colIter = this->gutterSize ; colIter < (this->sourceImg->w / (this->tileSize + this->gutterSize)) ; colIter += (this->tileSize + this->gutterSize)){
			tile iter;
			iter.tileSize = this->tileSize;
			iter.sourceImg = this->sourceImg;
			iter.sourceX = rowIter;
			iter.sourceY = colIter;

			this->tiles.push_back(iter);
		}//for each column of tiles(per row)
	}//for each row of tiles
}//void tileManager::loadTiles()

void tileMap::initMap(Uint16 map_width,Uint16 map_height){
	this->mapWidth = map_width;
	this->mapHeight = map_height;

	//Uint16 maxTile=0;
	//Uint16 randTile=0;
	//for(std::vector<tile>::iterator iter = this->tiles.begin() ; iter < this->tiles.end() ; iter++)
	//	maxTile++;

	//loop through each row of tiles
	for(int tileX=0 ; tileX < map_width ; tileX++){
		for(int tileY=0 ; tileY < map_height ; tileY++){
			//create an iterator to hold temporary data used to fill
			//the map that's being initialized
			tile iter;

			//randTile = rand()%maxTile;

			//randTile=rand()%maxTile;
			iter.sourceImg = this->sourceImg;
			iter.tileSize = this->tileSize;
			iter.sourceX = this->tiles[0].sourceX;
			iter.sourceY = this->tiles[0].sourceY;
			iter.drawX = tileX * this->tileSize;
			iter.drawY = tileY * this->tileSize;

			//add the tile to the map
			this->map.push_back(iter);
		}//for each column
	}//for each row
}//initMap(Uint16 map_width,Uint16 map_height)

void tileMap::drawMap(SDL_Surface* dest,int startX,int startY){
	//for each tile in the map
	SDL_Rect sourcePos;
	SDL_Rect destPos;
	for(std::vector<tile>::iterator iter = this->map.begin(); iter < this->map.end() ; iter++){
		//if it is on the surface horizontally (not too far left or right)
		if(iter->drawX + iter->tileSize > 0 && iter->drawX < dest->w){
			//if it is on the surface vertically (not too far up or down)
			if(iter->drawY + iter->tileSize > 0 && iter->drawY < dest->h){
				//grab the source positions and dimensions
				sourcePos.x = iter->sourceX;
				sourcePos.y = iter->sourceY;
				sourcePos.w = iter->tileSize;
				sourcePos.h = iter->tileSize;

				//get the destination position and dimensins
				destPos.x = (startX + iter->drawX);
				destPos.y = (startY + iter->drawY);
				//destPos.w = sourcePos.w;
				//destPos.h = sourcePos.h;

				//(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect))
				SDL_BlitSurface(iter->sourceImg,&sourcePos,dest,&destPos);
			}
		}
	}//for each tile in the map
}//void drawMap(SDL_Surface* dest,int startX,int startY);

Uint16 tileMap::getTotalTiles(){
	return this->totalTiles;
}//Uint16 getTotalTiles()

Uint16 tileMap::getTileSize(){
	return this->tileSize;
}//Uint16 getTotalTiles()

Uint8 tileMap::getGutterSize(){
	return this->gutterSize;
}//Uint16 getTotalTiles()

Uint16 tileMap::getMapWidth(){
	return this->mapWidth;
}//Uint16 tileMap::getMapWidth()

Uint16 tileMap::getMapHeight(){
	return this->mapHeight;
}//Uint16 tileMap::getMapHeight();

this is getting to me, i have no idea what i'm doing wrong... i really need some help on this.
Advertisement
oh yeah, here's the image i'm trying to use:

Wait, so are you trying to take that large image and break it into tiles, as outlined on the image in black?
my siteGenius is 1% inspiration and 99% perspiration
In order to help you, it'd be good if we knew what exactly was not working. If you simply throw code at us and say "Why isn't it working?" with no description of what its not doing properly, we can't help you at all. So if you could describe in a little more detail what exactly is happening thats not supposed to happen, and whats not happening thats supposed to happen, I, or one of the other great forum members here, can help you.
to silver:
yeah i'm trying to use a vector of those tile structs to hold the position from the image, and the size of the tile, the black lines are just visual seperators between the tiles(i accounted for that in the code though)

to scott:
i think i did a pretty good job describing what i want it to do in the top paragraph

if i knew what was wrong there would be no point in asking for help because i could just fix it myself.

I, or one of the other great forum members here

^wow...

but anyway, i did notice that i had the X and Y mixed up in the for loops, the loop for the X positions is supposed to be inside the loop for the Y positions, for going left to right.

i'm trying to track down what i'm doing wrong a little bit at a time, i think i have it, i had the Xs and Ys all wierd and tangled up.

here's a code::blocks project of my program, if anybody wants to take a look at it, though i'm using linux so you might have to change some things around if you're using windows, but it's probably good.

baby steps...
Alright, you don't know what's wrong, but can you at least tell us what it is doing? There's a whole lot of things that qualify as "not the right thing". Say, is it crashing? (if so, then it should be easy to fix with a debugger) Are the tiles just comming up blank? Are you getting the tiles correctly, but they aren't in the right position? Are you getting parts of tiles?

You get the point.

That said, I'm going to take a guess that this line of code is a problem (in both for loops):

rowIter < (this->sourceImg->w / (this->tileSize + this->gutterSize)) ; rowIter += (this->tileSize + this->gutterSize)

The bolded part doesn't seem right to me, when you take into account the last bit. The bolded part seems to be calculating the number of tiles in the image, and make sure that you don't exceed that amount. However, the next part seems to be incrementing by pixels, not by 'current tile number'. I'd change it to:


rowIter < this->sourceImg->w ; rowIter += (this->tileSize + this->gutterSize)

Note that you should change the colIter loop like this, too. And you know that you don't have to put this-> before every member variable?
oh, well, sometimes when i'm tweaking with the loading loop the tiles come up as blank, or only a couple will load, or it will grab the position from the middle of a tile(getting black lines across my tile).

i also simplified the(i forget what it's called)...finishing checking in my for loops by calculating how many are in a row before i make the loops, and using that variable in there.

i was looping by 1,2,3, then checking against the total number of tiles, then i'd get the position by multiplying the iterator number by the size of a tile and the gutter between them.

oh yeah, i know i don't have to use this-> but it's a force of habit that carried over from C# :/

but here's a pic of how it's acting now:


i wanted to load all the tiles up(like i said, left to right, down to the next row, left to right, etc). then i made a map 20 tiles wide(which happens to be the number of tiles in the image). then i blitted all the tiles out in order across the row, so it's working.

here's some pictures of when it wasn't working:

This topic is closed to new replies.

Advertisement