[SFML] I Finished Breakout! It's So Awesome!

Started by
12 comments, last by superman3275 11 years, 6 months ago
Hi everyone, I just thought I'd tell you that after a few weeks (and posts) worth of working on Breakout, I have finished it. Mind you, I'm still working on adding a main menu, a game over screen, and the works, however I hope to get that done by tomorrow smile.png. In the game there's four rows of Multicolored Blocks, and you use your paddle to make the ball hit the blocks. The game doesn't end, I'm thinking about adding lives. Powerups are in the works also. Anyway, Have fun knocking down those blocks. (Release Application and a Separate Source Code Download Below!)

WHAT I LEARNED IN THE PROCESS OF MAKING BREAKOUT

Object Oriented vs. Procedural Programming
Coming off of Pong, I tried to everything with classes. In my next iteration, I found a balance between Object-Oriented and Procedural Programming, creating functions to handle common tasks, and knowing what to make a member function and what to not. I'm now using both classes and functions depending on my needs, which makes my code cleaner, and more expansive. When I wanted to add a new row of bricks, all I did was type in 1 lines of code to create the bricks, but since I had a function that automatically updated a row I passed in as a parameter and a function that draws the row, it was ~4 more lines to add the row into my game loop.

Vectors and Arrays: Their Limitations and Uses
I ran into a predicament about halfway through where I couldn't use a non-default constructor on my array. I Googled Arrays and was pointed to vectors. In the documentation it talked about how to initialize an array of vectors using a non-default constructor. Problem Solved! I also learned array are automatically passed by reference, unlike vectors, and how I can use arrays vs. how I can use vectors.

Structure and Organization
Commenting. I fully commented my code, and made it a habit through this project. It should help your guys understanding, and mine if I ever want to modify my code. I also used white-space / indentation to structure and organize my code. Having a block of code for creating images, and another for loading those images from files, makes finding where I'm doing things and how I'm doing them easy.

DOWNLOAD:

Only Application: Here (Extract .rar and double click Breakout.exe to run game.)

Only Source Files: Here (Extract .rar)

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

Advertisement
Good job, that was quick. I was unable to play it though, it says MSVCP100D.dll is missing.
I'll fix that, it seems you must have Microsoft visual studio installed to run it. I'll fix it tomorrow. Try downloading the source code and then compiling

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !


Good job, that was quick. I was unable to play it though, it says MSVCP100D.dll is missing.


I'll fix that, it seems you must have Microsoft visual studio installed to run it. I'll fix it tomorrow. Try downloading the source code and then compiling

You'll need to compile your project in the "Release" configuration before distributing.
Congratulations on finishing this thing, and thanks for coming here to the forums and being excited about this stuff. I have a tendency (like many others, I suppose) to be all jaded and even bored about a lot of this, so it's nice to see someone who is enthusiastic and all fired up.

Anyway, my thoughts (somewhat random):

1) Source Releases

Your source-only release contains a lot of compiled binary .obj files, as well as DLLs and pre-compiled headers that greatly inflate the archive file size. For smaller downloads, source release packages should be stripped of any binary data like this. All of that stuff is generated in the compile process, so no need to ship it.

2) Resource Management

As you move on to more complicated projects, you are going to want to be smarter about how you handle resources such as images. In your program, the block, paddle and ball textures are loaded and used essentially as globals (not technically, but their usage patterns are global). That is, you create an essentially static object that exists for the lifetime of the program, and is handed to objects that need it.

In a more complicated program, though, that uses more assets, it is impractical to have all assets loaded for the lifetime of the program. You will instead want to implement a system for managing the lifetime of objects such as textures/images. An object can request a resource from the system, and it will load it (if needed) and return a reference or pointer to the asset. When the object no longer needs it, it is released. If no objects are referencing an asset, it can be unloaded. You can also implement a cache system that will keep some objects loaded if they are frequently used.

As an example of this, one of my earlier systems used an internal std::map of weak_ptrs keyed on a string (and later a hashed string). The string key can be filename, and the weak_ptr points to a texture resource. When a texture is requested, the system first checks to see if there is an entry in the map for the requested file. If so, then the weak_ptr is checked for validity. (If a resource is dropped, an entry will remain in the map, but the pointer itself will be invalid). If the pointer is invalid the resource is loaded. If the resource does not yet exist, it is loaded and a weak_ptr to it is placed in the map. Once the resource is located and loaded as needed, then a shared_ptr is cloned from the weak_ptr and returned.

As long as at least one shared_ptr exists, the resource will remain loaded. Once all objects holding a pointer to the resource are destroyed, though, and no shared_ptr exists, then the resource destructor is called and the resource is destroyed, the weak_ptr i the table invalidated. Requesting the resource, then, will cause it to be reloaded. You can implement a second map of shared_ptrs, keyed on name, as a cache to hold a copy of the resource and keep it from being dumped if all other shared_ptrs are dropped.

If you are anything like me, you will go through several iterations of your system until you get something you like, however you implement it. And if you are even more like me, this will be one of your first "reusable" systems that you drag with you from project to project, iterating and improving it as you go. Nailing this system down will vastly help you later, though, as you try to tackle more complicated projects.

3) Sneaky Side Effects

Take a look at your Block::Initialize method. The name suggests that the method will set some internal invariants and data in Block then exit. There is no reason to suspect it does anything else. Yet it has a side-effect, in that it takes references as parameters, and modifies the value of one of them. This sort of sneaky side effect is generally regarded as a Bad Thing[sup]TM[/sup]. Even if the side-effect is documented (it isn't) this is still something you should avoid. Either rename the method to reflect its actual behavior, or refactor to eliminate the side effect and find another way to accomplish what you need. Trust me, if you ever come back to this kind of code after a 6-month break during which you worked on something completely unrelated, these kinds of side-effects can cause you no end of headaches.

4) General Inconsistencies in Object Handling

Your Block class has an Initialize method, but neither your Paddle nor Ball class do. Ostensibly, they are all game objects, and ideally you would want at least some semblance of a common interface for dealing with them. In the past, people did this by implementing great, gawky, god-awful object inheritance hierarchies to abstract the handling of game objects. Current, modern thinking is to implement object composition, where the shared components have common interfaces. However you solve it, you should have some consistent, data-oriented means of creating, managing and destroying objects.

Implementing a sane object management policy means that you can, for example, destroy blocks that are hit, as opposed to just setting an internal flag to hide them. You can also spawn intermediate objects that perform assitance tasks, as well. For example, when a block is hit you can spawn an Explosion object whose sole purpose is to exist long enough to play an explosion animation and a sound effect, then self-destruct. The spawning of this object can be initiated by the block collision logic.

It's kind of... weird... that you implement your logic updates as functions. Really, object logic probably belongs inside the object itself, via some sort of Update method. An external function would iterate on objects and call their Update method. This way, you can implement different brands of logic merely by instancing different varieties of objects, and the main loop doesn't have to be modified to call another function. It can just keep calling Update as before.

Things such as collision detection are typically off-loaded into sub-systems of their own. For example, a physics sub-system. The sub-system will keep arrays of primitives and when a method is called, it will iterate the arrays in some fashion (this can get complex, for systems with lots of objects, but for small games it can be dead simple) and calculate collisions. It will determine which objects collide with each other, and it will somehow notify the interested parties of the collision so that they can update themselves accordingly. Then the main loop can just call UpdateCollisions after Update.

Again, as with anything, there are a thousand ways you can handle this stuff, but keeping essentially global references to all objects is not the optimal method.

5) Ball::SetVelocity

Huh. Why would a method named SetVelocity (which you would expect to accept as parameters a 2D velocity vector) accept a string parameter instead? I mean, I get what you are doing, but it just doesn't seem like the best way to do it.

6) Main Loop

There are problem with how you implement your loop. Moving things have a fixed, specified velocity which is applied each turn through the loop, but the loop doesn't take timing into account. It will run as fast (or as slow) as the CPU will allow. This means that if there are background tasks, for example, that pull away CPU time the simulation will slow down. It will also run faster or slower depending on the CPU speed. In the old DOS days, many games were implemented like this because the hardware at the time was all fairly similar. But once faster processors came around, many of those games became flat out unplayable, due to extreme speeds. It is generally a bad idea to allow your loop to run "unrestrained" like that.

As with everything else, there are a number of ways you can implement a proper game loop. Some loops will fix the logic update rate to a clock, and allow it to render as fast as possible, interpolating logical positions to make the visual update smooth. Others will update each time through the loop using a calculated elapsed-time delta to scale velocities based on how much time has passed since the last update. Still others will do one or the other of these, and limit the visual framerate to some rate in order to keep from hammering the video card too hard. What you do is a matter of taste, but I highly recommend you do a bit of research into it.

These are just a few of my first impressions upon looking at your code. Don't be discouraged if it seems like a lot. You've got plenty of time to figure all this stuff out, so just keep plugging away and trying to improve and you will get there. :D
Good job.
But you got few problems...
I downloaded the zip and i needed to put png files intro "./images/..." fix that. Also when a ball hits the paddle from side i was like 'nooo im gona lose' but then the ball went up ^^ should consider that as a lose.
Anyway 10/10! Package and price it 60$ and you will be rich in no time. rolleyes.gif

EDIT:
Also games paddle can go out of screen really far.
I just updated the link to the game. I compiled in release mode and tested it, it works on all computers now. Here's the new link for the game:
Game Link

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

Nice job and congratulations on finishing your game ;)

I played it a little, and have 2 complains on it. I didn't look at your code since I'm working on my own game, but still:
1) Paddle can get out of screen
2) Ball cannot fall down - when it touches bottom border it reflects back up.
Update: Breakout v2

CHANGELOG:
+Added a Main Menu!
+You lose when the ball hits the bottom of the screen! (Implementing Lives system soon!)
+Added Dynamic Buttons to the Main Menu!
+Fixed some bugs!

I've been working on this update for 2 days now. It only took an hour and a half for the main menu (I recently found out the difference between sf::MouseButton and sf::MouseMove!), and everything else if relatively minor. Hopefully I'll get you guys three lives and a game over screen on monday!

Application: Here

Source: Here

Link Fixed
Also, you need to take BackgroundImage.png, PlayImage.png, and ExitImage.png from the Source folder and put them in the images file of the application folder (That's my fault, sorry :))

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

Link is broken D:
what

This topic is closed to new replies.

Advertisement