RayLib has Clamp

I saw raymath.h contained a Clamp() method, so rather than doing a multi-condition check that discarded all movement if going out of bounds, it instead just acts like a cage and lets you carry on moving along any unconstrained walls or edge

I also didn’t want this cluttering my core loop directly, so refactored it out to a separate method that can be used generically for all Characters to keep them in bounds if desired. I did still place it immediately after knight.tick(); though, but it’s now just a call to keepCharacterInWorldBounds(knight);

void keepCharacterInWorldBounds(Character &character) {
    Vector2 mapSize { MAP_TILESIZE * MAP_X * MAP_SCALE, MAP_TILESIZE * MAP_Y * MAP_SCALE };
    auto worldPosition = character.getWorldPosition();
    auto x = Clamp(worldPosition.x, 0.f, mapSize.x - SCREEN_WIDTH);
    auto y = Clamp(worldPosition.y, 0.f, mapSize.y - SCREEN_HEIGHT);

    character.setWorldPosition((int)x, (int)y);
}

I just preferred this approach to having either a complicated logic or halting all movement if any one axis/direction was blocked.

Edit: Changed my code from a pointer instance to a stack scoped instance. Still knocking the rust (no pun) off my old knowledge of C/C++.

2 Likes

Also if I’m not mistaken, the drawing of the knight on screen took place in the tick() method before the world position / movement is being clamped (by if() condition or clamp() call).

For that I separately broke out and added a .draw() method to my character that I called after tick() and after the clamping too.

Great job!

I was wondering if you knew which method is the most effective in terms of resource utilization. Is there a way to calculate this easily in VS code?

I have no idea of VS Code’s profiling capabilities, sorry. I use CLion.

In this case I don’t think resource utilization makes a material difference anyway, better to use what provides the right purpose and readability for the task at hand.

1 Like

Not to nitpick, but you’re using a reference, not a pointer. Which uses the * operator.

That said, excellent job!

1 Like

It was a pointer before and used the arrow accessors before my edit which included changes to the code as well (e.g. Character *knight; and knight->tick();). I changed the code on purpose because I’m not used to the new fangled stuff in C++, and felt it better to stick with the style in play rather than my old comfort zone.

No worries though, I appreciate the review.

No worries, I may have also misread what you wrote. My apologies!

1 Like

“Maybe you should give 'em the clamps, Clamps.”

2 Likes

I’m sort of new to programming and could use some help clarifying how you got this to work? I saw the raymath function for the Clamp, but I’m not sure about how you are actually using the function parameters to pass the info into the function. What I can tell is you are using like a character reference to pass into the function, but then are you using the character’s instance info to change the variable values?

Yes, that’s right.

You’ll see that the last line of the code above makes a call to a method on my character class that was passed in. That method looks like this:

void Character::setWorldPosition(int x, int y) {
    worldPosition.x = static_cast<float>(x);
    worldPosition.y = static_cast<float>(y);
}

So right after my .tick() is called, I then process keepCharacterInWorldBounds() to act as a check and constrain any of the movements if the knight went too far. I’m letting the character class decide ultimately what to do with the data it is given, but for now it just accepts the changes and stores them against its instance info.

1 Like

Privacy & Terms