diff --git a/mkxp.conf b/mkxp.conf index 58c3e26..6e81adc 100644 --- a/mkxp.conf +++ b/mkxp.conf @@ -2,6 +2,7 @@ debugMode=true winResizable=true fullscreen=false +fixedAspectRatio=false vsync=true defScreenW=640 defScreenH=480 diff --git a/src/config.cpp b/src/config.cpp index bccf0c3..eacb4e7 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -32,6 +32,7 @@ Config::Config() : debugMode(false), winResizable(false), fullscreen(false), + fixedAspectRatio(false), vsync(false), defScreenW(640), defScreenH(480), @@ -48,6 +49,7 @@ void Config::read() READ_VAL(debugMode, Bool); READ_VAL(winResizable, Bool); READ_VAL(fullscreen, Bool); + READ_VAL(fixedAspectRatio, Bool); READ_VAL(vsync, Bool); READ_VAL(defScreenW, Int); READ_VAL(defScreenH, Int); diff --git a/src/config.h b/src/config.h index b603eaa..d0e93bf 100644 --- a/src/config.h +++ b/src/config.h @@ -33,6 +33,7 @@ struct Config bool winResizable; bool fullscreen; + bool fixedAspectRatio; bool vsync; int defScreenW; diff --git a/src/eventthread.h b/src/eventthread.h index e949c8b..c479a98 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -150,6 +150,7 @@ struct RGSSThreadData SDL_Window *window; Vec2 sizeResoRatio; + Vec2i screenOffset; Config config; diff --git a/src/graphics.cpp b/src/graphics.cpp index a0199f0..15ba8d9 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -451,11 +451,23 @@ struct Timer struct GraphicsPrivate { - /* Screen resolution */ + /* Screen resolution, ie. the resolution at which + * RGSS renders at (settable with Graphics.width/height). + * Can only be changed from within RGSS */ Vec2i scRes; - /* Actual screen size */ + + /* Screen size, to which the rendered frames are scaled up. + * This can be smaller than the window size when fixed aspect + * ratio is enforced */ Vec2i scSize; + /* Actual physical size of the game window */ + Vec2i winSize; + + /* Offset in the game window at which the scaled game screen + * is blitted inside the game window */ + Vec2i scOffset; + ScreenScene screen; RGSSThreadData *threadData; @@ -477,6 +489,7 @@ struct GraphicsPrivate GraphicsPrivate() : scRes(640, 480), scSize(scRes), + winSize(scRes), screen(scRes.x, scRes.y), frameRate(40), frameCount(0), @@ -515,12 +528,38 @@ struct GraphicsPrivate Vec2 &ratio = gState->rtData().sizeResoRatio; ratio.x = (float) scRes.x / scSize.x; ratio.y = (float) scRes.y / scSize.y; + + gState->rtData().screenOffset = scOffset; + } + + /* Enforces fixed aspect ratio, if desired */ + void recalculateScreenSize() + { + scSize = winSize; + + if (!gState->config().fixedAspectRatio) + { + scOffset = Vec2i(0, 0); + return; + } + + float resRatio = (float) scRes.x / scRes.y; + float winRatio = (float) winSize.x / winSize.y; + + if (resRatio > winRatio) + scSize.y = scSize.x / resRatio; + else if (resRatio < winRatio) + scSize.x = scSize.y * resRatio; + + scOffset.x = (winSize.x - scSize.x) / 2.f; + scOffset.y = (winSize.y - scSize.y) / 2.f; } void checkResize() { - if (threadData->windowSizeMsg.pollChange(&scSize.x, &scSize.y)) + if (threadData->windowSizeMsg.pollChange(&winSize.x, &winSize.y)) { + recalculateScreenSize(); screen.setScreenSize(scSize.x, scSize.y); updateScreenResoRatio(); } @@ -549,19 +588,10 @@ struct GraphicsPrivate FBO::blit(0, 0, 0, 0, scRes.x, scRes.y); } - void blitBuffer() - { - FBO::blit(0, 0, 0, 0, scRes.x, scRes.y); - } - - void blitBufferScaled() - { - FBO::blit(0, 0, scRes.x, scRes.y, 0, 0, scSize.x, scSize.y); - } - void blitBufferFlippedScaled() { - FBO::blit(0, 0, scRes.x, scRes.y, 0, scSize.y, scSize.x, -scSize.y); + FBO::blit(0, 0, scRes.x, scRes.y, + scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y); } /* Blits currently bound read FBO to screen (upside-down) */ diff --git a/src/input.cpp b/src/input.cpp index f070275..364bed3 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -618,12 +618,14 @@ int Input::dir8Value() int Input::mouseX() { - return EventThread::mouseState.x * gState->rtData().sizeResoRatio.x; + RGSSThreadData &rtData = gState->rtData(); + return (EventThread::mouseState.x - rtData.screenOffset.x) * rtData.sizeResoRatio.x; } int Input::mouseY() { - return EventThread::mouseState.y * gState->rtData().sizeResoRatio.y; + RGSSThreadData &rtData = gState->rtData(); + return (EventThread::mouseState.y - rtData.screenOffset.y) * rtData.sizeResoRatio.y; } Input::~Input()