I've gone over this trigger countless times, but I just can't figure out what the problem is. So I am gonna take a shot and hopefully someone going through this clearly really long trigger and figure out how to help me.
Anyways, as the title suggests this is a WASD 8 Way Movement system, my problem is that, for diagonal directions it isn't running properly, the unit moves smoothly along the diagonal, but the model rotates left/right repeatedly and moves twice as fast. I believe this means that after the diagonal actions run, one of the straight actions is also running (You would understand better why if you saw it, but just trust me on this). However I can't see why the straights would run.
If I remove everything after the marker I put below (Long line), then the diagonals run fine, but of course the straights do nothing. (Actions after that are for straights)
This trigger runs when 'W', 'A', 'S', or 'D' are pressed. No Conditions.
Event:
Player presses down W/S
Action:
Buttons_Down = Buttons_Down + 1
Speed = +5/-5 (or some number)
FacingUp = +1/-1
Event:
Player presses down A/D
Action:
Buttons_Down = Buttons_Down + 1
Strafe = +5/-5 (or some number)
FacingRight = +1/-1
Event:
Player presses up on W/A/S/D
Action:
Buttons_Down = Buttons_Down - 1
Speed/Strafe = 0
FacingUp/FacingRight = 0
Event:
Every 0.05 seconds of Game Time
Action:
Order (Unit) to Move targeting relative point near (Position of (Unit)) offset by (Speed * 0.707^(Buttons_Down-1) + Strafe * 0.707^(Buttons_Down-1))
towards ( (90 * gv_facingUp)*0.5^(ButtonsDown-1) + (90 - 90 * gv_facingRight)*0.5^(ButtonsDown-1) ) degrees.
I *think* the math works, but I'll need to doublecheck the numbers...
Okay, numbers look good!
Thanks for trying to help, but unfortunately, I intentionally did not use those methods.
The method you are using is far different from the one I am for two reasons;
1) This does not use Periodic Events, this means a bit more complication, but better performance.
2) This one moves the unit instantaneously instead of ordering it to move, ordering it to move is a lot more unreliable. For instance, if there is a thin pathing blocker and then the unit tries to walk around it.
Well that trigger is a huge mess! Hunting through that mess is enough to give anybody a headache :) A suggestion I would make for clarity in the future is to use the "If Then Else Multiple" option instead of nesting all those if statements. "If Then Else Multiple" is kind of confusing, but I figured it out earlier today (After getting fed up with nested if statements!)
Basically, create the if-then-else-multiple statement. Then, right click "If Then Else" and click "New Element" or just hit Ctrl+W. Do this for each "else if" you want to add, including the first "if". Much easier to read and keep track of, and no nesting!
As for your problem, that is a very complex set of variables you're keeping and checking. I know you're concerned about performance, but having a recurring timer that checks a single int variable every 0.0 or 0.5 or etc seconds is not going to make a difference in performance at all. The only time it would do more than check the single variable at all is when a button is pressed down, and in that case your trigger does the same amount of work at that point anyway.
I'll show you what I used for the WASD system in Reaper Madness, which has the same control system you want to set up. Note how simple it is to read:
The |= 0x0000 stuff may look confusing, but it's simple. When I run |= 0x0100 I'm setting the second digit (of the 4) to a 1, just as it appears. When I run ^= 0x0100 I am setting the second digit to a zero. This way, the 4 digits represent, in order: My D, S, A and W keys. 1 means they're pressed, 0 means they are not pressed.
I would say this is probably one of the most elegant and best performing methods.
Dude optimize your code, you should not repeat all the same actions after each conditions.
Use a variable that stores what's the angle of movement, then you can just order your unit to move in the direction stored inside the variable.
Anyway, the original post resembles the 'simplified AWSD' system posted a while ago, but mutated into a tank-crushing juggernaut. I don't think the original was really all that fast anyway - it is faster if you press nothing, but will actually do more work when you press multiple keys.
My suggestion is to throw out that mess and go with the tried and true: a single periodical trigger that adjusts heading based on which keys you pressed and then moves you forwards.
rrowland: wow, and there I thought I was the first to implement the bitfield solution. Mine is followed by a switch statement though, not nested ifs.
I've gone over this trigger countless times, but I just can't figure out what the problem is. So I am gonna take a shot and hopefully someone going through this clearly really long trigger and figure out how to help me.
Anyways, as the title suggests this is a WASD 8 Way Movement system, my problem is that, for diagonal directions it isn't running properly, the unit moves smoothly along the diagonal, but the model rotates left/right repeatedly and moves twice as fast. I believe this means that after the diagonal actions run, one of the straight actions is also running (You would understand better why if you saw it, but just trust me on this). However I can't see why the straights would run.
If I remove everything after the marker I put below (Long line), then the diagonals run fine, but of course the straights do nothing. (Actions after that are for straights)
This trigger runs when 'W', 'A', 'S', or 'D' are pressed. No Conditions.
Up/Left/Right/Down Key = Is W/A/D/S pressed down
My other theory is that the straights run on the second time the trigger is run, but still no idea how that could change anything. :(
I apologize if this description has been extremely unclear.
I'm not too sure what's causing the problem, but part of it is that you're making this too complicated.
If it was simpler, it would look something like this:
Global Variables: Buttons_Down (int), Speed (int), Strafe (int), FacingUp (int), FacingRight (int)
Event:
Player presses down W/S
Action:
Buttons_Down = Buttons_Down + 1
Speed = +5/-5 (or some number)
FacingUp = +1/-1
Event:
Player presses down A/D
Action:
Buttons_Down = Buttons_Down + 1
Strafe = +5/-5 (or some number)
FacingRight = +1/-1
Event:
Player presses up on W/A/S/D
Action:
Buttons_Down = Buttons_Down - 1
Speed/Strafe = 0
FacingUp/FacingRight = 0
Event:
Every 0.05 seconds of Game Time
Action:
Order (Unit) to Move targeting relative point near (Position of (Unit)) offset by (Speed * 0.707^(Buttons_Down-1) + Strafe * 0.707^(Buttons_Down-1))
towards ( (90 * gv_facingUp)*0.5^(ButtonsDown-1) + (90 - 90 * gv_facingRight)*0.5^(ButtonsDown-1) ) degrees.
I *think* the math works, but I'll need to doublecheck the numbers...
Okay, numbers look good!
Thanks for trying to help, but unfortunately, I intentionally did not use those methods.
The method you are using is far different from the one I am for two reasons;
1) This does not use Periodic Events, this means a bit more complication, but better performance.
2) This one moves the unit instantaneously instead of ordering it to move, ordering it to move is a lot more unreliable. For instance, if there is a thin pathing blocker and then the unit tries to walk around it.
Well that trigger is a huge mess! Hunting through that mess is enough to give anybody a headache :) A suggestion I would make for clarity in the future is to use the "If Then Else Multiple" option instead of nesting all those if statements. "If Then Else Multiple" is kind of confusing, but I figured it out earlier today (After getting fed up with nested if statements!)
Basically, create the if-then-else-multiple statement. Then, right click "If Then Else" and click "New Element" or just hit Ctrl+W. Do this for each "else if" you want to add, including the first "if". Much easier to read and keep track of, and no nesting!
As for your problem, that is a very complex set of variables you're keeping and checking. I know you're concerned about performance, but having a recurring timer that checks a single int variable every 0.0 or 0.5 or etc seconds is not going to make a difference in performance at all. The only time it would do more than check the single variable at all is when a button is pressed down, and in that case your trigger does the same amount of work at that point anyway.
I'll show you what I used for the WASD system in Reaper Madness, which has the same control system you want to set up. Note how simple it is to read:
Key Down (Any):
Key Up (Any):
The actual function, getWASDangle(), that translates the buttons being pressed into an angle we can use:
The trigger that runs every 0.0 seconds:
The |= 0x0000 stuff may look confusing, but it's simple. When I run |= 0x0100 I'm setting the second digit (of the 4) to a 1, just as it appears. When I run ^= 0x0100 I am setting the second digit to a zero. This way, the 4 digits represent, in order: My D, S, A and W keys. 1 means they're pressed, 0 means they are not pressed.
I would say this is probably one of the most elegant and best performing methods.
Dude optimize your code, you should not repeat all the same actions after each conditions.
Use a variable that stores what's the angle of movement, then you can just order your unit to move in the direction stored inside the variable.
He's not using move orders.
Anyway, the original post resembles the 'simplified AWSD' system posted a while ago, but mutated into a tank-crushing juggernaut. I don't think the original was really all that fast anyway - it is faster if you press nothing, but will actually do more work when you press multiple keys.
My suggestion is to throw out that mess and go with the tried and true: a single periodical trigger that adjusts heading based on which keys you pressed and then moves you forwards.
rrowland: wow, and there I thought I was the first to implement the bitfield solution. Mine is followed by a switch statement though, not nested ifs.
Really? I tried implementing a switch and the editor told me they weren't supported...