How do I get enemies to change direction when hitting walls?

  • Or more clearly - "why doesn't what I'm doing work properly?" I have no idea how I'm screwing up possibly the simplest thing you can do.

    drive.google.com/file

    /d/0Bz6k_T7ICBNmdjU5b0xNTnZ1bVU

    /view?usp=sharing

    (Edited to split this up because it doesn't work otherwise..)

    In the .capx linked are sprite enemies with a platform behaviour and a "Direction" instance variable, and a sprite called 'block' with a solid behaviour. Depending on the "Direction" of the enemy, it'll either simulate the platform behaviour to move left or right. In the events, if the enemy collides with the block and has the direction "Right", it'll set the instance variable to "Left" and simulate that movement. An identical event is there for the opposite direction. You probably worked all that out instantly just by looking at the 4 events.

    Real simple stuff, right? But when the enemy collides with the block whilst moving left, it'll refuse to set itself to right. It doesn't do anything, just sits attempting to move into the block. In the debug, the "Direction" variable doesn't change at all.

    I have no idea why it won't work. Everything is spelt correctly, the collision hitboxes are both just squares covering the entire sprite, and it works fine when hitting the block whilst moving right. It's like, the most basic thing in a platformer to get working, and it's seriously annoying me. I can't believe I'm making a thread here for something so simple.

    If anyone could spend just 30 seconds to find the problem and tell me why I'm stupid, that'd be great!

  • I believe it's because the instant you change it from going left to right, the next event in line triggers.. While still colliding with the Brick, so it simply moves left again. (following the Event sheet top to bottom). If you flip the Direction changing events around, you'll see what I mean.

    EDIT: A quick dirty fix:

    What I changed is fairly simple, we just need something to tell us that we've already changed direction so the next conditional event in line does not trigger.

  • There it is thats why you need triggers in construct 2 or an "or" function!

  • There it is thats why you need triggers in construct 2 or an "or" function!

    I don't see how or is applicable here, since that'd still execute the same events. An ELSE function that works with any and all conditions and triggers would be nice though, and definitely useful in this case.

    (Also, there is an OR block, if you have multiple conditions you can turn your block into one.)

  • or because you just want one condition triggered not both after each other.

    it is like

    main

    sub

    sub

    but it should be like:

    main

    sub1 sub2

    Anyway the variable works just fine.

    (I just call it or i dont mean the construct 2 or function)

    Maybe your right its more like an else chain:

    if a is true than "do something" else check if b is true than "do something" else check if c is true and so on...

    however its a bit offtopic here

  • I believe it's because the instant you change it from going left to right, the next event in line triggers.. While still colliding with the Brick, so it simply moves left again. (following the Event sheet top to bottom). If you flip the Direction changing events around, you'll see what I mean.

    I understand this now, and you're correct, flipping them does have the exact same effect on the opposite direction.

    A problem, though, with this:

    A quick dirty fix:

    What I changed is fairly simple, we just need something to tell us that we've already changed direction so the next conditional event in line does not trigger.

    Reading this through I'm not so sure I understand how that works.. after the "Shifted" number gets set to 1, wouldn't the events now never run because they don't meet the conditions? And if the number is also updated at the exact same time, how would this fix that original issue.

    Edit: I've just copied that identically and it plays out in the exact same way.

  • Make sure it is a local variable, basically despite the fact that this is not code we're dealing with Object Oriented behaviour and scopes.

    The -> Enemy On Collision with Brick event opens a new scope for the objects in question. (Thus, our current instances of Enemy and Brick) as triggers do. As long as you stay in this event (as my sub-events did) when you address the objects you're ONLY changing the ones within that scope. In code it'd more or less look as follows:

    internal static void OnCollision(Enemy instEnemy, Brick instBrick) {
        var Shifted = 0;
        if (instEnemy.Direction == "right" && Shifted == 0) {
            instEnemy.Direction = "left";
            Shifted = 1;
        }
        if (instEnemy.Direction == "left" && Shifted == 0) {
            instEnemy.Direction = "right";
            Shifted = 1;
        }
    }[/code:2z089kcj]
    
    Although that might not mean much to you, I suppose. We are still staying within a scope. <img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile"> (e.g. anything surrounded by { } is a scope, and variables initialized within one are usable inside said scope and any scopes created within said scopes but not outside of the scope they were created in. When a new scope begins, new variables are initialized and the old ones are NOT re-used.) If you want to know more about how Object Oriented languages deal with scopes, I would advice you to search around a bit on google. It might be helpful.
    
    But I digress, technical mumbo-jumbo. Basically, because I turned the conditions and variable into children of the collision trigger they only count for anything in that little block. The variable is not accessible globally, but only in that block and the conditions and actions trigger only on the items relevant to the trigger.
    
    But instead of trying to explain scopes and programming logic (at which I stink, I can write it just fine but explaining things without writing an essay full of examples and pictures won't be easy. <img src="{SMILIES_PATH}/icon_razz.gif" alt=":P" title="Razz">) here's the *.capx where I fixed it for you to play around with: [url=https://www.dropbox.com/s/crrauxq4wt0bnqx/Project.capx?dl=1]https://www.dropbox.com/s/crrauxq4wt0bn ... .capx?dl=1[/url]
    
    Just remember that positioning of variables, triggers, conditions and actions can be VERY important to the flow of your game.
    
    EDIT: Come to think of it, how did you copy it? With the indentation or without it? (I'll be heading off to bed in a moment, but I imagine other folks around could help you if you get stuck on this as well. <img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile">)
    
    (Of course you could be more efficient in code, and write something as follows:
    
    [code:2z089kcj]
    internal static void OnCollision(Enemy instEnemy, Brick instBrick) {
        instEnemy.Direction = instEnemy.Direction == "right" ? "left" : "right";
    }
    [/code:2z089kcj]
    But unfortunately we don't have the luxury of such operators in Construct. <img src="{SMILIES_PATH}/icon_e_sad.gif" alt=":(" title="Sad">)
  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • What he wants to say is local variables are only used in their event (and subevents below it) and reset them self every tick.

    So no it will not stay at 1 and cause the event to never run again.

  • What he wants to say is local variables are only used in their event (and subevents below it) and reset them self every tick.

    So no it will not stay at 1 and cause the event to never run again.

    Not entirely correct, as it is not on every tick.. (Scopes! A very important concept in OO behaviour!) but that is the general idea.

    And yes, I understand I turned this into a complex story right away.. But once you get what a scope does it'll make your life so much easier. (Alternatively, you could take my *.capx I posted and accept it works, and come back to the subject at a later day. I won't judge.. At least not harshly. )

  • Hmm no its not on every tick ?

    Isent the event triggerd ones per tick and the variable therefore reset every tick?

    I cant see why and how the scope of the variable should change this.

    (Maybe we have a different understanding of "scope")

  • If it were to reset every tick it would still affect other instances, but it doesn't. It only affects whatever is in the scope of the variable. Outside of the scope, the variable is moot. In another scope, when another object collides the variable is initialized again as we're outside the scope of the last event. (Any ''condition'' that has a little green arrow by it is also an event, they are triggered by the system, rather than constantly being checked for. So they're a bit more efficient than looking through all your conditions every tick when there's no need to do so.)

  • So you mean it only resets if the event is triggered?

  • It resets as soon as we leave the sub-event we've placed it in. (Or rather, it doesn't reset at all. But the variable is only valid in that specific sub-event and its children, any new sub-event of the sort will create a brand new variable. What we see in the UI does not equate to what happens on the internals of a programming/scripting language. The unused ones will eventually be picked up by the garbage collector and cleaned up as they're no longer in use.)

    The beauty of a scope, anything inside of it is valid while you're in the scope. Any time said scope is encountered the values start out completely unaware of the last time the code was run. (Unless specifically stated otherwise, but if we start including that now things will get really confusing.)

    If you're interested, there's some decent information regarding scopes and the reach of variables around the web. One such example would be this: http://people.cs.clemson.edu/~turner/co ... ch8_5.html

  • Its interesting so a local variable is created and destroyed every time the event runs instead of being simply

    reset to its starting value?

    So it will take up no memory while the programm is running other events?

    Makes kinda sense for optimization reasons i think.

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