What am I not understanding about programming?

Recommended Posts

I've typed this up several times, and I think this is as good as it's going to get.

For a long time, I've understood programming concepts, but I am unable to write programs that I want. My favorite language is C++, and think I have a pretty good grasp on it. Variables, data types, classes, etc... I know them well, and could explain what they do and how they work. My problem is, when it comes time to actually write functioning code, I just can't fgure out what to do. I don't know if this is a lack of code architecture knowledge, or just sucking at logic skills.

To make things worse, I look at examples of other people's work and become even more confused as to why they did it this way, used that data type or even become genuinely frustrated that I can't read their code(I know it's not always immediately obvious what some code is supposed to be doing, but it gets to me anyways). I stare at other's accomplished works and wonder what it is I'm missing to the point that I throw my hands up and walk away.

I would like to preface the end of this thread by saying that I've completed hundreds of programming challenges, ranging from beginner to advanced. Why I can complete them in a relatively quick time, but struggle for days to write code that'll keep a window open in some graphics library, I don't know. It's been a problem for a long time, and I'm tired of getting stuck in this cycle of Inspiration->Frustration->Quit.

Edit: To sum this up as a TL;DR: Why is it I can write several classes, flesh them out with their working code, but not put all of those things in working order to produce the main loop?

Edited by LuridRequiem
Added a TL;DR.

Share this post


Link to post
Share on other sites

Sounds like lack of practice to me. You say you have solved many programming challenges, so you obviously know how to write certain types of programs. I wouldn't give up, and instead I would try to get specific help with specific problems.

 

I have helped people learn how to write programs before. The method I recommend is starting with a fairly trivial program that you can compile and test. You then make some changes to get the program a bit closer to doing what you really want it to do. Compile. Test. Repeat.

It might take some practice before you even know how to make progress in this manner, so a bit of personal guidance could be useful. I am much too busy these days to promise you any of my time, but perhaps these forums can play the role of the mentor.

 

Share this post


Link to post
Share on other sites

Programming at is basics is a process of solving a problem, getting to know the problem, break it down into peaces and write a solution for those peaces to chain into each other to solve the problem. Some problems are small, for example the calculating a distance from A to B, so these self-contained actions performed to solve the task are called algorithm.

What might be hard at the beginning is to get the whole problem and declare steps to solve before getting to code. Solutions also could change during development process from cause of new upcomming knowledge, conditions changing (like there is a new fancy library upcomming) or features occuring/disappearing.

What in the end makes a good programmer in my opinion is not to know all your design patterns from memory but be able to see the essence of a task (self) guided to you and evolve a solution to solve it. (Someone may disagree but it is a personal sight of view). Most important is to have fun at what you are doing and talk to people that know it better to become better from understanding there solutions (even if you do not agree with them ;) ) but this will be the only way to be able to understand the problem itself and write your own solution.

And dont let people tell you that there is only one (there) way to solve a problem. Different people, different implementations and the only (right) way is the way you are happy with the solution.

I have had talked to people coding for a very long time and (especially in C++ where the "right" way to code changes with every revision) even they say that looking at old code makes them partially ashamed about what they wrote long time ago where some new technics become popular (like template meta programming)

Share this post


Link to post
Share on other sites

I definitely agree that I should put more time into it. I also know there are several ways to solve one problem. I think where I'm at right now, I feel like if I can code small parts, I should be capable of getting it all to work at once.

Take for example, my very first post on this website. The gist of it was what I'm explaining above. I wanted to build a super basic version of PONG. I wrote classes to handle the window and Player Paddle and placed it all in a game loop function that I called in main(). Everything at that point ran fine, but it wasn't what it should've been. Nothing else was completed. In this main loop, I was basically calling objects in full. I know now that I shouldn't have done it like that, but at that point, I didn't know how I was supposed to build this game loop that would keep the game running. I don't have the code on hand to show, but I remember well enough to know it was garbage.

Just thinking about that project, I visualize what I want to accomplish, but then it explodes in a million different directions like a scatterbrained bomb. It's like throwing all of your limbs in every direction just to move in some way.

Are there any references, books or youtube series you guys could recommend so that I can work through this?

Edited by LuridRequiem

Share this post


Link to post
Share on other sites
47 minutes ago, LuridRequiem said:

Are there any references, books or youtube series you guys could recommend so that I can work through this?

If you're referring to the pong attempt, then there is this https://www.pluralsight.com/courses/unreal-engine-4-blueprint-cplusplus-integration where you get to create a working Pong game in the unreal engine by the end of it.

Also that site offers a free trial, so you should be able to watch it for free, unless you've used up your free trial already :P

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
1 minute ago, MarcusAseth said:

If you're referring to the pong attempt, then there is this https://www.pluralsight.com/courses/unreal-engine-4-blueprint-cplusplus-integration

Also that site offers a free trial, so you should be able to watch it for free, unless you've used up your free trial already

I meant a resource for code structure/architecture. Is there even a difference between them?

Share this post


Link to post
Share on other sites
2 minutes ago, LuridRequiem said:

I meant a resource for code structure/architecture. Is there even a difference between them?

Well I mean, watching real project working doesn't achieve that as well? :P

I mean you see the structure of his paddle, who is handling the score, who is checking for collision and so on.

I don't think you should keep this all in the theoretical realm by just gathering up the perfect informations about how it should be done properly, because that is a lot of information all at once. I think I was in the same position until recently and just now I'm starting to get out of it, and the way I found to be working is "just do it, do it wrong, doesn't matter" maybe show it on the forum and someone will be kind enough to point out what you can do better, and then you can worry about how to do properly a certain aspect of your game/project later on, over time :)

Share this post


Link to post
Share on other sites

It just seems like you've never really studied programming. It's easy to think that completing challenges means that you understand how to get things done, but that doesn't mean you know the best ways and the worst ways, or the differences between them.

It's not meant to be something you can just work out by being intelligent and thinking about it. It's something we spend years trying to teach people in colleges and universities. So don't be surprised if it's not obvious. There are various different concepts that we follow to try and write 'good' code, and maybe picking up a book or doing a course on them will help.

Alternatively, you can pick up more as you go along, by perhaps posting some code here and asking for specific critique.

Share this post


Link to post
Share on other sites

Try reading some design books such as the classic "Design Patterns: Elements of Reusable Object-Oriented Software".

It is possible that you have a lack of practice, in which case: try to make some small programs (until they are finished: don't stop along the way). It is very important that you make enough progress, otherwise you will get frustrated and lose interest. So don't start with a multi-year project, but keep it (simple and) small first.

It is also possible that the code you are referring to is just bad and incomprehensible code. There is a difference between writing code that works and writing code that works, is maintainable and extensible.

Share this post


Link to post
Share on other sites
4 minutes ago, Kylotan said:

I personally recommend steering well clear of the Handmade Hero stuff when trying to work out how to write good code.

I can't comment on that since I saw only 20 videos and also don't have the tools/knowledge to judge it, though I can say I definetly wish more developers would attempt what he is attempting :)

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
50 minutes ago, MarcusAseth said:

Oh, by the way, since you specifically asked for architecture/structure, check this https://hero.handmade.network/episodes

He makes an entire engine + game and show you every line in more than 400 videos... 

 

Have you looked at that index? How is this going to motivate someone ;) ?

Furthermore, if you have trouble understanding someone else's C++ code (whether it is good or bad code), stay away from someone else's C code. I studied a compiler implementation written in C in some kind of OO fashion (very deep union/struct alternations); the verbose codebase was a real monstrosity.

Edited by matt77hias

Share this post


Link to post
Share on other sites
2 minutes ago, matt77hias said:

Have you looked at that index? How is this going to motivate someone ;) ?

lol

Still entertaining though, for when you want to just lay down on bed and passively assimilate some knowledge, it's just like listening to a podcast :D

 

Share this post


Link to post
Share on other sites
6 minutes ago, MarcusAseth said:

just lay down on bed and passively assimilate some knowledge

Not enough time for that :D .

It would have been nice if he can summarize everything in <10min. Currently it will take you more than 500h< to go through all that, passively or not.

Edited by matt77hias

Share this post


Link to post
Share on other sites
5 hours ago, LuridRequiem said:

I wanted to build a super basic version of PONG. I wrote classes to handle the window and Player Paddle and placed it all in a game loop function that I called in main(). Everything at that point ran fine, but it wasn't what it should've been. Nothing else was completed. In this main loop, I was basically calling objects in full. I know now that I shouldn't have done it like that, but at that point, I didn't know how I was supposed to build this game loop that would keep the game running.

I suspect you're hitting Analysis Paralysis by getting too hung up on doing things the "OO way".

Pong is really no different to any other kind of application:

  1. It gathers input
  2. It processes that input into some state
  3. It presents that state as output

The only notable variation is that for a real-time game those 3 step needs to occur every single frame.
So all we do is wrap them up in a game loop like this:

World world;

while (true) {
	Keys keysPressed = checkInputs();   // input
	update(keysPressed, world);         // process
	render(world);                      // output
}

 

World maintains the state of the game (paddles, players, scores, ball, etc) and its public methods model the interactions that you have available to you when playing. In the case of Pong it might have a method like: movePaddle(amount).

The update() function knows how to convert inputs (keypresses) into actions that modify the world. For example it knows that if you push the right-arrow key then it will invoke: world.movePaddle(1);

The job of the render() function is to translate the state held by World into something visual. If the process of rendering requires  state all of its own (textures, shaders, models, etc) then a simple render function isn't enough. That's fine. Just make it a method in a class:  renderer.render(world);  This class can now hold all that rendering gumpf, available only to the render() method.

 

Of course as you scale this up to larger and larger applications/games you'll find that these pieces become bloated. At which point you'll want to start sub-dividing ("refactoring") them.  For example you can move code out of your World class into Paddle and Ball classes and World just glues them together. Or you might move code out of render() (or Renderer) into renderPaddle, renderBall, etc.

This "refactoring" process helps keep your code organised and maintainable. But it's not where you start. You start simple and you subdivide structure into it only when needed. This is how we all do it!

With lots of experience we developers can sometimes foresee what sort of factoring is appropriate and then shoot straight for that. But in reality it's an unreliable process (because we're only human, we stumble across pitfalls or we learn something new or requirements change).  Ultimately it's a skill that you will never master and you will never stop improving!

 

Share this post


Link to post
Share on other sites

I sometimes find it helpful to tackle a big problem by looking at what sort of thing I want the end result to be and then figuring out the immediate steps my program needs to do it, then subdividing those and repeating the process - essentially writing the program in the reverse order in which the data is processed, using mock data to pretend that the preceding steps are in. I keep doing this until I have tasks at a level of granularity that I know how to solve. I'll give an example of this using Pong.

First I might think, "I want to display the game state to the player using graphics. In order to do that, I need to open a window and then draw the game world once per frame." The most granular task in that sentence is "open a window", so I'd go and write the code that displays a window. So then I want to draw a game world once per frame; in order to do that, I need to draw the paddles, the ball, and the players' scores.

To draw the paddles and ball, I need to be able to draw rectangles at arbitrary screen positions. That should be granular enough for a task, so I go and I implement rectangle drawing. Now that I know how to draw rectangles, I can make up some paddle and ball positions and write a bit of code that draws the paddles and the ball on the screen every frame.

To draw the players' scores, I need some way to draw text. Since I don't know enough about fonts to do this myself, if I want to draw text I either need to find a font-rendering framework of some kind or write one. I'll try the first one since that's easier. Suppose for the sake of argument that I'm working with the SFML library; turns out it already has font rendering built in, so I can use that. Now I discover that SFML's font rendering requires me to load in an external TrueType font. I need a .ttf file and some code to load it into a font object, so I go and grab the former and write the latter. Now that I can draw text, I can draw the player's scores - I make up some fake score data and write the code that does that.

This gets the game rendering, but it doesn't actually do anything yet. It's just a static image that looks like a game. I need to actually implement gameplay. Pong's gameplay is defined as follows:

  • the ball moves at a constant speed in a given direction
  • players move their paddles up and down
  • if the ball reaches an edge of the screen with a paddle, then the player on the other side of the screen receives a point and the ball respawns
  • if the ball reaches an edge of the screen without a paddle, then its motion along the axis perpendicular to that edge is reversed (ie. it "bounces")
  • if the ball reaches the edge of a paddle, it also "bounces"

The first statement is simple enough to implement as a task. Players moving their paddles up and down requires subdividing into "moving a paddle" and "checking input devices to see if we should move." The ball-screen collision behaviour requires a way to see if the ball is touching the edge of the screen, and if so which side. Ball-paddle collision requires a rectangle intersection algorithm, then using that rectangle intersection algorithm to check for hits.

And so on.

Share this post


Link to post
Share on other sites
1 hour ago, dmatter said:

I suspect you're hitting Analysis Paralysis by getting too hung up on doing things the "OO way".

Pong is really no different to any other kind of application:

  1. It gathers input
  2. It processes that input into some state
  3. It presents that state as output

The only notable variation is that for a real-time game those 3 step needs to occur every single frame.
So all we do is wrap them up in a game loop like this:


World world;

while (true) {
	Keys keysPressed = checkInputs();   // input
	update(keysPressed, world);         // process
	render(world);                      // output
}

 

World maintains the state of the game (paddles, players, scores, ball, etc) and its public methods model the interactions that you have available to you when playing. In the case of Pong it might have a method like: movePaddle(amount).

The update() function knows how to convert inputs (keypresses) into actions that modify the world. For example it knows that if you push the right-arrow key then it will invoke: world.movePaddle(1);

The job of the render() function is to translate the state held by World into something visual. If the process of rendering requires  state all of its own (textures, shaders, models, etc) then a simple render function isn't enough. That's fine. Just make it a method in a class:  renderer.render(world);  This class can now hold all that rendering gumpf, available only to the render() method.

 

Of course as you scale this up to larger and larger applications/games you'll find that these pieces become bloated. At which point you'll want to start sub-dividing ("refactoring") them.  For example you can move code out of your World class into Paddle and Ball classes and World just glues them together. Or you might move code out of render() (or Renderer) into renderPaddle, renderBall, etc.

This "refactoring" process helps keep your code organised and maintainable. But it's not where you start. You start simple and you subdivide structure into it only when needed. This is how we all do it!

With lots of experience we developers can sometimes foresee what sort of factoring is appropriate and then shoot straight for that. But in reality it's an unreliable process (because we're only human, we stumble across pitfalls or we learn something new or requirements change).  Ultimately it's a skill that you will never master and you will never stop improving!

 

You can try to program Pong in Elm (Functional Reactive programming). Very fast and a joy to debug due to the steps.

Share this post


Link to post
Share on other sites
6 hours ago, dmatter said:

I suspect you're hitting Analysis Paralysis by getting too hung up on doing things the "OO way".

Pong is really no different to any other kind of application:

  1. It gathers input
  2. It processes that input into some state
  3. It presents that state as output

The only notable variation is that for a real-time game those 3 step needs to occur every single frame.
So all we do is wrap them up in a game loop like this:


World world;

while (true) {
	Keys keysPressed = checkInputs();   // input
	update(keysPressed, world);         // process
	render(world);                      // output
}

 

World maintains the state of the game (paddles, players, scores, ball, etc) and its public methods model the interactions that you have available to you when playing. In the case of Pong it might have a method like: movePaddle(amount).

The update() function knows how to convert inputs (keypresses) into actions that modify the world. For example it knows that if you push the right-arrow key then it will invoke: world.movePaddle(1);

The job of the render() function is to translate the state held by World into something visual. If the process of rendering requires  state all of its own (textures, shaders, models, etc) then a simple render function isn't enough. That's fine. Just make it a method in a class:  renderer.render(world);  This class can now hold all that rendering gumpf, available only to the render() method.

 

Of course as you scale this up to larger and larger applications/games you'll find that these pieces become bloated. At which point you'll want to start sub-dividing ("refactoring") them.  For example you can move code out of your World class into Paddle and Ball classes and World just glues them together. Or you might move code out of render() (or Renderer) into renderPaddle, renderBall, etc.

This "refactoring" process helps keep your code organised and maintainable. But it's not where you start. You start simple and you subdivide structure into it only when needed. This is how we all do it!

With lots of experience we developers can sometimes foresee what sort of factoring is appropriate and then shoot straight for that. But in reality it's an unreliable process (because we're only human, we stumble across pitfalls or we learn something new or requirements change).  Ultimately it's a skill that you will never master and you will never stop improving!

 

This is how I was trying to build my game loop, but I didn't understand how to take everything I was going to write, and put it in the appropriate functions. 

I also get caught up on how to get classes to work inside other objects. For example, If I have a player class and a weapon class, I wouldn't know how to set up the weapon instance inside player.  I don't know if this makes sense at all, because it's difficult to explain what I mean. I think another issue I have is separating abstraction and implementation from one another. Just because an item or weapon has all the variable attributes of those things doesn't make that thing what it's emulating in the real world. It's still code representing a real world object, and I get hung up on how to replicate that object in code. 

I feel like I'm rambling at this point, and not doing any good at explaining what I'm trying to accomplish. If you do, by all means, respond as thoroughly as possible if you'd be so kind to do so. 

Share this post


Link to post
Share on other sites
15 minutes ago, LuridRequiem said:

For example, If I have a player class and a weapon class, I wouldn't know how to set up the weapon instance inside player.

I don't know that too, so I would try to decompose te tasks as @Oberon_Command did, I'll give it my best shot, for instance for me the first logical step would be that my player holds an array of pointers to weapons, and I assign a new weapon to the index[0]. The weapon should also go in my player hand, so I would think I would need some kind of socket variable inside my player to represent where the hand is, and then I would try and snap the gizmo of the weapon to that socket, maybe give it some offset.

The point is that what I said above is probably incorrent, but making the mistake is part of learning, in fact the next thing would be fo me to show on the forum what I did and ask if it was good/right.

So my whole message is, first give it your best shoot, do it wrong but see how far you get, and then show online and ask for feedback :D   

That's where you learn :P

 

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

Build the complete game. Don't worry about doing it wrong. Don't worry if it's messy, or has performance problems, or is hard to maintain, or whatever.

Just get it done. It is this practical experience that you are lacking, and completing some small programs will be an invaluable learning experience.

 

I'd suggest making Pong like this, then Breakout, and then attempting a couple of 1-2 week game jams.

Once you have some real experience putting together complete programs, you'll be better able to tell what has been a problem for you, what seems to work well, etc. and will have a better framework for understanding other people's suggestions for structuring your programs. 

Share this post


Link to post
Share on other sites
12 hours ago, LuridRequiem said:

I feel like I'm rambling at this point, and not doing any good at explaining what I'm trying to accomplish. If you do, by all means, respond as thoroughly as possible if you'd be so kind to do so. 

You're talking about a wide range of abstract problems, to which there are only abstract solutions.

Next time you get into difficulty, start a thread here on the forum, show some of the specific code that you're not happy with, and tell us what your concerns are and what you hope to achieve. People will give you advice and will explain their reasoning, and you can learn from that and improve your programming.

Share this post


Link to post
Share on other sites

You get the hang of it eventually. I was like that at one point, had a good understanding but didn't even know where to start.

 

Now I can be like, "Okay, I want to make a building system", open the script up and I just plow through it like it's nothing. Just practice and eventually you'll feel able to do it on your own. 

Share this post


Link to post
Share on other sites

The question you really need to ask yourself is do you really understand the fundamentals?...and by fundamentals I mean the very basics, variable type, function, function params vs arguments, loops among other things. If you really do, then simple text base programs that accept input and print something out to the console etc should be no worries. Then work your way up to more complex problems. If you can't make it past the first step of the simple programs, then you are working up for disappoint if you proceed to more complex problems. This should be an indication that you really have not grasp the basics.  As other have mentioned before, you just don't get good at something by 1. giving up or 2. dreaming. you have to do it over and over until you've mastered it or at least at a level of comfort where you know it like the back of your hand.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now