Original Post
Hi all, An interesting and perplexing (to me at least) bug has me scratching my head, and any help is much appreciated, as always! Basically, in my isometric strategy game (ala Civilization), I can scroll the world using either the arrow keys or via the cursor by placing it on a screen edge. And if I hold down either shift key or both, the scrolling is supposed to speed up either case. But what actually happens is, the left shift key works flawlessly, but the right shift key fails in a certain case. It fails to speed up scrolling if I press it prior to pressing an arrow key, but works fine if pressed after pressing the arrow key(s) and in all cases regarding cursor scrolling. Here's my code. xInc and yInc are pixel increment values, normally 2 horizontal pixels and 1 vertical pixel per scroll iteration, and 1/2 horizontal tile length and 1/2 vertical tile length if fast scrolling (tiles are 1/2 as high as they are wide, so I use HDiag (1/2 diagonal pixel length) and QDiag (quarter diag length) in the code. xPos and yPos are position relative to the center tile. The Center functions update which tile is center, and make sure xPos and yPos remain relative to the center tile. g_pcurMain is my main cursor object ptr. The 'ekey' enumerated type is just an OS & API independent key map to allow easy changes from DirectInput to Linux and Mac equivalents (when I get to them). Don;t know if this is a problem with DirectInput or not, so I put it here in General Programming. I think that covers it... so here's the code: Thanks for any help! :)
enum ekey // DIK equivalents
{
g_ceKEscape = DIK_ESCAPE,
g_ceK1,
g_ceK2,
g_ceK3,
//etc...
#define KeyDown(dikey) (g_diKeyState[dikey] & 0x80)
#define KeyDown_Shift() (KeyDown(DIK_LSHIFT) || KeyDown(DIK_RSHIFT))
#define KeyDownPrev(dikey) (g_diPrevKeyS[dikey] & 0x80)
#define KeyDownPrev_Shift() (KeyDownPrev(DIK_LSHIFT) || KeyDownPrev(DIK_RSHIFT))
// D I R E C T S C R O L L /////////////////////////////////////////////////
//
// Checks and executes key and mouse commands for direct scrolling the world
// view.
//
// return value - success or failure.
//
estate cworld::DirectScroll ()
{
// Check for direct scrolling.
if (!bLMBScrl)
{
// Check for accelerated key/edge scrolling
if (KeyDown_Shift ())
{
if (KeyDownPrev_Shift ())
{
xInc = nHDiag;
yInc = nQDiag;
}
else
{
if (bRight)
xInc = nHDiag - xPos;
if (bDownRight)
{
xInc = nHDiag - xPos;
yInc = nQDiag - yPos;
}
if (bDown)
yInc = nQDiag - yPos;
if (bDownLeft)
{
xInc = nHDiag + xPos;
yInc = nQDiag - yPos;
}
if (bLeft)
xInc = nHDiag + xPos;
if (bUpLeft)
{
xInc = nHDiag + xPos;
yInc = nQDiag + yPos;
}
if (bUp)
yInc = nQDiag + yPos;
if (bUpRight)
{
xInc = nHDiag - xPos;
yInc = nQDiag + yPos;
}
}
}
else
{
xInc = 2;
yInc = 1;
}
// Check for arrow key and/or screen edge scrolling requests.
bKeyScrl = false;
if (g_bGetInput)
{
if (((KeyDown (g_ceKRight) && KeyDown (g_ceKDown)) ||
g_pcurMain->DownRight ()) &&
!(bRight || bDown || bDownLeft ||
bLeft || bUpLeft || bUp || bUpRight))
{
xPos += xInc;
yPos += yInc;
CenterSE ();
bDownRight = true;
bKeyScrl = true;
}
if (((KeyDown (g_ceKDown) && KeyDown (g_ceKLeft)) ||
g_pcurMain->DownLeft ()) &&
!(bRight || bDownRight || bDown ||
bLeft || bUpLeft || bUp || bUpRight))
{
xPos -= xInc;
yPos += yInc;
CenterSW ();
bDownLeft = true;
bKeyScrl = true;
}
if (((KeyDown (g_ceKLeft) && KeyDown (g_ceKUp)) ||
g_pcurMain->UpLeft ()) &&
!(bRight || bDownRight || bDown ||
bDownLeft || bLeft || bUp || bUpRight))
{
xPos -= xInc;
yPos -= yInc;
CenterNW ();
bUpLeft = true;
bKeyScrl = true;
}
if (((KeyDown (g_ceKUp) && KeyDown (g_ceKRight)) ||
g_pcurMain->UpRight ()) &&
!(bRight || bDownRight || bDown ||
bDownLeft || bLeft || bUpLeft || bUp))
{
xPos += xInc;
yPos -= yInc;
CenterNE ();
bUpRight = true;
bKeyScrl = true;
}
if ((KeyDown (g_ceKRight) || g_pcurMain->Right ()) &&
!(bDownRight || bDown || bDownLeft ||
bLeft || bUpLeft || bUp || bUpRight))
{
if (KeyDown (g_ceKDown) || KeyDown (g_ceKUp))
{
bRight = true;
goto slow_down;
}
xPos += xInc;
CenterE ();
bRight = true;
bKeyScrl = true;
}
if ((KeyDown (g_ceKDown) || g_pcurMain->Down ()) &&
!(bRight || bDownRight || bDownLeft ||
bLeft || bUpLeft || bUp || bUpRight))
{
if (KeyDown (g_ceKRight) || KeyDown (g_ceKLeft))
{
bDown = true;
goto slow_down;
}
yPos += yInc;
CenterS ();
bDown = true;
bKeyScrl = true;
}
if ((KeyDown (g_ceKLeft) || g_pcurMain->Left ()) &&
!(bRight || bDownRight || bDown ||
bDownLeft || bUpLeft || bUp || bUpRight))
{
if (KeyDown (g_ceKDown) || KeyDown (g_ceKUp))
{
bLeft = true;
goto slow_down;
}
xPos -= xInc;
CenterW ();
bLeft = true;
bKeyScrl = true;
}
if ((KeyDown (g_ceKUp) || g_pcurMain->Up ()) &&
!(bRight || bDownRight || bDown ||
bDownLeft || bLeft || bUpLeft || bUpRight))
{
if (KeyDown (g_ceKRight) || KeyDown (g_ceKLeft))
{
bUp = true;
goto slow_down;
}
yPos -= yInc;
CenterN ();
bUp = true;
bKeyScrl = true;
}
}
// After key/edge release, continue scrolling until tiles are centered.
slow_down:
if (!bKeyScrl)
{
if (bDownRight)
{
xPos += xInc;
yPos += yInc;
CenterSE ();
if (!xPos)
bDownRight = false;
bKeyScrl = true;
}
if (bDownLeft)
{
xPos -= xInc;
yPos += yInc;
CenterSW ();
if (!xPos)
bDownLeft = false;
bKeyScrl = true;
}
if (bUpLeft)
{
xPos -= xInc;
yPos -= yInc;
CenterNW ();
if (!xPos)
bUpLeft = false;
bKeyScrl = true;
}
if (bUpRight)
{
xPos += xInc;
yPos -= yInc;
CenterNE ();
if (!xPos)
bUpRight = false;
bKeyScrl = true;
}
if (bRight)
{
xPos += xInc;
CenterE ();
if (!xPos)
bRight = false;
bKeyScrl = true;
}
if (bDown)
{
yPos += yInc;
CenterS ();
if (!yPos)
bDown = false;
bKeyScrl = true;
}
if (bLeft)
{
xPos -= xInc;
CenterW ();
if (!xPos)
bLeft = false;
bKeyScrl = true;
}
if (bUp)
{
yPos -= yInc;
CenterN ();
if (!yPos)
bUp = false;
bKeyScrl = true;
}
}
}
return g_eState;
}