SFML community forums

Help => Graphics => Topic started by: Ionut on May 27, 2017, 04:52:40 pm

Title: Tile Map
Post by: Ionut on May 27, 2017, 04:52:40 pm
Hello, I want to make a side scroller, and I don't know how to make the map(I mean the grass,dirt and the other things that you stay on), I did this with a map made in photoshop, but it was really big so I decided to do it differently, I heard of "tiles", so I downloaded a spritesheet with the dirt and the others(dimentions, 70x70 per sprite).I made it to only show a sprite from the spritesheet.But I don't know how to make an entire map out of it,how to multiply the sprites?
Title: Re: Tile Map
Post by: eXpl0it3r on May 27, 2017, 07:58:51 pm
You can use a vertex array of quads that define a tile each.

You write some simple file how the level should look like, then you load the file and fill the vertex array with quads that point to the correct tile on your spritesheet texture.
Title: Re: Tile Map
Post by: Hapax on May 28, 2017, 02:19:30 am
Remember that there is an example of how to create a simple tile map (https://www.sfml-dev.org/tutorials/2.4/graphics-vertex-array.php#example-tile-map) in the official SFML tutorials.
Title: Re: Tile Map
Post by: Ionut on May 28, 2017, 09:38:31 am
Can you please explain me how the vertex array positions(and the texture positions) work ? I mean what dimensions  to write in the parentheses ?
Title: Re: Tile Map
Post by: Elias Daler on May 28, 2017, 02:06:18 pm
This guide (https://www.sfml-dev.org/tutorials/2.4/graphics-vertex-array.php) will help you.
By the way, if you have questions, please open it in "Help" forum subsection. This section is made for showing off projects you're working on.
Title: Re: Tile Map
Post by: Ionut on May 28, 2017, 04:54:49 pm
Ok somehow I did it, but the "map" is blurry, why?
Title: Re: Tile Map
Post by: Ionut on May 28, 2017, 05:38:27 pm
I think I found the solution... I expanded 70x70 texture to a 800x70 texture, but how to put 1 by 1(I mean how to put like 11 70x70 squares)?
Title: Re: Tile Map
Post by: Ionut on May 29, 2017, 04:01:13 pm
Elias, the example isn't for a spritesheet ?, I have the sprites individually...
Title: Re: Tile Map
Post by: GameBear on May 29, 2017, 04:21:36 pm
There are multiple ways to do this, but the easy way is with a 2d array for the map info, and a "print" function for drawing.
Posido code:

//Array
int mapArray[4][5] =
    {
        {0,0,0,0,0},
        {0,1,1,1,0},
        {1,2,2,2,1},
        {2,2,2,2,2},
    };
//Some sprites
SF::sprite airSp....
SF::sprite grassSp....
SF::sprite dirtSp....

//Let's say all sprites are 8 by 8 pixels
Int spriteSize = 8;

//Render it
Window.beginDraw();
for(int i = 0; i < 4; i++){
for(int j = 0; j < 5; j++){
If(mapArray[i][j] == 0) {
  airSp.setPosition(i*spriteSize,j*SpriteSize);
  Window.draw(airSp);
}
Else If(mapArray[i][j] == 1) {
  grassSp.setPosition(i*spriteSize,j*SpriteSize);
  Window.draw(grassSp);
}

Else If(mapArray[i][j] == 2) {
  dirtSp.setPosition(i*spriteSize,j*SpriteSize);
  Window.draw(dirtSp);
}

}
}
Window.display();
 


Please note, this is posido code, not actual code.
Also, wrote iron my phone, so errors are most likely.... But the algorithm should be sound.
Title: Re: Tile Map
Post by: Ionut on May 29, 2017, 04:58:54 pm
Hmm...something is not right the window opens for a second and it closes(Note:The console remains opened)...that's the code....
#include <SFML/Graphics.hpp>
using namespace sf;

int main()
{
    RenderWindow window(VideoMode(800,600),"Platformer");
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(1);
    View view(FloatRect(0,0,800,600));
    Clock clock;
    int mapArray[4][5] =
    {
        {0,0,0,0,0},
        {0,0,0,0,0},
        {0,0,0,0,0},
        {1,1,1,1,1},
    };
    Texture TTileGrass;
    TTileGrass.loadFromFile("Textures/Map/Grass/slice03_03.png");
    TTileGrass.setSmooth(1);
    Sprite STileGrass;
    STileGrass.setTexture(TTileGrass);
    Texture TAdventurer;
    TAdventurer.loadFromFile("Textures/Characters/Adventurer/adventurer_tilesheet.png");
    TAdventurer.setSmooth(1);
    Sprite SAdventurer;
    SAdventurer.setTexture(TAdventurer);
    SAdventurer.setTextureRect(IntRect(0,0,80,110));
    SAdventurer.setPosition(0,440);
    Vector2f pos = SAdventurer.getPosition();
    while(window.isOpen() && !Keyboard::isKeyPressed(Keyboard::Return))
    {
        clock.restart();
        Event event;
        while(event.type == Event::Closed)
        {
            window.close();
        }
    window.clear();
    if(Keyboard::isKeyPressed(Keyboard::Up))
    {
        pos.y -= 5;
    }
    if(Keyboard::isKeyPressed(Keyboard::Left))
    {
        pos.x -= 5;
        view.move(-5,0);
    }
    if(Keyboard::isKeyPressed(Keyboard::Right))
    {
        pos.x += 5;
        view.move(5,0);
    }
    SAdventurer.setPosition(pos.x,pos.y);
    window.setView(view);
    window.draw(SAdventurer);
    for(int i = 0;i<4;i++)
    {
        for(int j = 0; j<5;i++)
    {
        if(mapArray[i][j] == 1)
        {
            STileGrass.setPosition(i * 70, j * 70);
            window.draw(STileGrass);
        }
    }
    }
    window.display();
    }
}
 
Title: Re: Tile Map
Post by: AFS on May 29, 2017, 07:35:11 pm
Hmm...something is not right the window opens for a second and it closes

You have to put your logic and drawing code inside a loop. Also, you are polling the events incorrectly. It should be like this:


#include <SFML/Graphics.hpp>
using namespace sf;

int main()
{

    // Your variables, like windows, textures and sprites, go outside the loop.
    RenderWindow window(VideoMode(800,600),"Platformer");
   
    (...)

    // Then you start the game loop.
    while( window.isOpen() )
    {

        // First you poll the events inside ANOTHER loop.

        Event event;
        while ( window.pollEvent(event) )
        {

             // The following should be "if", not "while" as you put in your code.
             if( event.type == Event::Closed )  
             {
                    window.close();
             }

        }

        // Now you do the rest of your code.

        if(Keyboard::isKeyPressed(Keyboard::Up))
        {
            pos.y -= 5;
        }
       
        (...)

        // Finally you draw.

        window.clear( sf::Color::White ) // You have to clear the window first, you forgot about this.

        window.setView(view);
        window.draw(SAdventurer);
        for(int i = 0;i<4;i++)
        {
            for(int j = 0; j<5;i++)
        {
            if(mapArray[i][j] == 1)
            {
                STileGrass.setPosition(i * 70, j * 70);
                window.draw(STileGrass);
            }
        }

        window.display();

    }

}
 

I really recommend reading and understanding the tutorials, otherwise you'll run into problems every five minutes, and we won't always be able to help you in time.
Title: Re: Tile Map
Post by: Ionut on May 29, 2017, 07:43:47 pm
Ok AFS, I did exactly how you said, but when I start the program it shows me "Platformer.exe has stopped working",why?
PS:I commented the for loop section and it worked, something is wrong with the for loops,but I don't have any idea what...
PSS:The code :
#include <SFML/Graphics.hpp>
using namespace sf;

int main()
{
    RenderWindow window(VideoMode(800,600),"Platformer");
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(1);
    View view(FloatRect(0,0,800,600));
    int mapArray[4][5] =
    {
        {0,0,0,0,0},
        {0,0,0,0,0},
        {0,0,0,0,0},
        {1,1,1,1,1},
    };
    Texture TTileGrass;
    TTileGrass.loadFromFile("Textures/Map/Grass/slice03_03.png");
    TTileGrass.setSmooth(1);
    Sprite STileGrass;
    STileGrass.setTexture(TTileGrass);
    Texture TAdventurer;
    TAdventurer.loadFromFile("Textures/Characters/Adventurer/adventurer_tilesheet.png");
    TAdventurer.setSmooth(1);
    Sprite SAdventurer;
    SAdventurer.setTexture(TAdventurer);
    SAdventurer.setTextureRect(IntRect(0,0,80,110));
    SAdventurer.setPosition(0,440);
    Vector2f pos = SAdventurer.getPosition();
    while(window.isOpen() && !Keyboard::isKeyPressed(Keyboard::Return))
    {
        Event event;
        while(window.pollEvent(event))
    {
        if(event.type == Event::Closed)
        {
            window.close();
        }
    }
    if(Keyboard::isKeyPressed(Keyboard::Up))
    {
        pos.y -= 5;
    }
    if(Keyboard::isKeyPressed(Keyboard::Left))
    {
        pos.x -= 5;
        view.move(-5,0);
    }
    if(Keyboard::isKeyPressed(Keyboard::Right))
    {
        pos.x += 5;
        view.move(5,0);
    }
    window.clear(Color::White);
    SAdventurer.setPosition(pos.x,pos.y);
    window.setView(view);
    window.draw(SAdventurer);
    for(int i = 0;i<4;i++)
    {
        for(int j = 0; j<5;i++)
    {
        if(mapArray[i][j] == 1)
        {
            STileGrass.setPosition(i * 70, j * 70);
            window.draw(STileGrass);
        }
    }
    }
    window.display();
    }
}
 
Title: Re: Tile Map
Post by: GameBear on May 29, 2017, 09:03:00 pm
for(int j = 0; j<5;i++)

The last i should be a j in this one :)
Title: Re: Tile Map
Post by: Ionut on May 29, 2017, 09:19:36 pm
Oh, sorry that was the problem thanks!  :P You are the best!  ;D
Title: Re: Tile Map
Post by: Ionut on May 29, 2017, 09:33:48 pm
But...how to change the mapArray to be like 0,530( I mean the map itself), because it is at 0,0
PS:I changed the Map array to : int mapArray[4][5] =
    {
        {1,0,0,0,0},
        {1,0,0,0,0},
        {1,0,0,0,0},
        {1,0,0,0,0},
    };
To show it horrizontally,not vertically, but it is in the left corner up(0,0) and I want it in the left corner down(0,530)
Title: Re: Tile Map
Post by: GameBear on May 30, 2017, 12:52:46 am
To draw in another place you can either set the view:
https://www.sfml-dev.org/tutorials/2.4/graphics-view.php
sf::View view(sf::FloatRect(0, -530, 600, 600));
window.setView(view);

 

Or draw with an offset:

//Wherever you declare variables//
Int xOffset = 0;
Int yOffset = 530;

//Render part.
 STileGrass.setPosition((i * 70)+xOffset ,( j * 70)+yOffset );
 window.draw(STileGrass);
 
If I understand correctly...

Out of curiosity, what is your native language?
Best regards :)
Title: Re: Tile Map
Post by: Ionut on May 30, 2017, 03:53:00 pm
I have just one more question...The array is vertically showing, how to put it horizontally ?
I mean to put it like int mapArray[4][5] =
    {
        {1,0,0,0,0},
        {1,0,0,0,0},
        {1,0,0,0,0},
        {1,0,0,0,0},
    };
to int mapArray[4][5] =
    {
        {0,0,0,0,0},
        {0,0,0,0,0},
        {0,0,0,0,0},
        {1,1,1,1,1},
    };
Title: Re: Tile Map
Post by: GameBear on May 30, 2017, 04:35:24 pm
Change STileGrass.setPosition(i * 70, j * 70);
To STileGrass.setPosition(i * 70, j * 70);

The setPosition() takes two operators,
X position and Y position. Like this:
setPosition(X,Y);
If X is j then j is horizontal
If Y is i then i is vertical.

Still, what is your language, I'd love to point you to some tutorials....
Title: Re: Tile Map
Post by: Ionut on May 30, 2017, 04:51:09 pm
I meant the array to be horizontally looking(because it's easier to look horizontally than vertically) ,not the setposition.
Something like :  int mapArray[4][5] =
    {
        {0,0,0,0,0},
        {0,0,0,0,0},
        {0,0,0,0,0},
        {1,1,1,1,1},
    };
Title: Re: Tile Map
Post by: Ionut on June 01, 2017, 10:52:50 am
Ok let the array be like that,but now I have a bigger problem,I tried to make a collision detector and it shows me that only the last piece of "map" collides with the player,how to make the entire "map" collidable ?