Because there was some interest in a part 3, of this series, I’ve written it, and in this part we’ll cover creating bounds that the camera can’t move beyond. Make sure you’ve read part 1 and part 2 before continuing.
In case you’re wondering what I mean by this, I mean restricting the movement of the camera to a “box”, as in, having minimum and maximum x/y coordinates for the camera. This comes in handy when you’re following players, for example, and you don’t want the camera to show any of the stuff beyond the level (usually blackness) when the player comes to an edge. Now of course, movement bounding can get much more complicated than a simple rectangle, you restrict it to certain paths and the like, but we’re going to keep it simple here.
We’re going to achieve this by clamping the x/y coordinates of the camera to the minimum and maximum x/y values given (the bounds). We’ll do this using a handy little clamping function, which I’ve named
function math.clamp(x, min, max) return x < min and min or (x > max and max or x) end
That’s a very compact version however, you may want to use this version for more clarity, if you’re still getting to grips with some of the subtleties of Lua:
function math.clamp(x, min, max) if x < min then return min elseif x > max then return max else return x end end
With that out of the way, we need to find a way to restrict the x/y values. We could do this only when they’re changed, by using a setter, or we could clamp them every single frame inside of
camera:set. The latter way is much less efficient, so I’m going with the former. Because the new module is rather large, I’ve put the code in a Gist; click the link and take a look at
camera.lua to get it. Take note that
math.clamp needs to be defined somewhere.
Here’s what has changed from part 1’s
- x/y values are now stored in
camera.y. Reference to those variables in the
cameramodule’s methods have been changed accordingly.
- We now use
setYto set the x/y positions.
setPositionnow just calls
setBoundshas been added.
Now, I would much rather be using my metatable approach to setters, but that would needlessly complicate things; you can convert the
camera to that if you want.
Anyway, how is this working? Well,
setY check if there is
camera._bounds exists, and if so, they use the respective values to make sure the x/y position of the camera never exceeds the maximum values provided. We can setup the bounds using
setBounds, which will create the
With that out of the way, I’m going to give you a quick example of how this might be used. In the same Gist I’ve put
main.lua which contains the example code.
love.load sets up tables for the player, the bounding walls (which is just box), and some random white boxes (used to see that you’re moving). It’s pretty obvious what
love.update is doing, allowing movement of the player via the arrow keys and making the camera centre on the player.
love.draw is just drawing the information contained in the tables.
Now for the important part. In
love.load we call
setBounds passing in a minimum x/y position of 0, 0, and a maximum of the width and height of the screen. 0, 0 comes from the x/y position of the box, but where does
height come from? Well the bottom-right corner of the box is
width * 2,
height * 2. We only want the camera to as far as the bottom-right corner, and since the camera’s “width” and “height” is equal to the width and height of the screen, the maximum x/y position is equal to
width * 2 - width,
height * 2 - height, or
boxWidth - cameraWidth,
boxHeight - cameraHeight, which of course equals,
Well, that’s all folks. I hope you’ve learnt something, and thanks for reading. If you’ve got any thoughts/comments/suggestions, please leave them in the comments section. Also remember the camera module and example code is a available at gist #961685.