This code should make the text on the screen go through the numbers 2 - 21 over and over again, right?
But that’s not what’s happening. Instead, it firstly works as supposed, but then the variable stops on 2.
If we add a wait block before the “increase variable”, it works as intended again. However if we add the Wait block after the increase block, the variable acts even weirder and just flips between 2 and 17.
I don’t know what’s causing this, if it’s my code or Hopscotch. It seems though as all the clones are increasing the variable during the same frame.
What you’re noticing isn’t a bug, but rather an awesome nuance of the Hopscotch player. Understand this and highly performance-optimized (low-lag) projects can be made using clones. Honestly, this is probably the singular reason why I haven’t yet become bored with the superficial limitations of Hopscotch.
I’ve been meaning to make a tutorial to explain the mechanics of what you’re seeing for some time but it’s difficult to explain.
I dont know how well I’ll do, but I’ll try to give a pithy explanation… As many Hops already know, code blocks are executed at 60 FPS, right? But that’s just one “layer” of code execution. All objects are executing their code blocks, evaluating conditionals (Check If blocks), and evaluating Rules at the same frame rate. But all objects don’t do this at exactly the same time.
1. There’s also an “intra-frame” layer of execution.
This intra-frame order of execution occurs in the order the objects are organized in (i.e., the creation order unless the objects are reordered). That’s great to know but to really unleash the power of Hopscotch, there’s one more execution timing nuance we have to have noticed.
2. Conditionals (Check If blocks) and Rules (Whens) are executed in conjunction with the first code block in the code path during the same intra-frame timing step.
Pictures would be worth a thousands words to explain the bolded key points. But alas I haven’t taken the time to do that yet. Give my explanations some thought and see if you can follow why your project plays the way it does.
Hint: ‘Test variable’ does not have a static value of 2 as it appears
Previously, I had figured that it must be stuck on 15(this was in another project but i’ll stick to the number 15) but then I did some more testing.
I already knew that events were executed in a specific order during a frame, and the reason I can think of is that the clones are increasing the variable all during one frame. (this would be the reason that the variable seems to be static)
This doesn’t really make much sense to me though, since as far as I know each block should take a frame to execute, which should result in it taking 15 frame for 15 clones to increase the variable to 15.
I didn’t really understand the second of your points though, can you try to explain that further?
The 2nd point is key to understanding what’s going on
I probably didn’t explain it very well. When Rules for each object & clone are evaluated sequentially during each frame. And the first code block of each When if evaluated as true is executed during that same frame, before going on to the next When of that object or beginning the evaluation of the When rules of the next object.
Let’s look at your code & jump to a point in time when
Keep referring the order of the objects and When rules (shown above) as we walk through this.
So at the beginning of the next frame, the player goes to the 1st object’s (“Text”'s) 1st When rule. When Test variable = 21. This is true, so it executes the 1st block of that When rule. (<<< this is the meaning of my 2nd point in the post above) Set Test variable to 2.
Then (even if there were more blocks in that 1st When) it goes to the next rule. When 7=7. This is also true, so the player executes the 1st block in that rule. Set Text to Test variable. So the text now reads “2”.
Then (even if there were more blocks in that When) it goes to the next rule. When Game Starts. Not true, so it skips the code inside the rule.
On to the next rule… ok, there are no more for the 1st object. So it goes to the 1st Rule of the 2nd object (Text 3 with Clone Index 1). When Text 3 Total Clones < 20. Not true, skip.
When Test variable = self Clone Index. Remember these go in the order of creation so we’re on Clone Index 1 with Test variable = 2. Therefore the rule is not true, skip.
Now on to the next object. Text 3 with Clone Index 2. When Text 3 Total Clones < 20. False, skip. When Test variable = self Clone Index. True, execute the 1st block in the rule. Increase Test variable by 1. So now Test variable equals 3.
On to the next object. Text 3 with Clone Index 3… Hopefully you seen the pattern. So after the Player finishes with all 20 Text 3 clones, what does Test variable equal? 21! And that ends the frame (remember, all of the above was during 1 frame).
Almost done with the explanation, just need to consider the beginning of the next frame. As the Player executes the next frame, if any rules from the last frame were still executing, it would go to the 2nd block of those rules instead of evaluating the rule. If the rule had ended it starts over and re-evaluates the rule. All your rules only had 1 code block so that makes it easier to understand as all rules had finished and will now be re-evaluated.
Looking at just the first 2 rules of the 1st object (Text), you’ll see that When Test variable = 21 is true, so it’s set to 2. Then the text set read “2”. And the frame continues until Test variable again equals 21 at the end of the frame. Test variable is continually incremented as expected, but is only equal to 2 when the Set Text block is executed.
@Liza The explaination hopefully shows why I keep requesting THT to fix the drag & drop reordering of When rules. The order of the rules is really important for more complex projects. Since drap & drop doesn’t work right, you have to cut & paste rules to end of the list of rules until they’re in the desired order! That’s really a pain when an object has a large number of rules!
Your very welcome! I’d mentioned the uses of this for applications like 3D several times over the last year, but no one picked up on it. Now you see the potential
Most projects I’ve made in the last 6 months or so make use of this understanding for significant optimization, including combination factorial calculation in 2 frames, the Control Tower (wip), the AI for Trap the Mosquito, and the AI for Dot Sweeper. At the moment I’m tinkering with @BuildASnowman’s challenge to calculate the nth digit of pi (using a spigot algorithm) - just working on a generic function to calculate log n to any base b so far
LOTS of time spent trying to understand my code when I was in situations very similar to COAN. And LOTS of mini test projects trying to isolate and understand the Player’s flow. The great thing about computers and coding is that you should be able to apply rigorous, through logic and figure out what’s going on.
I probably am missing something. If I understand what you said correctly, then how the Hopscotch player runs code is it goes through each object in order of in the editor. If an object has clones, it will go run through each clone in order of clone index before moving on to the next object, correct?
it goes through each object in order of in the editor. If an object has clones, it will go run through each clone in order of clone index before moving on to the next object
the Square with Clone Index 1 would go through the code, and change the values of X, Y and Index.
Then, Square with Index 2 would go through, and change the variables to its respective values, and so on with all 5 clones.
Now, when it comes to the Circle, the X, Y, and Index should equal the values set by the 5th Square clone, so the When Index = Self.CloneIndex should only run for the 5th Circle clone. However, it doesn’t. The When rule is run for all 5 clones.
This could mean clones are run after all the main objects. In this case, there are only two main objects so the order would just be
Square 1, Circle 1, Square 2, Circle 2
and so on.
Another question: When a clone is created during a frame, will the clone execute code during the same frame it was created in, or wait until the next frame before running?
Just confirming COAN is correct. And the sequence of ‘When Object is Cloned’ relative to ‘Create a Clone’ doesn’t matter. Execution of ‘When Object is Cloned’ (and any other Rules for the new clone) starts in the next frame following the Create a Clone block.
If multiple objects are creating multiple clones during the same frames, this creates an interleaved object order.
Object 1, clone index 1 (object on stage)
Object 2, clone index 1 (object on stage)
Object 1, clone index 2
Object 2, clone index 2
Object 1, clone index n
Object 2, clone index n
‘Total Clones’ for the object creating the clone is changed at the time of the Create a Clone block execution.
Also remember that When Object is Cloned, just like When Game Starts, isn’t necessarily 1st. All rules are evaluated according to their listed order