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.
This commit is contained in:
parent
8591a0b3dc
commit
debbb57066
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"/>
|
||||
|
||||
|
||||
<!-- Note that the game doesn't truly support small screen resolutions,
|
||||
it instead forces downscaling to work on these displays.-->
|
||||
<supports-screens
|
||||
android:smallScreens="false"
|
||||
android:smallScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:largeScreens="true"/>
|
||||
<!--android:xlargeScreens="true"-->
|
||||
android:largeScreens="true"
|
||||
android:xlargeScreens="true"/>
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
|
|
|
@ -30,6 +30,7 @@ enum Preferences {
|
|||
|
||||
public static final String KEY_LANDSCAPE = "landscape";
|
||||
public static final String KEY_IMMERSIVE = "immersive";
|
||||
public static final String KEY_POWER_SAVER = "power_saver";
|
||||
public static final String KEY_SCALE = "scale";
|
||||
public static final String KEY_MUSIC = "music";
|
||||
public static final String KEY_MUSIC_VOL = "music_vol";
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
*/
|
||||
package com.shatteredpixel.shatteredpixeldungeon;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
@ -34,6 +34,7 @@ import com.watabou.noosa.Game;
|
|||
import com.watabou.noosa.RenderedText;
|
||||
import com.watabou.noosa.audio.Music;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.GameMath;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import java.util.Locale;
|
||||
|
@ -172,7 +173,10 @@ public class ShatteredPixelDungeon extends Game {
|
|||
updateImmersiveMode();
|
||||
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
instance.getWindowManager().getDefaultDisplay().getMetrics( metrics );
|
||||
if (immersed() && Build.VERSION.SDK_INT > 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 );
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue
Block a user