You are not logged in.

#1 2017-04-26 00:24:25

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

[REQUEST] Feedback for my 2D tiling engine algorithms

Continuing from here: https://bbs.archlinux.org/viewtopic.php?id=65318&p=208. The project is on github: https://github.com/JohnBobSmith/john_tile_engine. It is, by far, the most amount of progress I've made with level design.

@Alad many thanks for the algorithm! I'll see if I can't implement it into my  project. On the topic of pass by reference, I actually found a use for that which shortened yet another 50 lines of code into 3. That's powerful!

@lahwaacz
The objects in question are some axis aligned bounding boxes. I'm expecting to have quite a lot of them but they are all static. More than 100 for sure. I'm not sure how well naming the objects would work. Basically, there are 15 objects on a tile sheet zero inclusive. I just need to tell the code to check for collisions with these objects but not with theses ones and so forth. The current code:

void Collision::positionWorldCollisionBoxes(const std::vector<long int> &level, std::string world)
{
    resetCollision();
    int x = 0;
    int y = 0;
    for (int i = 0; i < MAX_COLLISION_BOXES; ++i) {
        x += 32;
        if (i % 16 == 0) {
            //Adjust our positions, we have gone
            //off the edge of the screen.
            x = 0;
            y += 32;
        }
        //The world objects we should collide with per map basis.
        if (world == "grassland") {
            if (level[i] == 3 || level[i] == 6 || level[i] == 7 || level[i] == 10 ||
                        level[i] == 11 || level[i] == 12) {

                collVector[i]->setPosition(x, y - 32);
            }
        }
        if (world == "farmland") {
            if (level[i] == 3 || level[i] == 7 || level[i] == 8) {
                collVector[i]->setPosition(x, y - 32);
            }
        }
        if (world == "animprops") {
            if (level[i] == 1 || level[i] == 4) {
                collVector[i]->setPosition(x, y - 32);
            }
        }
    }
}

If we are in the farmland world and we've encounter tree, rock, bush, other obstruction, etc, place a collision box there. Unaffected boxes remain off of the map at 0,0 do to resetCollision()

void Collision::resetCollision()
{
    for (int i = 0; i < MAX_COLLISION_BOXES; ++i) {
        collVector[i]->setPosition(0, 0);
    }
}

I would love to be able to discuss this further. I'm all for improving things. This is just one of potentially a lot of solutions that do the job. I'd like to be able to do the job (placing collision boxes) well though too. smile

Continuing on in this thread, I'd also like to be able to improve my animation code:

void Player::animate()
{
    //Animate the player
    static int counter = 0;
    static float timer = 5.0f;
    if (isWalking) {
        timer -= 1.0f;
        if (timer == 0.0f) {
            //Cycle through our sprite sheet
            sprite.setTextureRect(sf::IntRect(counter, 0, 22, 32));
            timer = 5.0f;
        }
        counter += 22; //22 is the width of one sprite on the sheet
        //If we reached the end of the sheet, reset.
        if (counter == 88) {
            counter = 0;
        }
    }
}

Notice I'm using a timer with a magic number of 5.0f. Ideally, this should use "real" time. A value that is fixed at runtime but otherwise adjustable value to control how fast the animations (cycling through the sprite sheet) should play. But I'm not quite sure how to do that... Time for google and some experimentation with SFML's clock features.

Last edited by JohnBobSmith (2017-04-26 00:26:33)


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#2 2017-04-26 12:51:45

lahwaacz
Wiki Admin
From: Czech Republic
Registered: 2012-05-29
Posts: 749

Re: [REQUEST] Feedback for my 2D tiling engine algorithms

I've never written anything like this, so from a very quick look at your code I only have a few random comments.

- Is the size of the `level` vector always the same as MAX_COLLISION_BOXES? You can use `level.size()` to avoid the magic constant.
- The coordinates passed to the setPosition are always either (0, 0) if you don't collide, or 32*(i / 16, i % 16) if you collide, right? In that case you can pass just `i` to the setPosition function and do the conversion of coordinates inside it instead of doing it in the loop. Though if the `level` vector represents objects on a grid, it should probably use a 2D array for storage (I know that C++ does not have them) and also hold a tile size and provide a method for converting tile indices to pixels.
- The objects for each world should be configured outside of the positionWorldCollisionBoxes method, so that it would be used like this:

// somewhere in config
const std::unordered_set<int> objectsInGrassland = {3, 6, 7, 10, 11, 12};
const std::unordered_set<int> objectsInFarmland = {3, 7, 8};
const std::unordered_set<int> objectsInAnimprops = {1, 4};

// somewhere else...
positionWorldCollisionBoxes(level, objectsInGrassland)

// positionWorldCollisionBoxes:
void Collision::positionWorldCollisionBoxes(const something &level, const std::unordered_set<int> &objectsToCollideWith)
{
    // run the loop etc...
        // check if objectsToCollideWith contains level[i]
        if(objectsToCollideWith.count(level[i]))
            collVector[i]->setPosition(<something>);
}

As I said in the other thread, the container for objectsToCollideWith should be something with fast checking for the presence of a key, here I used std::unordered_set. Compared to the enum class that I also mentioned, this would give you the opportunity to change the objects in each world at runtime, which is what you might want for a 2.0 version.

Offline

#3 2017-04-26 23:33:44

JohnBobSmith
Member
From: Canada
Registered: 2014-11-29
Posts: 804

Re: [REQUEST] Feedback for my 2D tiling engine algorithms

Version 1.5 if you will of the algorithm: https://github.com/JohnBobSmith/john_ti … 65d511a995

16 lines of code reduced to 2 for Collision.cpp. Since I've started posting stuff here, I've managed to torch approximately 100 lines of code. Thank you to everyone who has contributed to furthering my understanding of C++ and game related algorithms thus far! smile

EDIT: The i for collisions must be bound to MAX_COLLISION_BOXES because the collision vector is defined by this value:

Collision::Collision()
{
    //Populate our collision vector
    for (int i = 0; i < MAX_COLLISION_BOXES; ++i) {
        collVector.push_back(new sf::RectangleShape);
        collVector[i]->setSize(sf::Vector2f(32, 32));
        collVector[i]->setFillColor(sf::Color::Cyan);
        collVector[i]->setPosition(32, 0);
    }
}

Otherwise, level.size() would have been a good choice.

Last edited by JohnBobSmith (2017-04-26 23:35:32)


I am diagnosed with bipolar disorder. As it turns out, what I thought was my greatest weakness is now my greatest strength.

Everyday, I make a conscious choice to overcome my challenges and my problems. It's not easy, but its better than the alternative...

Offline

#4 2017-04-27 15:05:44

Steef435
Member
Registered: 2013-08-29
Posts: 577
Website

Re: [REQUEST] Feedback for my 2D tiling engine algorithms

lahwaacz probably means that every std::vector has a size() method which returns the amount of elements in the vector.

Anyway, for for loops like this you can use the "new" range-based for loop:

for (auto &b : collVector) b.setPosition(0, 0);

Offline

Board footer

Powered by FluxBB