Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Tilebased map  (Read 3093 times)

0 Members and 1 Guest are viewing this topic.

Jeckie

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Tilebased map
« on: October 13, 2013, 01:43:18 pm »
I'm trying to make a tilebased map.
I made a texture for water,grass,lava.
Then I made a rectagle shapes:
        sf::RectangleShape grass;
        grass.setTexture(&grassTexture);
        grass.setSize(sf::Vector2f(50, 50));
       
        sf::RectangleShape water;
        water.setTexture(&waterTexture);
        water.setSize(sf::Vector2f(50, 50));

        sf::RectangleShape lava;
        lava.setTexture(&lavaTexture);
        lava.setSize(sf::Vector2f(50, 50));

Then and array for tiles:
sf::RectangleShape map[16][12];

And I put like this:
map[0][0] = grass;
map[0][1] = grass;
.....
map[15][11] = lava;

It takes a lot of space for all this.

Next I made and array for water collision and put in it all water tiles:
sf::RectangleShape waterCollision[56] = {map[1][1] , map[1][2] ,map[1][4]...};

And the at the end I draw them:
                for(int d=0; d < 16; d++)
                        {
                                for(int f=0; f < 12; f++)
                                {
                                        window.draw(map[d][f]);
                                }
                        }

All this works but is there any easier way to assign water,lava,grass to tiles?
And is there any easier way to do water collision?

Sorry for my english.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Tilebased map
« Reply #1 on: October 13, 2013, 02:13:42 pm »
I'm going to assume that by "easier" what you really mean is better/faster/more efficient, since what you wrote can't really be beat for visual simplicity.

1) Combine all the textures into one and use a vertex array so that the entire tilemap can be drawn with a single draw() call.  One of the official tutorials describes exactly how to do this, because it's such a common and fundamental optimization.
2) If you don't expect this tilemap to change very often, then draw it to a rendertexture, get the resulting texture out of it, and simply reuse that texture over and over instead of recomputing how to draw the map every frame.
3) For some strange reason you've assigned water to your tiles in a completely different way to how you assigned grass and fire.  Why on Earth did you do that?
4) You're storing several extra copies of your textures for no reason.  Just use an enum, let map be a 2D array of those enums and put a little if/else tree in your drawing logic to get the right texture for each enum value.  That'd save a ton of space.
5) Since you haven't shown us any actual collision code, I can't comment on that at all.  Merely assigning "water" to certain tiles is not a collision system.

Jeckie

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Re: Tilebased map
« Reply #2 on: October 13, 2013, 05:45:31 pm »
I'll try to find that tutorial with vertex array.
I'll see what a rendertexture is.
I assigned water the same way I did with grass and lava.
I'll see what an enum is.
I made a rectangle,movement and added collision like this:
rect.move(xVelocity, 0);

for(int i=0; i < 56;i++)
{
       if(rect.getGlobalBounds().intersects(waterCollision[i].getGlobalBounds())) rect.move(-xVelocity, 0);
}

rect.move(0, yVelocity);

for(int i=0; i < 56;i++)
{
       if(rect.getGlobalBounds().intersects(waterCollision[i].getGlobalBounds())) rect.move(0, -yVelocity);
}
 

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: Tilebased map
« Reply #3 on: October 13, 2013, 08:24:57 pm »
hi Jeckie, sorry for invading your topic, but this subject also interests me.
i'd like to know why did you use RectangleShapes instead of a Sprites?


1) Combine all the textures into one and use a vertex array so that the entire tilemap can be drawn with a single draw() call.  One of the official tutorials describes exactly how to do this, because it's such a common and fundamental optimization.
wait, each draw() is a call to the GPU??
i have made a tilemap, which draws sprites in a similar way tha Jeckie showed in the first post. but instead of lots of sprites, i have a single one, which i draw, change position, draw, change position again, draw again... end at the end i just call display(). is that slower than drawing everything to a RenderTexture and then drawing it's texture to the window?
Visit my game site (and hopefully help funding it? )
Website | IndieDB

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Tilebased map
« Reply #4 on: October 13, 2013, 09:57:43 pm »
Much slower. When I wrote my map loader for Tiled (tmx) maps I originally drew each tile as a separate sprite. Eventually I changed it to using a vertex array based on this and got over 1000(!) FPS increase in performance (without drawing anything else / doing any other kind of entity updates). Draw calls are probably one of the biggest performance hits

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Tilebased map
« Reply #5 on: October 13, 2013, 11:02:00 pm »
@Jeckie: It's probably more consistent/efficient to use enums for all three terrain types, then have your collision loops simply check if map[1][2] == Terrain::Water (where Terrain is your enum).  There's no reason to store the water information in a completely different way.

The actual logic of simply looping over all tiles is probably fine.  Depending on your exact requirements, there may be more efficient ways (eg, only checking the tile the player is trying to move into), but unless your tilemap is gigantic you can probably put that off until you have a more complete program and know for sure what collisions you want to detect.
« Last Edit: October 13, 2013, 11:05:05 pm by Ixrec »

Jeckie

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Re: Tilebased map
« Reply #6 on: October 14, 2013, 10:13:01 pm »
I saw a tutorial of enums but I don't understand this:
        enum Terrain
        {
             water,
             lava,
             grass,
        };
I did this but now I don't understand how to assign i.e a water texture to Terrain::water.
I couldnt find a good tutorial on enums and I really don't know what to do :(
Can someone explain me enums and then I'll try to make tiles.If I fail I'll ask someone for help.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Tilebased map
« Reply #7 on: October 14, 2013, 10:51:58 pm »
You don't assign a texture to an enum, lol.

An enum is just a handy way of representing a fixed list of objects, typically possible types of something.  In this case, a Terrain enum will let you list the possible types of terrain, refer to them in code with meaningful names like "water" and "lava", while allowing the actual code to just use integers like 0, 1 and 2 to represent them instead of wasting time and space with std::strings.

Here's a tutorial that does not suck: http://www.cplusplus.com/doc/tutorial/other_data_types/

The reason I suggested you use these instead of full texture is because having a zillion copies of your textures is a complete waste, and the actual information (which tiles are which types of terrain) can be just as easily represented by something as lightweight as an enum.  When you go to actually draw the tilemap, you'll probably have a switch(map[x ][y]) block with case water:, case lava: and so on, with each case using the actual texture for that type of terrain.