Jump to content
  • Advertisement
Sign in to follow this  
FantasyVI

Problem with tile map editor

This topic is 2522 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

Hello everyone

I have been working on a tile map editor and i have a small problem.

I have 6 buttons on my screen where you can choose what tile you want to draw. You click on the button and press on the screen to start drawing.

now the problem is when you click on grass tile and draw then click on ice tile, all the grass tiles turns into grass. what should happen is when you click on ice you draw ice and when you click on grass you draw grass not change the existing tile.

here is a video to explain my problem more.
BTW sorry i was listing to that song when i recorded and forgot to disable the sound :D.



Map.cpp

#include "Map.h"
#include "UI.h"

UI UI1;

Map::Map(float x, float y)
{
Delete=false;
Position = sf::Vector2f(x,y);

TileImage[0].LoadFromFile("Data/Tiles/Grass.png");
TileImage[1].LoadFromFile("Data/Tiles/Grass2.png");
TileImage[2].LoadFromFile("Data/Tiles/Dirt.png");
TileImage[3].LoadFromFile("Data/Tiles/Desert.png");
TileImage[4].LoadFromFile("Data/Tiles/Stone.png");
TileImage[5].LoadFromFile("Data/Tiles/Ice.png");
TileImage[6].LoadFromFile("Data/Tiles/Water.png");

TileSprite[0].SetImage(TileImage[0]);
TileSprite[1].SetImage(TileImage[1]);
TileSprite[2].SetImage(TileImage[2]);
TileSprite[3].SetImage(TileImage[3]);
TileSprite[4].SetImage(TileImage[4]);
TileSprite[5].SetImage(TileImage[5]);
TileSprite[6].SetImage(TileImage[6]);

TileImage[0].SetSmooth(false);
TileImage[1].SetSmooth(false);
TileImage[2].SetSmooth(false);
TileImage[3].SetSmooth(false);
TileImage[4].SetSmooth(false);
TileImage[5].SetSmooth(false);
TileImage[6].SetSmooth(false);
}

Map::~Map(void)
{
}

void Map::Init(sf::RenderWindow &Window)
{
MouseX = Window.GetInput().GetMouseX();
MouseY = Window.GetInput().GetMouseY();
}

void Map::AddTile()
{
TowerVector.push_back(new Map(MouseX, MouseY));
}

void Map::Event(sf::Event Event)
{
if(Event.Type == sf::Event::MouseButtonPressed && Event.MouseButton.Button == sf::Mouse::Left)
AddTile();

if(Event.Type == sf::Event::KeyPressed && Event.Key.Code== sf::Key::D)
Delete=true;
}

void Map::Draw(sf::RenderWindow &Window)
{
for(int x=4; x<28; x++)
for(int y=4; y<20; y++)
map[y][x] = 0;

for(int i = 0; i <TowerVector.size(); i++)
{
int X = TowerVector->Position.x / 32;
int Y = TowerVector->Position.y / 32;

map[Y][X] = 1;

for(int x=4; x<28; x++)
{
for(int y=4; y<20; y++)
{
if(X == x && Y == y)
{
if(UI1.GetTileID() == 0)
TileSprite[0].SetPosition(X*32, Y*32);

if(UI1.GetTileID() == 1)
TileSprite[1].SetPosition(X*32, Y*32);

if(UI1.GetTileID() == 2)
TileSprite[2].SetPosition(X*32, Y*32);

if(UI1.GetTileID() == 3)
TileSprite[3].SetPosition(X*32, Y*32);

if(UI1.GetTileID() == 4)
TileSprite[4].SetPosition(X*32, Y*32);

if(UI1.GetTileID() == 5)
TileSprite[5].SetPosition(X*32, Y*32);

if(UI1.GetTileID() == 6)
TileSprite[6].SetPosition(X*32, Y*32);
}
}
}

if(Delete==true)
{
TowerVector.erase(TowerVector.end() - 1);
}
Delete=false;

for(int i=0; i<6; i++)
Window.Draw(TileSprite);
}
}




UI.CPP

int UI::GetTileID()
{
if(Tiles[0].Clicked == true)
TileID = 0;

if(Tiles[1].Clicked == true)
TileID = 1;

if(Tiles[2].Clicked == true)
TileID = 2;

if(Tiles[3].Clicked == true)
TileID = 3;

if(Tiles[4].Clicked == true)
TileID = 4;

if(Tiles[5].Clicked == true)
TileID = 5;

if(Tiles[6].Clicked == true)
TileID = 6;

return TileID;
}


Main.cpp


#include <SFML/Graphics.hpp>
#include <iostream>
#include "Map.h"
#include "UI.h"

int main()
{
sf::RenderWindow Window (sf::VideoMode(1024, 768, 32),"vovo");
Map Map(0,0);
UI UI;

UI.LoadFiles();
while(Window.IsOpened())
{
Window.SetFramerateLimit(60);
sf::Event Event;
Map.Init(Window);

while(Window.GetEvent(Event))
{
Map.Event(Event);
UI.Event(Event);
}

Window.Clear();
Map.Draw(Window);
Map.DrawLines(Window);
UI.Draw(Window);
Window.Display();
}
return 0;
}

Share this post


Link to post
Share on other sites
Advertisement
When drawing the map, you don't check what the tile is at each position, but use a global type for each. Hence, they are all the same. Also, you are looping the the whole map for each object. You don't need that. Just get the position of the object and draw.

Share this post


Link to post
Share on other sites

When drawing the map, you don't check what the tile is at each position, but use a global type for each. Hence, they are all the same. Also, you are looping the the whole map for each object. You don't need that. Just get the position of the object and draw.


ok my question is how can i get each tile position ?
sorry but I'm an absolute newbie.

Share this post


Link to post
Share on other sites
Hi,

A bit of non-constructive criticism : your tile drawing logic is rather strange. Your tile map structure is also rather strange.

Anyhow, to make a fix to it, I think that you'll need to change your structures:

Some pseudo-code. The code doesn't work without changes. It is just to give you idea how to store a simple tile map to your computer's memory and how to draw it simply.



class Tile
{
public:
int TileID;

Tile()
{
TileID = 0;
}
}

class Map
{
public:
std::vector<Tile> TileMap;

float MapOffsetX,MapOffsetY;

void InitMap()
{
TileMapSizeX =24;
TileMapSizeY=16;

TileMap.resize(TileMapSizeX * TileMapSizeY);

MapOffsetX = 4 * 32; //offset to make a gap between sides of the screen (as on your example)
MapOffsetY = 4 * 32;

//Init your textures here

//Init your sprites here
}


void DrawMap()
{
for(int i=0;i<TileMap.size();++i)
{
int PosX = i % TileMapSizeX;
int PosY = i / TileMapSizeX;

TileSprite[TileMap.TileID].SetPosition(PosX * 32 + MapOffsetX, PosY * 32 + MapOffsetY);

Window.Draw(TileSprite[TileMap);
}

void ChangeTile(int MouseX,int MouseY,int TileID)
{

MouseX -= MapOffsetX;
MouseY -= MapOffsetY;

MouseX /= 32;
MouseY /= 32;

if(MouseX>= 0 && MouseX<TileMapSizeX && MouseY>= 0 && MouseY<TileMapSizeY)
{
TileMap.TileID = TileID;
}

}
};



Best regards!

Share this post


Link to post
Share on other sites

Hi,

A bit of non-constructive criticism : your tile drawing logic is rather strange. Your tile map structure is also rather strange.

Anyhow, to make a fix to it, I think that you'll need to change your structures:

Some pseudo-code. The code doesn't work without changes. It is just to give you idea how to store a simple tile map to your computer's memory and how to draw it simply.



class Tile
{
public:
int TileID;

Tile()
{
TileID = 0;
}
}

class Map
{
public:
std::vector<Tile> TileMap;

float MapOffsetX,MapOffsetY;

void InitMap()
{
TileMapSizeX =24;
TileMapSizeY=16;

TileMap.resize(TileMapSizeX * TileMapSizeY);

MapOffsetX = 4 * 32; //offset to make a gap between sides of the screen (as on your example)
MapOffsetY = 4 * 32;

//Init your textures here

//Init your sprites here
}


void DrawMap()
{
for(int i=0;i<TileMap.size();++i)
{
int PosX = i % TileMapSizeX;
int PosY = i / TileMapSizeX;

TileSprite[TileMap.TileID].SetPosition(PosX * 32 + MapOffsetX, PosY * 32 + MapOffsetY);

Window.Draw(TileSprite[TileMap);
}

void ChangeTile(int MouseX,int MouseY,int TileID)
{

MouseX -= MapOffsetX;
MouseY -= MapOffsetY;

MouseX /= 32;
MouseY /= 32;

if(MouseX>= 0 && MouseX<TileMapSizeX && MouseY>= 0 && MouseY<TileMapSizeY)
{
TileMap.TileID = TileID;
}

}
};



Best regards!


thank you very much now the code is working. :D
now I know that the code is very bad written but I just wanted the code to work then back it up and then start cleaning it and fixing it.
here is the full code if anyone is interested in making a map editor in sfml.

thank you again :D

Map.h

//This Code is verion 3 -- 22/12/2011.
#pragma once
#include <SFML\Graphics.hpp>
#include <SFML\Audio.hpp>
#include <iostream>
#include <string>
#include <fstream>

class Map
{
public:
Map(float x, float y);
~Map(void);
void Init(sf::RenderWindow &Window);
void Event(sf::Event Event);
void AddTile();
void WriteData();
void DrawLines(sf::RenderWindow &Window);
void Draw(sf::RenderWindow &Window);

private:
sf::Vector2f Position;
std::vector<Map*> TowerVector;
std::vector<int> TileID;

int ID;
float MouseX, MouseY;
bool Delete;
sf::Image TileImage[10];
sf::Sprite TileSprite[10];

int map[25][25];
int X, Y;

float MapSizeX, MapSizeY, MapOffsetX, MapOffsetY;
};



map.cpp

#include "Map.h"
#include "UI.h"

UI UI1; // GUI if button click do something

Map::Map(float x, float y)
{
Delete=false;
Position = sf::Vector2f(x,y);

TileImage[0].LoadFromFile("Data/Tiles/Grass.png");
TileImage[1].LoadFromFile("Data/Tiles/Grass2.png");
TileImage[2].LoadFromFile("Data/Tiles/Dirt.png");
TileImage[3].LoadFromFile("Data/Tiles/Desert.png");
TileImage[4].LoadFromFile("Data/Tiles/Stone.png");
TileImage[5].LoadFromFile("Data/Tiles/Ice.png");
TileImage[6].LoadFromFile("Data/Tiles/Water.png");

TileSprite[0].SetImage(TileImage[0]);
TileSprite[1].SetImage(TileImage[1]);
TileSprite[2].SetImage(TileImage[2]);
TileSprite[3].SetImage(TileImage[3]);
TileSprite[4].SetImage(TileImage[4]);
TileSprite[5].SetImage(TileImage[5]);
TileSprite[6].SetImage(TileImage[6]);

TileImage[0].SetSmooth(false);
TileImage[1].SetSmooth(false);
TileImage[2].SetSmooth(false);
TileImage[3].SetSmooth(false);
TileImage[4].SetSmooth(false);
TileImage[5].SetSmooth(false);
TileImage[6].SetSmooth(false);
}

Map::~Map(void)
{
}

void Map::Init(sf::RenderWindow &Window)
{
MouseX = Window.GetInput().GetMouseX();
MouseY = Window.GetInput().GetMouseY();
ID = UI1.GetTileID(); //if button click get Tile ID
}

void Map::AddTile()
{

TowerVector.push_back(new Map(MouseX, MouseY));
TileID.push_back(UI1.GetTileID());

for(int i = 0; i< TileID.size(); i++)
std::cout<<TileID;
}

void Map::Event(sf::Event Event)
{
if(Event.Type == sf::Event::MouseButtonPressed && Event.MouseButton.Button == sf::Mouse::Left)
AddTile();


if(Event.Type == sf::Event::KeyPressed && Event.Key.Code== sf::Key::D)
Delete=true;
}

void Map::WriteData()
{
std::ofstream WriteFile("Map.Data");
if(WriteFile.is_open())
{
for(int x=4; x<28; x++)
{
for(int y=4; y<20; y++)
{
WriteFile << map[y][x] << " ";
}
WriteFile << "\n";
}
WriteFile.close();
}
else
std::cout<<"Unable to open file";
}

void Map::DrawLines(sf::RenderWindow &Window)
{
for(int X=128; X<672; X+=32)
{
sf::Shape LineX = sf::Shape::Line(128, X, 896, X, 1, sf::Color(255, 0, 0));
Window.Draw(LineX);
}

for(int Y=128; Y<928; Y+=32)
{
sf::Shape LineY = sf::Shape::Line(Y, 128, Y, 640, 1, sf::Color(255, 0, 0));
Window.Draw(LineY);
}
}

void Map::Draw(sf::RenderWindow &Window)
{
for(int x=4; x<28; x++)
for(int y=4; y<20; y++)
map[y][x] = 0;

for(int i = 0; i <TowerVector.size(); i++)
{
int X = TowerVector->Position.x / 32;
int Y = TowerVector->Position.y / 32;

map[Y][X] = 1;

for(int x=4; x<28; x++)
{
for(int y=4; y<20; y++)
{
if(X == x && Y == y)
{
TileSprite[TileID].SetPosition(X*32, Y*32);
}
}
}
for(int i=0; i<6; i++)
Window.Draw(TileSprite);
}
}

Share this post


Link to post
Share on other sites
Hi,

I'm happy to hear that you have been able to advance in your project.

Anyway, I'd take another look in my code sample.

For example, your drawing code has a loop which iterates 384 * TowerVector.size() times. This gets slow in long run.
You draw also your GUI tiles 6 * TowerVector.size() times.

I suggest you to reserve a constant size vector (see the TileMap.resize() in my example). This way every tile has a known position and drawing is much simpler.

When adding a new tile you always create a new Map object, which sounds counter-intuitive. I figure that you store a position in your map structure, but I feel that it doesn't really belong there. In my example, you may also add any information to the Tile structure, which makes the system easily expandable.

Cheers!

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!