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

Pages: [1]
1
General / AA unit square collisions with a grid of AA unit squares
« on: August 06, 2023, 01:15:17 am »
this seems really simple, and it probably is, but as a beginner with the c++ language and SFML, I'm having a hard time figuring this out.

I have a player, that is a square, one unit by one unit. I have a grid that is my map, that is a grid of squares, each one unit by one unit. The problem comes from the fact that I can't just check for collisions with every box in the map, as my map is 2000x900, and possibly larger. What I was doing was finding the block each vertex of my player was in, and checking if that block was empty or not. the problem with this method though was that there was glitchy behaviour, holding jump and to the right on a wall to the right of the player would result in the player getting stuck, while holding jump and left on a wall to the left would rocket the player upwards. in short, this method was inconsistent and ugly.

I'm wondering if there's any simpler methods? a pseudocode example or simple explanation would be best. the code is quite long, and creating a minimum example would still be large, but if you need the code I can send it.

2
ok, so to preface I've found success with using an image, texture and sprite, and instead of looping over every block, calculate exactly which blocks are on screen. this technique does not scale with map size, so it's perfect.

the amount of blocks on screen was 64x36, which seems reasonable to me. each block was 30x30 pixels on screen, and 1x1 in the texture.I think it was almost certainly either updating the tilemap every frame which caused the FPS issue, or not setting the grid size the the screen size, but to the map size.

3
sorry for responding so late. I've got it all fixed and working now. I'm going to try implementing your progress bar as well, as my own doesn't seem to be working. Thanks again for all the help you've given me!
EDIT:
though I forgot to mention testing full size worlds (2000x900), even on release mode, I get single digit framerates. I think the only thing possible at this point is maybe a vertex array, or going back to using an image but in a smarter way.

EDIT AGAIN:
after some thinking, I've reimplemented my image method, but I've made it so that it only iterates over the blocks visible, instead of the whole image, and then checking if it's visible. It's fast, even at larger world sizes.

4
switching to tilemap, the game loads fine, the map is made fine, I get no errors, but the tilemap only renders as a transparent rectangle with the dimensions I specified. I have no clue if this is just due to a function I need to run, (I've run setSize, setTexture, setTextureTileSize, setOutOfBoundsTile, and setLevel, as well as update and redraw in the draw loop) or if I'm doing it wrong.

int main()
{
    tileMapImg.loadFromFile("Assets/Textures/tilemap.png");
    mapTex.create(32, 32);
    mapTex.update(tileMapImg);
    tileMapDisplay.setSize(sf::Vector2f(mapWidth * blockZoom, mapHeight * blockZoom));
    tileMapDisplay.setTexture(mapTex);
    tileMapDisplay.setTextureTileSize(sf::Vector2u(1, 1));
    tileMapDisplay.setOutOfBoundsTile(3);
    sf::RenderWindow window(sf::VideoMode(sf::VideoMode::getDesktopMode().width, sf::VideoMode::getDesktopMode().height), "Teria: also try pixel game!", sf::Style::Fullscreen);
    window.setVerticalSyncEnabled(true);
    view.setSize(sf::VideoMode::getDesktopMode().width, sf::VideoMode::getDesktopMode().height);
    view.setCenter(0, 0);
    window.setView(view);

    //map generation code here
    {
        ...
    }

    tileMapDisplay.setLevel(map, mapWidth);

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

            if (event.type == sf::Event::Resized)
            {
                sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                window.setView(sf::View(visibleArea));
            }
        }

        window.clear(sf::Color::Blue);

        sf::Time elapsed = gameClock.restart();

        //game update logic (doesn't work in it's own function for unknown reasons)
        {
            //map drawing
            {
                tileMapDisplay.update();
                tileMapDisplay.redraw();
               
                window.draw(tileMapDisplay);
            }

            //player movement
            {
              ...
            }

        }



        window.display();
    }




    return 0;
}

EDIT:
fixed it, turns out I misunderstood a function and was only rendering the first 16x16 square of tiles.

5
thanks for this, that fixed that particular error. I do think I'm eventually going to use tilemap, but while getting tilemap to work, I found that I had placed my draw call that drew the whole map inside the loop that iterates over every block, thus I was drawing the map thousands of times. I feel incredibly stupid. moving that draw call outside the loop fixes all performance issues. I am still going to switch to tilemap however.

6
oh, it really was just as simple as removing the size parameter. thanks again for the help! I'm embarrased I didn't catch that sooner.

7
about linking actually, using setLevel(), the parameters are: (std::vector<T>& level, int, int)
I know what an std::vector<T> is, but what is the & level at the end? just passing in my map vector, it's size, and it's width gives me an error due to the mismatched arguments.
thanks for your patience and help so far, btw!

8
ah I see, so just keep the hpp and inl files besides eachother, got it. thanks!

EDIT:
further question, should my map be a seperate array/list/vector of ints, that I then pass to the tilemap for display, or should I store my map directly in the tilemap?

9
okay, I have a question: the tilemap comes with an hpp file like normal, but also an inl file, instead of a cpp file. is the inl file like a cpp file? if it's different, how do I use it?
sorry if this is a really beginner question, this is my first project in c++ as well as SFML.

10
the error was just that I put the header files in a seperate folder, and PixelDisplay.cpp didn't know which folder they were in, so the #include "PixelDisplay.hpp" line didn't point to the right file.
tilemap sounds like exactly what I need, a large, optimized scrolling map. I'm going to take a break for an hour or two, but when I come back and implement this, I'll let you know how it works.

11
the title, again.
using the pixel display is even slower than all of the previous methods. I'm going to try the tilemap, and if that doesn't work, I guess I'll try a vertexArray, and if that doesn't work, I'm going to go back to individual rectangleShapes.

12
PixelDisplay.cpp was included, and it was actually the error. I've fixed it now.
I'll definitely look into texturing and tile maps later, but for my purposes I think this might work for now.
I'm iffy on texturing because I don't know anyone good at texturing, including myself.

13
well now I'm getting an error with my includes. I'm including Common.hpp, and PixelDisplay.hpp, both autocompleteted in the VS editor, both present in the same folder. Common.hpp works fine, but I'm getting a "file does not exist" error with PixelDisplay.hpp . both have the correct caps and spelling, given they were autocompleted.
EDIT:
the error wasn't with my includes in main.cpp, but in PixelDisplay.cpp. changed that, it's fixed now

14
thanks for the reply, I'm going to check that out if an idea I have doesn't work, (changing the way the for loop works to hopefully optimize it)
you're right, I didn't mean to set screenHeight to screenWidth, but that screenWidth = (long code) was to reduce the amount of variables declared, I use that screenWidth variable later to check distance with a cube to the center of the screen for rendering. an impermanent solution that would render a circle of cubes around the screen instead of exactly only the cubes visible. the diagonal of a quarter of the screen is the exact smallest length that renders a circle exactly large enough to cover the screen.

EDIT:
for loop optimization did not work, but I did fix the glitchy map (somewhat). I'm going to try out this pixel display thing. I just download this and place it in my project folder, or does this have an installation page?
EDIT AGAIN:
figured out installation

15
Graphics / Every time I optimise my map rendering code, it gets slower.
« on: August 01, 2023, 03:02:13 am »
I'm making a game similar to terraria in SFML, but I'm completely fine with absolutely every graphic in the game being flat colored rectangles. my map is on a grid, and will be roughly 2000x900 tiles.

my first attempt at rendering this map was just making a lot of rectangleShapes, and window.draw()ing each one. that one did not perform well. my second attempt was to make the map a texture, and use img.setpixel() to change the texture. load that onto a sprite, and draw that. Contrary to expectation, that performed worse. So I optimized it by manipulating a pixel array directly, and loading the image from that. it performed worse again (with the added benefit of the map looking glitchy, though that can be fixed.)

I'm making this in x86, and I've been running in debug mode.
here's the relevant code:
//map drawing
            {
                sf::Vector2i middleOfScreen(window.getSize().x / 2, window.getSize().y / 2);
                sf::Uint8* pixels = new sf::Uint8[mapWidth * mapHeight * 4];
                // Convert pixel coordinates to world coordinates
                sf::Vector2f worldCoords = window.mapPixelToCoords(middleOfScreen);

                float screenwidth = sf::VideoMode::getDesktopMode().width;
                float screenheight = sf::VideoMode::getDesktopMode().width;
                screenwidth = sqrt((screenwidth / 2) * (screenwidth / 2) + (screenheight / 2) * (screenheight / 2));
                for (auto it = map.begin(); it < map.end(); ++it) {
                    int item = *it;
                    int position = std::distance(map.begin(), it);



                    sf::RectangleShape rect(sf::Vector2f(blockZoom, blockZoom));
                    rect.setPosition(position % mapWidth * blockZoom, position / mapWidth * blockZoom);
                    rect.setFillColor(blockColors[item]);
                    //std::cout << item;
                    int x(position % mapWidth), y(floor(position/mapWidth));


                    float distance = sqrt((rect.getPosition().x - worldCoords.x) * (rect.getPosition().x - worldCoords.x) + (rect.getPosition().y - worldCoords.y) * (rect.getPosition().y - worldCoords.y));
                    bool visible = (distance < screenwidth);
                    if (visible && item != 0)
                    {
                        sf::Color pixCol(blockColors[item]);
                       
                        pixels[4 * (y * mapHeight + x)] = pixCol.r; // R?
                        pixels[4 * (y * mapHeight + x) + 1] = pixCol.g; // G?
                        pixels[4 * (y * mapHeight + x) + 2] = pixCol.b; // B?
                        pixels[4 * (y * mapHeight + x) + 3] = pixCol.a; // A?
                    }

                    mapimg.create(mapWidth, mapHeight, pixels);
                    maptex.update(mapimg);
                    sf::Sprite sprite;
                    sprite.setScale(blockZoom, blockZoom);
                    sprite.setPosition(0, 0);
                    sprite.setTexture(maptex);
                    window.draw(sprite);
                }
            }
forgive me if the code looks terrible, this is my first SFML project ever.

Pages: [1]
anything