mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Add notifications when saving and new upgrades are available, minor improvements
This commit is contained in:
@@ -19,6 +19,7 @@ import { HUDStatistics } from "./parts/statistics";
|
||||
import { MetaBuilding } from "../meta_building";
|
||||
import { HUDPinnedShapes } from "./parts/pinned_shapes";
|
||||
import { ShapeDefinition } from "../shape_definition";
|
||||
import { HUDNotifications, enumNotificationType } from "./parts/notifications";
|
||||
|
||||
export class GameHUD {
|
||||
/**
|
||||
@@ -51,12 +52,15 @@ export class GameHUD {
|
||||
|
||||
pinnedShapes: new HUDPinnedShapes(this.root),
|
||||
|
||||
notifications: new HUDNotifications(this.root),
|
||||
|
||||
// betaOverlay: new HUDBetaOverlay(this.root),
|
||||
};
|
||||
|
||||
this.signals = {
|
||||
selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
|
||||
shapePinRequested: /** @type {TypedSignal<[ShapeDefinition, number]>} */ (new Signal()),
|
||||
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
|
||||
};
|
||||
|
||||
if (!IS_MOBILE) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { makeDiv, randomInt } from "../../../core/utils";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { enumNotificationType } from "./notifications";
|
||||
|
||||
export class HUDGameMenu extends BaseHUDPart {
|
||||
initialize() {}
|
||||
@@ -14,6 +15,10 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
handler: () => this.root.hud.parts.shop.show(),
|
||||
keybinding: "menu_open_shop",
|
||||
badge: () => this.root.hubGoals.getAvailableUpgradeCount(),
|
||||
notification: /** @type {[string, enumNotificationType]} */ ([
|
||||
"A new upgrade is available!",
|
||||
enumNotificationType.upgrade,
|
||||
]),
|
||||
},
|
||||
{
|
||||
id: "stats",
|
||||
@@ -23,10 +28,16 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
},
|
||||
];
|
||||
|
||||
/** @type {Array<{ badge: function, button: HTMLElement, badgeElement: HTMLElement, lastRenderAmount: number }>} */
|
||||
/** @type {Array<{
|
||||
* badge: function,
|
||||
* button: HTMLElement,
|
||||
* badgeElement: HTMLElement,
|
||||
* lastRenderAmount: number,
|
||||
* notification: [string, enumNotificationType]
|
||||
* }>} */
|
||||
this.badgesToUpdate = [];
|
||||
|
||||
buttons.forEach(({ id, label, handler, keybinding, badge }) => {
|
||||
buttons.forEach(({ id, label, handler, keybinding, badge, notification }) => {
|
||||
const button = document.createElement("button");
|
||||
button.setAttribute("data-button-id", id);
|
||||
this.element.appendChild(button);
|
||||
@@ -45,6 +56,7 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
lastRenderAmount: 0,
|
||||
button,
|
||||
badgeElement,
|
||||
notification,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -68,8 +80,9 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
|
||||
update() {
|
||||
let playSound = false;
|
||||
let notifications = new Set();
|
||||
for (let i = 0; i < this.badgesToUpdate.length; ++i) {
|
||||
const { badge, button, badgeElement, lastRenderAmount } = this.badgesToUpdate[i];
|
||||
const { badge, button, badgeElement, lastRenderAmount, notification } = this.badgesToUpdate[i];
|
||||
const amount = badge();
|
||||
if (lastRenderAmount !== amount) {
|
||||
if (amount > 0) {
|
||||
@@ -78,6 +91,9 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
// Check if the badge increased
|
||||
if (amount > lastRenderAmount) {
|
||||
playSound = true;
|
||||
if (notification) {
|
||||
notifications.add(notification);
|
||||
}
|
||||
}
|
||||
this.badgesToUpdate[i].lastRenderAmount = amount;
|
||||
button.classList.toggle("hasBadge", amount > 0);
|
||||
@@ -87,6 +103,9 @@ export class HUDGameMenu extends BaseHUDPart {
|
||||
if (playSound) {
|
||||
this.root.soundProxy.playUi(SOUNDS.badgeNotification);
|
||||
}
|
||||
notifications.forEach(([notification, type]) => {
|
||||
this.root.hud.signals.notification.dispatch(notification, type);
|
||||
});
|
||||
}
|
||||
|
||||
onGameSaved() {
|
||||
|
||||
@@ -13,13 +13,18 @@ const logger = createLogger("hud/mass_selector");
|
||||
|
||||
export class HUDMassSelector extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
const removalKeybinding = this.root.gameState.keyActionMapper
|
||||
.getBinding("confirm_mass_delete")
|
||||
.getKeyCodeString();
|
||||
const abortKeybinding = this.root.gameState.keyActionMapper.getBinding("back").getKeyCodeString();
|
||||
|
||||
this.element = makeDiv(
|
||||
parent,
|
||||
"ingame_HUD_MassSelector",
|
||||
[],
|
||||
`
|
||||
Press <code class="keybinding">DEL</code> to remove selected buildings
|
||||
and <code class="keybinding">ESC</code> to cancel.
|
||||
Press <code class="keybinding">${removalKeybinding}</code> to remove selected buildings
|
||||
and <code class="keybinding">${abortKeybinding}</code> to cancel.
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
52
src/js/game/hud/parts/notifications.js
Normal file
52
src/js/game/hud/parts/notifications.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumNotificationType = {
|
||||
saved: "saved",
|
||||
upgrade: "upgrade",
|
||||
success: "success",
|
||||
};
|
||||
|
||||
export class HUDNotifications extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
this.element = makeDiv(parent, "ingame_HUD_Notifications", [], ``);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.root.hud.signals.notification.add(this.onNotification, this);
|
||||
|
||||
/** @type {Array<{ element: HTMLElement, expireAt: number}>} */
|
||||
this.notificationElements = [];
|
||||
|
||||
// Automatic notifications
|
||||
this.root.signals.gameSaved.add(() =>
|
||||
this.onNotification("Your game has been saved.", enumNotificationType.saved)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} message
|
||||
* @param {enumNotificationType} type
|
||||
*/
|
||||
onNotification(message, type) {
|
||||
const element = makeDiv(this.element, null, ["notification", "type-" + type], message);
|
||||
element.setAttribute("data-icon", "icons/notification_" + type + ".png");
|
||||
|
||||
this.notificationElements.push({
|
||||
element,
|
||||
expireAt: this.root.time.realtimeNow() + 5,
|
||||
});
|
||||
}
|
||||
|
||||
update() {
|
||||
const now = this.root.time.realtimeNow();
|
||||
for (let i = 0; i < this.notificationElements.length; ++i) {
|
||||
const handle = this.notificationElements[i];
|
||||
if (handle.expireAt <= now) {
|
||||
handle.element.remove();
|
||||
this.notificationElements.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export const defaultKeybindings = {
|
||||
menu_open_shop: { keyCode: key("F") },
|
||||
menu_open_stats: { keyCode: key("G") },
|
||||
|
||||
confirm_mass_delete: { keyCode: 46 }, // DEL
|
||||
confirm_mass_delete: { keyCode: key("X") }, // DEL
|
||||
toggle_hud: { keyCode: 113 }, // F2
|
||||
},
|
||||
|
||||
|
||||
0
src/js/translations/en.yaml
Normal file
0
src/js/translations/en.yaml
Normal file
Reference in New Issue
Block a user