Just figured out why the rendering messes up when I try a virtual resolution with a different aspect ratio of that of my monitor.
The problem is that renderToImage() behaves radically different than I had expected.
Quote the documentation:
"when you render to an image it will draw to the image exactly what it would have drawn to the screen"
This means that if my virtual resolution has a different aspect ratio than my monitor, and I render to an image, then that image will include black bars to make the virtual resolution fit the monitor.
So I tried playing along with this. The code below works. Only problem is that I can't figure out how to calculate the values for CreateRenderImage()
It should be based on screenW x screenH, but with width or hight extended to make it match the monitor's aspect ratio (so it fits how screenW x screenH will be displayed with black borders added)
CreateRenderImage( sceneImg, 640, screenH, 0, 0 ) is right in this case, since extending the width from 200 to 640 makes it fit a 16:9 aspect ratio if black borders are added to the sides. But how do I find those numbers?
// This is my pixelart screen res
#constant screenW 200
#constant screenH 360 // weird values
#constant KEY_ESCAPE 27
#constant KEY_SPACE 32
#constant TRUE 1
#constant FALSE 0
SetErrorMode(2)
// set window properties
SetWindowTitle( "thing for pixelart maybe" )
SetWindowSize( 140, 360, 1 ) // "1" goes fullscreen (the first two values have no effect)
SetWindowAllowResize( 0 ) // Don't allow the user to resize the window
SetVirtualResolution( screenW,screenH )
SetVSync(1)
SetResolutionMode(1)
UseNewDefaultFonts(1) // since version 2.0.22 we can use nicer default fonts
SetClearColor(40,40,40)
SetBorderColor(0,0,0)
SetDefaultMagFilter(0) // 0 nearest 1 liniar
SetDefaultMinFilter(0)
SetGenerateMipmaps(0)
SetAntialiasMode(0)
SetRawMouseVisible(0)
// calculate the time passed between frames
// use this value as a multiplier that gets applied to any movement.
// (it is the time difference between this frame and the last)
Global fDif as float
// create render image
global sceneImg as integer
sceneImg = 1
CreateRenderImage( sceneImg, 640, screenH, 0, 0 )
SetImageMagFilter( sceneImg, 0 )
SetImageMinFilter( sceneImg, 0 )
// create sprite to display the render image
Global screenSpr as integer
ScreenSpr = createSprite(sceneImg)
SetSpriteSize(screenSpr,GetDeviceWidth(),getDeviceHeight() )
SetSpriteDepth (ScreenSpr, 3)
// Hero sprite you can move with WASD
global heroSpr
heroSpr = createsprite(0)
SetSpriteColor( heroSpr, 20, 255, 0, 255 )
SetSpritePosition(heroSpr, 10, 10)
SetSpriteSnap ( heroSpr, 1 )
setSpriteSize (heroSpr, 3.0, 3.0) // Why is a sprite size in floats???
setSpriteDepth (heroSpr,50)
SetSpritePhysicsOn(heroSpr,2) // 1: static; 2: dynamic; 3:kinematic
SetSpritePhysicsCanRotate( heroSpr, 0 ) // 1 to allow rotation, 0 to prevent it.
SetSpritePhysicsDamping( heroSpr, 2.0 )
SetSpritePhysicsMass( heroSpr, 0.1 )
SetPhysicsGravity( 0.0, 0.0 )
SetPhysicsScale( 0.10 )
SetPhysicsWallBottom(1)
SetPhysicsWallLeft(1)
SetPhysicsWallRight(1)
SetPhysicsWallTop(1)
pushForce as float = 10.0
repeat
SetVirtualResolution( screenW,screenH )
fDif = GetFrameTime() // multiply any movement stuff with fDif
if GetRawKeyState (65) = TRUE then SetSpritePhysicsForce(heroSpr,GetSpriteXByOffset(heroSpr),GetSpriteYByOffset(heroSpr),-pushForce,0) // "A" Move player
if GetRawKeyState (87) = TRUE then SetSpritePhysicsForce(heroSpr,GetSpriteXByOffset(heroSpr),GetSpriteYByOffset(heroSpr),0,-pushForce) // "W"
if GetRawKeyState (83) = TRUE then SetSpritePhysicsForce(heroSpr,GetSpriteXByOffset(heroSpr),GetSpriteYByOffset(heroSpr),0,pushForce) // "S"
if GetRawKeyState (68) = TRUE then SetSpritePhysicsForce(heroSpr,GetSpriteXByOffset(heroSpr),GetSpriteYByOffset(heroSpr),pushForce,0) // "D"
// Render scene to an image
SetBorderColor(255,0,0) // red borders (just so you can see that the borders are saved to the image)
Update(0) //update sprite positions
SetRenderToImage( sceneImg, 0) //set the world to render to the Texture Image
ClearScreen() // Clears back buffer and fills it with the chosen clear color
Render() //render the world to the Texture Image ... THE ERROR IS HERE!!!
// Save a screenshot. This confirms that the image size is screenW X screenH (200x360)
// HOWEVER, it has captured "the virtual resolution AS IT SHOULD WOULD HAVE BEEN DISPLAYED ON THE MONITORS 16:9 resolution"
// if getRawKeyPressed(KEY_SPACE) then saveImage( sceneImg, "raw:" + GetDocumentsPath() + "\SAVEDIMG_978689.jpg") // JPG to get see the border color. (.png gives transparency)
SetVirtualResolution( GetDeviceWidth(),getDeviceHeight() ) // because this is the aspect ratio of the rendered image
// Try to display that image to the screen
SetRenderToScreen() //set the world to render to the screen
SetBorderColor(0,0,255) // blue borders
ClearScreen() //clear the buffer of old data
setSpriteVisible (ScreenSpr, TRUE)
DrawSprite( ScreenSpr )
Swap() //displays the buffer to the screen
setSpriteVisible (ScreenSpr, FALSE)
until GetRawKeyPressed (KEY_ESCAPE) = TRUE
end