Find Nearest (>=) Graphics Mode

BlitzMax Forums/BlitzMax Beginners Area/Find Nearest (>=) Graphics Mode

MGE(Posted 2008) [#1]
I needed a routine to return the nearest graphics mode available to my game resolution. The returned mode has to be => than the requested mode. I think this routine is working, but it's been a long night. ;)

Usage:
xres:int=800
yres:int=600
FindNearestGraphicsMode(xres,yres)
If a mode was found, xres/yres will equal the new x/y resolution, otherwise they will equal zero.

Function FindNearestGraphicsMode(modex:Int Var,modey:Int Var)
 '
 Local workx:Int = 0
 Local worky:Int = 0
 Local match:Int = 0
 Local calcx:Int = 30000
 Local calcy:Int = 30000
 Local mode:TGraphicsMode
 '
 For mode = EachIn GraphicsModes()
  If match = 0
   If mode.width = modex And mode.height = modey
    modex = mode.width
    modey = mode.height
    match = 1
   EndIf
   If match = 0
    If mode.width >= modex And mode.height >= modey
     If (mode.width - modex) < calcx And (mode.height - modey) < calcy
      calcx = Mode.width - modex
      calcy = mode.height - modey
      workx = mode.width
      worky= mode.height
     EndIf
    EndIf
   EndIf
  EndIf
 Next
 '
 If match = 0
  If workx > 0 And worky > 0
   modex = workx
   modey = worky
  Else
   modex = 0
   modey = 0
  EndIf
 EndIf
 '
End Function



Grey Alien(Posted 2008) [#2]
Looks useful, I've bookmarked it.


JazzieB(Posted 2008) [#3]
I have a similar set of Functions myself, although mine look a little more complicated. Although, I do also take the aspect ratio into account as well.


GfK(Posted 2008) [#4]
Seems a bit lengthy. I'm sure there's a shorter way...


GfK(Posted 2008) [#5]
gWidth:Int = 800
gHeight:Int  = 600

findNearestGraphicsMode(gWidth,gHeight)
Print gWidth + "x" + gHeight

Function findNearestGraphicsMode(width:Int Var, height:Int Var)
        Local found:byte = False
	For m:TGraphicsMode = EachIn GraphicsModes()
		If m.width >= width
			If m.height >= height
				width = m.width
				height = m.height
				found = True
                                Exit
			EndIf
		EndIf
	Next
	If (Not Found)
                RuntimeError "No graphics mode found!"
        EndIf
End Function
I've set it to throw an error if it doesn't find a match. You could change it to zero the vars if you wanted to.


Dreamora(Posted 2008) [#6]
erm this fires an error on the first attempt ...
the runtime error should be after the loop, shouldn't it?

Might I ask for the logic of >= instead of <= and an >= with a temporal compy of height and width for the maximum (ie search for the maximum where m.width and m.height are larger than the current width and height and which is smaller than the maximum width and height).
Reason I ask: Smaller resolutions than that can be created, larger perhaps not depending on the screen, so it makes no sense (at least to me, why I ask this perhaps stupid question) to look for >= to me.


GfK(Posted 2008) [#7]
erm thats what happens when you type code straight into a reply box and don't test it. Error aside, its still 30% of the size of the original function.

Can't make head nor tail of your second paragraph, so I can't really help you there.


Bremer(Posted 2008) [#8]
This should fix the problem of always throwing the error.

gWidth:Int = 1280
gHeight:Int  = 720

findNearestGraphicsMode(gWidth,gHeight)
Print gWidth + "x" + gHeight

Function findNearestGraphicsMode(width:Int Var, height:Int Var)
	Local found:Int
	For m:TGraphicsMode = EachIn GraphicsModes()
		If m.width >= width
			If m.height >= height
				width = m.width
				height = m.height
				found = True
				Exit
			EndIf
		EndIf
	Next	
	If Not found Then RuntimeError "No graphics mode found!"
End Function



Dreamora(Posted 2008) [#9]
On the second part:

All these functions test if m.height >= height and m.width >= width.

My question is why larger than the initial size (given that the = can not be found) as it makes no sense to me to look for something that is larger than what you looked for and potentially larger than what the screen physically supports (if you were looking for the nearest fullscreen mode for example)

The other part was: why not such an approach to get the max "within the borders":

Function findNearestGraphicsMode(width:Int Var, height:Int Var)
  Local maxWidth:Int = width
  Local maxHeight:Int = height
  width = 0
  height = 0
  For Local m:TGraphicsMode = EachIn GraphicsModes()
	
    ' This size is larger than the desired sizes so drop it
    If m.width > maxWidth Or m.height > maxHeight    Continue
	
    If m.width >= width
      If m.height >= height
        width = m.width
        height = m.height
      EndIf
    EndIf
  Next	
  If height<> 0 And width <> 0 Return
  RuntimeError "No graphics mode found!"
End Function




GfK(Posted 2008) [#10]
Would you consider it to be retaliation/reflection of your own pickiness if I were to point out that you're missing an EndIf?

Also, your code will throw an error every time, whether it finds a resolution or not.


MGE(Posted 2008) [#11]
The suggested revisions do not work.

What my initial routine does is go through all the available modes and finds the "lowest resolution" that still fully accomidates the requested resolution.

This combined with sswift's projection matrix handling allows me to automatically setup the best full screen mode complete with proper aspect ratio and if needed auto widescreen/letterbox support.

This basically removes the need to worry about the desktop resolution and potentially running your game at the desktop res which could cause slow rendering speeds.


Dreamora(Posted 2008) [#12]
Gfk: where do I miss the endif? the middle ifs are closed (2 if, 2 endif), the first one does not need it, its a single line if check. If it throws an error then its a copy paste error from the board. I can compile it without any problem


MGE: Nice usage of such an automatic :) Did never think of such a simple adaptive solution