Goofans Game Discussion

809 replies [Last post]
Joined: 07/08/2011

No, I've been making header files to put the vast majority of my code in, and if you didn't notice before, it's organized. (kind of)

Joined: 09/01/2009

And AAAAAAAS I was saying before, function implementations in header files = bad idea.

Joined: 12/23/2010

I totally agree with MOM4Evr. Classes (or whatever you'd use for additional .cpp files) all the way.

Joined: 08/06/2010

I put some code in headers, such as minor libraries (so that I don't need to link them), but for a big project you should make a misc.cpp file for the stuff.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 07/08/2011

Asking my dad, he says putting everything in header files is perfectly fine. The whole purpose of headers is for a place to put code, so putting functions there is totally fine. (if you doubt him, he is 63 and pioneered programming; he was there when it was just inputting numbers into a pad)

Joined: 08/06/2010

Technically it's fine, just messier. Your call, I guess.

The point of headers is actually to put declarations, but not definitions. You can get around this with preprocessor directives, which I think is what you're doing. (#ifndef HEADER_H #define HEADER_H 1 ... #endif)

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 07/08/2011

Woops! Forgot to put them. Tongue

Joined: 09/01/2009

TL;DR
What AP said. It's messier. ^^

Of course you can put anything in headers (you can even #include "thisfile.cpp" if you want at the top of some other file). The reason I'm saying that it's a bad idea is twofold:

1. Convention
Generally, it's a good idea to stick to common programming conventions. Some are strange, stupid, and obnoxious, but others make sense, and anyone who sees code that lacks indentation (or some other common convention) will automatically think you're a total idiot, regardless of the rest of the structure of your code. It's also a terrible headache for anyone else who tries to look at your code later (which will undoubtedly happen if you release something open-source). What convention comes into play here? The convention of naming anything ".h" in the first place. The h stands for HEADER file. Meaning that function HEADERS should go there. ".cpp" files are commonly called IMPLEMENTATION files, meaning function IMPLEMENTATIONS go there.
I'm also speaking from experience here. Any time I place a function in a header file, I confuse myself months down the road. Without fail. While it's easy to keep track of where functions are in a small program, as it grows, it becomes harder and harder to remember, and, quite frankly, it can become painstaking finding what function is where, and you'll waste what otherwise would have been productive programming time.
Example: I worked a job programming over the summer, and the lead programmer didn't indent his code according to common convention. Nobody was happy with that, and our boss kind of chewed him out over it.

Btw, by "inputting numbers into a pad", do you mean low-level assembly and machine code? That stuff is fun! XD

2. Extensibility
Having all kinds of stuff in a header is perfectly fine for a small project. You can do anything you want with a small project, really; even remove all the whitespace so you have one line of code; and it'll still be mostly readable and understandable. But what happens when you start expanding? Suddenly, your "misc.cpp" file where you have everything (Also talking @AP here) grows to a few thousand lines of code, and your scroll bar on the right of Code::Blocks becomes a tiny button you can barely click on, and dragging it up and down a pixel at a time jumps half a page (Not to mention using your mouse scroll wheel takes forever to get anywhere). Your editor starts bogging down from how many lines the file has, and you're forced to make another ".cpp" file to keep your sanity. You include the same header into both files, and guess what? You now have linker errors. Why? Multiple declarations of the same function. Since a function is declared in a header file, and included in two separate implementation files, the linker thinks you've created two functions with the same name. And it's not because the linker is stupid and doesn't know any better; it's because you're not supposed to program that way.

This is also from personal experience. You've seen the videos of Cheese Master, right? The game I'm working on. I ran into this problem with global variables being included into multiple files (another reason global variables aren't too good of an idea, either), and ended up using some complex macros to work around it. Also, my game is in VERY early pre-alpha stages, and it's got 7901 lines of code already. And I've barely started. A game is a massive programming project. You cannot physically put all your functions in one file and keep your sanity. One of my files is 1488 lines of code, and it's really hard to find anything I'm looking for in the file as it is! (btw, these 7901 lines of code are split into 18 files. Makes it much easier to find stuff)

By the way, there also is another good reason to have multiple small files rather than one huge file. It's the whole premise behind a Makefile, actually: Only compile the stuff you need to. The "make" program (Which Code::Blocks uses, to the best of my knowledge) checks the timestamps on each file to determine if it needs to be recompiled or not. This way, it only has to compile stuff it absolutely has to.
So what? This program only takes a few seconds to compile, anyway, right?
Well, for now. But as code grows, so does compile times. The Linux kernel, for example, takes half an hour to compile, bare minimum on a really fast machine. I recently compiled FFMPEG, and it took several minutes. Compiling Wine takes quite a while. While the game may not end up THAT complicated, it may get surprisingly close!
The good news about makefiles is that you'll only have to compile code that you've changed (But only as long as you have lots of small files!). Then, all you have to do is link everything together, which is fairly fast in comparison.
So coming back to my practical example: Suppose I modify something in my 1488-line file. I press "compile" (Actually, I usually just press F9, but that's beside the point). How long does it take it to compile the code? Not too long. What if I had all 7901 lines of code in that file? Well, it'd take 7901/1488 = ~5.3 times as long. Not bad for small programs, but what happens as the program gets larger? If it takes the file 1 minute to compile now, you're sitting there, unproductive, for 5 minutes in the future. If it takes it 5 minutes to compile, you'd be sitting there twiddling your thumbs for nearly half an hour. Small files are your friend. :happyface:

/walloftext (speaking of lots of lines per file! Tongue)

But anyway, it's your call. Laughing out loud You asked for suggestions about code messiness, that's all. This is just a messy way of programming imo.

Joined: 07/08/2011

(replied to in Skype)

Joined: 09/01/2009

Ok, so to clear some stuff up from my wall of text above, and also the Skype conversation...

1. Header files are your friend
We know this, right? That's why everybody uses them; so they can include the same header in multiple files, and even multiple projects.

2. Header files generally don't include function implementations (the functions themselves)
The reasons for this are complex and explained in nerdspeak above. BUT THIS DOESN'T MEAN THAT YOU CAN'T USE THESE FUNCTIONS IN SEVERAL FILES OR PROGRAMS. On the contrary, that's what headers are for. Headers generally contain function DECLARATIONS, which are basically all the info that somebody else needs to call this function. So, example:
Suppose we have a function declaration in a file called "foo.h":

int foo();

Notice that this includes all that anybody needs to know to call this function: the return value (int) and the function parameters (in this case, void). Also, note the semicolon. This means that this function is actually implemented elsewhere. So to call this function (most likely in some other file - let's say "misc.cpp"), you'd say something like:
int i = foo();

When the compiler comes to this line of code, it looks in the header file (so as long as you #include "foo.h" in the top of "misc.cpp" you're fine). It sees (thanks to the function declaration) that somewhere there should be a function called foo() that returns an int and has no parameters. The compiler continues happily along, not knowing or caring where this function is.
Of course, if you don't actually MAKE the function, you'll get a linker error saying something like "undefined reference to int foo(void)" or something like that. This is where the function IMPLEMENTATION comes in.
For the purposes of our example, we'll make a file called "foo.cpp" (it's generally a good idea to have function implementations in a .cpp file with the same name as the .h file they were declared in) and write the following:
#include "foo.h"
 
int foo()
{
  return 1;
}

So, this is the ACTUAL function, or, more technically correct, the function IMPLEMENTATION. When the linker comes along after the compiler (as long as this file is in your project), it sees that this is the function you were talking about in your file "misc.cpp", and makes it point here and it all works out nicely.

So what? Why do I care?
For the reasons outlined above. Basically, it's all complicated, but having function IMPLEMENTATIONS in header files is always a bad idea unless they're very small AND inline (meaning the preprocessor replaces them like macros anyway). Otherwise, you end up with messy code, huge header files, long compile times, etc.

In fact, if you look in any files you're including (right-click your line #include <SDL.h> and choose to open it in Code::Blocks), you'll see a bunch of function declarations. No implementations. Where are these functions actually?
This is another point of having headers vs not: Code abstraction. You shouldn't know or care how SDL loads images. You just want to call IMG_Load() and have it work out nicely. If you open SDL_image.h, you'll see the following line:
extern DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file);
So where's the function? This is just the declaration, which is a cucumber of a lot easier to look at. The answer to where this function actually is lies in one of the linker settings in your Code::Blocks project:
-lSDL_image
This tells the linker (in this case) that the function IMG_Load() will actually not be in any .cpp file at all. It'll be found at runtime in the same folder as the program (I'm simplifying things slightly here, but you get the point) in a file called SDL_image.dll . DLL, by the way, stands for "Dynamically Linked Library", which means that when the program wants to call IMG_Load(), it'll stop and look in "SDL_image.dll" for the function.

Am I making sense? If so, nod your head mechanically and say "Yes, master..." Tongue

But hopefully you understand what I'm saying. Header files should only include function declarations, never implementations. Trust me, it'll save you a cucumber of a lot of heartache later if you follow this convention.

Joined: 07/08/2011

Ah, yep. True, but I don't want to redo everything. Tongue

If you do that for me, it'd be great.

EDIT: I'm just being lazy. I might do this sometime in the future, but I'm not really interested now.

Joined: 09/01/2009

Hee, hee.
It's not hard. Send me code and I'll do it.

Joined: 07/08/2011

K, I'll reupload when I go to sleep tonight. Since you just ended our (very long) Skype call, I'm assuming you're going to bed soon. Take care of it whenever.

EDIT: Here's what I got done tonight:

I'm actually not done for the night yet. I'll upload in a bit.

EDIT2: Here is the latest code. If you could also allow it to compile on Linux as well that would be amazing. Honestly, I have no idea what I could do to help for the Linux port.

EDIT3: Oh, forgot about #include <windows.h> Tongue

Joined: 09/01/2009

And gah, running into the same problems I'm having with global variables being included in more than one file... and I honestly don't know if the way I used to get out of it is a good idea or not...

Joined: 08/06/2010

Default Solution: Define them only in the CPP file they're used in. Move all your code to the main file. Problem solved. Wink

Simple solution: use preprocessor directives to only define it once, then use "extern" to access it in CPP files.

Complicated solution: Link it to a file for global variables. GlobalVars.cpp or something.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 07/08/2011

I like the Complicated Solution. Tongue

EDIT: I love how that video is randomly exactly 1:00 long and all the related videos have something to do with Miley Cyrus. Tongue

Joined: 09/01/2009

Ah, ok. I've been using the "simple solution" myself; just wasn't sure how technically good of a programming practice it was. But come to think of it, global variables aren't technically good programming practice anyway, so who cares?

Joined: 07/08/2011

Actually the simple solution is what I used when I wasn't stuffing everything in headers. Tongue

Joined: 09/01/2009

I'll be honest; I'm surprised the code even compiles. You aren't #include'ing anything in some of the headers, and using SDL stuff, and not even any compiler warnings. Me very confused.

Joined: 08/06/2010

For me, SDL always says "Undefined Reference to SDL\SDL.h". Could I borrow your computer? Tongue

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 07/08/2011

MOM, I never #include anything more than once, and they're all #included in main.cpp. It compiles the headers one by one going down, so every header listed that uses another header's variables just has to be lower on the list.

AP, that may just be your compiler. I've never gotten that error, even on my netbook. What IDE do you use?

Joined: 08/06/2010

MSYS with G++ and NOTEPAD++. Nothing else, really.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 07/08/2011

Oh, that's alright, I guess, but it seems you might just have a bad binary of SDL. Maybe check for new versions?

Joined: 09/01/2009

Nonononono, nothing like that.

The compiler just has to know where to look for the said SDL.h. In Windows machines, generally you just use #include <SDL.h>. It depends on where you installed the SDL SDK, which some compilers have automatically and some don't. If worst comes to worst, you can download the headers from SDL's website and make your compiler point to them manually. But all you should have to do is fiddle with your compiler settings.

In Linux, btw, all you have to do is "sudo apt-get install libsdl1.2-dev" and you compiler already knows where to look. Wink Linux is a lot easier when it comes to compiling programs. A lot faster at compiling, too.

Joined: 07/08/2011

I had to download them from the website. Tongue I assumed he did the same. I put them all in a 3include folder with my project (for 3rd-party libraries and whatnot) to make sure anybody with a basic installation of Code::Blocks would be able to compile.

If you're having trouble with SDL, just download Code::Blocks and use my Project File and wipe the contents. The project is already linked to SDL and everything. The library's headers are included.

Joined: 12/23/2010

*doesn't read half of the above*

I'll stick to reading about AS3 for now Tongue

Joined: 07/08/2011

Still waiting for MOM to post updated code. Tongue

Joined: 02/20/2011

hey, can you post the link to the engine? i'll need it for my new hard drive i'm getting.

-_-

Joined: 07/08/2011

My link is http://files.redthegreen.com/Player.zip

In the Debug folder there is an executable. If you press F3 then N in-game, you will be able to move the rectangle with the arrows. Tongue

Joined: 07/08/2011

I'm working on the conversion myself, actually. A lot of code has to be rewritten. I now know my original way wasn't bad, but it wasn't what C++ was made for. Using implementation files, I have to find a better way then just having loads of global variables.