Thinking Objectively

Our code is getting quite messy now that we’ve added all these variables to track velocity, position, acceleration, etc in the main function, so I think it’s time to roll another class that will contain all the things we need for an object with the following traits:

  • position
  • velocity
  • acceleration
  • max speed
  • SDL_Texture

and have the following functions:

  • edge collision handling
  • display
  • load image
  • update

We’ll also need to add a destructor that will handle clearing the SDL_Texture.

This should allow the object to abstract away all of this complexity within itself instead of spilling out into the main function. Borrowing from Daniel Shiffman’s Nature of Code, which I am referencing, we’ll call this the mover class.

 

Firstly, we’ll create a new branch to work on this code and then merge it later when we’re done. We’ll create a new branch in git by running git checkout -b mover, where mover is the name of the branch.

Now that we’re in our new branch, our class should look something like this:

[pastacode lang=”cpp” manual=”class%20mover%0A%7B%0Apublic%3A%0A%20%20%20%20vec2%20position%3B%0A%20%20%20%20vec2%20velocity%3B%0A%20%20%20%20vec2%20acceleration%3B%0A%20%20%20%20float%20maxSpeed%3B%0Aprivate%3A%0A%20%20%20%20SDL_Texture*%20image%3B%0A%0Apublic%3A%0A%20%20%20%20mover(float%20posX%3D1%2C%20float%20posY%3D1%2C%20float%20velX%3D0%2C%20float%20velY%3D0%2C%20float%20AccX%3D0%2C%20float%20AccY%3D0%2C%20float%20maxS%3D0)%3B%0A%20%20%20%20~mover()%3B%0A%20%20%20%20void%20edgeCollision()%3B%0A%20%20%20%20void%20display(SDL_Renderer*%20ren)%3B%0A%20%20%20%20void%20loadImage(std%3A%3Astring%20imagePath%2C%20SDL_Renderer**%20ren)%3B%0A%20%20%20%20void%20update()%3B%0A%0A%7D%3B%0A%0Amover%3A%3Amover(float%20posX%2C%20float%20posY%2C%20float%20velX%2C%20float%20velY%2C%20float%20accX%2C%20float%20accY%2C%20float%20maxS)%0A%7B%0A%20%20%20%20position.setX(posX)%3B%0A%20%20%20%20position.setY(posY)%3B%0A%20%20%20%20velocity.setX(velX)%3B%0A%20%20%20%20velocity.setY(velY)%3B%0A%20%20%20%20acceleration.setX(accX)%3B%0A%20%20%20%20acceleration.setY(accY)%3B%0A%20%20%20%20maxSpeed%20%3D%20maxS%3B%0A%7D%0A%0Amover%3A%3A~mover()%0A%7B%0A%20%20%20%20SDL_DestroyTexture(image)%3B%0A%7D%0A%0Avoid%20mover%3A%3AedgeCollision()%0A%7B%0A%20%20%20%20if%20(position.getX()%20%3E%20SCREEN_WIDTH)%0A%20%20%20%20%20%20%20%20position.setX(0)%3B%0A%20%20%20%20else%20if(position.getX()%20%3C%200)%0A%20%20%20%20%20%20%20%20position.setX(SCREEN_WIDTH)%3B%0A%0A%20%20%20%20if%20(position.getY()%20%3E%20SCREEN_HEIGHT)%0A%20%20%20%20%20%20%20%20position.setY(0)%3B%0A%20%20%20%20else%20if%20(position.getY()%20%3C%200)%0A%20%20%20%20%20%20%20%20position.setY(SCREEN_HEIGHT)%3B%0A%7D%0A%0Avoid%20mover%3A%3Adisplay(SDL_Renderer*%20ren)%0A%7B%0A%20%20%20%20renderTexture(image%2C%20ren%2C%20position.getX()%2C%20position.getY())%3B%0A%7D%0A%0Avoid%20mover%3A%3AloadImage(std%3A%3Astring%20imagePath%2C%20SDL_Renderer**%20ren)%0A%7B%0A%20%20%20%20%20%20%20%20image%20%3D%20loadTexture(imagePath%2C*ren)%3B%0A%7D%0A%0Avoid%20mover%3A%3Aupdate()%0A%7B%0A%20%20%20%20velocity.add(acceleration)%3B%0A%20%20%20%20velocity.limit(maxSpeed)%3B%0A%20%20%20%20position.add(velocity)%3B%0A%7D%0A” message=”mover” highlight=”” provider=”manual”/]

 

There’s quite a lot going on here, but nothing we haven’t seen so far, it’s just moved into it’s own class. the member variables are pretty self explanatorys o let’s go through the functions:

edgeCollision()

This is the same collision code we had before that detects the window edge and wraps the object if it hits the border.

display(SDL_Renderer* ren)

This function runs the renderTexture() function from the sdl_helpers.h

loadImage(std::string imagePath, SDL_Renderer*& ren)

This function loads an image with the provided path and uses the renderer that we pass in via pointer reference.

update()

This function simply performs the same vectors add that we were doing before to create motion.

~mover();

Finally, the destructor destroys any texture we might create for this object.

 

Also worth noting is that the two consts for screen width and height were moved into their own globals.h.

 

After all that we can now add the following to our main function and render loop respectively:

[pastacode lang=”cpp” manual=”%3C~%20in%20main%20~%3E%0A%0Amover%20ball(1%2C1%2C0%2C0%2C0%2C0%2C10)%3B%0Aball.loadImage(%22Images%2Fball.png%22%2C%20renderer)%3B%0Aball.acceleration.setMag(.1)%3B%0A%0A%0A%3C~%20in%20loop%20~%3E%0A%0Aball.update()%3B%0Aball.edgeCollision()%3B%0Aball.display(renderer)%3B” message=”” highlight=”” provider=”manual”/]

These six lines replace all the code we previously had for an autonomously moving object.

 

Now that we have all of this implemented into our mover branch, we need to merge our changes, we can do this by running a commit of the code, checking out the master branch and running  git merge mover to merge the changes into the master branch. This is a simple merge as no changes were made to master since the branch was created, if there had been changes we would have had to deal with conflicts.

 

Next time we’ll add a way for our mover object to experience external forces such as wind, gravity and friction.

Leave a Reply

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