Jump to content

  • Log In with Google      Sign In   
  • Create Account


Needing some quick tips on how to organize my code


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
20 replies to this topic

#1 Master thief   Members   -  Reputation: 246

Like
2Likes
Like

Posted 15 March 2014 - 04:37 PM

I've been learning C++ from a book lately and I've been making something of a console game/thingy, and a map editor for it... Whatever it is I'm just coding and it's being fun and interesting, but I've coded it all in one file, both because I wasn't expecting to get so far with it, and because I don't know any better. At some point I moved all the declarations into a header file to make it easier to tweak things without as much hassle, but it's still being a huge hassle, it's becoming too much to cope with. I'm well over 2000 lines of code (on the map editor alone, including comments and garbage), and I'm finding it too confusing. An example of a side effect I found was that I was assigning values to the same variable from three different functions during the initialization. But I'm finding it hard to detect and fix stuff like this in all of this mess.

 

So I need to separate my code into more files, but I haven't learned anything about classes or even header files yet. I "know" what they are and what they're for, but I can't make them on my own yet. So what I need is a quick (and maybe dirty) way to just break up the code and make it bearable, because if I stop working on it I'll eventually lose motivation to keep learning. It doesn't matter if it's a cheap thing to do, the project isn't important, it's just a way to get my hands dirty and learn from mistakes. Like my father said once, analogously, your first car is for you to break.

 

So if anyone could give me some hints or thoughts on how to go about separating the code into more .cpp or .h files I'd really appreciate it. My biggest problem is with avoiding calling the same header file from several files, I think. But I also feel confused on things like, should I just create header files, should I just create cpp files, should I create both as needed, and how do I determine if they're needed, and how exactly do I make the code from one file interact with the code from the other...

 

Any help is greatly appreciated. Thanks.


Edited by Master thief, 15 March 2014 - 04:39 PM.


Sponsor:

#2 BHXSpecter   Members   -  Reputation: 1522

Like
5Likes
Like

Posted 15 March 2014 - 05:44 PM

I'm sorry, I don't know if this will help, but I found it a while back and thought it was an interesting article about C++ Project Structure. http://hiltmon.com/blog/2013/07/03/a-simple-c-plus-plus-project-structure/


"Through vengence I was born.Through war I was trained.Through love I was found. Through death I was released. Through release I was given a purpose."


#3 RnaodmBiT   Members   -  Reputation: 626

Like
8Likes
Like

Posted 15 March 2014 - 05:55 PM

Quite simply the best way (both short and long term) will be to learn the basics of classes and how to use them. They are not very complicated, you can probably learn the basics in a day or two. The key thing about classes is that generally you write them so that they are responsible for doing one single task. I.e. a file parser or graphics controller. You mentioned that you were having trouble keeping track of which variables were being used where and this is another example of what makes classes helpful is that nothing else can touch a classes local variable unless you let them which means that only that instance of the class can read/write it saving lots of confusion later on.

 

-BiT



#4 dmatter   Crossbones+   -  Reputation: 3046

Like
7Likes
Like

Posted 15 March 2014 - 06:03 PM


So if anyone could give me some hints or thoughts on how to go about separating the code into more .cpp or .h files I'd really appreciate it.

You might start with identifying related bits of functionality (e.g. graphics, ui, file IO, etc) and moving them out to their own files.

 

My biggest problem is with avoiding calling the same header file from several files, I think.

That's not an issue, there's no reason to avoid calling the same header multiple times. You just have to make sure that it's guarded (either with #pragma once or pre-processor guards).

 

But I also feel confused on things like, should I just create header files, should I just create cpp files, should I create both as needed, and how do I determine if they're needed

Source (.cpp) files usually contain actual code.

Header (.h or .hpp) files usually contain declarations.

 

A source file usually has a corresponding header file, to declare all its functions/classes/whatever. You almost never have a source file by itself (A notable exception to this rule is that you might well not create a header that corresponds to the source file containing the main() function).

 

Occasionally you have a header by itself (without a source file), if you only need some declarations, or are dealing with inline code only, or are dealing with templates.

 

 

and how exactly do I make the code from one file interact with the code from the other...

Your header and source files can #include other header files (the declarations of functions, etc). That way they gain access to that functionality. The functionality is implemented in other source files. But you never ever #include a source file. The 'top level' source file would be the one with your main() function it it.

 

Example:

 

Graphics.h - Declares functions for doing graphical stuff

Graphics.cpp - Will include Graphics.h and will actually have code to implement those functions/classes.

 

MapEditor.h - Declares functions for doing map-editory stuff

MapEditor.cpp - Will include MapEditor.h and will implement those functions. May also include Graphics.h to access the graphicsy functions (or it might be that some of these things were also needed in MapEditor.h in which case the header would include Graphics.h and then the source file will gain it just by including MapEditor.h).

 

Main.cpp - Defines your main() function, includes MapEditor.h to gain access to the map-editory stuff.



#5 dejaime   Crossbones+   -  Reputation: 4014

Like
6Likes
Like

Posted 15 March 2014 - 06:10 PM

My personal experience was similar to yours. I started programming with really basic C, that could all fit in one implementation file or, at most, the implementation and a header. To step forward, I had a tough time, since I didn't really know what the problem was (what exactly I wasn't grasping).

 

I started to study C++ and Object Orientation, and that gave me an overview of modeling and architecture. I was then able to separate my code better, so I did with the files.

 

But the only time I really learned to structure my files was when I started to use an IDE. I had been using notepad++ and a command line compiler. I started to use the IDE templated file creation features to create files with some pre-defined code (such as the basic class structure and this kind of stuff); it forced me into a good style, somehow.

 

So, study more, it will suddenly become clearer. It is kind of like learning a new spoken language; one day you can't understand anything you're hearing, but the next one you can't believe you understand almost everything.


Edited by dejaime, 15 March 2014 - 06:12 PM.


#6 Vortez   Crossbones+   -  Reputation: 2698

Like
4Likes
Like

Posted 15 March 2014 - 06:15 PM

A class is just a group of functions and variables tie together to acheive a specific goal if you think about it. Nothing complicated about that. For example, i often create an OpenGL class to handle the graphic side of an application or game, this class is responsible for everything opengl related and nothing more. It usually have functions like InitOpenGL(), ShutdownOpenGL(), LoadTexture() and FreeTexture(), Render() and Update() ect. For small project you usually don't need more than a few, or even none, but as the project grow larger it's usually best to start splitting things up into classes.

 

Take a look at this, that's my main code library i've built over the years, don't look at the code but focus on the files names, every one does a specific tasks. The code in .h files are a little weird since they was initially used in multiples languages as a dll, hence the weird bits, but you get the idea. Also a lot of them aren't used frequently (or at all) but some of them are really usefull (especially FileIO and RawBuffer).


Edited by Vortez, 15 March 2014 - 06:23 PM.


#7 Master thief   Members   -  Reputation: 246

Like
1Likes
Like

Posted 15 March 2014 - 07:21 PM

Thanks everyone for the responses. It's being quite insightful. I'm going to try some stuff tomorrow.

I've also just found an article that may also be helpful, though not today. smile.png

 

@Vortez, about the classes, I have... some degree of awareness on how to make them and how to use them, since I was starting to use them in actionscript 2 a few years ago before I stopped coding then. But there's two problems: 1-  I always just create a bunch of files and end up staring at them indecisively, due to not quite having an idea where to put what, and 2- I'm not yet familiar with c++'s syntax for classes and their baggage. I skipped a bit in the book I'm reading to quickly get to pointers, but I'm intending to get back to what I skipped (structs, enums, and more on strings). I don't want to rush it.

 

@dejaime, well... I'm extremely (really) picky when it comes to colors. I can't stand writing code in a white background, and I like to just get my hands dirty when I'm learning something. All the IDEs I tried (well, CB, VC and DC, don't know any others), kind of got in the way of it. There's always something that needs to be set or some intricacy that needs to be understood (i.e., project templates, MS's main() arguments), or otherwise something that doesn't work for very specific reasons. I've been away from C++ for years because of this. Also, they clutter my hard drive with project folders (VS is particularly unorganized, it mixes projects from all apps in one folder by default) when all I want at this point is a source file to experiment with. When learning the basics, I need a basic setup to get right down to it and keep me focused and without obstacles.

 

To that end I'm using Sublime Text for now, which seems to work well so far, though I see times where an IDE would be beneficial. But I find that those apps aren't much good at replicating the level of customization from ST, sadly. ST is great in it's keyword highlighting and dark background, it makes me feel extremely comfortable. So, at least for now I'm stuck with it. That said, I'm still using CB to, for example, compile tutorials I'm following on SDL. I code them in ST and compile them in CB. I still think it's too early for me to be delving into their distractions. I rather be reading the book instead of losing time with the IDEs.

 

 

EDIT: By the way, should, or could, variable declarations go on (non-class) header files too?


Edited by Master thief, 15 March 2014 - 07:25 PM.


#8 dejaime   Crossbones+   -  Reputation: 4014

Like
6Likes
Like

Posted 15 March 2014 - 08:39 PM


I'm extremely (really) picky when it comes to colors. I can't stand writing code in a white background

We're two then! I am lightly photophobic, and I use a modified version of the C::B theme called Son of Oblivion (a Son of Obsidian port to C::B). I also program with only around 15% brightness on my LED monitor (40% during the day, but I do the huge majority of my coding at night)...

I also search the web with blackle.com, feels better (I don't know if it really saves any energy in LED monitors)

(GD.net is too white, but we can't have everything, can we? biggrin.png )

 

I assure you, the thing that helped me the most was actually studying Object Orientation. It helped clear where one part of the code ends and the other starts, so it helps define/choose the files I needed/wanted.

But It is a fact that using IDEs helped me further in learning some more. Still, I know some guys to what it did the opposite and made them go on brainless file creation rampages on every project they started!

 

I also use IDEs for their color schemes, even though Sublime Text is said to be the best here. But as IDEs have a world of more features for C++ development, I can't go with a fancy Text Editor over an Integrated Environment; or else, I'd need to write loads of build scripts that wouldn't be necessary with a full fledged IDE).

I like how C::B handles its highlighting color schemes, maybe I am just used to it...

It also has some neat features for C++, such as active/inactive code highlighting (to name one):

 

C_B.png

 

Comment the #define

 

C_B.png

 

About variable declarations, they surely can go on header files. If the variables are global, declaring them on the header will be enough, but if they are "class globals" (static class variables) you need to put them in the class definition and then declare them in the .cpp file.


Edited by dejaime, 16 March 2014 - 09:48 AM.


#9 tanzanite7   Members   -  Reputation: 1247

Like
1Likes
Like

Posted 15 March 2014 - 09:38 PM

@dejaime, well... I'm extremely (really) picky when it comes to colors. I can't stand writing code in a white background, and I like to just get my hands dirty when I'm learning something. All the IDEs I tried (well, CB, VC and DC, don't know any others), kind of got in the way of it. There's always something that needs to be set or some intricacy that needs to be understood (i.e., project templates, MS's main() arguments), or otherwise something that doesn't work for very specific reasons. I've been away from C++ for years because of this. Also, they clutter my hard drive with project folders (VS is particularly unorganized, it mixes projects from all apps in one folder by default) when all I want at this point is a source file to experiment with. When learning the basics, I need a basic setup to get right down to it and keep me focused and without obstacles.

I would recommend you to reconsider - a proper ide (which Sublime Text at least does not seem to be from my cursory examination) is an invaluable assistance, especially if you are relatively new. And even more so when you are not new and your projects grow to anything above trivial.

I would recommend Visual Studio 2013 (for desktops, express edition - ie. free). Its coloring scheme is highly customizable - comes even with a "dark" theme as a preset option (or a starting point for your own customizations).

Syntax coloring options include separation of: global/local/member/static-member variables, namespaces/classes/enums/types, static/non-static member functions, macros etc...

Intellisense can also automatically pick up and mark with red-wiggles most errors without the need to compile and its hover-tooltips, as you will see below, are quite informative.

An example of my, slightly altered from default, coloring (i prefer white - used to prefer dark when i first started out ~20y ago):

http://postimg.org/image/r0ckj03i7/

edit: Uh, what, why the downvote? That makes no sense.

Edited by tanzanite7, 15 March 2014 - 09:58 PM.


#10 tanzanite7   Members   -  Reputation: 1247

Like
1Likes
Like

Posted 15 March 2014 - 09:56 PM

I like how C::B handles its highlighting color schemes, maybe I am just used to it...
It also has some neat features for C++, such as active/inactive code highlighting (to name one):

Just used to it tongue.png.

I have never used Code::Blocks myself - does it have comparable highlighting options to VS (look my pic in previous post [VS has quite a lot of type separation too - but i have colored almost all of them with the same color])?

The active/inactive code highlighting is obviously present in VS too - and its presence in CB hints that it too might have some Intellisense-esque capabilities, hence the Question.

Edited by tanzanite7, 15 March 2014 - 10:00 PM.


#11 BHXSpecter   Members   -  Reputation: 1522

Like
1Likes
Like

Posted 16 March 2014 - 12:31 AM

Depending on the project (ie single file or multiple) I use Geany and invert colors so the background is black and the Sons of Oblivion theme in C::B if I'm doing a large project. It isn't so much that I have issues with white backgrounds (and in fact I get nostalgic and change to them once in a while), but rather at night the dark IDE doesn't put off so much light so I don't wake my son while I'm programming. 


"Through vengence I was born.Through war I was trained.Through love I was found. Through death I was released. Through release I was given a purpose."


#12 Master thief   Members   -  Reputation: 246

Like
1Likes
Like

Posted 16 March 2014 - 09:09 AM

@dejaime, from reading that article, which I noticed is quite class heavy (which I guess was to be expected), I think I have to admit that separating code and creating classes seem to be two things that don't really go too well without each other. But classes are 6 chapters away in the book.... I guess I'll make a detour and see what I can manage to do.

 

I kind of noticed CB had themes, but I didn't feel like losing time with it. I may still try some sometime. One thing I noticed about CB is that it allows you to create a list of "user keywords", which probably helps if I want to make it look more similar to ST. But this is something I don't want to get distracted with right now. It's been two days since I last messed up with my code, and it was always distractions that made me end up stopping in the past...

 

@tanzanite7, sublime text isn't a "proper IDE", it's just a proper generalized text editor with lots of potential to be a decent coding environment. Much like TextMate (I think) and Vim and another one I can't remember. But of course it never reaches the same level of functionalities of an IDE that's made specifically for a language. I will probably want to use the debugger at some point.


Edited by Master thief, 16 March 2014 - 10:07 AM.


#13 Master thief   Members   -  Reputation: 246

Like
1Likes
Like

Posted 16 March 2014 - 03:13 PM

I started placing stuff into a new file just to see if I could make sense of it. This is what I could gather so far, but I have conflicting ideas here:
 
I don't know if I should ask the GraphicsM class to draw the map on the buffer, or if that class should allow other classes to draw on it. Or maybe I'm missing something else that might solve my dilema. Or maybe I'm simply doing it all wrong. smile.png

class GraphicsManager
{
	private:
		char tempBuffer[18][35]; 

	public:
		void drawOnBuffer();   // draw something on the buffer?
		void blit();
		void clearBuffer();
		void paintBackground(int symbol);    // paints background with the specified ascii symbol
};
class Map
{
	private:
		int map[18][35];  // the object is given a map from an output source (file), or from user interface (map editing)
		int tileset[2][7];  // class stores active tileset here

	public:
		drawMap();  // draw the map to the buffer?   // or maybe ask the graphics manager to do it instead?
		drawTileset(); // draw the tileset to the buffer?
};

I still haven't read about constructors and such, so don't mind the lack of anything that may be lacking. This is not even the real thing, it's just me trying to understand how to put it together from the code I already have and from what I already learned (which isn't much).


Edited by Master thief, 16 March 2014 - 03:18 PM.


#14 Vortez   Crossbones+   -  Reputation: 2698

Like
2Likes
Like

Posted 16 March 2014 - 06:59 PM

What i would do is create the Map class and let it handle the drawing, then i might add it to the GraphicManager later on, and access it from there.

The truth is, there is no perfect answer to this, but the map class should be responsible to draw the map (and do other map related stuffs) and nothing more.

 

Blit? what api are you using to draw your stuff? I generally just let a function called RenderScene() to do all the rendering to be honest, which call other classes or functions to draw the different parts of the scene.

 

Here's a small sample of my main drawing routine of an old game of mine

			// Disable lightning + depth test
			glDisable(GL_LIGHTING);
			glDisable(GL_DEPTH_TEST);

			// Draw the sky
			RenderSkyDome();
			RenderSkyPlane();

			// Enable lightning + depth test
			glEnable(GL_LIGHTING);
			glEnable(GL_DEPTH_TEST); 

			// Draw solid objects
			RenderTerrain(UseLodModels());
			RenderRocks();
			RenderColumn();
			// Render chess board
			RenderChessBoard();
			// Render chess pieces
			RenderReflectedPcx(UseLodModels());
			RenderChessPieces(UseLodModels());
			RenderChessPiecesNextMoves(UseLodModels());
			// Draw transparent objects
			RenderWater(UseLodModels());
		
			// Check the sun visibility status
			pCam->SunVisStatus = DoLensFlareTests(pCam);

			// Generate the shadows effects
			if(Menus.Options.ShowShadows){
				if(Menus.Options.ShadowMode == SHADOW_SIMPLE){
					CastPlanarShadow();
				} else {
					Cast3DShadows(pCam);
				}
			}

This is just to give you an idea. As you can see, i havent splitted objects into class, i just wrote a function to handle each of them, but it's an old game, today i might do this differently, but this was the simplest solution i though of at the time. I do however usually use a menu class to draw menu related stuff (not shown here).

 

Maybe you should start writting it in a more functionnal way, then refactor it later into classes, since you look a bit lost on what you are trying to achieve.

OOP is great, but it's a bit hard to get everything right the first time to be honest.


Edited by Vortez, 16 March 2014 - 07:17 PM.


#15 Master thief   Members   -  Reputation: 246

Like
1Likes
Like

Posted 16 March 2014 - 08:21 PM

No APIs, just pure c++ and the console. I'm not sure if it matters much but since I'm making it purely on the windows console, the "rendering" may be a little different. Still, I'm doing something comparable to double buffering, where I'm drawing everything to an array, clear the screen, and then draw the whole array on the screen. That's why I named that function blit(), it was just the first thing that came to mind when I needed a name for it. Same with one I have called doThingsWithInput(). smile.png

 

Here's the source code, by the way. If it matters.

 

The way I'm "rendering" it has it's caveats, is kind of slow and forced me to use system calls (for CLS - and this is because I didn't want to have the whole history of the console above, and also because the scrolling seemed worse to watch) for lack of better options. I made a post on TIG about it but no one seemed to have any better solutions that didn't involve external libraries. Still, I'm not really worried about that, I'm more worried about progressing. I'll do something better with SDL one of these days. I'm also enjoying the challenge of getting around the limitations of the console.

 

So, I don't know, since everything that needs to be drawn is drawn on that array before it gets drawn on the screen, either everything draws in it, or everything tells the class what to draw in it... I suppose those are the options, but I'm not sure which to choose. But if I choose the latter, I'm not sure how to make that class grasp every other class's needs.

 

So the first option, which is basically what you're saying, seems easier.


Edited by Master thief, 16 March 2014 - 08:25 PM.


#16 DareDeveloper   GDNet+   -  Reputation: 938

Like
4Likes
Like

Posted 17 March 2014 - 01:38 AM

You have the right idea ... isolating the thing you are working on rather than fighting several battles at once.

But I guess your project might be too ambitious.

Refactoring existing code is hard as hell. I think you would need a mentor who can explain what you did right and what problems you might run into with a chosen approach.

 

I would isolate practicing game logic algorithms (and data structures for those) on the one hand and managing complexity on the other.

To get better at adding complexity I would follow the suggested path here: going through games like Tetris, Snake etc.

You don't need to abandon your project completely, but you need to think about refactoring the right way and that takes time.

 

You can see how far you get with a common sense approach - making incremental changes that you feel confident about.

Read some articles about principles like DRY (Don't Repeat Yourself) and SoC (Separation of Concerns) ...

but be aware that there can be no simple answer here that explains it all.

 

You can read about UML class diagrams. There might be articles that help with thinking about structuring software the right way.


Given enough eyeballs, all mysteries are shallow.

ProcGames.com


#17 Master thief   Members   -  Reputation: 246

Like
1Likes
Like

Posted 17 March 2014 - 03:05 AM

I read (vaguely) something about complexity somewhere but I can't recall where... Not sure if it was in the book I'm reading. Which is C++ Primer, by the way.

My only fear at this point - 5 chapters away from classes and not yet much more versed in anything that I wasn't before - would actually be to end up repeating myself, even if I was trying not to, since if I delve into another project the only things I'll do better right now are maybe just to make use of a few more I/O functions and a few tricks I learned about strings.

Or maybe, since the map editor is pretty much finished (except for one slightly important functionality that I couldn't implement due to the messy code (and loading maps)), I might get back to the game itself and start applying whatever else I learn in the next days.

But maybe I'm getting ahead of myself in my thinking. I'll do some reading as you suggested. Thanks.

Edited by Master thief, 17 March 2014 - 03:07 AM.


#18 Master thief   Members   -  Reputation: 246

Like
1Likes
Like

Posted 22 March 2014 - 02:53 PM

One question, from what I understand from what I've been reading, vectors are great to be used for, say, a player or a room's inventory. Would they be just as good for maps? Considering that the maps as I'm using them, are just an array of ints, I suppose at first they might be, but then the maps are sort of constant (the number of elements never changes in a map, an index's value can change (i.e, closed door (visible)/open door (not visible), but that's about it).

If so then I wonder if I have any use for arrays at all for what I'm doing.

Edited by Master thief, 22 March 2014 - 02:58 PM.


#19 BHXSpecter   Members   -  Reputation: 1522

Like
1Likes
Like

Posted 22 March 2014 - 06:24 PM

I think (and I could be wrong) the general rule is that anything you use an array for, you can use a vector for. Obviously, the first major trade off is you can now make maps any size (so you can make maps that get larger as the player goes on) and resize it per level. This would be a plus in puzzle games as you could start small and get bigger as the player plays and learns more, for example. 


Edited by BHXSpecter, 22 March 2014 - 06:27 PM.

"Through vengence I was born.Through war I was trained.Through love I was found. Through death I was released. Through release I was given a purpose."


#20 Master thief   Members   -  Reputation: 246

Like
0Likes
Like

Posted 22 March 2014 - 07:15 PM

I've planned the maps to be of a fixed size, where you can "travel" from one map to the other in an open-world-ish kind of way. But who knows I may change my mind given the opportunity...




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS