How do I consistently re-size my game window and elements?
- by Milo
In my 2D game, I have a flow layout. Inside the flow layout are tables. I have a slider that lets the user make the tables larger or smaller. This makes the background larger or smaller too. Everything should scale proportionally which means the background should stay at the same position when I make things larger, and it almost does. When the scrollbar is at 0, it does exactly this. As the scrollbar gets further down problems arise. I'll toggle the slider maybe 3 times and on the fourth time, the background jumps a little lower on the Y axis.
In order to be efficient, I only start rendering the background near the parent of the flow layout. Here it is:
void LobbyTableManager::renderBG( GraphicsContext* g, agui::Rectangle& absRect, agui::Rectangle& childRect )
{
int cx, cy, cw, ch;
g->getClippingRect(cx,cy,cw,ch);
g->setClippingRect(absRect.getX(),absRect.getY(),absRect.getWidth(),absRect.getHeight());
float scale = 0.35f;
int w = m_bgSprite->getWidth() * getTableScale() * scale;
int h = m_bgSprite->getHeight() * getTableScale() * scale;
int numX = ceil(absRect.getWidth() / (float)w) + 2;
int numY = ceil(absRect.getHeight() / (float)h) + 2;
float offsetX = m_activeTables[0]->getLocation().getX() - w;
float offsetY = m_activeTables[0]->getLocation().getY() - h;
int startY = childRect.getY();
if(moo)
{
std::cout << "S=" << startY << ",";
}
int numAttempts = 0;
while(startY + h < absRect.getY() && numAttempts < 1000)
{
startY += h;
if(moo)
{
std::cout << startY << ",";
}
numAttempts++;
}
if(moo)
{
std::cout << "\n";
moo = false;
}
g->holdDrawing();
for(int i = 0; i < numX; ++i)
{
for(int j = 0; j < numY; ++j)
{
g->drawScaledSprite(m_bgSprite,0,0,m_bgSprite->getWidth(),m_bgSprite->getHeight(),
absRect.getX() + (i * w) + (offsetX),absRect.getY() + (j * h) + startY,w,h,0);
}
}
g->unholdDrawing();
g->setClippingRect(cx,cy,cw,ch);
}
The numeric problem seems to be in the value of startY.
I outputted startY figuring out its value:
As you can see here, this is me only zooming in, pay attention to the final number before the next s=. You'll notice that, what should happen is, the numbers should be linear, ex: -40, -38, -36, -34, -32, -30, etc. As you'll notice, the start numbers linearly correlate ex: 62k, 64k, 66k, 68k, 70k etc.. but the end result is wrong every third or 4th time.
Here is most of the resize code:
void LobbyTableManager::setTableScale( float scale )
{
scale += 0.3f;
scale *= 2.0f;
agui::Gui* gotGui = getGui();
float scrollRel = m_vScroll->getRelativeValue();
setScale(scale);
rescaleTables();
resizeFlow();
if(gotGui)
{
gotGui->toggleWidgetLocationChanged(false);
}
updateScrollBars();
float newVal = scrollRel * m_vScroll->getMaxValue();
if((int)(newVal + 0.5f) > (int)newVal)
{
newVal++;
}
m_vScroll->setValue(newVal);
static int x = 0;
x++;
moo = true;
//std::cout << m_vScroll->getValue() << std::endl;
if(gotGui)
{
gotGui->toggleWidgetLocationChanged(true);
}
if(gotGui)
{
gotGui->_widgetLocationChanged();
}
}
void LobbyTableManager::valueChanged( agui::VScrollBar* source,int val )
{
if(getGui())
{
getGui()->toggleWidgetLocationChanged(false);
}
m_flow->setLocation(0,-val);
if(getGui())
{
getGui()->toggleWidgetLocationChanged(true);
getGui()->_widgetLocationChanged();
}
}