Programming best (and worst) practices

Discussion and feedback on Construct 2

Post » Fri Feb 08, 2013 12:29 am

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
B
7
Posts: 38
Reputation: 476

Post » Fri Feb 08, 2013 12:45 am

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 !
B
34
S
16
G
16
Posts: 2,222
Reputation: 16,564

Post » Fri Feb 08, 2013 2:08 am

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.

B
90
S
30
G
24
Posts: 3,189
Reputation: 32,400

Post » Fri Feb 08, 2013 2:17 am

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
ImageImageImageImage
B
140
S
58
G
36
Posts: 2,547
Reputation: 31,170

Post » Fri Feb 08, 2013 3:04 am

[QUOTE=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.)



[/QUOTE]

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.
B
26
S
8
G
3
Posts: 210
Reputation: 5,973

Post » Fri Feb 08, 2013 5:04 am

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! :DYann2013-02-08 05:16:17
Last edited by Yann on Sun Sep 14, 2014 11:29 am, edited 1 time in total.
B
60
S
22
G
14
Posts: 1,479
Reputation: 16,346

Post » Fri Feb 08, 2013 11:27 am

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.
B
90
S
30
G
24
Posts: 3,189
Reputation: 32,400

Post » Fri Feb 08, 2013 11:45 am

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!
B
134
S
65
G
16
Posts: 1,765
Reputation: 19,188

Post » Fri Feb 08, 2013 1:19 pm

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.

B
90
S
5
G
7
Posts: 164
Reputation: 7,571

Post » Thu Feb 14, 2013 4:01 am

[QUOTE=Yann]
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.[/QUOTE]

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:



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?"
B
24
S
4
G
1
Posts: 244
Reputation: 3,462

Next

Return to Construct 2 General

Who is online

Users browsing this forum: alextro, Mirlas, wrighthill, Yura G and 16 guests