Bug in my behavior code - help?

Discussion and feedback on Construct 2

Post » Tue Aug 23, 2011 1:55 am

Hello!
I've been working on this plugin for a couple of days, and am now messing with the SOL, so that I can return the objects that obey the condition, as would be expected of a plugin of this nature.

In the example, there are three objects. When they enter the arc, they are selected, and the ones who didn't enter the arc are not selected (as expected).

However, when they enter the arc and then leave, if one object stays within the arc, objects that were selected remain selected, even if they are outside the arc - in other words, as long as at least one object stays in the firing arc, the other objects can't be deselected when they leave!

I don't know what the problem is - my "check between angle" and "check within range" functions are OK, so the problem has to be somewhere else

I know my code is a horrible mess and I probably did things in a crazy inefficient way, so forgive me for that.

Example file with behavior: http://www.sigsonic.com/turret.zip

Live preview courtesy of DropBox

This is not fully functional yet, so some options are missing or might not work.Fimbul2011-08-23 02:07:20
B
35
S
8
G
8
Posts: 532
Reputation: 6,868

Post » Wed Aug 24, 2011 3:59 pm

First of all, some tips:
- script didn't run at first because you don't declare 'i' and 'len' before using them in some places (remember C2 scripts run in strict mode)
- don't use 'this.memberFunction = function(...' to make member functions. Add them to the prototype, e.g. 'behinstProto.memberFunction = function(...'. If you assign a function to this.memberFunction, each instance of the behavior gets its own copy of the function which wastes memory.
- those conditions are pretty expensive O(n^2) - you might want to build in, or at least encourage users to use, some kind of timed update (like every 500ms, rather than every tick). IIRC the Classic turret behavior updates the range checks every 500ms.

The main problem:
You wrote in a comment "C2 will invert the picking automatically for us". It doesn't! It only inverts the result of the condition function (return true/return false). C2 has no idea what the body of your function does and has no control over it. The way you've written it, you pick objects within range to the SOL even when the condition is inverted. You have to handle inverted yourself in this case, which is done like so:

[code]// Get the inverted status of this condition
var cnd_inverted = this.runtime.getCurrentCondition().inverted;

// ...
var i, len;
for(i = 0, len = instances.length; i < len; i++)
{
     obj = instances[i ]; // forum makes this italic if i don't put a space
     
     // 'xor' handles the invert flag
     if (cr.xor(this.withinAngle(obj.x, obj.y), cnd_inverted))
          picked.push(obj);
}

if (picked.length)
{
     sol.select_all = false;
     sol.instances = picked;
     return !cnd_inverted; // C2 inverts the result
}
else
{
     return cnd_inverted; // C2 inverts the result
}
[/code]

A little explanation:
XOR computes invert, because of its truth table. See:

A = object met condition
B = invert status

A - B - Result
0 - 0 - 0
1 - 0 - 1
0 - 1 - 1
1 - 1 - 0

So if you XOR your picking condition with the invert status, you'll pick it correctly for all combinations of object meeting the condition and condition being inverted. That's what I've done above.

The next trick is remember C2 inverts the result of your condition function if the condition is inverted. If the event is inverted and we picked no objects, and return false, C2 inverts false to true (because it's inverted) and the event runs. Woops! So to counteract this, the returned value from the condition has to be inverted too. In other words, if nothing was picked, we want to return false if the condition was not inverted, or true if the condition was inverted - i.e., the invert flag itself. And vice versa for if we did pick objects.

Hopefully that makes sense - once I made those changes to all three conditions, it seems to be working ok now!Ashley2011-08-24 16:03:53
Scirra Founder
B
359
S
214
G
72
Posts: 22,946
Reputation: 178,478

Post » Wed Aug 24, 2011 11:48 pm

I'll correct that and optimize it to make less redundant checks. Going to optimize my spaceship movement too. Thanks for the help!
B
35
S
8
G
8
Posts: 532
Reputation: 6,868


Return to Construct 2 General

Who is online

Users browsing this forum: Mirlas, newt and 2 guests