diff --git a/public/images/ui/cursor_reverse.png b/public/images/ui/cursor_reverse.png new file mode 100644 index 00000000000..57fb297747e Binary files /dev/null and b/public/images/ui/cursor_reverse.png differ diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 87a971a5612..ba70415dab6 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -248,6 +248,7 @@ export default class BattleScene extends Phaser.Scene { this.loadImage('command_fight_labels', 'ui'); this.loadAtlas('prompt', 'ui'); this.loadImage('cursor', 'ui'); + this.loadImage('cursor_reverse', 'ui'); for (let wv of Utils.getEnumValues(WindowVariant)) { for (let w = 1; w <= 4; w++) this.loadImage(`window_${w}${getWindowVariantSuffix(wv)}`, 'ui/windows'); diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index 2e7bc4810ea..9c8b5b76b8c 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -10,10 +10,24 @@ interface RankingEntry { wave: integer } +enum ScoreboardCategory { + DAILY, + WEEKLY +} + export class DailyRunScoreboard extends Phaser.GameObjects.Container { private loadingLabel: Phaser.GameObjects.Text; private titleLabel: Phaser.GameObjects.Text; private rankingsContainer: Phaser.GameObjects.Container; + private prevCategoryButton: Phaser.GameObjects.Sprite; + private nextCategoryButton: Phaser.GameObjects.Sprite; + private prevPageButton: Phaser.GameObjects.Sprite; + private pageNumberLabel: Phaser.GameObjects.Text; + private nextPageButton: Phaser.GameObjects.Sprite; + + private pageCount: integer; + private page: integer; + private category: ScoreboardCategory; constructor(scene: BattleScene, x: number, y: number) { super(scene, x, y); @@ -22,24 +36,71 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { } setup() { - const titleWindow = addWindow(this.scene, 0, 0, 114, 16, false, false, null, null, WindowVariant.THIN); + const titleWindow = addWindow(this.scene, 0, 0, 114, 18, false, false, null, null, WindowVariant.THIN); this.add(titleWindow); this.titleLabel = addTextObject(this.scene, titleWindow.displayWidth / 2, titleWindow.displayHeight / 2, 'Daily Rankings', TextStyle.WINDOW, { fontSize: '64px' }); this.titleLabel.setOrigin(0.5, 0.5); this.add(this.titleLabel); - const window = addWindow(this.scene, 0, 15, 114, 115, false, false, null, null, WindowVariant.THIN); + const window = addWindow(this.scene, 0, 17, 114, 115, false, false, null, null, WindowVariant.THIN); this.add(window); - this.rankingsContainer = this.scene.add.container(6, 19); + this.rankingsContainer = this.scene.add.container(6, 21); this.add(this.rankingsContainer); this.loadingLabel = addTextObject(this.scene, window.displayWidth / 2, window.displayHeight / 2 + 16, '', TextStyle.WINDOW); this.loadingLabel.setOrigin(0.5, 0.5); this.loadingLabel.setVisible(false); + this.prevCategoryButton = this.scene.add.sprite(4, 4, 'cursor_reverse'); + this.prevCategoryButton.setOrigin(0, 0); + this.add(this.prevCategoryButton); + + this.prevCategoryButton.setInteractive(new Phaser.Geom.Rectangle(0, 0, 6, 10), Phaser.Geom.Rectangle.Contains); + this.prevCategoryButton.on('pointerup', () => { + this.update(this.category ? this.category - 1 : Utils.getEnumKeys(ScoreboardCategory).length - 1); + }); + + this.nextCategoryButton = this.scene.add.sprite(window.displayWidth - 4, 4, 'cursor'); + this.nextCategoryButton.setOrigin(1, 0); + this.add(this.nextCategoryButton); + + this.nextCategoryButton.setInteractive(new Phaser.Geom.Rectangle(0, 0, 6, 10), Phaser.Geom.Rectangle.Contains); + this.nextCategoryButton.on('pointerup', () => { + this.update(this.category < Utils.getEnumKeys(ScoreboardCategory).length - 1 ? this.category + 1 : 0); + }); + + this.prevPageButton = this.scene.add.sprite(window.displayWidth / 2 - 16, titleWindow.displayHeight + window.displayHeight - 16, 'cursor_reverse'); + this.prevPageButton.setOrigin(0, 0); + this.prevPageButton.setAlpha(0.5); + this.add(this.prevPageButton); + + this.prevPageButton.setInteractive(new Phaser.Geom.Rectangle(0, 0, 6, 10), Phaser.Geom.Rectangle.Contains); + this.prevPageButton.on('pointerup', () => { + if (this.page > 1) + this.update(undefined, this.page > 1 ? this.page - 1 : this.pageCount); + }); + + this.pageNumberLabel = addTextObject(this.scene, window.displayWidth / 2, titleWindow.displayHeight + window.displayHeight - 17, '1', TextStyle.WINDOW, { fontSize: '64px' }); + this.pageNumberLabel.setOrigin(0.5, 0); + this.add(this.pageNumberLabel); + + this.nextPageButton = this.scene.add.sprite(window.displayWidth / 2 + 16, titleWindow.displayHeight + window.displayHeight - 16, 'cursor'); + this.nextPageButton.setOrigin(1, 0); + this.nextPageButton.setAlpha(0.5); + this.add(this.nextPageButton); + + this.nextPageButton.setInteractive(new Phaser.Geom.Rectangle(0, 0, 6, 10), Phaser.Geom.Rectangle.Contains); + this.nextPageButton.on('pointerup', () => { + if (this.page < this.pageCount) + this.update(undefined, this.page < this.pageCount ? this.page + 1 : 0); + }); + this.add(this.loadingLabel); + + this.page = 1; + this.category = ScoreboardCategory.DAILY; } updateRankings(rankings: RankingEntry[]) { @@ -70,21 +131,34 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { }); } - update() { + update(category: ScoreboardCategory = this.category, page: integer = this.page) { this.rankingsContainer.removeAll(true); this.loadingLabel.setText('Loading…'); this.loadingLabel.setVisible(true); - Utils.apiFetch(`daily/rankings`) - .then(response => response.json()) - .then(jsonResponse => { - if (jsonResponse) { - this.loadingLabel.setVisible(false); - this.updateRankings(jsonResponse); - } else - this.loadingLabel.setText('No Rankings'); - }); + if (category !== this.category) + this.page = page = 1; + + Utils.executeIf(category !== this.category || this.pageCount === undefined, + () => Utils.apiFetch(`daily/rankingpagecount?category=${category}`).then(response => response.json()).then(count => this.pageCount = count) + ).then(() => { + Utils.apiFetch(`daily/rankings?category=${category}&page=${page}`) + .then(response => response.json()) + .then(jsonResponse => { + this.page = page; + this.category = category; + this.titleLabel.setText(`${Utils.toReadableString(ScoreboardCategory[category])} Rankings`); + this.prevPageButton.setAlpha(page > 1 ? 1 : 0.5); + this.nextPageButton.setAlpha(page < this.pageCount ? 1 : 0.5); + this.pageNumberLabel.setText(page.toString()); + if (jsonResponse) { + this.loadingLabel.setVisible(false); + this.updateRankings(jsonResponse); + } else + this.loadingLabel.setText('No Rankings'); + }); + }); } } diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index 7b0d1cae5b6..f1c702bbbfb 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -33,7 +33,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler { this.splashMessage.setAngle(-20) this.titleContainer.add(this.splashMessage); - this.dailyRunScoreboard = new DailyRunScoreboard(this.scene, 1, 49); + this.dailyRunScoreboard = new DailyRunScoreboard(this.scene, 1, 47); this.dailyRunScoreboard.setup(); this.titleContainer.add(this.dailyRunScoreboard);