Don't scale controls (Autofit)

Monkey Forums/Monkey Programming/Don't scale controls (Autofit)

erebel55(Posted 2014) [#1]
I am using autofit, but I don't think it makes since to scale the virtual controls (left/right move and jump buttons).

Is there some way to tell autofit not to scale them?

Thanks


DruggedBunny(Posted 2014) [#2]
It should be possible to do something like:

Method OnUpdate ()

	' Check for on-screen control hits using plain MouseX/MouseY instead of VMouseX/VMouseY
	
End

Method OnRender ()

	UpdateVirtualDisplay

	Cls

	' Draw game...

	PushMatrix
		Scale Your_X_Scale, Your_Y_Scale
		' Draw controls
	PopMatrix

End


... not tested though!


erebel55(Posted 2014) [#3]
Thanks DruggedBunny

I gave that a try, but it still looks to be scaling the buttons when I resize the window.

	Method OnRender:Int()
		UpdateVirtualDisplay()
		Cls 
		level.Draw()
		player.Draw()
		
		
		' don't scale controls
		PushMatrix
			'Scale 1,1
			
			' draw buttons
			restartButton.Draw()
			moveLeftButton.Draw()
			moveRightButton.Draw()
			jumpButton.Draw()
			
		PopMatrix
		return 0
	End Method	



DruggedBunny(Posted 2014) [#4]
Sorry, kinda forgot about this -- that clearly didn't work, but I have just whipped up this test version with a new command, DisableVirtualDisplay, along with optional commands to store the virtual display (before you disable it) and to restore it afterwards.

http://www.hi-toro.com/monkey/autofit/autofit_test.zip

You can (hopefully) just call DisableVirtualDisplay after all your other drawing is complete, then draw your overlay.

However, if you still need (for whatever reason) to get back to the virtual display after drawing your overlay, then you need to:

1) store the virtual display settings with StoreVirtualDisplay;
2) use the full display area with DisableVirtualDisplay;
3) put the virtual display back in place with RestoreVirtualDisplay.

The demo uses the Space key to disable the virtual display, draws a green rectangle using the full device display area/scaling, then draws a red rectangle demonstrating that the virtual display is back in place.

Only tested on this little demo!


erebel55(Posted 2014) [#5]
This is awesome, I'm going to take a look now :D

Edit: That worked perfectly.
Thank you!

(By the way, it would be amazing if you could look at my Autofit Portrait vs Landscape thread too. I have been anxiously waiting for you to see it)


SLotman(Posted 2014) [#6]
Is it a wise choice to *not* scale controls? Say you make your game at 480x800 - then you run it on a phone with 240x320 resolution... your control is going to be too big, if not scaled down!
Now say you run the same game on a Retina iphone... 2048x1536, your control is going to be much smaller!

I understand the need to scale controls, so in 10' devices it won't become huge... but just setting the scale to 1,1 seems very wrong to me... maybe the best approach would be to detect display size and dpi and then scale accordingly? (I currently not doing that - I just leave everything scaled and just pray for the best =P)


Supertino(Posted 2014) [#7]
I think you should at least give the user the option to resize the controls, I'd give the user 3 levels based on % of screen space.

If you want to go further you can return the bucket DPI and bucket Density of a screen and use that to scale your controls to real values such as cm and inches, it wont be 100% on all devices but should be with a 10% tolerance,

Here is a good explanation of it http://www.captechconsulting.com/blog/steven-byle/understanding-density-independence-android
Here is me trying to figure it all out http://www.monkeycoder.co.nz/Community/posts.php?topic=4958


Powelly(Posted 2014) [#8]
This is the way I've done it:

Java code:
("androiddpi.java" file)
class AndroidDpi {
	public static int GetAndroidDpi() {
		DisplayMetrics metrics = new DisplayMetrics();
		BBAndroidGame._androidGame._activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
		int dpi= metrics.densityDpi;
		return dpi;
	}
	
	public static float GetAndroidXDpi() {
		DisplayMetrics metrics = new DisplayMetrics();
		BBAndroidGame._androidGame._activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
		float dpi= metrics.xdpi ;
		return dpi;
	}
}


Monkey code:
Field preVirtualMatrix:Float[]
Field dpiScale:Float = 1
Field buttonWidth:Float
Field buttonHeight:Float

Method OnCreate:Int()
	...
	dpiScale = AndroidDpi.GetAndroidXDpi() / 160 ' Button images are the correct size at 160 dpi
	buttonWidth = buttonLeftImage.Width() * dpiScale
	buttonHeight = buttonLeftImage.Height() * dpiScale
	...
End
	
Method OnRender:Int()
	preVirtualMatrix = GetMatrix()
	UpdateVirtualDisplay()
	
	'Draw normal screen here
	
	'Draw on screen controls last
	SetMatrix(preVirtualMatrix)
	SetScissor(0, 0, DeviceWidth(), DeviceHeight())
	SetAlpha(0.35) ' Make the controls translucent
	DrawImage(buttonLeftImage, 0, DeviceHeight() - buttonHeight, 0, dpiScale, dpiScale)
	DrawImage(buttonRightImage, buttonWidth, DeviceHeight() - buttonHeight, 0, dpiScale, dpiScale)
	DrawImage(buttonFireImage, DeviceWidth() - buttonWidth, DeviceHeight() - buttonHeight, 0, dpiScale, dpiScale)
End


The above code draws left and right buttons in the bottom left of the display and a fire button in the bottom right of the display.
You can see it in action here: http://www.loadcode.co.uk/software/android-software/invaders/

I've drawn the bitmaps of the buttons at 160 DPI, and at that size the buttons are the correct size for a finger.
In the code; dpiScale is calculated by dividing the device dpi by 160 to get the correct scaling amount, so if your controls are drawn at a different DPI you will have to adjust that.

The buttons should appear at almost the same size no matter how big the screen is, or the resolution.


erebel55(Posted 2014) [#9]
Thanks guys, this is great stuff.