I blame my procrastination on my first year computer science course. On the first assignment they showed us this basic mouse that had to find its way out of an arbitrary maze by only knowing what's in front, left or right of it. I could not solve the problem for every maze. I still cannot to this day, and it haunts me. Yes, that's right - I fail at programming.
But otherwise, I feel the most important thing is to actually work on what you enjoy doing. If you don't enjoy doing something, you might as well stop right now, because if you're like me, it's realistically never going to get finished unless it's homework. I am also a fan of prototyping new ideas as much as possible. If you find something cool that looks doable, and if you've got time, try and implement it. Regardless of whether you succeed or not, it'll give you some motivation to do some other work done.
Also, I've experimented with multiple design techniques to create applications. The obvious one is the top-down approach: implement the high-level code first, writing stubs for lower-level functions and classes, and recurse until the thing works. This doesn't work, because it takes forever to get something that compiles and see a result, real bad for motivation. Another one is the bottom-up method, where you implement the independent, low-level part of the code first, in nice, reusable modules, and then glue them all together to create something useful. This is better, but doesn't work great either, because you will probably get sidetracked and waste a lot of time, and there may be unforeseen design issues with how different parts of the program interact. It also takes a long time to get some feedback on the code.
What I found works for me is a mix of those two approaches, trying to implement the bare minimum (I don't write games, so your mileage may vary, but for instance I'll try and get basic input/output working before thinking out anything else) and design my different classes to require as little interaction as possible, and to make them as simple as possible, so that they may be tested independently. Always try and keep a single variable changing with all others constant if you want to fix issues, otherwise you will get frustrated.
Also, stop worrying about how much better other games are. I like to go with the mindset that there is always someone better than me at X, for any X. Get comfortable with this, because you will never be the best. And even if you are, you'll have no way of knowing. So just go with this, improve yourself and your games/programs, perhaps later join a team to code with, and so on... one day you'll be able to implement the effects you see in current games, but by that time you'll see even better effects, and the cycle will continue. You will always want more, all human beings do, and you can't let your motivation be eaten away by that.