Properly planning a game and its structure

Started by
19 comments, last by Eck 10 years, 3 months ago

You really want to be making commits of each feature and/or refactor, so that you can step through the history change-by-change to analyse when bugs were introduced.

Thats what I meant(I guess I was a little unclear) I commit nightly. Usually I am able to knock out at least one small feature a day(2-3 hours of work) so nighly committing is usually sufficient.

Advertisement

One thing i did when rewriting one of my application is to write a coupe of interfaces before actually starting coding it. I dunno exactly why but this helped tremendously.

Here's an example of one of them:


class IRemotePC {
public:
        virtual void Reset() = 0;
        virtual void ProcessRemotePCMessages(MsgHeaderStruct *pMsgHeader, BYTE *pMsgData){}
        
        virtual bool InitOpenGL(){return false;}
        virtual void ShutdownOpenGL(){}
        virtual void RenderTexture(){}
        virtual void ClearScreen(){}

        virtual void WaitForScreenShotThreadToFinish(){}
};

class IRemotePCServer : public IRemotePC {
public:
        virtual void SetLoginInfo(char *pUserName, char *pPassword) = 0;
        virtual void OnLoginRequest(LoginInfoStruct *pInfo) = 0;
        virtual void SendLoginResult(LoginResults Results) = 0;
        
        virtual void OnScreenshotRequest(ScrFormat *pFormat) = 0;
        virtual void SendScreenshot(CRawBuffer *pBuffer) = 0;

        virtual void OnMouseMsg(CMouseInputMsgStruct* pMsg) = 0;
        virtual void OnKeyboardMsg(CKeyboardInputMsgStruct* pMsg) = 0;
};

class IRemotePCClient : public IRemotePC {
public:
        virtual void SendLoginRequest(char *pUserName, char *pPassword) = 0;
        virtual void OnLoginResult(LoginResultStruct* pLoginResult) = 0;
        
        virtual void SendScreenshotRequest() = 0;
        virtual void OnScreenshotMsg(MsgHeaderStruct *pMsgHeader, BYTE *pMsgData) = 0;

        virtual void SendMouseMsg(CMouseInputMsgStruct *mm) = 0;
        virtual void SendKeyboardMsg(CKeyboardInputMsgStruct *km) = 0;
};

At first the functions arguments where empty, then got filled as i was adding more code. This helped me a lot to know where i was going.

Hi,

Properly planning a game takes time to learn on your own. It can be one of those things that a programmer has to experience to understand. Unless you have worked for a large company who would obviously have a structure in place on how a game is designed. For an Indie developer this can seem complicated once your game code starts to get over a few hundred lines of code. What I've learned from my game design attempts is that you have to try to separate each part of the game into sections. Try to keep different areas of your game code organized so that if you need to update one area you can do it easily. It's kind of like writing a book. You have to learn how to put it together so that it's organized and well written. Other programmers always say to make sure to put lots of notes in your code so that if someone else needs to update it later they can easily get an understanding how your game code works. This can also help yourself when you need to come back and make changes.

"seeing that I was headed towards coding myself into a corner."

How do you think you were coding into a corner?

Modularity is the one word that springs to mind.

Rather than writing a load of spaghetti code and then throwing it all away, take something away from each project. A prime example - I started writing a clicker-style game the other week but I've had to scrap it now I've started work again (alongside studying for my final year it just wasn't really viable). That didn't mean the hours spent working on it have amounted to nothing - I took away a static Utilities class that did simple calculations (kind of a math library I guess), a FontManager class, a LayoutManager class (for calculating the required scaling of text/an image to fit in a certain area) and also a ButtonObject class that eventually grew to be quite large. No doubt I can use these elsewhere because they're MODULAR - any game that uses fonts can use the font manager. Any game that uses button sprites can use the ButtonObject class and any game I write (at least in 2D) can use the LayoutManager to be easily portable to multiple screen resolutions. Same for the Utilities class I guess! From my next project when I get some free time I'll probably add some extras like a resource manager, an audio manager etc..

As others have said, there's no shame in failing again and again, it's all practice and learning. Instead of beating yourself up over failing, why not look at what you took away from/learnt in the project? In reverse, why not start a project with the intention of learning? Anything that comes out of it can be seen as a bonus ;)

So the questions:

1) Modularity.
2) Hmm probably not. Your standard loop is, as you appear to know, GetInput, Process, Render (maybe you use diff. words, it doesn't matter). These steps will be different for every program, although what they do is generally the same (as their name suggests). You're touching on game engines by suggesting modularity of these components which is a whole 'nother ball park.

Hope this helps :)

BSc Computer Games Programming (De Montfort University) Graduate

Worked on Angry Birds Go! at Exient Ltd

Co-founder of Stormburst Studios

lol, keep doing what your doing, in ten years, you'll be where I'm at. Hopefully a hell of a lot better though.

You'll find out eventually if you code because you love it or if your chasing a rabbit.

I got on a pathfinding kick once that lasted for 6 months. Tons of unusable code, unreadable notes. In the end I did produce something that I still implement in any game I make using path finding though, regardless of which language I use.

The moral of my little verbal toilet spackle? The majority of the stuff I have made in the past 10 years is useless, but when I look at the steps and problems I overcame getting past each point, each one is an invaluable lesson!

Keep going or get into paper mache' little doggies with 1 jelly bean inside. (<---- my backup plan)

The things that has worked for me are twofold. Firstly, I make sure to write my code in a way that is modular and easy to change and refactor. By this I mean that, well, code is always changing. You'll have to rewrite classes, separate classes into multiple classes and interfaces, refactor code, etc. In the end, you need to get used to the code changing. When you get to that point, you're in business -- having to rewrite the interface of a class or refactor a single giant class into many modular pieces becomes easy (especially with copy and paste!). If the project actually is useless, take it as a learning experience. I tend to program in units, so I write crap code while I work out my idea, and then copy/paste/rewrite my production code in the actual engine. Keep the code for nostalgia/as notes, but you can move on from those little tests and know you learned a lot from it!

Secondly, I've also noticed that I can work a problem a few ways -- this is what works for me. I tend to start at the outermost layer and figure out the interface I want for the class. From there I'll then begin unit testing each method I write for the class, but making sure I meet the interface I want for the class so it all looks nice to the user/works to my software design/engineering needs. Again, things change, and I refactor code all the time, but with a little planning on the interactions and outside interface of the class, it works out nicely.

Modularity also helps, as well as experience over time. I've written the same engine in a couple different languages, multiple times in each language. Each time I get more tired of writing the same code, so I got used to changing classes and isolating dependencies and BAM, I got a nice way of furthering the engine of the game without having to keep starting over or scrapping my code. As people have said above, pencil/pen and paper always solves your problems. UML has helped me a bit laying out interactions between classes. Try different things, and with time you'll be well and better off :)

You should use modular programming, that is the technical term, there are a couple of tutorials on it on YouTube. Also, write pseudocode.

I made something I call a customizable game script. It's a template for making a game that has all the essential parts of a game ready to go. I also made it flexible (all my functions use arguments that can be changes outside of the functions. I also name my variables and functions with non-specific names (can be changed to specific names per game.)
Here is one of them:

They call me the Tutorial Doctor.

Reading the Book "Clean Code" helped me understand how to avoid making a "big ball of mud", and creating "Technical Debt"

Big Ball of Mud - http://en.wikipedia.org/wiki/Big_ball_of_mud

Technical Debt - http://en.wikipedia.org/wiki/Technical_debt

My Projects: - www.repulse.com

"seeing that I was headed towards coding myself into a corner."

How do you think you were coding into a corner?

It was because I felt overwhelmed by the code I was writing and it was indeed a big digital bowl of spaghetti code. Although I did have certain parts of the code in separate classes, there still wasn't much modularity. So when a bug pops up I spend all day swimming through the code in order to find it. It only became tougher the more code I wrote. I'll need to do a bit more modularity moving forward. But the previous comments are all very helpful. Coding does feel somewhat of an iterative learning process. It helps to know that I'm not just missing some big picture. Thank you all for the helpful input.

This topic is closed to new replies.

Advertisement