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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - frienzy

Pages: [1]
1
Graphics / Re: Tilemap cell ID
« on: April 12, 2021, 12:57:13 pm »
Yes Paul!
It works! :) So I'm still copying all tiles from vertices into std::vector<sf::ConvexShape> tileShapes;
Meanwhile I made a function void checkTiles which checks mouse position and calculates region of 3 tiles based on 32x32 tile size. It selects closest tile to mouse and 1 up from it and 1 down from it. I didn't check to left and right because tile sizes on X doesn't change and is always 32. This function saves int variable representing tile ID into std::vector<unsigned int> vec; and it matches the tile sequence of std::vector<sf::ConvexShape> tileShapes;
Then based on what ID's I'm having currently I'm checking for tileShapes[vec] and saving all 4 corner positions into std::vector<sf::Vector2f> v1, v2 and v3. Then I'm running your algorithm on these 3 vectors and checking which v is true in a separate function - unsigned int currentTile(mousePosView). And then in gamestate rendering it like that: this->window->draw(this->map.tileShapes[map.currentTile(mousePosView)]);

Only thing I'm struggling with now is that when mouse position on X axis is right on the edge of 2 tiles it's calling tileShape[0] for some reason :/
Any ideas?

Here is my code:
#pragma once

#include <SFML/Graphics.hpp>

class TileMap : public sf::Drawable, public sf::Transformable
{
public:

    std::vector<sf::ConvexShape> tileShapes;
    std::vector<unsigned int> vec;
    std::vector<sf::Vector2f> v;
    std::vector<sf::Vector2f> v1;
    std::vector<sf::Vector2f> v2;
    std::vector<sf::Vector2f> v3;

    void checkTiles(sf::Vector2f mousePosView, sf::Vector2i tileSize, unsigned int width, unsigned int height)
    {
       
        vec[0] = unsigned int(((int)mousePosView.x / tileSize.x + ((int)mousePosView.y / tileSize.y) * width));
        if((int)mousePosView.y < (height * 32) - 32)
        vec[1] = unsigned int(((int)mousePosView.x / tileSize.x + (((int)mousePosView.y / tileSize.y) + 1) * width));  
        else
            vec[1] = unsigned int(((int)mousePosView.x / tileSize.x + ((int)mousePosView.y / tileSize.y) * width));
        if ((int)mousePosView.y > 32)
            vec[2] = unsigned int(((int)mousePosView.x / tileSize.x + (((int)mousePosView.y / tileSize.y) - 1) * width));
        else
            vec[2] = unsigned int(((int)mousePosView.x / tileSize.x + ((int)mousePosView.y / tileSize.y) * width));

        if ((int)mousePosView.y < height * 32 && (int)mousePosView.x < width * 32)
        {
            v1 = { {tileShapes[vec[0]].getPoint(0)}, {tileShapes[vec[0]].getPoint(1)}, {tileShapes[vec[0]].getPoint(2)}, {tileShapes[vec[0]].getPoint(3)} };
            v3 = { {tileShapes[vec[2]].getPoint(0)}, {tileShapes[vec[2]].getPoint(1)}, {tileShapes[vec[2]].getPoint(2)}, {tileShapes[vec[2]].getPoint(3)} };
            v2 = { {tileShapes[vec[1]].getPoint(0)}, {tileShapes[vec[1]].getPoint(1)}, {tileShapes[vec[1]].getPoint(2)}, {tileShapes[vec[1]].getPoint(3)} };
        }      
    }

    int PointInPolygon(const sf::Vector2f& p, const std::vector<sf::Vector2f>& v)
    {
        int i, j, c = 0;
        for (i = 0, j = v.size() - 1; i < v.size(); j = i++)
        {
            if (((v[i].y > p.y) != (v[j].y > p.y)) &&
                (p.x < (v[j].x - v[i].x) * (p.y - v[i].y) / (v[j].y - v[i].y) + v[i].x))
                c = !c;
        }
        return c;
    }

    unsigned int currentTile(sf::Vector2f mousePosView)
    {

        if (PointInPolygon(static_cast<sf::Vector2f>(mousePosView), v1))
        {
            return vec[0];
        }
        else if (PointInPolygon(static_cast<sf::Vector2f>(mousePosView), v2))
        {
            return vec[1];
        }
        else if (PointInPolygon(static_cast<sf::Vector2f>(mousePosView), v3))
        {
            return vec[2];
        }
    }
   
    bool load(const std::string& tileset, sf::Vector2i tileSize, const int* tiles, unsigned int width, unsigned int height, std::vector<std::vector<int>> m_heightmap, sf::Color gridColor)
    {
        // load the tileset texture
        if (!m_tileset.loadFromFile(tileset))
            return false;
       
        // resize the vertex array to fit the level size
        m_vertices.setPrimitiveType(sf::Quads);
        m_vertices.resize(width * height * 4);
        m_gridX.setPrimitiveType(sf::Lines);
        m_gridX.resize(width * height * 4);
        m_gridY.setPrimitiveType(sf::Lines);
        m_gridY.resize(width * height * 4);      
        tileShapes.resize(width * height);
        v.resize(4);
        vec.resize(3);

        for (auto i = 0; i < tileShapes.size(); i++) {
            tileShapes[i].setPointCount(4);
            tileShapes[i].setOrigin(0, 0);
        }
                   
        // populate the vertex array, with one quad per tile
        for (unsigned int x = 0; x < width; ++x)
            for (unsigned int y = 0; y < height; ++y)
            {
                // get the current tile number
                int tileNumber = tiles[x + y * width];
                                       
                // find its position in the tileset texture
                int tu = tileNumber % (m_tileset.getSize().x / tileSize.x);
                int tv = tileNumber / (m_tileset.getSize().x / tileSize.x);

                // get a pointer to the current tile's quad
                sf::Vertex* quad = &m_vertices[(x + y * width) * 4];
                sf::Vertex* gridX = &m_gridX[(x + y * width) * 4];
                sf::Vertex* gridY = &m_gridY[(x + y * width) * 4];      
                           
                // define its 4 corners
                quad[0].position = sf::Vector2f(x * tileSize.x, y * tileSize.y + m_heightmap[x][y]);
                quad[1].position = sf::Vector2f((x + 1) * tileSize.x, y * tileSize.y + m_heightmap[x + 1][y]);
                quad[2].position = sf::Vector2f((x + 1) * tileSize.x, (y + 1) * tileSize.y + m_heightmap[x + 1][y + 1]);
                quad[3].position = sf::Vector2f(x * tileSize.x, (y + 1) * tileSize.y + m_heightmap[x][y + 1]);

                tileShapes[x + y * width].setPoint(0, quad[0].position);
                tileShapes[x + y * width].setPoint(1, quad[1].position);
                tileShapes[x + y * width].setPoint(2, quad[2].position);
                tileShapes[x + y * width].setPoint(3, quad[3].position);
                       
                gridX[0].position = quad[0].position;
                gridX[1].position = quad[1].position;
                gridX[2].position = quad[3].position;
                gridX[3].position = quad[2].position;

                gridY[0].position = quad[0].position;
                gridY[1].position = quad[3].position;
                gridY[2].position = quad[1].position;
                gridY[3].position = quad[2].position;
                             
                gridX[0].color = gridColor;
                gridX[1].color = gridColor;
                gridX[2].color = gridColor;
                gridX[3].color = gridColor;

                gridY[0].color = gridColor;
                gridY[1].color = gridColor;
                gridY[2].color = gridColor;
                gridY[3].color = gridColor;
               
                // define its 4 texture coordinates
                quad[0].texCoords = sf::Vector2f(tu * tileSize.x, tv * tileSize.y);
                quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
                quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
                quad[3].texCoords = sf::Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);                                  
            }
       
        return true;      
    }

private:

    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        // apply the transform
        states.transform *= getTransform();

        // apply the tileset texture
        states.texture = &m_tileset;

        // draw the vertex array
        target.draw(m_vertices, states);
        target.draw(m_gridX);
        target.draw(m_gridY);
    }

    sf::VertexArray m_vertices;
    sf::VertexArray m_gridX;
    sf::VertexArray m_gridY;
    sf::Texture m_tileset;
   
};

2
Graphics / Re: Tilemap cell ID
« on: April 10, 2021, 12:38:59 am »
Thanks, Paul!
I don't quite understand this statement: if (PointInPolygon(mouse, top_left, top_right, bottom_right, bottom_left)

Can you explain please what is PointInPolygon and how do I check if the mouse is within those 4 coordinates?

3
Graphics / Re: Tilemap cell ID
« on: April 08, 2021, 01:59:14 am »
Yeah well, I'm probably pretty thick but I just can't figure out the way of making this statement work if the tile isn't rectangle...

sf::Vector2i current_tile(sf::Mouse::getPosition(window).x/tile_size.x, sf::Mouse::getPosition(window).y/tile_size.y);

yes I got a std::vector<std::vector<int>> m_heightmap;
which holds height variables for every quad on the map and is shared with all 4 tiles surrounding it.
but still can't see a way of calculating the shape of a tile from that...

4
Graphics / Re: Tilemap cell ID
« on: April 06, 2021, 01:51:40 pm »
Well, that's what I mean - how would I check the tile height if I don't have anything to identify this tile with?
When I create convex shapes - I can use getGlobalBounds... what can I use with vertices?

5
Graphics / Re: Tilemap cell ID
« on: April 05, 2021, 10:02:49 pm »
Yes, I have that at quad positions.

But I don't see this working because tile_size.y might not be 32...
sf::Vector2i current_tile(sf::Mouse::getPosition(window).x/tile_size.x, sf::Mouse::getPosition(window).y/tile_size.y);

6
Graphics / Re: Tilemap cell ID
« on: April 05, 2021, 08:45:32 pm »
so I made std::vector<sf::ConvexShape> tileShape;
in the tilemap for loop where setting quad positions I'm copying those quads and saving them into ConvexShape.
So I basically copying the entire map into the convex shapes... which in my view defeating the whole purpose of VertexArray tilemap, isn't it?
Or is it OK? What do you guys think?
Is there another lightweight way? :)

7
Graphics / Re: Tilemap cell ID
« on: April 05, 2021, 07:16:01 pm »
That's cool! But I don't have flat 32x32 tiles - I have a height attribute (with varying y points). So I need to take those quad transformations into account.

8
Graphics / Tilemap cell ID
« on: April 05, 2021, 02:29:46 pm »
Hi guys!
Apologies for the noob question :)
I'm trying to figure out the way I could map my Tilemap's vertex arrays elements with IDs of the tiles, so I could access and address any individual tile from outside - for example, get tile coordinates after clicking on it.
I came up with the idea of creating a separate vector of rectangles generated from tilemap for loop but it seems very inefficient and unnecessary. There must be an easier way right? :)

9
Graphics / Re: 2D or 3D?
« on: April 03, 2021, 08:00:45 pm »
Thank you, Paul!
You helped so much! I made std::vector<std::vector<int>> m_heightmap(width + 1, std::vector<int>(height + 1))
in the end, which allowed to address any individual quad on the map.
Now I need to figure out the way to edit this m_heightmap in the editor - similar to the example with a bigger hills :)

10
Graphics / Re: Sprite animation with mouse control
« on: April 03, 2021, 12:02:41 am »
Yes I got it working now, but I had it a bit more complex than that - I had the rotation being performed (the sprite animation cycling not actual sprite rotation).
So I had two variables - float currentAngle and float newAngle - where everytime mouse is being clicked the newAngle is saved to currentAngle. After the click the difference in angle is being calculated and normalized into third variable = angle.
int angle = (int)newAngle - (int)currentAngle;
      angle += (angle > 180) ? -360 : (angle < -180) ? 360 : 0;

this line makes sure that Angle is always 0 in the direction the character is facing.
And then just perform the check if Angle is changing and if changing inside the condition += currentAngle until the currentAngle reaches newAngle. (performing sprite animations along the way while degrees are adding.

11
Graphics / Re: 2D or 3D?
« on: March 13, 2021, 04:20:55 pm »
That's great! Thank you, Paul, but I'm not sure how would I create this offset in the height axle...
The code for tilemap I have currently is:
// populate the vertex array, with one quad per tile
        for (unsigned int i = 0; i < width; ++i)
            for (unsigned int j = 0; j < height; ++j)
            {
                // get the current tile number
                int tileNumber = tiles[i + j * width];

                // find its position in the tileset texture
                int tu = tileNumber % (m_tileset.getSize().x / tileSize.x);
                int tv = tileNumber / (m_tileset.getSize().x / tileSize.x);

                // get a pointer to the current tile's quad
                sf::Vertex* quad = &m_vertices[(i + j * width) * 4];

                // define its 4 corners
                quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
                quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
                quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
                quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);

                // define its 4 texture coordinates
                quad[0].texCoords = sf::Vector2f(tu * tileSize.x, tv * tileSize.y);
                quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
                quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
                quad[3].texCoords = sf::Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
            }

12
Graphics / 2D or 3D?
« on: March 12, 2021, 09:28:23 pm »
I want to implement the amplitude vector to my tilemap. Is there a way to achieve this with 2D techniques or is it 3D space? Any tips on where to start? :)
Thanks!
Attached the picture.

13
Graphics / Sprite animation with mouse control
« on: March 12, 2021, 09:11:00 pm »
Hi!
I have a character sprite controlled by a mouse (first selected and then moved to the clicked location).
I can't figure out how to set the "sprite.setTextureRect" sprite location depending on what direction the character is going to be traveling.
This is what I have:

#include "player.h"

Player::Player(sf::String F, int X, int Y, float W, float H) {
       
        dir = 6;
        speed = 0; playerScore = 0; health = 100; dx = 0; dy = 0;
        life = true; isMove = false; isSelected = false;
        File = F;
        w = W;
        h = H;
        image.loadFromFile("" + File);
        texture.loadFromImage(image);
        sprite.setTexture(texture);
        x = X, y = Y;
        sprite.setTextureRect(sf::IntRect(0, 195, w, h));
        sf::Rect<float> size = sprite.getGlobalBounds();
        sprite.setOrigin(sf::Vector2f(size.width / 2, size.height -20));
}


void Player::update(float time) {
        switch (dir) {
        case 0: dx = -speed; dy = 0;  break;        //left
        case 1: dx = -speed; dy = -speed; break;  //up left
        case 2: dx = 0; dy = speed; break;        //down
        case 3: dx = speed; dy = speed; break;    //down right
        case 4: dx = speed; dy = 0; break;        //right
        case 5: dx = -speed; dy = speed; break;  //down left
        case 6: dx = 0; dy = -speed; break;       //up
        case 7: dx = speed; dy = -speed; break;    //down right
        }

        x += dx * time;
        y += dy * time;

        speed = 0;
        sprite.setPosition(x, y);

}
int main()
{
 
    sf::RenderWindow window(sf::VideoMode(1366, 768), "a2", Style::Fullscreen);
    //window.setFramerateLimit(20);
    view.reset(sf::FloatRect(0, 0, 1366, 768));
   
    const int level[] =
    {
        17, 17, 17, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        17, 17, 17, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
        29, 29, 29, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
        29, 29, 29, 0, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 0, 0,
        113, 113, 113, 0, 3, 3, 3, 0, 0, 0, 1, 1, 1, 2, 0, 0,
        113, 113, 113, 0, 3, 0, 2, 2, 0, 0, 1, 1, 1, 1, 2, 0,
        121, 121, 121, 0, 3, 0, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1,
        121, 121, 121, 0, 3, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1,
    };

    TileMap map;
    if (!map.load("tiles.png", sf::Vector2u(32, 32), level, 16, 8))
        return -1;
   
    Player p ("pikeman_walk.png", 80, 16, 38, 55);     // x offset 3,  y offset 11.5f


    sf::Font font;
    font.loadFromFile("roboto.ttf");
    sf::Text text_fps("", font, 20);
    sf::String fps;

    sf::Clock clock;
    float timer = 0;
    int frames = 0;
   
    float currentFrame = 0;
    bool isMove = false;
    float dx = 0;
    float dy = 0;
    int tempX = 0;
    int tempY = 0;
    float distance = 0;

   

    while (window.isOpen())
    {
        float time = clock.getElapsedTime().asMicroseconds();
        timer += clock.getElapsedTime().asSeconds();
        frames++;
        clock.restart();
        time = time / 1000;

        if (timer >= 1.0f) {
            fps = std::to_string(frames);
            timer = 0;
            frames = 0;
        }

        sf::Vector2i pixelPos = sf::Mouse::getPosition(window);
        sf::Vector2f pos = window.mapPixelToCoords(pixelPos);

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();

            if(event.type == sf::Event::MouseButtonPressed)
                if (event.key.code == sf::Mouse::Left) {
                    if (p.sprite.getGlobalBounds().contains(pos.x, pos.y)) {
                        p.isSelected = true;
                    }
                }
            if(p.isSelected)
                if(event.type == sf::Event::MouseButtonPressed)
                    if (event.key.code == sf::Mouse::Left) {
                        p.isMove = true;
                        tempX = pos.x;
                        tempY = pos.y;
                        float dx = pos.x - p.x;
                        float dy = pos.y - p.y;
                        float rotation = (atan2(dy, dx)) * 180 / 3.14159265;
                        //p.sprite.setRotation(rotation);   <-- sprite rotation
                       
                        if (p.dir == 0) {                          // ??? this is where I'm messing up ????
                            p.speed = 0.05;
                            currentFrame += 0.01 * time;
                            if (currentFrame > 10) currentFrame -= 10;

                            p.sprite.setTextureRect(sf::IntRect(34 * int(currentFrame), 84, 34, 52));                      
                        }                      
                    }
           
        }
       
        if (p.isMove) {
            distance = sqrt((tempX - p.x) * (tempX - p.x) + (tempY - p.y) * (tempY - p.y));
            if (distance > 2) {
                p.x += 0.1 * time * (tempX - p.x) / distance;
                p.y += 0.1 * time * (tempY - p.y) / distance;
             
            }
            else
            {
                p.isMove = false;
            }
        }

        sf::Vector2i localPosition = Mouse::getPosition(window);
        if (localPosition.x < 3) { view.move(-1.0 * time, 0); }
        if (localPosition.x > window.getSize().x-3) { view.move(1.0 * time, 0); }
        if (localPosition.y > window.getSize().y - 3) { view.move(0, 1.0 * time); }
        if (localPosition.y < 3) { view.move(0, -1.0 * time); }


        window.setView(view);
        p.update(time);
        window.clear();    
        window.draw(map);    
        changeView();

        text_fps.setString(fps);
        text_fps.setPosition(20, 20);
        window.draw(text_fps);

       
        window.draw(p.sprite);
        window.display();
    }

    return 0;
}

Pages: [1]