1
\$\begingroup\$

Considering I have four variables event binded to each arrow key, that can be 0 or 1

My current approach to this issue is simply 8 nested ifs checking each combination or keys

Is there a more math-y clever way to solve this issue?

\$\endgroup\$
  • \$\begingroup\$ Use piece wise functions. love2d automatically converts true to 1 and false to 0. Therefore, you can use the conditional as the assignment value. Definitely an important optimization to make. I've seen movement systems without fixing that where the lag just keeps building upon itself as more entities are spawned in. \$\endgroup\$ – user64742 Oct 13 '16 at 3:34
6
\$\begingroup\$

Given 4 variables up left down right with values zero or one, the simplest method is to define a 2-component direction vector (dx, dy) like so:

dx = right - left
dy = up - down

(No conditionals required!)

If you need more specialized logic/behaviour for each direction, I'd be inclined to do something like...

directionIndex = 3 * (up - down) + right - left;

Then the directions shake out like so:

-4 down-left
-3 down
-2 down-right
-1 left
 0 center / canceling
 1 right
 2 up-left
 3 up
 4 up-right

If you store an array of 9 direction vectors, you can add 4 to the index above to look up into your (zero-based) array, getting your direction in a single table lookup, again branch-free.

Or you could use this index as the control for a single switch-case statement, to do unique actions for each direction without more than one level of nesting. (Since I see you're asking about LÖVE, you can use a Lua analog of a switch like this)

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This is by far the more useful answer, imo. I have been considering for many years how one would make motion in different coordinate systems for different shapes in 3D stuff or whatever. This is inherently much more useful because one can easily make the directions anything you need them to be (even function data types if the direction varies by position!). \$\endgroup\$ – user64742 Oct 13 '16 at 3:26
  • \$\begingroup\$ And a function data type is merely a tree of different math operator objects holding math operator objects. Evaluating it would be done via recursive calling down the tree. \$\endgroup\$ – user64742 Oct 13 '16 at 3:36
4
\$\begingroup\$

A common method is to combine the opposite direction keys into a single axis, giving you X and Y movements, then you combine the X and Y into a single 2D movement vector.

Here's what that code might look like:

local dx,dy = 0,0
if (keyPressed.up) then dy = dy - 1 end
if (keyPressed.down) then dy = dy + 1 end
if (keyPressed.left) then dx = dx - 1 end
if (keyPressed.right) then dx = dx + 1 end

You need to decide a few things from here:

  • What to do if the player presses opposite directions (e.g. left and right) together. The example given cancels them both out, but perhaps you want to have one override the other.
  • If diagonals should be faster than single axis directions. If not, find a decent 2D vector library and use normalise.

This method has the advantage of being adaptable across different input devices. Gamepads for example will give you analog stick input as X and Y values between -1 and 1.

The code here is not too bad but still seems repetitive - there are four virtually identical if conditions. But you'll see a lot of code like this when dealing with 2D (or 3D) problems. It's possible to refactor this code to have less repetition but there's a tradeoff between math-heavy code that's non-obvious. You need to decide whether having less repetitive code that's harder to understand is worth it.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ true and false in love2d are automatically converted to 1 and 0.Therefore,the if then clause is pointless.One can simply assign the condition to the variables for dx and dy.This is by far a more useful solution as parallelism in computer hardware will try to predict which branch the code will go down while other values are still catching up.If those values cause the if branch to not be evaluated the way the hardware predicted,it ends up wasting processing power which can contribute to bottlenecks and lag.Always try to eliminate simple if statements like this.It is a VITAL optimization :) \$\endgroup\$ – user64742 Oct 13 '16 at 3:29
  • \$\begingroup\$ @thegreatduck what a ridiculous statement. Besides, this answer is better as it talks about the strafe run problem. I.e. diagonals are faster than cardinal movement if you don't treat them as proper vectors and normalise. \$\endgroup\$ – Pod Oct 13 '16 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.