How do I run actions sequentially? lots of subevents with condition using incrementing variable?

  • I'm a medium-level Construct user, trying to understand how to build code that runs conditional logic in sequence.

    How do I add conditional behavior that performs sequentially?

    this is very simple in normal code: if BOOl1 then ACTION1 /elseif BOOL2 then ACTION 2 / elseif BOOl3 then ACTION3 /.../ end if.

    Construct seems to want to conduct ALL conditionals in parallel!

    DETAILS:

    I've got a card game. (nonworking partly done code on "play" event sheet: c3p)

    I am animating comparing 2 cards. Each card is a sprite belonging to 1 of 2 families. both families have the same 5 boolean variables. the booleans match icons arranged vertically on the cards. I want a sprite to move down the icons, one by one, and show a smiley emoticon if they match, and a frowny if they don't.

    Here's my current plan. It is not elegant (but may work, dunno yet). Is there a better way?

    I created a function that accepts two UIDs of the cards. It has these parts:

    1) selects and positions the cards, then 2) positions the highlight sprite over the first item. 3) if booleans match, show sprite "smiley" else show sprite "frowny" 4) advance to next attribute

    I am trying this by dividing the code by subevents, and incrementing a global number "sequential" to force subevents to run in order:

    a subevent conditions are cards match the UID parameter. it sets sequential to 0.

    another subevent condition is cards match and sequential is 0. it does 1) and 2) above, and sets "sequential" to 1.

    another subevent conditions are cards match, plus "sequential" = 2. It then does 3) and sets sequential 2

    Reading the manual on picking, I don't understand the following:

    Families pick instances in the event sheet independently of the object types in the family. For example, consider Family1 consisting of SpriteA and SpriteB. Conditions for Family1 will never affect which SpriteA and SpriteB instances are picked. It will only affect which instances are affected when running an action for Family1. Likewise, conditions picking SpriteA and SpriteB instances will never affect which instances are picked in Family1. In other words, in the event sheet families are treated like an entirely separate object type, which just happens to have instances from other object types. This can be taken advantage of if you need a single event to pick two separate lists of instances from the same object type.

    Is there any better explanation?

  • Construct does not run any events in parallel. All events, conditions and actions run sequentially in top-to-bottom order.

  • Thank you Ashley for the reply.

    OK, thank you for replying.

    English is too vague for coding, sometimes. I think I should post code, not describe. So here's a test:

    It creates 5 sprites at x=0,50,100,150,200. Each is followed by a 2-second wait. Sprite #1 is created in main, #2 and #3 in a function with one subevent, #4 in a second subevent, and #5 after the function call.

    So what do you think will happen here?

    I would expect the sprites to appear, one by one with a 2-second delay between each, in order from left to right, but that's not what happens.

    Reading around the forums I wonder if "wait" may be the problem, but if so, I can't grasp why wait doesn't make the code wait, or what if any workarounds I should use when I need events to happen slowly enough for users to see in sequence.

    c3p is here: dropbox.com/s/bo6ncbd7twdvxfk/sequential-test.c3p

    Thank you so much for your help. I've searched the forums but not sure what terms to search...surely it's been covered before. Please refer me to existing posts or examples if this topic is already explained somewhere else. I'll try my best to grasp that before posting more.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Firstly, the origin image point in your sprite is off, so you don't even see the first created instance. Also, instead of creating sprites, I suggest using Browser-Log action, it will allow you to understand better in which order events and actions are running.

    When you call a function, the next action will run after the function ends. However, if there are any "waits" in the function, construct will create separate threads for them and move to the next event. Basically, the whole function is executed in one tick, but some actions from it are scheduled to run later.

    If you change your code like this, then all 5 circles will be created with 2 seconds delay between them:

    Note, that event #3 is a sub-event under #2.

  • If I follow through your logic, your code behaves as expected.

    To clarify, let's keep track of a pseudo game time: 0 seconds (gt 0s) and indent the steps

    1) Sprite at 0,50 is created (gt 0s)

    2) Wait 2 seconds (gt 0s)

    3) Call function (gt 2s)

    4) Create object at 50,50 (gt 2s)

    5) Wait 2 seconds (gt 2s)

    6) Create object at 100,50 (gt 4s)

    7) Wait 2 seconds (gt 2s)

    8) Create object at 150,50 (gt 2s)

    9) Wait 2 seconds (gt 2s)

    10) Create object at 200,50 (gt 4s)

    Now let's check which objects get created at which "game time".

    gt 0s: object at 0,50

    gt 2s: object at 50,50 , object at 150,50

    gt 4s: object at 100,50 , object at 200,50

    Also ction 8) is fired immediately when the function is called.

    Construct runs the events sequentially through each event branch. As dop200 indicated, since 8) is not a sub-event and therefore will get fired right away, not caring about the wait in the action block above it.

  • Big ups for replying in detail! I'm ...kinda...getting it...

    DL;DR

    Q: I want a sequential conditional ( if/then/else structure) that runs slowly (2 seconds between conditions) so the player can see if/else block execute.

    A: For if/then/else, use sub-events, nested elses. to slow it, make each sub-event set a variable and add conditions to nested levels that check it. If you want real-time, set and compare using the system clock ('it's been 2 seconds since the last action ran').

    I just made up most of those words in that last sentence. Are there standard terms I should have used?

    DETAIL:

    Regarding wait: "The whole function is executed in one tick, but some actions from it are scheduled to run later. "

    Gah! So confusing for me! It feels like it breaks the "everything is sequential" idea that Ashley stated in an earlier reply to this thread.

    Is wait the only action that does this? Does it work like tween does?

    Is there a list of actions that do and don't complete somewhere in the docs?

    So, now I'm wondering if it's possible to create new action. I'll call it a 'delay' function. Like wait, but makes Construct run the next action once the timer completes.

    Why? So I can do what I was tyring to do with wait: create a sequence of actions, and they will happen slowly, one after the other, in the same indentation block, instead of a very deep nest of sub-sub-sub events.

    I'm not asking for single-threaded wait - I understand that would freeze Construct.

    1. My 'delay' runs the next CONDITION, where 'wait' runs the next ACTION

    2. My 'delay' restores execution in the middle of a list of actions, where 'wait' skips ahead.

    How? Uhhh... naively I imagine it would make Construct push its position and pick list in the current indentation block. Then it'd break out of the block and execute the next condition, and keep running. Once the delay timer finished, Construct returns to the incomplete block, restores the pick list, and executes the next action after the delay.

    yeah, that may not make sense...maybe you advanced coders can help me grasp this.

  • So, now I'm wondering if it's possible to create new action. I'll call it a 'delay' function. Like wait, but makes Construct run the next action once the timer completes.

    Why? So I can do what I was tyring to do with wait: create a sequence of actions, and they will happen slowly, one after the other, in the same indentation block, instead of a very deep nest of sub-sub-sub events.

    Could you use wait for signal and signal for this?

  • I'm pretty sure "Wait for signal" works the same way. It will not pause loop execution, the loop will still be completed immediately in one tick. But all actions inside the loop which are below "wait" action will be delayed and executed later when they receive the signal.

    Basically, if in other languages you have this code:

    For i=0 to 4 {
    	Create object
    	Delay 2 seconds
    }
    Display message "5 objects have been created!"
    

    In Construct you need to do this:

    Repeat 5 times
    	Wait 2*loopindex
    	Create object
    
    Wait 10 seconds
    Display message "5 objects have been created!"
    
  • the way I like to delay actions is to make a global variable to indicate that some kind of sequence is running - so that when the sequence is over, nothing is happening (other than checking if a sequence is running).

    and I use a variable "Delay" set to how long to wait. Every tick dt is subtracted from it, so when it gets down to zero, the next step can take place. that step then sets the length of the delay until the next step or marks the sequence as complete.

    that code creates 4 objects, two seconds apart, at an X of 0, 50, 100, 150.

    the first object gets created immediately because Delay starts at zero.

    EDIT: of course there are lots of other ways to achieve similar results: if you are using tweens to make something happen, you can advance the sequence when the tween ends, or if you have a sequence of animations, you can advance the sequence when the animation ends, etc...

  • I think most of the problem comes from the misconception that "Wait" from other blocks of events influence the flow of the "main" block of events.

    You should add a "Wait for signal" after the function call, and signal at the end of the function. It should start to behave like you originally thought.

  • I think the dt countdown hassle is what I really need, and wait is seductively simple but ultimately not the right solution.

    I FINALLY found a deep official discussion of wait:

    construct.net/en/tutorials/how-to-use-the-system-wait-action-63

    Here's a sample:

    "The Wait action saves which objects are picked and cancels the current event. When the wait time has expired or it is signalled, the picked objects are restored as they were when the wait started (minus any objects that got destroyed), and the event is resumed from the action following the wait action. It continues to run any subevents as well. At any point if another wait action is encountered, the same save-picked-objects-and-wait process happens, so you can make different parts of an event run at different times."

  • the way I like to delay actions is to make a global variable to indicate that some kind of sequence is running - so that when the sequence is over, nothing is happening (other than checking if a sequence is running).

    and I use a variable "Delay" set to how long to wait. Every tick dt is subtracted from it, so when it gets down to zero, the next step can take place. that step then sets the length of the delay until the next step or marks the sequence as complete.

    THANK YOU!

    Of course, an idea this good will generate questions :)

    Do you see any way to make your idea more readable? the nested subevents make it very hard to follow the flow of the actions. (Wait is very easy to read - I'll say that for it... :)

    -Josh

  • FYI, for others with my issue, there is a new feature in the latest (stable) release "Wait for previous actions to complete." Not sure how it interacts with various parallal processes (e.g. tween) but hopeful this is a useful new tool. Looking forward to trying it.

  • whitkin This action only works with asynchronous events (like AJAX->Request, Local Storage->Get/Set, Pathfinding->Find Path etc.), it won't work with Tween or loops or anything like that.

    See this Ashley's video about this new feature:

    youtube.com/watch

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)