"For Each" Help

Get help using Construct 2

Post » Wed Mar 13, 2013 6:44 pm

I cannot figure out why these lines of codes only work ~90% of the time when multiple enemies are on the screen and affected by this.



Basically what is happening is when the enemy is hit by FrostNova, if it's not already frozen (Freeze = -9999), it spawns an iceblock on an enemy and "Freezes" it for 3 seconds. Once the 3 seconds is up, it destroys the iceblock and unfreezes the enemy.

If there is only 1 enemy on the screen, it works perfect every time, but the second you introduce 1+, it seems to get more complicated. With 2, it will usually delete both of them, but randomly will leave 1 undeleted while the enemy acts unfrozen.

Can anyone see anything wrong with this? Thanks.ome6a17172013-03-13 18:45:30
B
22
S
3
Posts: 451
Reputation: 2,135

Post » Wed Mar 13, 2013 7:10 pm

Are you sure you need that 'For each'? Most events work for each instance automatically.
Scirra Founder
B
359
S
214
G
72
Posts: 22,952
Reputation: 178,600

Post » Wed Mar 13, 2013 7:19 pm

I actually don't need the for each, but regardless of whether or not it is there, it still seems to have this issue.
B
22
S
3
Posts: 451
Reputation: 2,135

Post » Wed Mar 13, 2013 7:21 pm

You don't need the top For-Each block:

The relevant trigger is 'On collision'. Getting rid of the For-Each will cut a lot of un-needed processing.

Since you threw in the 'once ever .1 sec' condition, and thus 'Freeze' can only ever change at that frequency, I would rewrite it with that as the primary event trigger, which should reduce processing overhead, and furthermore, I would change the destroying of the ice block(s) as shown:

Event: Sys: Every .1 sec
--> subEvent: Enemies: Freeze > 0: Sub 1 from Freeze
--> subEvent: Enemies: Freeze = 0: do stuff...
--> subSubEvent: Pick all IceBlocks && IceBlock.PinnedUID = Enemies.UID: destroy IceBlock

       
B
14
S
4
G
1
Posts: 26
Reputation: 1,747

Post » Wed Mar 13, 2013 7:31 pm

Oh, and it is not quite clear what your problem precisely is...

You said:
With 2, it will usually delete both of them, but randomly will leave 1 undeleted while the enemy acts unfrozen.


'delete both of them' refers to what exactly?
'leave 1 undeleted' refers to what exactly?

I assumed IceBlocks...

And also, are you saying the enemy fails to freeze for 30 secs, randomly, in the cases of two or more enemies?

In both cases, it is pointing to a failure to pick precisely what you want to affect.

I think the code change I suggested above will fix the IceBlock issue, if I assumed correctly.

B
14
S
4
G
1
Posts: 26
Reputation: 1,747

Post » Wed Mar 13, 2013 8:16 pm

Hey Jaycephus,

Your assumption is correct - it's not deleting all of the iceblocks. The enemy is always frozen as it should be, but occasionally when the 3 seconds is up, one of the iceblocks will NOT be deleted. I can't figure out a way to trigger the bug, either.

Just curious (I'm not at home to test this yet), but if I change the code to "Pick all IceBlocks", won't it delete them all instead of each one individually once the freeze timer is up? (ie. if an enemy is hit by frostnova, and a further enemy is hit by frost nova 1 second later, they should each have their own timer for when iceblock is deleted so they are NOT deleted at the same time).

Let me know if I'm not making any sense.

Thanks.
B
22
S
3
Posts: 451
Reputation: 2,135

Post » Wed Mar 13, 2013 9:13 pm

Your last event needs a 'For each enemies' before 'For each IceBlock' otherwise you're only picking the IceBlock that's pinned to the first enemy with Freeze = 0.ramones2013-03-13 21:14:40
B
54
S
28
G
18
Posts: 1,520
Reputation: 25,020

Post » Wed Mar 13, 2013 9:23 pm



So I wrote:
--> subSubEvent: Pick all IceBlocks && IceBlock.PinnedUID = Enemies.UID: destroy IceBlock

This was my short-hand for two conditions:
---> subSubEvent: Cond1: Pick all IceBlocks
----------------> Cond2: IceBlock.Pin.PinnedUID = Enemies.UID
--------------------------> Action: Destroy IceBlock

So just to be precise, there are multiple conditions:
1st the .1 second timer triggers.
2nd, a specific enemy is being processed at a given instant, and only from the subset of enemies that have their Freeze variable equal to 0, be that 0, 1, or 13 different enemies at once...
Then the Pick All IceBlocks has a second condition that you also use above in your code, which discards any IceBlocks that are not pinned to the specific enemy being processed at that moment, meaning it only does this action on one IceBlock, or none if for some reason no IceBlock is pinned to the specific enemy being processed. Of course, if somehow two enemies are selected because they each are at Freeze = 0 state, then they will still be processed in turn, and only one IceBlock will be destroyed in turn for each enemy.
B
14
S
4
G
1
Posts: 26
Reputation: 1,747

Post » Wed Mar 13, 2013 9:33 pm

@Jaycephus 'IceBlock.Pin.PinnedUID = Enemies.UID' is a 'System: Compare two values' event. It doesn't do any picking so you need the 'For each IceBlock' before it.
B
54
S
28
G
18
Posts: 1,520
Reputation: 25,020

Post » Wed Mar 13, 2013 10:20 pm

Yes, you are right. I was thinking of the 'Compare Instance Variable' condition of a Sprite, but then he would have to store the Enemies UID in an instance variable of IceBlock to facilitate that. I just shy away from doing For-Eaches on every tick if it can easily be avoided.
B
14
S
4
G
1
Posts: 26
Reputation: 1,747

Next

Return to How do I....?

Who is online

Users browsing this forum: alextro, MarkStockley and 0 guests