Direction Booleans into single Integer

Started by
17 comments, last by frob 8 years, 11 months ago

Hey,

i have Input Data from a Gamepads DPad in form of 4 Booleans (Up, Down, Left and Right).

I need those to be converted into an Integer ranging from 0 to 8, where 0 is the Null State.


Up		1		0000 0001
Up-Right	2		0000 0010
Right		3		0000 0011
Down-Right	4		0000 0100
Down		5		0000 0101
Down-Left	6		0000 0110
Left		7		0000 0111
Up-Left		8		0000 1000

I haven't come up with a nice solution, nor found any pattern yet. So that's what i am asking for. Is there any nice Bit Operation Magic to put that into 1-5 nice lines?

Currently i am using this trivial but horrible way:


        if (Up && Down)
	{
		Up = FALSE;
		Down = FALSE;
	}

	if (Left && Right)
	{
		Left = FALSE;
		Right = FALSE;
	}

	if (Left)
	{
		ReportByte[0] = 0x07;
	}
	else if (Right)
	{
		ReportByte[0] = 0x03;
	}

	if (Up)
	{
		if (Right)
		{
			ReportByte[0] = 0x02;
		}
		else if (Left)
		{
			ReportByte[0] = 0x08;
		}
		else
		{
			ReportByte[0] = 0x01;
		}
	}
	else if (Down)
	{
		if (Right)
		{
			ReportByte[0] = 0x04;
		}
		else if (Left)
		{
			ReportByte[0] = 0x06;
		}
		else
		{
			ReportByte[0] = 0x05;
		}
	}

So any suggestions are welcome.

Blog: http://www.julianloehr.de

Twitter: https://twitter.com/jloehr_gamedev

HID Wiimote - Windows Device Driver for Wii Remote & Wii U Pro Controller: http://julianloehr.de/educational-work/hid-wiimote/

Advertisement

Does any 0 to 8 mapping work, or are you set on using the constants in your table?

Use a bit field. Also, why is this in Coding Horrors?

Following code is C# but the bitfield concept holds elsewhere:


[Flags]
public enum Direction
{
  None  = 0,
  Up    = 1,
  Down  = 2,
  Left  = 4,
  Right = 8,

  UpLeft = Up | Left,
  UpRight = Up | Right,
  DownLeft = Down | Left,
  DownRight = Down | Right,
}
Use | and & to perform bitwise manipulation.



This breaks your existing values, but will be much easier to deal with in the long run.

If the 0-8 range cannot be changed, then just go with your current code; it's not that bad.

The 0-8 range and values are fix and cannot be changed.

I forgot to mention that the code is for a Windows Kernel-Mode Driver, so it's Microsoft C and it uses the Windows Kernel-Mode Run-Time Library(Rtl) instead of STL.

On one hand i personally just don't like such nested multi-branch conditional statements. I think they are not good in terms of readability and maintainability.

On the other hand i just tinkered around myself and wasn't able to find any bit pattern for such conversion. So i am just curious if there is one.

I put it into coding horros because of the forums description. If this topic might be better suited in the General Programming forum feel free to move it.

Blog: http://www.julianloehr.de

Twitter: https://twitter.com/jloehr_gamedev

HID Wiimote - Windows Device Driver for Wii Remote & Wii U Pro Controller: http://julianloehr.de/educational-work/hid-wiimote/

In that case, you can do the bitfield as a temporary, then use that in a lookup table (this is C-like pseudocode so it won't necessarily actually compile):


int lookups[] = { 0, 1, 5, 0, 7, 8, 6, 7, 3, 2, 4, 3, 0, 1, 5, 0 };

int index = (up ? 1 : 0) + (down ? 2 : 0) + (left ? 4 : 0) + (right ? 8 : 0);

ReportByte[0] = lookups[index];
Should be damn efficient, and the code is compact.


(edit) My lookup table had zeroes for all of the 3-bit combinations instead of only cancelling out the opposing directions. Fixed.
Well, since we are in the coding horrors forum, I give you a branch-less, lookup table free solution:

return (up * (1 + down * 3 * (1 + 2 * (left + right + left * right)) + right * (7 + left * 2)) +
        down * (5 + left * 3 + right * 5 + left * right) + left * 7 + right * 3 + left * right * 8) % 9
This assumes up, down, left, right are always 0 or 1. This simplifies quite a bit if you don't need to support the situation where both up and down or left and right are true at the same time.

return (up * (1 + right * 7) + down * (5 + left * 3 + right * 5) + left * 7 + right * 3) % 9

Well, since we are in the coding horrors forum...


Well, we sure are NOW anyway smile.png

int lookup[3][3] = {
{8,1,2},
{7,0,3},
{6,5,4}
};
int direction = lookup[1+down-up][1+right-left];

I thought this is a nice way to represent it if you go with a lookup... Array has only the values you need, and theyre arranged visually so its easy to change them if you want. You can easily extend it into 3D too if you need another axis of freedom.

o3o

STOP

Previously "Krohm"

Why stop?

Waterlimons proposal looks good, i think i am going to use that.

Blog: http://www.julianloehr.de

Twitter: https://twitter.com/jloehr_gamedev

HID Wiimote - Windows Device Driver for Wii Remote & Wii U Pro Controller: http://julianloehr.de/educational-work/hid-wiimote/

This topic is closed to new replies.

Advertisement