Jump to content


2D Tile engine using stl vectors.


  • You cannot reply to this topic
11 replies to this topic

#1 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 19 November 2007 - 07:22 PM

Hi everyone , im new here, and i have some questions before i start making a game.


1)I know that the best replacement for dynamic arrays is a vector array.
I declare the array like this:
]
vector<unsigned int> Map(width * height)
width : we divide screen width with tile width
height: we divide screen height with tile height

Thats correct? is there anything bad in my code?


2)
Here's my map file!!:
25 20
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000001111110000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
00000000000000000000000
11111111111111111111111

And here's how i load the map file into the vector :
 bool LoadMap(string File,vector<int>& MAP)
 {
std::ifstream map( File.c_str() );

 if(map==NULL)return false;//damn !
int x=0,y=0;//array dimensions

MAP.clear();

map>>x>>y;//get array dimensions from file!

vector< int > temp(x * y);//create a temp vector array!

for( int i = 0; i < x*y; i++ )//add the values!
{
char character;
map >> character;
int num = character-'0';
temp[i]=num;
}

//assign temp to MAP!
MAP = temp;

//clear temp !
temp.clear();

//close the file!
map.close();

return true;//all fine?
}

Im doing it right?

3)Here's my tile class!(and where i really need your help!!)
class Tile
{
public:
Tile();
Render(int tile_id);//ie : TILE_WALL = 1 , TILE_EMPTY =0..
bool Blocked;
}cTile;
Question 1: Using the linear vector array , how can i render the tiles on the screen?


Thats all , i hope i can get some replies!!!
Thanks!

#2 .oisyn

    DevMaster Staff

  • Moderators
  • 1822 posts

Posted 19 November 2007 - 09:35 PM

WannaDev said:

And here's how i load the map file into the vector :
 bool LoadMap(string File,vector<int>& MAP)

You defined the map to be a vector<unsigned int> earlier.

Quote

//assign temp to MAP!
MAP = temp;
For these kinds of constructs it's always handy to use swap() rather than an assignment. This avoids the copying of data, as the pointers to the data internal to std::vector are exchanged, which makes it much more efficient.

But in this case I would say: why not write directly to the passed vector anyway?

Quote

//clear temp !
temp.clear();

//close the file!
map.close();
Not really necessary, temp and map will be destroyed after going out of scope (that is, when leaving the function) anyway. I'm not saying it is bad practice to clear them yourself, I'm just saying you will not leak resources when doing otherwise :).

Quote

3)Here's my tile class!(and where i really need your help!!)
class Tile
{
public:
Tile();
Render(int tile_id);//ie : TILE_WALL = 1 , TILE_EMPTY =0..
bool Blocked;
}cTile;
My first question to you would be: why use a std::vector<unsigned int> when you have a Tile class? How did you expect to be using them?

Secondly, why has it a method Render() that accepts a tile_id? Isn't that a property of the tile itself? And is Blocked not completely dependent on what tile it is? That is, will you ever need blocking empty tiles? And what about non-blocking wall tiles?

But all the answers to these questions become moot - you don't need a tile class. It's clumsy. Do you really need to copy it's properties for every instance of a tile? Your map is a std::vector<unsigned int>, keep it that way (or perhaps write up a 2d array variant, but I'm focussing on the int part). Next, you'll need a table containing all tile properties. About whether they're blocking, what color key you need to open the door on the tile, and what sprite you need to render. Now this info could be in a Tile class or struct, although I wouldn't call it "Tile" since it doesn't represent a single tile, but rather a class of tiles having the same identifier and properties.

Your tile renderer can be a seperate class (or function in your general renderer class) that takes a tile map, the tile info table and the current view settings to render the map onto the screen, by simply going over the subset of tiles that are visible, looking up the respective info in the tile info table with each tile id, and render the graphics.

I know this is probably not the way you learned object oriented programming in college/university, but they tend to over-engineer everything for the sake of education. It's not always very practical.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#3 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 20 November 2007 - 09:04 AM

Thanks for replying ".oisyn" !

Quote


You defined the map to be a vector<unsigned int> earlier.


Oops..i'll fix it asap!


Quote

For these kinds of constructs it's always handy to use swap() rather than an assignment. This avoids the copying of data, as the pointers to the data internal to std::vector are exchanged, which makes it much more efficient.

But in this case I would say: why not write directly to the passed vector anyway?
I thought that linear vector array was different than a normal vector array!.
So , i assigned the data of the resized vector(the first line of the map file has the dimensions:value,value => x*y) to the main vector(non-linear).


Quote

temp and map will be destroyed after going out of scope (that is, when leaving the function) anyway
Ah..i never thought of that...

Quote

My first question to you would be: why use a std::vector<unsigned int> when you have a Tile class? How did you expect to be using them?

Secondly, why has it a method Render() that accepts a tile_id? Isn't that a property of the tile itself? And is Blocked not completely dependent on what tile it is? That is, will you ever need blocking empty tiles? And what about non-blocking wall tiles?

Well , tile_id is an array index id.
To get a better understanding , here's the render() function !:
//GetTexture() parameters:
// (unsigned int)tile index(#..) , (unsigned int)extra flags(IF_NOT_EXISTS_RETURN,IF_NOT_EXISTS_RELEASE_SYSTEM)
// (typedef)"IF_NOT_EXISTS_RETURN"
// if the texture isn't available(invalid index or if the vector is empty) , 
//then instead of crashing ,don't bind anything and just return!
    Texure_Database->GetTexture(t_id,IF_NOT_EXISTS_RETURN);//select the texture from the list
    glBegin(GL_QUADS);//build our damned tile!!
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f( 0, 0, 0 );
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f( Box.w, 0, 0 );
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(  Box.w, Box.h, 0 );
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f( 0,  Box.h, 0 );
    glEnd();
    glLoadIdentity();//restore matrix
//todo  : Fade effect on mouse over

And cRect("Box" object) class:
struct cRect
{
float x,y,w,h;
};

Quote


But all the answers to these questions become moot - you don't need a tile class. It's clumsy. Do you really need to copy it's properties for every instance of a tile? Your map is a std::vector<unsigned int>, keep it that way (or perhaps write up a 2d array variant, but I'm focussing on the int part). Next, you'll need a table containing all tile properties. About whether they're blocking, what color key you need to open the door on the tile, and what sprite you need to render. Now this info could be in a Tile class or struct, although I wouldn't call it "Tile" since it doesn't represent a single tile, but rather a class of tiles having the same identifier and properties.

Your tile renderer can be a seperate class (or function in your general renderer class) that takes a tile map, the tile info table and the current view settings to render the map onto the screen, by simply going over the subset of tiles that are visible, looking up the respective info in the tile info table with each tile id, and render the graphics.
Alright then!
I'll do exactly what you said.
There's one thing that i don't understand , and i can't find information on the net.
How im i supposed to read those values stored in linear vector?

Im not sure if this will work:
for (int i=0;i<width;i++)
for (int j=0;i<height;i++)
switch(MAP[i][j])
{
case TILE_WALL:
render(TILE_WALL);
}

Can someone help me ..just a little? :)!

#4 .oisyn

    DevMaster Staff

  • Moderators
  • 1822 posts

Posted 20 November 2007 - 09:46 AM

WannaDev said:

I thought that linear vector array was different than a normal vector array!.
So , i assigned the data of the resized vector(the first line of the map file has the dimensions:value,value => x*y) to the main vector(non-linear).
I'm not sure what you mean, but why? They're both a std::vector<int>, so they both have the same properties - a contiguous array of data (ints in this case). I see you do MAP[i][j] further on - of course that won't work, MAP[i] returns an int and you can't do a [] on an int. Perhaps your MAP to be a std::vector<std::vector<int> > (that is, an array of an array of ints)? Otherwise you'll have to use something like MAP[y * width + x] for the subscription.

Quote

How im i supposed to read those values stored in linear vector?

Im not sure if this will work:
for (int i=0;i<width;i++)
for (int j=0;i<height;i++)
switch(MAP[i][j])
{
case TILE_WALL:
render(TILE_WALL);
}
That will work, but why not simply do "render(MAP[i][j])" in the loop? :) And I think you are forgetting to pass the coordinates - how would the render() function know where to render the tile on the screen?
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#5 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 20 November 2007 - 10:07 AM

Quote

And I think you are forgetting to pass the coordinates - how would the render() function know where to render the tile on the screen?
+

Quote

MAP[y * width + x

!!!You just saved me!!!

I wrote a test render function and it works!
Yeah! , now im happy!(lol)

//25x25 map..

for (int i=0;i<25;i++)

{

for (int j=0;j<25;j++)

{

glTranslatef(i*32,j*32,0);

if(MAPDATA[j*25+i]==1) 

glColor3ub(255,0,255);

else 

glColor3ub(255,255,255);

    glBegin(GL_QUADS);

    glVertex3f( 0, 0, 0 );

    glVertex3f( 32, 0, 0 );

    glVertex3f(  32, 32, 0 );

    glVertex3f( 0,  32, 0 );

    glEnd();

glLoadIdentity();

}

}

Quote

That will work, but why not simply do "render(MAP[i][j])" in the loop?
Good idea , i'll do it!

Thanks for everything!

-------------edited--------------
Hmm.. something isn't right.

Here's the map:

25 25

11000000000000000000001

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000001

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000100000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

00000000000000000000000

10000000000000000000001


And the output:
http://img230.images...e=failedsy2.jpg
http://img230.images...e=failedsy2.jpg

..why ?!

#6 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 20 November 2007 - 05:38 PM

Never mind! , i found the bug in my code!.

Now i'll start making the level editor(yeah!!).

Screenshot: http://img131.images...wootwootnk1.jpg
!!!

#7 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 20 November 2007 - 07:33 PM

Congrats, mate....

You've done the first steps.. It will get harder, but not much (really). Continue your project. I'm sure you will have a lot of fun while doing so and you will pick up lots of experience and skill along the road!

Nils
My music: http://myspace.com/planetarchh <-- my music

My stuff: torus.untergrund.net <-- some diy electronic stuff and more.

#8 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 911 posts

Posted 20 November 2007 - 07:56 PM

Haha, nice level man! Keep it up.
"Stupid bug! You go squish now!!" - Homer Simpson

#9 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 21 November 2007 - 04:17 PM

Thanks for the nice comments("Nils Pipenbrinck","Kenneth Gorking") , and , hell yeah! im having a lot of fun!

PS :I do understand that have to work really hard in order to catch up with the standards..

#10 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 21 November 2007 - 05:26 PM

I have a question(very simple).
While searching on google , i found this tutorial:
http://lazyfoo.net/S...son29/index.php

Why he's using classes instead of a normal grid ? is it better?

#11 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 911 posts

Posted 21 November 2007 - 10:30 PM

Well, the thing that comes to mind is that by using classes he can later subclass his 'Tile' class to create specialized tiles. The Tile baseclass could have a virtual function like 'OnPlayerEnter()' which could then be overriden by other classes to create traps that kill the player, teleporters that send the player across the map, or whatever.
"Stupid bug! You go squish now!!" - Homer Simpson

#12 WannaDev

    New Member

  • Members
  • PipPip
  • 18 posts

Posted 22 November 2007 - 08:54 PM

Oh i see! , thanks!
I think i will use classes too.
Its much easier than a using grid!





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users