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 - Paul

Pages: 1 2 [3] 4 5 6
31
General / Re: need a better collision idea
« on: July 23, 2020, 12:08:54 am »
Framebuffer like everything else in OpenGL is drawn from bottom left position, inverting helped.

glReadPixels(mouse.x, window.getSize().y - mouse.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);

Now it works, it seems like slowest part (cca 3 ms on my PC) is rendering sprites into buffer/RenderTexture with shader (without shader it's cca 0.3 ms). I have no experience with them, hard to say. I rewrote it a bit to make more sense (use texture from post above). There are no extra optimalizations, it render all sprites to buffer etc. Anyway, this is probably the slowest way to do it. With some complex scene it can be pretty slow.

#include <string>
#include <iostream>

#include <SFML/OpenGL.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

class Entity
{
public:
        size_t objectID;
        sf::Sprite sprite;
        unsigned int frame;
        sf::Vector2f pos;
        sf::Vector2f speed;

        Entity(const sf::Texture& texture, const unsigned int& frame, const size_t& objectID, const sf::Vector2f& pos, const sf::Vector2u& texture_size, const sf::Vector2u& frame_size) : objectID(objectID), frame(frame), pos(pos)
        {
                speed = { rand() % 500 / 10 + 50.f, rand() % 500 / 10 + 50.f };

                sf::IntRect frameRect;
                frameRect.left = (frame % texture_size.x) * frame_size.x;
                frameRect.top = (frame / texture_size.x) * frame_size.y;
                frameRect.width = frame_size.x;
                frameRect.height = frame_size.y;

                sprite.setTexture(texture);
                sprite.setTextureRect(frameRect);
                sprite.setPosition(pos);
        }

        void OnUpdate(const float& dt, const sf::Vector2u& posLimit)
        {
                pos.x += speed.x * dt;
                pos.y += speed.y * dt;

                if ((pos.x > posLimit.x - 64) || (pos.x < 0))
                {
                        speed.x = -speed.x;
                }

                if ((pos.y > posLimit.y - 64) || (pos.y < 0))
                {
                        speed.y = -speed.y;
                }

                sprite.setPosition(pos);
        }
};

class EntityManager
{
public:
        size_t lastID;
        bool sorting;
        std::vector<Entity> v;

public:
        EntityManager() : lastID(0), sorting(false) {};

        void Add(const int& number, const sf::Texture& texture, const sf::Vector2u& posLimit, const sf::Vector2u& texture_size, const sf::Vector2u& frame_size )
        {
                v.reserve(v.size() + number);
                for (int i = 0; i < number; i++)
                {
                        v.emplace_back(Entity(texture, rand() % 36, lastID, { rand() % posLimit.x + 50.f, rand() % posLimit.y + 50.f }, texture_size, frame_size));
                        lastID++;
                }
        };

        void OnUpdate(const float& dt, const sf::Vector2u posLimit, const bool& movingObjects)
        {
                if (movingObjects)
                {
                        for (Entity& entity : v)
                                entity.OnUpdate(dt, posLimit);

                        if (sorting)
                                Sort();
                }
        }

        void Sort()
        {
                std::sort(v.begin(), v.end(), [](const Entity& lhs, const Entity& rhs)
                        {
                                return lhs.pos.y < rhs.pos.y;
                        });
        }

        void Draw(sf::RenderWindow& window)
        {
                for (Entity& entity : v)
                {
                        window.draw(entity.sprite);
                }
        }

        void PrintOut(const size_t& objectID)
        {
                for (Entity& entity : v)
                {
                        if (entity.objectID == objectID)
                        {
                                std::cout << "-------------------- " << std::endl;
                                std::cout << "ID: " << entity.objectID << std::endl;
                                std::cout << "Pos: [" << entity.pos.x << "; " << entity.pos.y << "] " << std::endl;
                                return;
                        }
                }
                std::cout << "Entity with ID: " << objectID << " not found." << std::endl;
        }
};

int main() {
        sf::RenderWindow window(sf::VideoMode(800, 600), "Tests");
        //window.setVerticalSyncEnabled(true);
        window.setFramerateLimit(60);
        sf::Clock clock;
        sf::Vector2i mouse;

        sf::VertexArray vertices;
        vertices.setPrimitiveType(sf::Quads);

        sf::Texture texture; // 9 x 4 = 36 frames (64x64 pixels)
        texture.loadFromFile("texture.png");
        sf::Vector2u texture_size = { 9, 4 }; // Rows, cols
        sf::Vector2u frame_size = { 64, 64 }; // In pixels             

        sf::Shader shader;
        shader.loadFromFile("shaders/test.frag", sf::Shader::Fragment);
        shader.setUniform("texture", texture);

        sf::RenderTexture buffer;
        buffer.create(window.getSize().x, window.getSize().y);
        sf::Sprite rt_buffer_sprite;
        sf::Sprite buffer_spr(texture); // Temp
        buffer_spr.setTexture(texture);

        sf::RenderStates rs;
        rs.texture = &texture;
        rs.shader = &shader;

        EntityManager objectManager;
        objectManager.Add(100, texture, { window.getSize().x - 100, window.getSize().y - 100 }, texture_size, frame_size);
        objectManager.Sort();

        bool drawBuffer = true;
        bool drawObjects = false;
        bool movingObjects = false;
        bool benchmarkOutput = false;

        int selected_ID;

        while (window.isOpen())
        {
                // Process events
                sf::Event event;
                while (window.pollEvent(event))
                {
                        switch (event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;

                        case sf::Event::KeyPressed:
                        {
                                if (event.key.code == sf::Keyboard::Num1)
                                        drawBuffer = !drawBuffer;

                                if (event.key.code == sf::Keyboard::Num2)
                                        drawObjects = !drawObjects;

                                if (event.key.code == sf::Keyboard::Space)
                                        movingObjects = !movingObjects;

                                if (event.key.code == sf::Keyboard::S)
                                        objectManager.sorting = !objectManager.sorting;

                                if (event.key.code == sf::Keyboard::B)
                                        benchmarkOutput = !benchmarkOutput;
                        }
                        break;

                        case sf::Event::MouseButtonPressed:
                        {
                                if (event.mouseButton.button == sf::Mouse::Left)
                                {
                                        if (selected_ID > -1)
                                        {
                                                objectManager.PrintOut(selected_ID);
                                        }
                                }
                        }
                        break;

                        default: break;
                        }
                }

                // Update
                mouse = sf::Mouse::getPosition(window);
                objectManager.OnUpdate(1 / 60.f, window.getSize(), movingObjects);

                // Buffer
                clock.restart();
                buffer.clear();
                for (int i = 0; i < objectManager.v.size(); i++)
                {
                        // Calc ID
                        size_t ID = objectManager.v[i].objectID + 50;
                        int r = (ID & 0x000000FF) >> 0;
                        int g = (ID & 0x0000FF00) >> 8;
                        int b = (ID & 0x00FF0000) >> 16;

                        shader.setUniform("color_id", sf::Glsl::Vec4(r / 255.0f, g / 255.0f, b / 255.0f, 255));

                        sf::IntRect frameRect;
                        frameRect.left = (objectManager.v[i].frame % texture_size.x) * frame_size.x;
                        frameRect.top = (objectManager.v[i].frame / texture_size.x) * frame_size.y;
                        frameRect.width = frame_size.x;
                        frameRect.height = frame_size.y;

                        buffer_spr.setTextureRect(frameRect);
                        buffer_spr.setPosition(objectManager.v[i].pos);
                        buffer.draw(buffer_spr, rs); // Bit slow ??
                        //buffer.draw(buffer_spr);
                }
                buffer.display();

                //sf::Texture::bind(&buffer.getTexture(), sf::Texture::CoordinateType::Pixels); // It's not needed?
                unsigned char data[4];
                //glPixelStorei(GL_PACK_ALIGNMENT, 1);
                glReadPixels(mouse.x, window.getSize().y - mouse.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);

                // Get ID from color
                selected_ID = (data[0] + data[1] * 256 + data[2] * 256 * 256) - 50;

                // Benchmark end
                sf::Time benchmark = clock.getElapsedTime();
                if (benchmarkOutput)
                        std::cout << (float)benchmark.asMicroseconds() / 1000 << " ms \n";

                //std::cout << "RGBA: [" << static_cast<unsigned int>(data[0]) << " " << static_cast<unsigned int>(data[1]) << " " << static_cast<unsigned int>(data[2]) << "] " << static_cast<unsigned int>(data[3]) << "\n";
                std::string title = "Mouse: [" + std::to_string(mouse.x) + "; " + std::to_string(mouse.y) + "]     " +
                        "R[" + std::to_string((unsigned char)data[0]) + "] G:[" + std::to_string((unsigned char)data[1]) +
                        "] B:[" + std::to_string((unsigned char)data[2]) + "] A:[" + std::to_string((unsigned char)data[3]) + "]";

                if (objectManager.sorting)
                        title += +"  SORTING";

                if (selected_ID > -1)
                        title += +"  ID: " + std::to_string(selected_ID);
                window.setTitle(title);

                // Draw
                window.clear({ 20, 20, 20 });

                if (drawBuffer)
                {
                        rt_buffer_sprite.setTexture(buffer.getTexture());
                        window.draw(rt_buffer_sprite);
                }

                if (drawObjects)
                        objectManager.Draw(window);

                window.display();
        }
        return 0;
}

32
General / Re: need a better collision idea
« on: July 22, 2020, 03:54:00 pm »
Good, I thought it would be necessary to call more OpenGL functions :)

It seems like you get the mouse coordinates outside the window. With few changes it reads right RGBA values from screen. There is still one problem if you call buffer.display(), rendered texture is mirrored while framebuffer? isn't, so it doesn't match. Then some GL function is missing or maybe it would be enough to recalculate the mouse coordinates.

#include <string>
#include <fstream>
#include <iostream>
#include <SFML/OpenGL.hpp>

#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

int main() {
        sf::RenderWindow window(sf::VideoMode(800, 600), "Tests");
        window.setVerticalSyncEnabled(true);
        sf::Clock clock;
        sf::Vector2i mouse;    

        sf::Vector2u tile_size(64, 64);
        sf::Vector2u map_size(8, 8);
        sf::Texture tileset;
        tileset.loadFromFile("texture.png");

        sf::VertexArray vertices;
        vertices.setPrimitiveType(sf::Quads);
        vertices.resize(map_size.x * map_size.y * 4);

        const int level[] = {
                   0, 1, 2, 3, 4, 5, 6, 7,
                   8, 9, 10, 11, 12, 13, 14, 15,
                   16, 17, 18, 19, 20, 21, 22, 23,
                   24, 25, 26, 27, 28, 29, 30, 31,
                   0, 1, 2, 3, 4, 5, 6, 7,
                   8, 9, 10, 11, 12, 13, 14, 15,
                   16, 17, 18, 19, 20, 21, 22, 23,
                   24, 25, 26, 27, 28, 29, 30, 31,
        };

        for (unsigned int i = 0; i < map_size.x; ++i) {
                for (unsigned int j = 0; j < map_size.y; ++j) {
                        int tileNumber = level[i + j * map_size.x];
                        int tu = tileNumber % (tileset.getSize().x / tile_size.x);
                        int tv = tileNumber / (tileset.getSize().x / tile_size.x);
                        sf::Vertex* quad = &vertices[(i + j * map_size.x) * 4];

                        quad[0].position = sf::Vector2f(i * tile_size.x, (j)*tile_size.y);
                        quad[1].position = sf::Vector2f((i + 1) * tile_size.x, (j)*tile_size.y);
                        quad[2].position = sf::Vector2f((i + 1) * tile_size.x, (j + 1) * tile_size.y);
                        quad[3].position = sf::Vector2f(i * tile_size.x, (j + 1) * tile_size.y);

                        quad[0].texCoords = sf::Vector2f(tu * tile_size.x, tv * tile_size.y);
                        quad[1].texCoords = sf::Vector2f((tu + 1) * tile_size.x, tv * tile_size.y);
                        quad[2].texCoords = sf::Vector2f((tu + 1) * tile_size.x, (tv + 1) * tile_size.y);
                        quad[3].texCoords = sf::Vector2f(tu * tile_size.x, (tv + 1) * tile_size.y);
                }
        }

        sf::Shader shader;
        shader.loadFromFile("shaders/test.frag", sf::Shader::Fragment);
        shader.setUniform("texture", tileset);

        sf::RenderTexture buffer;
        buffer.create(window.getSize().x, window.getSize().y);
        sf::Sprite buffer_spr(tileset);

        sf::RenderStates rs;
        rs.texture = &tileset;
        rs.shader = &shader;

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

                mouse = sf::Mouse::getPosition(window);
               
                buffer.clear();
                for (size_t y = 0; y < map_size.y; y++) {
                        for (size_t x = 0; x < map_size.x; x++) {

                                // Calc ID
                                int ID = 50 + y * map_size.x + x;
                                int r = (ID & 0x000000FF) >> 0;
                                int g = (ID & 0x0000FF00) >> 8;
                                int b = (ID & 0x00FF0000) >> 16;

                                shader.setUniform("color_id", sf::Glsl::Vec4(r / 255.0f, g / 255.0f, b / 255.0f, 255));

                                int tileNumber = level[y * map_size.x + x];
                                int tu = tileNumber % (tileset.getSize().x / tile_size.x);
                                int tv = tileNumber / (tileset.getSize().x / tile_size.x);

                                buffer_spr.setTextureRect(sf::IntRect(tu * tile_size.x, tv * tile_size.y, tile_size.x, tile_size.y));
                                buffer_spr.setPosition(x * tile_size.x, y * tile_size.y);
                                buffer.draw(buffer_spr, rs);
                        }
                }
                //buffer.display(); // Mirrored        

                clock.restart();
                sf::Texture::bind(&buffer.getTexture(), sf::Texture::CoordinateType::Pixels);
                unsigned char data[4];
                glReadPixels(mouse.x, mouse.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
                sf::Time benchmark = clock.getElapsedTime();
                std::cout << (float)benchmark.asMicroseconds() / 1000 << " ms \n";

                // Get ID from color
                int selected_ID = (data[0] + data[1] * 256 + data[2] * 256 * 256) - 50;

                //std::cout << "RGBA: [" << static_cast<unsigned int>(data[0]) << " " << static_cast<unsigned int>(data[1]) << " " << static_cast<unsigned int>(data[2]) << "] " << static_cast<unsigned int>(data[3]) << "\n";
                std::string title = "Mouse: [" + std::to_string(mouse.x) + "; " + std::to_string(mouse.y) + "]     " +
                        "R[" + std::to_string((unsigned char)data[0]) + "] G:[" + std::to_string((unsigned char)data[1]) +
                        "] B:[" + std::to_string((unsigned char)data[2]) + "] A:[" + std::to_string((unsigned char)data[3]) + "]";

                if (selected_ID > -1)
                        title +=  + "  ID: " + std::to_string(selected_ID);
                window.setTitle(title);

                window.clear(sf::Color::White);        
                window.draw(vertices, &tileset);
                sf::Sprite test_sprite(buffer.getTexture());
                window.draw(test_sprite);
                window.display();
                //sf::sleep(sf::milliseconds(10));
        }
        return 0;
}


33
General / Re: need a better collision idea
« on: July 15, 2020, 10:57:35 pm »
In case of drawing into RenderTexture you can draw only objects near cursor or just buffer with 1/4 of screen size. So theoretically buffer can be very small, I'm not sure if it reduce GPU/CPU bottleneck.

There is still glReadPixels() mentioned in KaM arcticle, you must bind texture to frame buffer otherwise it can't be used. Again it's plain OpenGL. (https://www.khronos.org/opengl/wiki/Pixel_Transfer)


34
General / Re: need a better collision idea
« on: July 14, 2020, 10:24:51 pm »
And that's where I ended up :) It seems like basic function to get pixel color from screen or texture, but whole graphics accelerated concept doesn't think so at all, you need to know API.

Shader approach is for example described here: https://stackoverflow.com/questions/53757376/how-to-retrieve-z-depth-and-color-of-a-rendered-pixel

35
General / Re: need a better collision idea
« on: July 11, 2020, 07:45:49 pm »
This is bit tricky in OpenGL, all graphics is in VRAM.

I'm not sure for which purposes you're rotating view, but one way is bitmask checking.
1) Generate bitmasks (array of bits) for your building images (*.png, *.bmp) where transparent pixels/colors will be 0
2) Check mouse cursor vs sprites on screen (point vs rectangle). If you get more than 1, select one which is closest to the player on screen (by y position for example)
3) Check whether the cursor collides with bitmask for given sprite

Overall, this is not entirely practical, generating bitmasks on the start of progam can be slow if you have a lot of sprites or sprite atlases. In case they are pre-generated you still must deal with extra data, it's too complicated.

Better is something like render sprites with colors into some buffer (where unique color means object ID), then just check color under cursor and return ID (https://www.kamremake.com/devblog/unit-picking/). I haven't impemented this yet. Maybe shaders would help.

36
With current system and gpu drivers I can't.

Ok, thanks.

I get it most likely, what I can do is create static sf::View with given resolution like 1366 x 768 and use window.mapPixelToCoords to recalculate sf::Mouse::getPosition() otherwise it will return values tied to window size, which will be bigger in case of fullscreen.

37
Because games normally offer full range of resolutions supported by graphics card and monitor in fullscreen mode, not only those supported by the system. Not all applications are running only in some borderless window if they can't run native fullscreen. Plus I wanted debug more scenarios.

I can stay with native or add support for borderless, but it's bit weird.


38
I have problem with this. On my PC (W10, AMD RX 480) when resolution isn't in supported fullscreen modes and window is fullscreen then sf::Mouse::getPosition(window) return desktop values. If it's windowed it works normally.

For example, when is created window with parameters 1366 x 768 and fullscreen it doesn't work.

Supported video modes:
VideoMode: 1920 1080
VideoMode: 1680 1050
VideoMode: 1600 900
VideoMode: 1280 1024
VideoMode: 1280 720
VideoMode: 1024 768
VideoMode: 800 600
VideoMode: 720 400
VideoMode: 640 480

// Game.h
class Game
{
public:
        sf::RenderWindow window;
};
 


// Game.cpp
Game::Game()
{
        std::vector<sf::VideoMode> supportedVideoModes;
        supportedVideoModes = sf::VideoMode::getFullscreenModes();
        for (auto it : supportedVideoModes)
        {
                std::cout << "VideoMode: " << it.width << " " << it.height << std::endl;
        }

        window.create(sf::VideoMode(1366, 768), "SFML", true ? sf::Style::Fullscreen : sf::Style::Close);
}


Game::Update()
{
        std::cout << sf::Mouse::getPosition(window).x << ", " << sf::Mouse::getPosition(window).y << std::endl;
}

39
Graphics / Re: VertexArray Isometric
« on: July 05, 2020, 12:48:17 am »
If you use correct math (http://clintbellanger.net/articles/isometric_math/) then no matter which dimensions/ratio your tiles have (code bellow), it's universal. Tile selection by mouse cursor works according to the screen to grid formula in article.

If you use any offsets like people who are dividing Y by something for some reason then you must correct all calculations. Anyway it's easier forget about offsets, scales - stuff like sf::Shape, setOrigin or setScale. I really see no big point using it, it's only confusing.

For example you can stay with plain math, draw all needed map tiles (those that are visible on screen) to their true world positions, use sf::View for moving around world and for zooming if you need, use window.mapPixelToCoords(..) for mouse screen/world coords conversion.

sf::Vertex vertex[4];
sf::Vector2f pos;
sf::Color color;       

int map_w = 32;
int map_h = 32;
int cell_w = 96;
int cell_h = 64;

sf::VertexArray va_Quads;
va_Quads.clear();

for (int y = 0; y < map_h; y++)
{
        for (int x = 0; x < map_w; x++)
        {      
                color = sf::Color(50 + (unsigned char)round((155 / w) * x), 50 + (unsigned char)round((155 / h) * y), 50 + (unsigned char)round((155 / h) * y));

                pos.x = (x - y) * cell_w / 2;
                pos.y = (x + y) * cell_h / 2;

                vertex[0].position.x = pos.x + cell_w / 2;
                vertex[0].position.y = pos.y;
                vertex[0].color = color;
                       
                vertex[1].position.x = pos.x + cell_w;
                vertex[1].position.y = pos.y + cell_h / 2;
                vertex[1].color = color;
                       
                vertex[2].position.x = pos.x + cell_w / 2;
                vertex[2].position.y = pos.y + cell_h;
                vertex[2].color = color;
                       
                vertex[3].position.x = pos.x;
                vertex[3].position.y = pos.y + cell_h / 2;
                vertex[3].color = color;
                       
                va_Quads.append(vertex[0]);
                va_Quads.append(vertex[1]);
                va_Quads.append(vertex[2]);
                va_Quads.append(vertex[3]);
        }
}

window.draw(va_Quads);
 

40
Graphics / Re: VertexArray Isometric
« on: July 01, 2020, 06:54:44 pm »
It's worth noting that "distorting" a square/rectangle texture to fit a diamond shape will not be perfect.

Which kind of distortion? If you use square texture (64 x 64 pix) and isometric cell with 2/1 ratio (64 x 32 pix) then mapped texture will have correct proportions.

If you want connected cells and create an illusion of 3d terrain, different sizes of cells and such dynamics things use quads + textures. If you want pixel perfect look, use isometric bitmaps/sprites which fits exactly to the dimensions of the cell.

41
Graphics / Re: VertexArray Isometric
« on: June 30, 2020, 01:16:59 pm »
Isometric math is different from Cartesian system. Like everything else, you can do it in different ways, there is no ultimate approach. Plus there is diamond shape (Age of Empires) and staggered map (Civilization), both have different calculations.

Isometric tile is something like this:

quad[0].position = sf::Vector2f(x + tileSize.x / 2, y);
quad[1].position = sf::Vector2f(x + tileSize.x, y + tileSize.y / 2);
quad[2].position = sf::Vector2f(x + tileSize.x / 2, y + tileSize.y);
quad[3].position = sf::Vector2f(x, y +  tileSize.y / 2);

Then you need some formula for distribution and drawing in correct order, just use google.

42
Feature requests / Use premake instead of cmake
« on: June 18, 2020, 01:09:51 am »
SFML compilation is not user friendly with current rocket scientist manual. Isn't possible to use premake for example instead of CMake for future versions? It's simple, readable, easily configurable, no problems with project structure, dependency or multiple projects in solution etc.

It should be 2 bulletproof tasks:
1) Download SFML repository (premake binary can be included there) with all needed 3rd party repositories by single command
2) Generate project/solution/whatever via batch file (or by equivalent script)

43
Check SFML tutorials on main web site how to use framework correctly (it's described very well) and try to make simple games like Pong from scratch. Only with C++ & SFML documentation. That's the only way how to learn.


44
General / Re: Isometric tilemap design (suggestions appreciated)
« on: March 31, 2020, 05:41:22 pm »
I'm not sure there is any solution how achieve it and stay in 2D.

How it's done in isometric games:
- terrain is build from sprites and there is no overlap with rest of sprites like buildings and units thanks to right view angle and limited height (Transport Tycoon, Age of Empires 2)
- "3D terrain" also with limited heights which don't overlap sprites (Age of Empires 2 HD)

45
DotNet / New project from scratch (VS 2019)
« on: March 02, 2020, 04:44:07 pm »
I don't like automated repo packages like NuGet much, it can be old etc.

Then I did this:
1) Download SFML NET and CSFML packages from https://www.sfml-dev.org/
- remove "-2" from CSFML*-2.dll filenames

2) New project in VS 2019 - Console App (.NET Core)

3) Add CSFML dll's to project
- right click on "Project name" in Solution Explorer
- add/Existing files - select CSFML*.dll files and openal32.dll
- select these dll's and in Solution Explorer + right click on "Properties"
- select "Copy if newer" in "Copy to output directory"

4) Use SFML NET source files
- right click on "Solution" in Solution Explorer
- add/Existing Project../ and add all System/Window/.. *.csproj SFML NET 2.5 directory
- right click on "Project" in Solution Explorer/Add/Reference../Projects/ select all SFML.* projects

It works but there is still NuGet SFML Net package thanks to added projects in solution. In output it generate "runtimes" folder with libraries. Is there any way how to get rid NuGet package of it?

Edit:

Because step 4. creates various strange things, is better add reference to SFML dll's instead. Not sure if there is any difference between lib builds (debug and realease), whereas it is just an interface.

Pages: 1 2 [3] 4 5 6