v3.0.0: substantially improved games in progress scene

This commit is contained in:
Evan Debenham
2025-01-29 16:20:56 -05:00
parent 062cb3f11e
commit 0b887a3ee4
5 changed files with 118 additions and 13 deletions

View File

@@ -102,7 +102,13 @@ scenes.rankingsscene.no_games=No games have been played yet.
scenes.rankingsscene.no_info=No additional information
scenes.startscene.title=Games in Progress
scenes.startscene.one_minute_ago=1 minute ago
scenes.startscene.minutes_ago=%d minutes ago
scenes.startscene.hours_ago=%d hours ago
scenes.startscene.days_ago=%d days ago
scenes.startscene.new=New Game
scenes.startscene.sort_level=Sort: Level
scenes.startscene.sort_recent=Sort: Recent
scenes.supporterscene.title=Support the Game
scenes.supporterscene.intro=I want Shattered Pixel Dungeon to be free of ads and invasive microtransactions, which ruin so many free games. Instead, I'd rather ask players to support the game directly!

View File

@@ -217,6 +217,7 @@ public class Dungeon {
public static boolean dailyReplay;
public static String customSeedText = "";
public static long seed;
public static long lastPlayed;
//we initialize the seed separately so that things like interlevelscene can access it early
public static void initSeed(){
@@ -603,6 +604,7 @@ public class Dungeon {
private static final String CUSTOM_SEED = "custom_seed";
private static final String DAILY = "daily";
private static final String DAILY_REPLAY= "daily_replay";
private static final String LAST_PLAYED = "last_played";
private static final String CHALLENGES = "challenges";
private static final String MOBS_TO_CHAMPION = "mobs_to_champion";
private static final String HERO = "hero";
@@ -629,6 +631,7 @@ public class Dungeon {
bundle.put( CUSTOM_SEED, customSeedText );
bundle.put( DAILY, daily );
bundle.put( DAILY_REPLAY, dailyReplay );
bundle.put( LAST_PLAYED, lastPlayed = Game.realTime);
bundle.put( CHALLENGES, challenges );
bundle.put( MOBS_TO_CHAMPION, mobsToChampion );
bundle.put( HERO, hero );
@@ -872,6 +875,7 @@ public class Dungeon {
info.customSeed = bundle.getString( CUSTOM_SEED );
info.daily = bundle.getBoolean( DAILY );
info.dailyReplay = bundle.getBoolean( DAILY_REPLAY );
info.lastPlayed = bundle.getLong( LAST_PLAYED );
Hero.preview( info, bundle.getBundle( HERO ) );
Statistics.preview( info, bundle );

View File

@@ -82,7 +82,15 @@ public class GamesInProgress {
Info curr = check(i);
if (curr != null) result.add(curr);
}
Collections.sort(result, scoreComparator);
switch (SPDSettings.gamesInProgressSort()){
case "level": default:
Collections.sort(result, levelComparator);
break;
case "last_played":
Collections.sort(result, lastPlayedComparator);
break;
}
return result;
}
@@ -129,6 +137,8 @@ public class GamesInProgress {
public static void set(int slot) {
Info info = new Info();
info.slot = slot;
info.lastPlayed = Dungeon.lastPlayed;
info.depth = Dungeon.depth;
info.challenges = Dungeon.challenges;
@@ -165,7 +175,7 @@ public class GamesInProgress {
public static class Info {
public int slot;
public int depth;
public int version;
public int challenges;
@@ -174,6 +184,7 @@ public class GamesInProgress {
public String customSeed;
public boolean daily;
public boolean dailyReplay;
public long lastPlayed;
public int level;
public int str;
@@ -190,12 +201,21 @@ public class GamesInProgress {
public int maxDepth;
}
public static final Comparator<GamesInProgress.Info> scoreComparator = new Comparator<GamesInProgress.Info>() {
public static final Comparator<GamesInProgress.Info> levelComparator = new Comparator<GamesInProgress.Info>() {
@Override
public int compare(GamesInProgress.Info lhs, GamesInProgress.Info rhs ) {
int lScore = (lhs.level * lhs.maxDepth * 100) + lhs.goldCollected;
int rScore = (rhs.level * rhs.maxDepth * 100) + rhs.goldCollected;
return (int)Math.signum( rScore - lScore );
if (rhs.level != lhs.level){
return (int)Math.signum( rhs.level - lhs.level );
} else {
return lastPlayedComparator.compare(lhs, rhs);
}
}
};
public static final Comparator<GamesInProgress.Info> lastPlayedComparator = new Comparator<GamesInProgress.Info>() {
@Override
public int compare(GamesInProgress.Info lhs, GamesInProgress.Info rhs ) {
return (int)Math.signum( rhs.lastPlayed - lhs.lastPlayed );
}
};
}

View File

@@ -146,6 +146,8 @@ public class SPDSettings extends GameSettings {
public static final String KEY_SYSTEMFONT = "system_font";
public static final String KEY_VIBRATION = "vibration";
public static final String KEY_GAMES_SORT = "games_sort";
//0 = mobile, 1 = mixed (large without inventory in main UI), 2 = large
public static void interfaceSize( int value ){
put( KEY_UI_SIZE, value );
@@ -221,6 +223,14 @@ public class SPDSettings extends GameSettings {
return getBoolean(KEY_VIBRATION, true);
}
public static String gamesInProgressSort(){
return getString(KEY_GAMES_SORT, "level");
}
public static void gamesInProgressSort(String value){
put(KEY_GAMES_SORT, value);
}
//Game State
public static final String KEY_LAST_CLASS = "last_class";

View File

@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.scenes;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
import com.shatteredpixel.shatteredpixeldungeon.GamesInProgress;
import com.shatteredpixel.shatteredpixeldungeon.SPDSettings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.journal.Journal;
@@ -33,11 +34,13 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.Button;
import com.shatteredpixel.shatteredpixeldungeon.ui.ExitButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.StyledButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.windows.IconTitle;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndGameInProgress;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Image;
import com.watabou.noosa.NinePatch;
@@ -82,18 +85,21 @@ public class StartScene extends PixelScene {
int slotCount = Math.min(GamesInProgress.MAX_SLOTS, games.size()+1);
int slotGap = 10 - slotCount;
int slotsHeight = slotCount*SLOT_HEIGHT + (slotCount-1)* slotGap;
slotsHeight += 14;
while (slotsHeight > (h-title.bottom()-2)){
while (slotGap >= 2 && slotsHeight > (h-title.bottom()-2)){
slotGap--;
slotsHeight -= slotCount-1;
}
float yPos = (h - slotsHeight + title.bottom() + 2)/2f;
float yPos = (h - slotsHeight + title.bottom() + 2)/2f - 4;
yPos = Math.max(yPos, title.bottom()+2);
float slotLeft = (w - SLOT_WIDTH) / 2f;
for (GamesInProgress.Info game : games) {
SaveSlotButton existingGame = new SaveSlotButton();
existingGame.set(game.slot);
existingGame.setRect((w - SLOT_WIDTH) / 2f, yPos, SLOT_WIDTH, SLOT_HEIGHT);
existingGame.setRect(slotLeft, yPos, SLOT_WIDTH, SLOT_HEIGHT);
yPos += SLOT_HEIGHT + slotGap;
align(existingGame);
add(existingGame);
@@ -103,18 +109,51 @@ public class StartScene extends PixelScene {
if (games.size() < GamesInProgress.MAX_SLOTS){
SaveSlotButton newGame = new SaveSlotButton();
newGame.set(GamesInProgress.firstEmpty());
newGame.setRect((w - SLOT_WIDTH) / 2f, yPos, SLOT_WIDTH, SLOT_HEIGHT);
newGame.setRect(slotLeft, yPos, SLOT_WIDTH, SLOT_HEIGHT);
yPos += SLOT_HEIGHT + slotGap;
align(newGame);
add(newGame);
}
GamesInProgress.curSlot = 0;
String sortText = "";
switch (SPDSettings.gamesInProgressSort()){
case "level":
sortText = Messages.get(this, "sort_level");
break;
case "last_played":
sortText = Messages.get(this, "sort_recent");
break;
}
StyledButton btnSort = new StyledButton(Chrome.Type.TOAST_TR, sortText, 6){
@Override
protected void onClick() {
super.onClick();
if (SPDSettings.gamesInProgressSort().equals("level")){
SPDSettings.gamesInProgressSort("last_played");
} else {
SPDSettings.gamesInProgressSort("level");
}
ShatteredPixelDungeon.seamlessResetScene();
}
};
btnSort.textColor(0xCCCCCC);
if (yPos + 10 > Camera.main.height) {
btnSort.setRect(slotLeft - btnSort.reqWidth() - 6, Camera.main.height - 14, btnSort.reqWidth() + 4, 12);
} else {
btnSort.setRect(slotLeft, yPos, btnSort.reqWidth() + 4, 12);
}
if (games.size() >= 2) add(btnSort);
fadeIn();
}
@Override
protected void onBackPressed() {
ShatteredPixelDungeon.switchNoFade( TitleScene.class );
@@ -126,6 +165,7 @@ public class StartScene extends PixelScene {
private Image hero;
private RenderedTextBlock name;
private RenderedTextBlock lastPlayed;
private Image steps;
private BitmapText depth;
@@ -144,6 +184,9 @@ public class StartScene extends PixelScene {
name = PixelScene.renderTextBlock(9);
add(name);
lastPlayed = PixelScene.renderTextBlock(6);
add(lastPlayed);
}
public void set( int slot ){
@@ -191,6 +234,21 @@ public class StartScene extends PixelScene {
classIcon.copy(Icons.get(info.heroClass));
}
long diff = Game.realTime - info.lastPlayed;
if (diff > 99L * 30 * 24 * 60 * 60_000){
lastPlayed.text(" "); //show no text for >99 months ago
} else if (diff < 60_000){
lastPlayed.text(Messages.get(StartScene.class, "one_minute_ago"));
} else if (diff < 2 * 60 * 60_000){
lastPlayed.text(Messages.get(StartScene.class, "minutes_ago", diff / 60_000));
} else if (diff < 2 * 24 * 60 * 60_000){
lastPlayed.text(Messages.get(StartScene.class, "hours_ago", diff / (60 * 60_000)));
} else if (diff < 2L * 30 * 24 * 60 * 60_000){
lastPlayed.text(Messages.get(StartScene.class, "days_ago", diff / (24 * 60 * 60_000)));
} else {
lastPlayed.text(Messages.get(StartScene.class, "months_ago", diff / (30L * 24 * 60 * 60_000)));
}
depth.text(Integer.toString(info.depth));
depth.measure();
@@ -200,10 +258,12 @@ public class StartScene extends PixelScene {
if (info.challenges > 0){
name.hardlight(Window.TITLE_COLOR);
lastPlayed.hardlight(Window.TITLE_COLOR);
depth.hardlight(Window.TITLE_COLOR);
level.hardlight(Window.TITLE_COLOR);
} else {
name.resetColor();
lastPlayed.resetColor();
depth.resetColor();
level.resetColor();
}
@@ -238,9 +298,14 @@ public class StartScene extends PixelScene {
name.setPos(
hero.x + hero.width() + 6,
y + (height - name.height())/2f
y + (height - name.height() - lastPlayed.height() - 2)/2f
);
align(name);
lastPlayed.setPos(
hero.x + hero.width() + 6,
name.bottom()+2
);
classIcon.x = x + width - 24 + (16 - classIcon.width())/2f;
classIcon.y = y + (height - classIcon.height())/2f;