From debbb570662343b5a74b11057d1b67d257e6f95f Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Fri, 30 Sep 2016 04:30:24 -0400 Subject: [PATCH] v0.4.3: implemented a new 'Power Saver' mode As a bonus, this allows shattered to run on small screen devices, by forcing power saver, which downsamples in this specific case allowing for the minimum 2x game scale. --- .../java/com/watabou/input/Touchscreen.java | 12 ++- .../src/main/java/com/watabou/noosa/Game.java | 8 +- core/src/main/AndroidManifest.xml | 10 ++- .../shatteredpixeldungeon/Preferences.java | 1 + .../ShatteredPixelDungeon.java | 80 +++++++++++++++++-- .../scenes/PixelScene.java | 2 + .../ui/OptionSlider.java | 12 +-- .../windows/WndSettings.java | 36 +++++++-- .../messages/windows/windows.properties | 4 + 9 files changed, 138 insertions(+), 27 deletions(-) diff --git a/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java b/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java index 513bf6045..013e93e85 100644 --- a/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java +++ b/SPD-classes/src/main/java/com/watabou/input/Touchscreen.java @@ -24,6 +24,7 @@ package com.watabou.input; import java.util.ArrayList; import java.util.HashMap; +import com.watabou.noosa.Game; import com.watabou.utils.PointF; import com.watabou.utils.Signal; @@ -96,6 +97,9 @@ public class Touchscreen { float x = e.getX( index ); float y = e.getY( index ); + + x /= (Game.dispWidth / (float)Game.width); + y /= (Game.dispHeight / (float)Game.height); start = new PointF( x, y ); current = new PointF( x, y ); @@ -104,7 +108,13 @@ public class Touchscreen { } public void update( MotionEvent e, int index ) { - current.set( e.getX( index ), e.getY( index ) ); + float x = e.getX( index ); + float y = e.getY( index ); + + x /= (Game.dispWidth / (float)Game.width); + y /= (Game.dispHeight / (float)Game.height); + + current.set( x, y ); } public Touch up() { diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Game.java b/SPD-classes/src/main/java/com/watabou/noosa/Game.java index ef43c6a68..9ffd27131 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Game.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Game.java @@ -53,8 +53,12 @@ import android.view.View; public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTouchListener { public static Game instance; + + //actual size of the display + public static int dispWidth; + public static int dispHeight; - // Actual size of the screen + // Size of the EGL surface view public static int width; public static int height; @@ -107,6 +111,8 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou DisplayMetrics m = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics( m ); density = m.density; + dispHeight = m.heightPixels; + dispWidth = m.widthPixels; try { version = getPackageManager().getPackageInfo( getPackageName(), 0 ).versionName; diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 1889491bd..0f4a860a3 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -13,12 +13,14 @@ - + + - + android:largeScreens="true" + android:xlargeScreens="true"/> Build.VERSION_CODES.JELLY_BEAN_MR1) + getWindowManager().getDefaultDisplay().getRealMetrics( metrics ); + else + getWindowManager().getDefaultDisplay().getMetrics( metrics ); boolean landscape = metrics.widthPixels > metrics.heightPixels; if (Preferences.INSTANCE.getBoolean( Preferences.KEY_LANDSCAPE, false ) != landscape) { @@ -274,6 +278,7 @@ public class ShatteredPixelDungeon extends Game { ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } Preferences.INSTANCE.put( Preferences.KEY_LANDSCAPE, value ); + ((ShatteredPixelDungeon)instance).updateDisplaySize(); } public static boolean landscape() { @@ -284,11 +289,8 @@ public class ShatteredPixelDungeon extends Game { Preferences.INSTANCE.put( Preferences.KEY_SCALE, value ); } - // *** IMMERSIVE MODE **** - private static boolean immersiveModeChanged = false; - @SuppressLint("NewApi") public static void immerse( boolean value ) { Preferences.INSTANCE.put( Preferences.KEY_IMMERSIVE, value ); @@ -297,21 +299,78 @@ public class ShatteredPixelDungeon extends Game { public void run() { updateImmersiveMode(); immersiveModeChanged = true; + //ensures surfacechanged is called if the view was previously set to be fixed. + ((ShatteredPixelDungeon)instance).view.getHolder().setSizeFromLayout(); } } ); } @Override public void onSurfaceChanged( GL10 gl, int width, int height ) { + super.onSurfaceChanged( gl, width, height ); + updateDisplaySize(); + if (immersiveModeChanged) { requestedReset = true; immersiveModeChanged = false; } } - @SuppressLint("NewApi") + private void updateDisplaySize(){ + DisplayMetrics m = new DisplayMetrics(); + if (immersed() && Build.VERSION.SDK_INT >= 19) + getWindowManager().getDefaultDisplay().getRealMetrics( m ); + else + getWindowManager().getDefaultDisplay().getMetrics( m ); + dispHeight = m.heightPixels; + dispWidth = m.widthPixels; + + float dispRatio = dispWidth / (float)dispHeight; + + float renderWidth = dispRatio > 1 ? PixelScene.MIN_WIDTH_L : PixelScene.MIN_WIDTH_P; + float renderHeight = dispRatio > 1 ? PixelScene.MIN_HEIGHT_L : PixelScene.MIN_HEIGHT_P; + + //force power saver in this case as all devices must run at at least 2x scale. + if (dispWidth < renderWidth*2 || dispHeight < renderHeight*2) + Preferences.INSTANCE.put( Preferences.KEY_POWER_SAVER, true ); + + if (powerSaver()){ + + int maxZoom = (int)Math.min(dispWidth/renderWidth, dispHeight/renderHeight); + + renderWidth *= GameMath.gate( 2, (float)Math.ceil(maxZoom/2f), 4); + renderHeight *= GameMath.gate( 2, (float)Math.ceil(maxZoom/2f), 4); + + if (dispRatio > renderWidth / renderHeight){ + renderWidth = renderHeight * dispRatio; + } else { + renderHeight = renderWidth / dispRatio; + } + + final int finalW = Math.round(renderWidth); + final int finalH = Math.round(renderHeight); + if (finalW != width || finalH != height){ + + runOnUiThread(new Runnable() { + @Override + public void run() { + view.getHolder().setFixedSize(finalW, finalH); + } + }); + + } + } else { + runOnUiThread(new Runnable() { + @Override + public void run() { + view.getHolder().setSizeFromLayout(); + } + }); + } + } + public static void updateImmersiveMode() { if (android.os.Build.VERSION.SDK_INT >= 19) { try { @@ -336,7 +395,14 @@ public class ShatteredPixelDungeon extends Game { return Preferences.INSTANCE.getBoolean( Preferences.KEY_IMMERSIVE, false ); } - // ***************************** + public static boolean powerSaver(){ + return Preferences.INSTANCE.getBoolean( Preferences.KEY_POWER_SAVER, false ); + } + + public static void powerSaver( boolean value ){ + Preferences.INSTANCE.put( Preferences.KEY_POWER_SAVER, value ); + ((ShatteredPixelDungeon)instance).updateDisplaySize(); + } public static int scale() { return Preferences.INSTANCE.getInt( Preferences.KEY_SCALE, 0 ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/PixelScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/PixelScene.java index d10e0661f..66256f009 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/PixelScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/PixelScene.java @@ -54,6 +54,7 @@ public class PixelScene extends Scene { public static int defaultZoom = 0; public static int maxDefaultZoom = 0; + public static int maxScreenZoom = 0; public static float minZoom; public static float maxZoom; @@ -82,6 +83,7 @@ public class PixelScene extends Scene { } maxDefaultZoom = (int)Math.min(Game.width/minWidth, Game.height/minHeight); + maxScreenZoom = (int)Math.min(Game.dispWidth/minWidth, Game.dispHeight/minHeight); defaultZoom = ShatteredPixelDungeon.scale(); if (defaultZoom < Math.ceil( Game.density * 2 ) || defaultZoom > maxDefaultZoom){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/OptionSlider.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/OptionSlider.java index a49900c30..1680849f1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/OptionSlider.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/OptionSlider.java @@ -54,6 +54,12 @@ public abstract class OptionSlider extends Component { public OptionSlider(String title, String minTxt, String maxTxt, int minVal, int maxVal){ super(); + //shouldn't function if this happens. + if (minVal > maxVal){ + minVal = maxVal; + active = false; + } + this.title.text(title); this.minTxt.text(minTxt); this.maxTxt.text(maxTxt); @@ -61,12 +67,6 @@ public abstract class OptionSlider extends Component { this.minVal = minVal; this.maxVal = maxVal; - //really shouldn't display the slider if this happens. - if (minVal > maxVal){ - active = false; - visible = false; - } - sliderTicks = new ColorBlock[(maxVal - minVal) + 1]; for (int i = 0; i < sliderTicks.length; i++){ add(sliderTicks[i] = new ColorBlock(1, 11, 0xFF222222)); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java index 7bd0f62d9..2bf23cc14 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java @@ -127,12 +127,9 @@ public class WndSettings extends WndTabbed { } }; scale.setSelectedValue(PixelScene.defaultZoom); - if ((int)Math.ceil(2* Game.density) < PixelScene.maxDefaultZoom) { - scale.setRect(0, 0, WIDTH, SLIDER_HEIGHT); + scale.setRect(0, 0, WIDTH, SLIDER_HEIGHT); + if ((int)Math.ceil(2* Game.density) < PixelScene.maxDefaultZoom) add(scale); - } else { - scale.setRect(0, 0, 0, 0); - } OptionSlider brightness = new OptionSlider(Messages.get(this, "brightness"), Messages.get(this, "dark"), Messages.get(this, "bright"), -2, 2) { @@ -142,7 +139,7 @@ public class WndSettings extends WndTabbed { } }; brightness.setSelectedValue(ShatteredPixelDungeon.brightness()); - brightness.setRect(0, scale.bottom() + GAP_SML, WIDTH, SLIDER_HEIGHT); + brightness.setRect(0, scale.bottom() + GAP_TINY, WIDTH, SLIDER_HEIGHT); add(brightness); CheckBox chkImmersive = new CheckBox( Messages.get(this, "soft_keys") ) { @@ -152,11 +149,34 @@ public class WndSettings extends WndTabbed { ShatteredPixelDungeon.immerse(checked()); } }; - chkImmersive.setRect( 0, brightness.bottom() + GAP_LRG, WIDTH, BTN_HEIGHT ); + chkImmersive.setRect( 0, brightness.bottom() + GAP_SML, WIDTH, BTN_HEIGHT ); chkImmersive.checked(ShatteredPixelDungeon.immersed()); chkImmersive.enable(android.os.Build.VERSION.SDK_INT >= 19); add(chkImmersive); + CheckBox chkSaver = new CheckBox( Messages.get(this, "saver") ) { + @Override + protected void onClick() { + super.onClick(); + checked( !checked() ); + ShatteredPixelDungeon.scene().add(new WndOptions( + Messages.get(ScreenTab.class, "saver"), + Messages.get(ScreenTab.class, "saver_desc"), + Messages.get(ScreenTab.class, "okay"), + Messages.get(ScreenTab.class, "cancel")){ + @Override + protected void onSelect(int index) { + if (index == 0){ + checked( !checked() ); + ShatteredPixelDungeon.powerSaver(checked()); + } + } + }); + } + }; + chkSaver.setRect( 0, chkImmersive.bottom() + GAP_TINY, WIDTH, BTN_HEIGHT ); + chkSaver.checked(ShatteredPixelDungeon.powerSaver()); + if (PixelScene.maxScreenZoom >= 2) add(chkSaver); RedButton btnOrientation = new RedButton( ShatteredPixelDungeon.landscape() ? Messages.get(this, "portrait") @@ -166,7 +186,7 @@ public class WndSettings extends WndTabbed { ShatteredPixelDungeon.landscape(!ShatteredPixelDungeon.landscape()); } }; - btnOrientation.setRect(0, chkImmersive.bottom() + GAP_LRG, WIDTH, BTN_HEIGHT); + btnOrientation.setRect(0, chkSaver.bottom() + GAP_SML, WIDTH, BTN_HEIGHT); add( btnOrientation ); } } diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/windows/windows.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/windows/windows.properties index 56b6bfe23..edeb39906 100644 --- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/windows/windows.properties +++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/windows/windows.properties @@ -88,6 +88,10 @@ windows.wndsettings$screentab.brightness=Brightness windows.wndsettings$screentab.dark=Dark windows.wndsettings$screentab.bright=Bright windows.wndsettings$screentab.soft_keys=Hide Software Keys +windows.wndsettings$screentab.saver=Power Saver Mode +windows.wndsettings$screentab.saver_desc=Power saver mode draws the game at a reduced size and scales it up to fit your screen.\n\nThis will make the graphics less crisp, but will improve performance and battery life.\n\nYou may need to restart the game for changes to take effect. +windows.wndsettings$screentab.okay=Okay +windows.wndsettings$screentab.cancel=Cancel windows.wndsettings$screentab.portrait=Switch to portrait windows.wndsettings$screentab.landscape=Switch to landscape windows.wndsettings$uitab.mode=Toolbar Mode: