I'd never use #defines in the manner in which I posted. that was just copied straight out of an MFC class...oops did i just admit that. Slap my wrist for not posting good style....as well as the bitwise operator bug....I'll get my coat.
Bitwise Operations
Quote:Original post by Serapth
Why dont you ever see something like:#pragma pack(1)struct _PackedChar { const unsigned char bitOne :1; const unsigned char bitTwo :1; const unsigned char bitThree :1; const unsigned char bitFour :1; const unsigned char bitFive :1; const unsigned char bitSix :1; const unsigned char bitSeven :1; const unsigned char bitEight :1;};#pragma pack()
One reason is that the order of the members may vary between compilers and platforms. Thus it is not portable in many circumstances (such as data loaded from a file). Another is that it is more convenient to waste a few bytes and just use bools.
Quote:Original post by JohnBoltonQuote:Original post by Serapth
Why dont you ever see something like:#pragma pack(1)struct _PackedChar { const unsigned char bitOne :1; const unsigned char bitTwo :1; const unsigned char bitThree :1; const unsigned char bitFour :1; const unsigned char bitFive :1; const unsigned char bitSix :1; const unsigned char bitSeven :1; const unsigned char bitEight :1;};#pragma pack()
One reason is that the order of the members may vary between compilers and platforms. Thus it is not portable in many circumstances (such as data loaded from a file). Another is that it is more convenient to waste a few bytes and just use bools.
Order wouldnt matter though, would it? I mean, even if you run it on a machine with different endian-ness _PackedChar.bitOne would resolve to the same value. Infact, wouldnt that solve endian issues? I mean, if your code used say WM_PAINT with a value of say 0x0001, unless you have a conditional define for reversed endian processors, the value you mask WM_PAINT against will fail?
If anything, I would think a packed bit struct would be more portable then a #define... not that I like either.
He's talking about the situation where you write out a PackedChar to a file, and then read it back in as a char, on a different platform - or even the same platform, with the code compiled by a different compiler, or different compiler settings.
I have seen it used in older game programming books(lamothe game programming books) in regard to mouse and joystick input using the win32api.
The new and easier way is to use directx.
See for yourself how it was used to detect mouse and joystick input here
And as you can see here is some of my code for a win32api game engine and it's pretty ugly:
where
typedef WORD JOYSTATE;
const JOYSTATE JOY_NONE = 0x0000L,
JOY_LEFT = 0x0001L,
JOY_RIGHT = 0x0002L,
JOY_UP = 0x0004L,
JOY_DOWN = 0x0008L,
JOY_FIRE1 = 0x0010L,
JOY_FIRE2 = 0x0020L;
The new and easier way is to use directx.
See for yourself how it was used to detect mouse and joystick input here
And as you can see here is some of my code for a win32api game engine and it's pretty ugly:
[source language=cpp]BOOL GameEngine::InitJoystick(){ // Make sure joystick driver is present UINT uiNumJoysticks; if ((uiNumJoysticks = joyGetNumDevs()) == 0) return FALSE; // Make sure the joystick is attached JOYINFO jiInfo; if (joyGetPos(JOYSTICKID1, &jiInfo) != JOYERR_UNPLUGGED) m_uiJoystickID = JOYSTICKID1; else return FALSE; // Calculate the trip values JOYCAPS jcCaps; joyGetDevCaps(m_uiJoystickID, &jcCaps, sizeof(JOYCAPS)); DWORD dwXCenter = ((DWORD)jcCaps.wXmin + jcCaps.wXmax) / 2; DWORD dwYCenter = ((DWORD)jcCaps.wYmin + jcCaps.wYmax) / 2; m_rcJoystickTrip.left = (jcCaps.wXmin + (WORD)dwXCenter) / 2; m_rcJoystickTrip.right = (jcCaps.wXmax + (WORD)dwXCenter) / 2; m_rcJoystickTrip.top = (jcCaps.wYmin + (WORD)dwYCenter) / 2; m_rcJoystickTrip.bottom = (jcCaps.wYmax + (WORD)dwYCenter) / 2; return TRUE;}void GameEngine::CaptureJoystick(){ // Capture the joystick if (m_uiJoystickID == JOYSTICKID1) joySetCapture(m_hWindow, m_uiJoystickID, NULL, TRUE);}void GameEngine::ReleaseJoystick(){ // Release the joystick if (m_uiJoystickID == JOYSTICKID1) joyReleaseCapture(m_uiJoystickID);}void GameEngine::CheckJoystick(){ if (m_uiJoystickID == JOYSTICKID1) { JOYINFO jiInfo; JOYSTATE jsJoystickState = 0; if (joyGetPos(m_uiJoystickID, &jiInfo) == JOYERR_NOERROR) { // Check horizontal movement if (jiInfo.wXpos < (WORD)m_rcJoystickTrip.left) jsJoystickState |= JOY_LEFT; else if (jiInfo.wXpos > (WORD)m_rcJoystickTrip.right) jsJoystickState |= JOY_RIGHT; // Check vertical movement if (jiInfo.wYpos < (WORD)m_rcJoystickTrip.top) jsJoystickState |= JOY_UP; else if (jiInfo.wYpos > (WORD)m_rcJoystickTrip.bottom) jsJoystickState |= JOY_DOWN; // Check buttons if(jiInfo.wButtons & JOY_BUTTON1) jsJoystickState |= JOY_FIRE1; if(jiInfo.wButtons & JOY_BUTTON2) jsJoystickState |= JOY_FIRE2; } // Allow the game to handle the joystick HandleJoystick(jsJoystickState); }
where
typedef WORD JOYSTATE;
const JOYSTATE JOY_NONE = 0x0000L,
JOY_LEFT = 0x0001L,
JOY_RIGHT = 0x0002L,
JOY_UP = 0x0004L,
JOY_DOWN = 0x0008L,
JOY_FIRE1 = 0x0010L,
JOY_FIRE2 = 0x0020L;
I have another question about bitwise operations. How do you know what bitwise operator to use in your program? Do you just experient with combining two binary numbers until you get the result you want or is there a method to the madness? I know shifting multiplies and divides, but what does & and | do other then compare bits of two differnt numbers?
You use | to set them and & to check them. Using my example above:
status = DEAD; // => 0000 0010
// Set it
status = status | ALIVE; // easier is status |= ALIVE;
This will do
If you want to check to see if the DEAD flag is set you do:
if ( status & DEAD )...
This will do:
if the flag is not set, say UNDEAD
if ( status & UNDEAD )
status = DEAD; // => 0000 0010
// Set it
status = status | ALIVE; // easier is status |= ALIVE;
This will do
0000 0010 OR0000 0001-----------0000 0011 = 3 => New value for status ( note how it didn't affect the DEAD bit )
If you want to check to see if the DEAD flag is set you do:
if ( status & DEAD )...
This will do:
0000 0011 AND0000 0010--------------0000 0010 => Non zero = true
if the flag is not set, say UNDEAD
if ( status & UNDEAD )
0000 0011 AND0000 0100----------0000 0000 => 0 = false (flag not set)
AND(&) asks are the bits in value1 and value2 both 1, then it remains 1, otherwise it is set to 0.
For example 0101 & 0100 would become 0100
OR(|) asks if either bit is 1, if either is 1 ( or both bits ), the result is 1.
For example 1100 | 0101 would become 1101
For example 0101 & 0100 would become 0100
OR(|) asks if either bit is 1, if either is 1 ( or both bits ), the result is 1.
For example 1100 | 0101 would become 1101
With | your person is both dead and alive? lol Sets flags to both dead and alive?
With & your person is dead. Checks to see if the flag for dead is set?
With & your person is dead. Checks to see if the flag for dead is set?
Quote:Original post by Chris27
I have another question about bitwise operations. How do you know what bitwise operator to use in your program? Do you just experient with combining two binary numbers until you get the result you want or is there a method to the madness? I know shifting multiplies and divides, but what does & and | do other then compare bits of two differnt numbers?
The operators are named after their boolean algebra equivalents. Your probably want to learn how binary and hexadecimal works as well if you really want to understand what is going on.
&(and) = any bit multipled by a 0 becomes 0.
101010& 110110-------- 100010
Say you had a byte and wanted to get what just the last two bits equaled:
unsigned char SomeByte = 0x9A;
unsigned char Upper2Bits = SomeByte & 0x60;
This is equal to:
10011010(SomeByte)& 11000000(0x60)---------- 10000000(Upper2Bits);
|(or) = any bit plus 1 becomes 1.
101010| 110110-------- 111110
Using daviangel's example lets say we have a 16-bit integer with data from the joystick. Now if you want to know if the FIRE1 button was press:
10111000(Joystick data)& 00010000(JOY_FIRE1, 0x0010)---------- 00010000(Above 0 = true);
Now if you wanted to set the JOY_FIRE1 bit:
10101000(Joystick data)| 00010000(JOY_FIRE1, 0x0010)---------- 10111000(Joystick data now has JOY_FIRE1 set);
If you still don't understand it, do searches for binary, boolean algebra and hexadecimal(preferably in that order).
Edit: Way too slow :(
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement