Completing the second tutorial section

In completing the second section of the TwinkleBearDev tutorial, they pose an exercise for the reader: given an image to small to fill the background, how do we tile the background such that the image fills the available area? My solution was to use SDL_QueryTexture to get the width and height of the image and then, in a set of nested for loops, render the image as many times as necessary to fill the screen.

[pastacode lang=”cpp” manual=”%20%20%20%20SDL_RenderClear(renderer)%3B%0A%0A%20%20%20%20int%20bW%2C%20bH%3B%0A%20%20%20%20SDL_QueryTexture(background%2CNULL%2CNULL%2C%26bW%2C%20%26bH)%3B%0A%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20SCREEN_HEIGHT%3B%20i%20%3D%20i%20%2B%20bH)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20for%20(int%20j%20%3D%200%3B%20j%20%3C%20SCREEN_WIDTH%3B%20j%20%3D%20j%20%2B%20bW)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20renderTexture(background%2C%20renderer%2C%20j%2C%20i)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20SDL_RenderPresent(renderer)%3B%0A%20%20%20%20SDL_Delay(2000)%3B” message=”” highlight=”” provider=”manual”/]

This excerpt does the following:

  • Clears the renderer
  • Instantiates the bW and bH variables
  • Checks the texture to see what it’s dimensions are
  • Enters a loop that iterates through a number of steps equal to the window height divided by the texture height
  • Enters a loop within the first loop that iterates through a number of steps equal to the window width divided by the texture width and deposits an instance of the texture at that location
  • Renders the scene to the window
  • Delays for 2 seconds so we can see the result

This allows me to use a tile of any size and the system will automatically tile it as many times as required to fill the window.


Section 3

In section 3, TwinkleBearDev introduces the SDL_image addon module that allows us to import images in most common formats, including PNG with transparency. With a few minor modifications to the loadTexture method we can now import PNG images!

Later on we overload the renderTexture method to allow for scaling by setting the width and height of the destination SDL_rect, this allowed for some more interesting behaviour for my tiling algorithm above. Now that we can specify an arbitrary scale, we’ll need to be able to take the scale into account. this is done by the following:

[pastacode lang=”cpp” manual=”%20%20%20%20int%20scaler%20%3D%203%3B%0A%0A%20%20%20%20int%20bW%2C%20bH%3B%0A%20%20%20%20SDL_QueryTexture(background%2CNULL%2CNULL%2C%26bW%2C%20%26bH)%3B%0A%20%20%20%20for%20(int%20i%20%3D%200%3B%20i%20%3C%20SCREEN_HEIGHT%3B%20i%20%3D%20i%20%2B%20bH%20%2F%20scaler)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20for%20(int%20j%20%3D%200%3B%20j%20%3C%20SCREEN_WIDTH%3B%20j%20%3D%20j%20%2B%20bW%20%2F%20scaler)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20renderTexture(background%2C%20renderer%2C%20j%2C%20i%2C%20bW%20%2F%20scaler%2C%20bH%20%2F%20scaler)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D” message=”” highlight=”” provider=”manual”/]

 

As you can see, we’ve added a scaler variable that we can modify to set the scale of our tile and we’ve also modified the nested for loops to scale based on this value as well, the result is that no matter what the scale, the image tiles perfectly. It’s simple and purpose-built, but it serves as a good exercise.


Roger Roger, what’s our vector Victor?

After getting images on the screen I decided to start work on the vector class that will be the heart of the motion system that I plan on developing. To start, I had to learn the operations I wanted to perform: addition, subtraction, multiplication, getting the magnitude and normalization. The first three are very simple and the last two are related.

For addition and subtraction, it’s a simple matter of doing the basic operation on each of the components: given two vectors (x1,y1 and x2,y2) we would simply add x1 to x2 and y1 to y2.

For multiplication, we’re actually talking about scaling, we multiply the vector by a scaler by multiplying both it’s components by the scaler, preserving the direction but increasing the magnitude.

To get the magnitude of a vector, we treat it as a right triangle where x = a, y = b and we are solving for c, the hypotenuse. Using the Pythagorean theorem we know that a2 + b2 = c2 so if we take the square root of  a2 +b2 we get the magnitude.

For normalization, we get the magnitude and then divide each component of the vector by the magnitude, this gives us a unit vector, or a vector that retains it’s direction but has a magnitude of 1.

as a bonus, to set the magnitude, we can first normalize and then multiply by a scaler to get the magnitude we are looking for.

I implemented like this:

[pastacode lang=”cpp” manual=”class%20vec2%0A%7B%0A%20%20%20%20float%20x%3B%0A%20%20%20%20float%20y%3B%0A%0Apublic%3A%0A%20%20%20%20float%20getX()%20%7Breturn%20x%3B%7D%3B%0A%20%20%20%20float%20getY()%20%7Breturn%20y%3B%7D%3B%0A%20%20%20%20void%20setX(float%20i)%20%7Bx%20%3D%20i%20%3B%7D%3B%0A%20%20%20%20void%20setY(float%20i)%20%7By%20%3D%20i%20%3B%7D%3B%0A%0A%20%20%20%20void%20add(vec2%20vec)%3B%0A%20%20%20%20void%20mult(int%20scaler)%3B%0A%20%20%20%20void%20sub(vec2%20vec)%3B%0A%20%20%20%20float%20getMag()%20%7Breturn%20sqrt(%20(x*x)%20%2B%20(y*y)%20)%3B%7D%3B%0A%20%20%20%20void%20setMag(float%20mag)%3B%0A%20%20%20%20void%20normalize()%3B%0A%7D%3B%0A%0Avoid%20vec2%3A%3Aadd(vec2%20vec)%0A%7B%0A%20%20%20%20this-%3Ex%20%2B%3D%20vec.x%3B%0A%20%20%20%20this-%3Ey%20%2B%3D%20vec.y%3B%0A%0A%7D%0A%0Avoid%20vec2%3A%3Amult(int%20scaler)%0A%7B%0A%20%20%20%20this-%3Ex%20*%3D%20scaler%3B%0A%20%20%20%20this-%3Ey%20*%3D%20scaler%3B%0A%7D%0A%0Avoid%20vec2%3A%3Asub(vec2%20vec)%0A%7B%0A%20%20%20%20this-%3Ex%20-%3D%20vec.x%3B%0A%20%20%20%20this-%3Ey%20-%3D%20vec.y%3B%0A%7D%0A%0Avoid%20vec2%3A%3Anormalize()%0A%7B%0A%20%20%20%20float%20mag%20%3D%20this-%3EgetMag()%3B%0A%20%20%20%20this-%3Ex%20%3D%20this-%3Ex%20%2F%20mag%3B%0A%20%20%20%20this-%3Ey%20%3D%20this-%3Ey%20%2F%20mag%3B%0A%7D%0A%0Avoid%20vec2%3A%3AsetMag(float%20mag)%0A%7B%0A%20%20%20%20this-%3Enormalize()%3B%0A%20%20%20%20this-%3Emult(mag)%3B%0A%7D” message=”” highlight=”” provider=”manual”/]

I ran some test scenarios in the console and verified that my code is working as intended, with the vector class tested and working now, my next step will be extract it from the main.cpp and set it up into it’s own header and cpp files so I can include it without cluttering my main.cpp and after that I can get started on using it to implement some motion using a primitive rendering loop.

Leave a Reply

Your email address will not be published. Required fields are marked *