Game Tutorial Performance

Hi everybody, I’m following a tutorial made for Construct 2 about a Match-3 game, I’m here:
Chapter 3

The game is working, but I’m losing a lot of performance. It started to become slower after add the two match functions, but after “join” them in a big match detection function the performance went to Mars :smiley:
I would be grateful if someone could thest both projects (the first with two match detection functions, and the second with only one), to know if:
-It is my relatively old computer :neutral_face:
and/or -GD is a little slow with functions, I mean… sometimes I have to wait 1-2 seconds to complete the match detection, I tested it in the debugger and the number of iterations are 200-300 (maybe they are too many… the function is recursive, but only check two times an object’s position and an object’s variable)

Here is the game:

Thanks :slight_smile:

I’ve tried both projects and on the first one, I don’t get any lag at all. The 2nd version however does lag for me. At the very start it lags at most 2.75 seconds and just 1.7 seconds the rest of the time gradually becoming faster and faster as blocks disappear. I’d say I have a pretty decent 4 month old laptop with dedicated graphics card so I’m guessing it’s GD?

Yes, you probably know it, but while blocks disappear, the number of iterations decrease :slight_smile:

Well, I don’t know… maybe I’m abusing with the number of recursions (anyway the Construct’s game runs smooth), or I don’t realize that I’m doing something wrong :blush: (perhaps the way GD’s and Construct’s functions work is slightly different), and I should change something.

It seems like you are checking so much stuff every frame? Why not put some timers on some of this stuff to reduce the CPU load?

Yup, checking for those every 0.01 seconds (heck, even 0.1) won’t make big difference from user’s perspective than checking every frame, it’ll be slight delay, but not big.

Although I agree if that’s GD’s fault, it should be addressed.

I take a look at your code and I notice that you’re making a lot of overprocessing…

1. Every time you check for matches you iterate TWO times trough the blocks instances.

2. Every time you iterate trough the blocks instances, you do it trough ALL the blocks instances.

Why do you iterate TWO times trough the blocks instances? You can do all the things you’re doing trough the same iteration.

Put all the conditions and events where you’re searching for BOTH vertical and horizontal matches under the same “For each ____ object…” event.

And why are you iterating through ALL the block objects? The second change I suggest even makes obsolete the use of that “For each…” event in this script.

By common sense, there is no way in what a moved block can make a match with blocks that aren’t in the SAME row and column. So you only need to list and to iterate trough the blocks in the same row and column where the selected block was moved to.

Let’s do the math!

Let’s suppose we have a 10 x 10 blocks grid. That’s 100 blocks at all.

In your script you’re iterating through all the blocks TWICE, so by now we can say the set of conditions your game use to check if there is match is revisited a minimum of 200 times in just 1 cycle of your main script loop. And if your script find a match it performs again the same function for the next block, wich anyways will be revisited when it comes its turn in the block iteration and it will perform the same re-matches by its own, so if there’s a full match (3-in-line) every one of the 3 blocks that make the line will be checked 3 times. That’s a minimum of 209 revisitations to the match conditions for a simple match (because it can be a double or triple match).

If you want to see it by yourself, just make a global variable and set it to 0 every time after enter to the block iteration, then adds 1 every time you find a match and put the result in a textbox or check it via the debugger window. You will notice that every time the game find a simple 3-in-a-row match your variable will be set at 9 when it just have to be 3 (one for every block of the match) and that my friend is a lot of useless reprocessing.

Now, we’re still at the same 10 x 10 example board. In a optimized code (in this case, script) you’ll only check the blocks that belongs to the row and column where the selected block was moved to; and that is just 20 iterations of the match conditions.

And if you want to optimize your script even more, you can make 4 different lists of blocks to check:

One list for the blocks that belongs to the same column and are above the selected block (this list need to be checked in reverse order)
One list for the blocks that belongs to the same column and are below the selected block
One list for the blocks that belongs to the same row and are to the right of the selected block (this list need to be checked in reverse order)
One list for the blocks that belongs to the same row and are to the left of the selected block

In this last optimized system you are checking for un-matches, so if you don’t find a match you stop and continues with the next list.

With this last optimization the maximum iterations you will perform per cycle is 6 and the minimum is 4.

[200/209] vs [20] vs [6/4]

Now, you can see why your game is running slow.

Take care and good luck! :wink:

Mmm… I check matches just one time after a block swapping, I could improve it only a bit checking matches just after a successful swap (not a canceled one) :confused:

erdo, I have to admit that what you say makes a lot of sense :neutral_face: :
-I didn’t consider that the Construct’s “smooth” game I played is the finished one.
-In the next chapters, the match detection is retouched.
-Some algorithms are added then to prevent an automatic match creation, so it becomes really impossible that a match extends beyond the concerned blocks (swapped ones) or gravity :smiley:
-Anyway I didn’t read any performance note in the Chapter 3.

Finally I’ll continue with the tuto to see if the performance improves… or decreases, in that case I’ll have to make my own optimized match detection function, and thanks for the “Let’s do math” section erdo, I know math but if I get stuck I have something to read :wink:

Performance can be impacted by the heavy use of functions, as they are using strings to pass parameter so it force you to convert to strings and then back to a number, and doing these two operations a lot are quite bad for performances… I’m still searching for a solution to this.