Programming best (and worst) practices

0 favourites
From the Asset Store
Best car suspension with spring effect and very cool terrain generation.
  • Hi all,

    What are your tips and best practices for creating C2 "code"?

    I'm a game designer and not by any means a programmer. I've just decided to restart my strategy game project as my "code" is too complicated and messy and it's not all working as I want it to. So I'm making a clean file and rebuilding. It seems like a good time to take stock of what I've learned.

    Best practices

    • Write a clear design document (e.g. in word)
    • Start small and simple (e.g. with small arrays)
    • Test often (e.g. show array variables in a text box on screen to figure out what is / isn't working)
    • Put complicated or repeated code into functions and call these from the main body of the code (less messy and less redundancy)
    • Save a new version of the project often so you can go back if you mess something up
    • Give variables a descriptive name
    • Add lots of comments
    • Break down functions to keep them simple (rather have a lot of simple ones than a few complicated ones)
    • I made a spreadsheet to work out where to place elements on screen (it calculates the midpoints)

    Worst practices

    • Build complicated functions (e.g. nested for-loops updating arrays) which then don't work (better to start simple)
    • Resize graphics within C2 (better to create them at the correct size e.g. in paint.net and import them cleanly)

    What do you think? Do you agree with these? What have you learned that we could add to this list?

    Thanks,

    Mike

  • Yup ! Some of mine ... are !

    • Order your events in groups and sub-groups
    • Name the groups by a detailled way (Ex : Player | Jumping )
    • Compact your events in 1 to 2 events fashion by actions ( If possible ; Repeating events is a bad practice )
    • Dump all your objects on a layout so they won't interfere with the main layout
    • To pick the ID of an object ; Give that object an instance variable and set the ID manually ...

    I had more but I forgot ...

    Oh well , hope that helped !

    Cheers !

  • Good practices (all personal opinions):

    -In my opinion, it's best to use a small amount of object types. For example, there's no need to have a 'tree' and 'rock' object if they have an identical function.

    -Don't use a behavior if you don't use all or most of its features. It will be more efficient to code it out manually.

    -Use 'Every X seconds' sparingly. Timer variables are more easily controlled.

    -Have your layer setup fleshed out before making the first level of a game with many layouts. It's incredibly boring to mirror layer changes across 50+ levels. (@Ashley this seems something the engine could well improve upon.)

    -Put all your code into groups, unless you love scrolling.

    -Resize graphics within C2 to as small a size as possible, otherwise you are wasting RAM.

  • There's not much to add to Whiteclaws and sqiddster lists..

    • I like to have separate things on separate event sheets.

    Event sheet for global variables

    Event sheet for player controls

    Event sheet for game mechanics

    etc

    and include them whenever I need to, for example

    +Turn = human

    + include Human event sheet

  • -Have your layer setup fleshed out before making the first level of a game with many layouts. It's incredibly boring to mirror layer changes across 50+ levels. (@Ashley this seems something the engine could well improve upon.)

    I can't agree with this more. Your UI and controls should be finished before you even think of level design.

    And, yes, I would to see a "duplicate layer" feature.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • As far as I'm concerned, I don't like working with too many layout or event sheet.

    I only duplicate event sheet if a part of my code needs to be reused in more than one event sheet (which rarely happens)

    OR

    If I'm making a series and I have a common part and a variable part. This way I can use .bat files to always keep my common part in sync with the series (of course using the save as project for everything)

    I use groups where most people use tonnes of event sheet. To organize code.

    And sometimes, because it's easier, I use activation/deactivation. But I don't like it too much since I'm never quite sure I won't rename a group and then break these actions at some point.

    Anyway the advantage of groups over event sheets to me, is that you can do

    - a rightclick > collapse all to have a better view of all the part of your code and quickly access them.

    - you can be more descriptive with a group (like what it does and then in description I often put a list of the function definede inside that group)

          - it's easier to read than tab names when there's a lot of them

          - it's also easier to do a search on all your events if you only have to search one event sheet. For instance, if I want to see where a function is called (because I want to add or remove an argument), I just type the name of this function in the search bar and I can quickly access all the references.

    Now as far as code goes:

    • I put everything under functions. This way I always know and control when a part of code is executed and I avoid most problematic ordering issues. The only things I don't use functions for are:

          - things that should happen or be evaluated every ticks

          - things under triggers (on click, on key press, etc) though I often call functions from there like "Button: on click -> Function: Call Button.action() with action an instance variable containing the name of the function to call.

    • I use global variables sparringly. For the same reason. If you modify global variables in two different areas of your game, you have to always keep track of when things happen. It's asking for trouble. Also polluting the global scope is a pain (too much thing in combobox menus)
    • Instead of global variables, I use a lot of static local variable. They behave the same but since they are scoped I'm sure they are modified only inside their limited scope.
    • I avoid like plague what is called "magic numbers". A magic number is any number you use in an expression. There are two reasons I avoid them:

          - first, they doesn't mean anything by themselves. What does 1.73 means? Nothing.

          - Second, they may change during your development. For instance if you have a grid based game and at some point you find out that the size of the grid is wrong, you'll have to change all the expression where the width and height are used.

    • I use constants a lot! Mainly to define most magic numbers. This way I can do Global constant number MY_HEIGHT = 1.73. I even do something like TRUE = 1 and FALSE = 0 and I also name array indexes like X_ = 0 and Y_ = 0 (the underscore is here because I often use x and y as temporary local variables)
    • Constants can be global since they can't be changed. But using local constant can be a good idea since you limit global scope pollution.
    • I always write my function in subevents of the "on function" event this way they collapse more nicely, and I add a little comment on top explaining what argument they take and what they return (if it's not obvious). This way I can forget how they are implemented (abstraction).
    • I use only one "on start of layout" event and I put it on top of the event sheet. Rarely in a group.
    • I agree with squiddster, I try to use as less object types as possible. For instance I use only one Button object and I do what I explained above "Button: on click -> Function: Call button.action()

    I talk more about my practices in my C2 Channel by the way. I'll soon start a RPG series where amongst many other things, I'll show you how I handle the problem described by sqiddster:

    "Have your layer setup fleshed out before making the first level of a game with many layouts. It's incredibly boring to mirror layer changes across 50+ levels. (@Ashley this seems something the engine could well improve upon.)"

    Which is something I try to avoid, it's too hard to anticipate all the layer you'll need, you kind of lock your development too early in my opinion.

    I fell into the "mirror layer changes across 50+ levels" trap.... Never again! Yann2013-02-08 05:16:17

  • Great stuff, Yann! I will very much like to see your solution to the layer problem. I agree very much that it's very difficult to anticipate all the layers you will need.

  • Interesting how you use functions so much, I hardly use them � I should look into it more, it sounds useful.

    The constants/"magic numbers" is a good practice too, I need to do that more often, should make for some quicker editing!

  • Hi all!

    Well there is a practice I commonly use, which is to put variables that manage/affect an object directly inside this object, like a instance variable. Because this way I do not pollute the code, with many variables, and if one object is not needed anymore, I just destroy it and his variables are destroyed too.

  • Now as far as code goes:

    - I put everything under functions. This way I always know and control when a part of code is executed and I avoid most problematic ordering issues.

    Just as an extra little tip on top of this: Namespace your functions. I've been working on a little side-project and decided to do the entire thing in functions. I found using the following setup works really well:

    <img src="https://dl.dropbox.com/u/20830426/goodFunctions.png" border="0" />

    It comes in real handy when you end up with functions doing something really ambiguous like "Setup animations" or "Set death state" and you run into naming conflicts or just scope confusion like "What was this setting a death state on? The enemy? The player?"

  • Hey guys, these are some great tips! Thanks ;) I've started using some of them and it's helping a lot.

  • If you sit down to write you code with a pen and paper, I find the best method is to work with 'states'.

    This is because C2 runs events every tick you need to know what state the program is in at any one time. It just simplifies the workflow.

    I create global static variables with each possible state and a global variable containing the current state. I also use states for individual objects.

    So instead of activating/deactivating groups use states in my opinion.

    Otherwise all the comments above sound good.

  • Kyatric , You should add this to the FAQ or sticky it !

    There's some valuable pratics around here !

  • Yann I agree mostly on everything, but the event sheets vs groups.

    Of course it's just a personal opinion, but I think to event sheets like they were classes in OOP. With this in mind, I put everything that concerns a subject (e.g. "Deck" or "Grid") in the specific event sheet, so I know where to find the function I need.

    Nothing says, of course, you cannot combine the two when the code in the single "class" becomes messy or too long.

  • Jeff Skyrunner

    Interesting comparaison. I tried a bit of Java some month ago, and work a bit with ActionScript and they indeed split every class into files.

    But in that case, OOP is enforced by the language, and you tend to build your application around the concept. Whereas in C2, even if you have OOP concepts driving how C2 works, the event sheet itself doesn't really use those concepts (no encapsulation, no real polymorphism,...).

    As far as I'm concerned, after working on some big projects, I noticed that I was losing tonnes of time looking for pieces of code in all my event sheets.

    And for a practical example: in one of my last project I had a createPolygon function. It was all fine, but at some point I wanted to add an angle parameter. I was a bit unsure, since I didn't remember where I used this function. But I just did a simple search on all my event sheet and voil�.

    If I had split everything in event sheet I probably would have had about 10 of them, and it's super easy to overlook one event sheet amonst 10 while you are searching.

    And finding such bug in my 1005 events would have been a real pain :D

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)