Handling Duplicates - Part II
Submitted:|| 14th April, 2011
I touched on this in my previous article, but this is just a more thorough explanation of how Object Matching works in MMF2.
Note: I originally posted this article on the Clickteam forums, after someone there asked for help with it. This is just copied & pasted from there.
What is "Object Matching"?
"Object Matching" (aka. "Automatic Pairing") is a simple way to match instances of two different object types, without having to resort to spread values/fastloops etc (and it's much easier and more efficient because of that).
For example:- You could have several tanks, each composed of separate hull and turret objects, like so:
-> Turret: Set position at 0,0 from "Hull"
This will position a different Turret on each Hull.
It's not really important to know this, but MMF2 chooses which Turret to pair with which Hull, according to the order in which they were created. It starts with the most recently created Turret object, and matches that with the most recently created Hull object. It then matches the second newest Turret to the second newest Hull, and so on.
Again, you don't really need to know this, because 99% of the time you will want to have the same number of each object, but...
If there were more Turrets than Hulls, it would do exactly the same thing, but then start over when it runs out of Hulls. So if you have 5 Turrets but only 3 Hulls, they would be paired as follows:
Turret #1 + Hull #1
Turret #2 + Hull #2
Turret #3 + Hull #3
Turret #4 + Hull #1
Turret #5 + Hull #2
(#1 = newest instance)
Another interesting feature, is that you can filter which objects to pair. In the example above, we used the condition "Always", which doesn't select any specific Turret or Hull objects. However, we could change that, and only have some of the objects paired.
For example:- Okay, I can't think of a good example right now, so I'll just go with this...
You could say:
+ Turret is NOT overlapping an obstacle
-> Turret: Set position at 0,0 from Hull
This time, any Turret which is overlapping an obstacle, will NOT be paired with a Hull - it will just stay where it is.
Instead, the newest Turret not overlapping an obstacle, will be paired with the newest Hull; the second newest Turret not overlapping an obstacle will be paired with the second newest Hull...
Now, suppose we want to give each Hull an alterable value which determines the angle of the Turret, relative to the angle of the Hull (useful if you want to limit the rotation of the Turret, for example).
-> Turret: Set Angle to Angle("Hull") + TurretOffset("Hull")
You can see that this time we are comparing the angle of paired objects, and also an alterable value - in fact, you can use any kind of variables you like.
This also demonstrates another point - you generally want to keep any persistent values in the parent object (Hull) rather than the child (Turret) - ie. Offset is a property of the Hull, not the Turret. This just helps avoid problems as objects are created and destroyed.
That was a fairly basic example, but you can also do more complicated things.
For example:- You could have multiple Enemy objects, each with its own invisible collision Detector, which lets you check if they have been shot specifically in the head.
-> Detector: Set position at 0,0 from Enemy
+ Detector collides with Bullet
-> Detector: Set "Hit" to 1
-> Enemy: Set "Headshot" to Hit("Detector")
+ If Headshot("Enemy") = 1
-> Play animation "HeadShot"
+ Animation "HeadShot" has finished
-> Enemy: Destroy
+ NObjects( "Detector" ) > NObjects( "Enemy" )
-> Run fastloop "DestroyDetector", NObjects( "Detector" ) - NObjects( "Enemy" ) times
+ On loop "DestroyDetector"
+ Pick one Detector at random
-> Detector: Destroy
Remember, we want to always keep the same number of Detectors as Enemies. Using a fastloop allows us to do this instantly, even if multiple Enemy objects are destroyed at exactly the same time.
You can use this for anything involving detectors, including custom platform engines.
Anyway, I think that's enough for now - have a play around with it yourself.
It's a very simple and very powerful technique, once you understand how it works.
Finally, I'm just going to recommend you also read this article:
(Note that you should be using the ForEach extension for this kind of thing, rather than fastloops, as it's more efficient - it's just that the extension didn't exist when I wrote the article).