mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Initial support for themes, sound improvements
This commit is contained in:
parent
236859baa1
commit
7870f011b8
@ -9,7 +9,7 @@ function gulptasksSounds($, gulp, buildFolder) {
|
|||||||
return gulp.src(builtSoundsDir).pipe($.clean({ force: true }));
|
return gulp.src(builtSoundsDir).pipe($.clean({ force: true }));
|
||||||
});
|
});
|
||||||
|
|
||||||
const filters = ["loudnorm", "volume=0.2"];
|
const filters = ["volume=0.2"];
|
||||||
|
|
||||||
const fileCache = new $.cache.Cache({
|
const fileCache = new $.cache.Cache({
|
||||||
cacheDirName: "shapezio-precompiled-sounds",
|
cacheDirName: "shapezio-precompiled-sounds",
|
||||||
@ -27,8 +27,8 @@ function gulptasksSounds($, gulp, buildFolder) {
|
|||||||
.audioBitrate(48)
|
.audioBitrate(48)
|
||||||
.audioChannels(1)
|
.audioChannels(1)
|
||||||
.audioFrequency(22050)
|
.audioFrequency(22050)
|
||||||
.audioCodec("libmp3lame");
|
.audioCodec("libmp3lame")
|
||||||
// .audioFilters(["volume=0.25"])
|
.audioFilters(["volume=0.3"]);
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "music",
|
name: "music",
|
||||||
|
BIN
res_raw/sounds/music/menu.mp3
Normal file
BIN
res_raw/sounds/music/menu.mp3
Normal file
Binary file not shown.
Binary file not shown.
3
res_raw/sounds/ui/badge_notification.wav
Normal file
3
res_raw/sounds/ui/badge_notification.wav
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:dba7e859fb98713943890281a543e209d57c6633496090bd70d23dc58bed4405
|
||||||
|
size 743136
|
@ -37,7 +37,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
// Belt speeds
|
// Belt speeds
|
||||||
// NOTICE: Update webpack.production.config too!
|
// NOTICE: Update webpack.production.config too!
|
||||||
beltSpeedItemsPerSecond: 1,
|
beltSpeedItemsPerSecond: 10,
|
||||||
itemSpacingOnBelts: 0.63,
|
itemSpacingOnBelts: 0.63,
|
||||||
minerSpeedItemsPerSecond: 0, // COMPUTED
|
minerSpeedItemsPerSecond: 0, // COMPUTED
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
debug: {
|
debug: {
|
||||||
/* dev:start */
|
/* dev:start */
|
||||||
// fastGameEnter: true,
|
fastGameEnter: true,
|
||||||
noArtificialDelays: true,
|
noArtificialDelays: true,
|
||||||
// disableSavegameWrite: true,
|
// disableSavegameWrite: true,
|
||||||
showEntityBounds: false,
|
showEntityBounds: false,
|
||||||
|
@ -252,7 +252,7 @@ export class GameState {
|
|||||||
* @returns {string|null}
|
* @returns {string|null}
|
||||||
*/
|
*/
|
||||||
getThemeMusic() {
|
getThemeMusic() {
|
||||||
return null;
|
return MUSIC.menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||||
|
import { THEME } from "./theme";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for items on belts etc. Not an entity for performance reasons
|
* Class for items on belts etc. Not an entity for performance reasons
|
||||||
@ -28,6 +29,6 @@ export class BaseItem extends BasicSerializableObject {
|
|||||||
draw(x, y, parameters, size) {}
|
draw(x, y, parameters, size) {}
|
||||||
|
|
||||||
getBackgroundColorAsResource() {
|
getBackgroundColorAsResource() {
|
||||||
return "#eaebec";
|
abstract;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { makeDiv, randomInt } from "../../../core/utils";
|
import { makeDiv, randomInt } from "../../../core/utils";
|
||||||
|
import { SOUNDS } from "../../../platform/sound";
|
||||||
|
|
||||||
export class HUDGameMenu extends BaseHUDPart {
|
export class HUDGameMenu extends BaseHUDPart {
|
||||||
initialize() {}
|
initialize() {}
|
||||||
@ -60,12 +61,13 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
this.trackClicks(this.saveButton, this.startSave);
|
this.trackClicks(this.saveButton, this.startSave);
|
||||||
|
|
||||||
this.musicButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted);
|
this.musicButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted);
|
||||||
this.sfxButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted);
|
this.sfxButton.classList.toggle("muted", this.root.app.settings.getAllSettings().soundsMuted);
|
||||||
|
|
||||||
this.root.signals.gameSaved.add(this.onGameSaved, this);
|
this.root.signals.gameSaved.add(this.onGameSaved, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
|
let playSound = false;
|
||||||
for (let i = 0; i < this.badgesToUpdate.length; ++i) {
|
for (let i = 0; i < this.badgesToUpdate.length; ++i) {
|
||||||
const { badge, button, badgeElement, lastRenderAmount } = this.badgesToUpdate[i];
|
const { badge, button, badgeElement, lastRenderAmount } = this.badgesToUpdate[i];
|
||||||
const amount = badge();
|
const amount = badge();
|
||||||
@ -73,10 +75,18 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
if (amount > 0) {
|
if (amount > 0) {
|
||||||
badgeElement.innerText = amount;
|
badgeElement.innerText = amount;
|
||||||
}
|
}
|
||||||
|
// Check if the badge increased
|
||||||
|
if (amount > lastRenderAmount) {
|
||||||
|
playSound = true;
|
||||||
|
}
|
||||||
this.badgesToUpdate[i].lastRenderAmount = amount;
|
this.badgesToUpdate[i].lastRenderAmount = amount;
|
||||||
button.classList.toggle("hasBadge", amount > 0);
|
button.classList.toggle("hasBadge", amount > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (playSound) {
|
||||||
|
this.root.soundProxy.playUi(SOUNDS.badgeNotification);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onGameSaved() {
|
onGameSaved() {
|
||||||
|
@ -4,13 +4,7 @@ import { DrawParameters } from "../../core/draw_parameters";
|
|||||||
import { types } from "../../savegame/serialization";
|
import { types } from "../../savegame/serialization";
|
||||||
import { BaseItem } from "../base_item";
|
import { BaseItem } from "../base_item";
|
||||||
import { enumColors, enumColorsToHexCode } from "../colors";
|
import { enumColors, enumColorsToHexCode } from "../colors";
|
||||||
|
import { THEME } from "../theme";
|
||||||
/** @enum {string} */
|
|
||||||
const enumColorToMapBackground = {
|
|
||||||
[enumColors.red]: "#ffbfc1",
|
|
||||||
[enumColors.green]: "#cbffc4",
|
|
||||||
[enumColors.blue]: "#bfdaff",
|
|
||||||
};
|
|
||||||
|
|
||||||
export class ColorItem extends BaseItem {
|
export class ColorItem extends BaseItem {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -39,7 +33,7 @@ export class ColorItem extends BaseItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBackgroundColorAsResource() {
|
getBackgroundColorAsResource() {
|
||||||
return enumColorToMapBackground[this.color];
|
return THEME.map.resources[this.color];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,8 +69,8 @@ export class ColorItem extends BaseItem {
|
|||||||
context.scale((dpi * w) / 12, (dpi * h) / 12);
|
context.scale((dpi * w) / 12, (dpi * h) / 12);
|
||||||
|
|
||||||
context.fillStyle = enumColorsToHexCode[this.color];
|
context.fillStyle = enumColorsToHexCode[this.color];
|
||||||
context.strokeStyle = "rgba(100,102, 110, 1)";
|
context.strokeStyle = THEME.items.outline;
|
||||||
context.lineWidth = 2;
|
context.lineWidth = 2 * THEME.items.outlineWidth;
|
||||||
context.beginCircle(2, -1, 3);
|
context.beginCircle(2, -1, 3);
|
||||||
context.stroke();
|
context.stroke();
|
||||||
context.fill();
|
context.fill();
|
||||||
|
@ -2,6 +2,7 @@ import { DrawParameters } from "../../core/draw_parameters";
|
|||||||
import { types } from "../../savegame/serialization";
|
import { types } from "../../savegame/serialization";
|
||||||
import { BaseItem } from "../base_item";
|
import { BaseItem } from "../base_item";
|
||||||
import { ShapeDefinition } from "../shape_definition";
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
|
import { THEME } from "../theme";
|
||||||
|
|
||||||
export class ShapeItem extends BaseItem {
|
export class ShapeItem extends BaseItem {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -33,6 +34,10 @@ export class ShapeItem extends BaseItem {
|
|||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBackgroundColorAsResource() {
|
||||||
|
return THEME.map.resources.shape;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} x
|
* @param {number} x
|
||||||
* @param {number} y
|
* @param {number} y
|
||||||
|
@ -4,6 +4,7 @@ import { DrawParameters } from "../core/draw_parameters";
|
|||||||
import { BaseMap } from "./map";
|
import { BaseMap } from "./map";
|
||||||
import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils";
|
import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
|
import { THEME } from "./theme";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the view of the map, it extends the map which is the raw model and allows
|
* This is the view of the map, it extends the map which is the raw model and allows
|
||||||
@ -16,7 +17,7 @@ export class MapView extends BaseMap {
|
|||||||
/**
|
/**
|
||||||
* DPI of the background cache images, required in some places
|
* DPI of the background cache images, required in some places
|
||||||
*/
|
*/
|
||||||
this.backgroundCacheDPI = 4;
|
this.backgroundCacheDPI = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cached background sprite, containing the flat background
|
* The cached background sprite, containing the flat background
|
||||||
@ -109,14 +110,16 @@ export class MapView extends BaseMap {
|
|||||||
});
|
});
|
||||||
context.scale(dpi, dpi);
|
context.scale(dpi, dpi);
|
||||||
|
|
||||||
context.fillStyle = "#fff";
|
context.fillStyle = THEME.map.background;
|
||||||
context.fillRect(0, 0, dims, dims);
|
context.fillRect(0, 0, dims, dims);
|
||||||
|
|
||||||
context.fillStyle = "#fafafa";
|
const borderWidth = THEME.map.gridLineWidth;
|
||||||
context.fillRect(0, 0, dims, 1);
|
context.fillStyle = THEME.map.grid;
|
||||||
context.fillRect(0, 0, 1, dims);
|
context.fillRect(0, 0, dims, borderWidth);
|
||||||
context.fillRect(dims - 1, 0, 1, dims);
|
context.fillRect(0, borderWidth, borderWidth, dims);
|
||||||
context.fillRect(0, dims - 1, dims, 1);
|
|
||||||
|
context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth);
|
||||||
|
context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth);
|
||||||
|
|
||||||
this.cachedBackgroundCanvas = canvas;
|
this.cachedBackgroundCanvas = canvas;
|
||||||
this.cachedBackgroundContext = context;
|
this.cachedBackgroundContext = context;
|
||||||
|
@ -7,6 +7,7 @@ import { createLogger } from "../core/logging";
|
|||||||
import { Vector } from "../core/vector";
|
import { Vector } from "../core/vector";
|
||||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||||
import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors";
|
import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors";
|
||||||
|
import { THEME } from "./theme";
|
||||||
|
|
||||||
const rusha = require("rusha");
|
const rusha = require("rusha");
|
||||||
|
|
||||||
@ -274,8 +275,8 @@ export class ShapeDefinition extends BasicSerializableObject {
|
|||||||
context.rotate(rotation);
|
context.rotate(rotation);
|
||||||
|
|
||||||
context.fillStyle = enumColorsToHexCode[color];
|
context.fillStyle = enumColorsToHexCode[color];
|
||||||
context.strokeStyle = "#555";
|
context.strokeStyle = THEME.items.outline;
|
||||||
context.lineWidth = 1;
|
context.lineWidth = THEME.items.outlineWidth;
|
||||||
|
|
||||||
const insetPadding = 0.0;
|
const insetPadding = 0.0;
|
||||||
|
|
||||||
|
7
src/js/game/theme.js
Normal file
7
src/js/game/theme.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export const THEMES = {
|
||||||
|
dark: require("./themes/dark.json"),
|
||||||
|
light: require("./themes/light.json"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Make themes customizable
|
||||||
|
export const THEME = THEMES.light;
|
20
src/js/game/themes/dark.json
Normal file
20
src/js/game/themes/dark.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"uiStyle": "dark",
|
||||||
|
"map": {
|
||||||
|
"background": "#2e2f37",
|
||||||
|
"grid": "rgba(255, 255, 255, 0.02)",
|
||||||
|
"gridLineWidth": 0.5,
|
||||||
|
|
||||||
|
"resources": {
|
||||||
|
"shape": "#3d3f4a",
|
||||||
|
"red": "#4a3d3f",
|
||||||
|
"green": "#3e4a3d",
|
||||||
|
"blue": "#35384a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"items": {
|
||||||
|
"outline": "#111418",
|
||||||
|
"outlineWidth": 0.75
|
||||||
|
}
|
||||||
|
}
|
20
src/js/game/themes/light.json
Normal file
20
src/js/game/themes/light.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"uiStyle": "light",
|
||||||
|
"map": {
|
||||||
|
"background": "#fff",
|
||||||
|
"grid": "#fafafa",
|
||||||
|
"gridLineWidth": 1,
|
||||||
|
|
||||||
|
"resources": {
|
||||||
|
"shape": "#eaebec",
|
||||||
|
"red": "#ffbfc1",
|
||||||
|
"green": "#cbffc4",
|
||||||
|
"blue": "#bfdaff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"items": {
|
||||||
|
"outline": "#55575a",
|
||||||
|
"outlineWidth": 0.75
|
||||||
|
}
|
||||||
|
}
|
@ -74,10 +74,17 @@ class MusicInstance extends MusicInstanceInterface {
|
|||||||
autoplay: false,
|
autoplay: false,
|
||||||
loop: true,
|
loop: true,
|
||||||
html5: true,
|
html5: true,
|
||||||
volume: 0.3,
|
volume: 1,
|
||||||
preload: true,
|
preload: true,
|
||||||
pool: 2,
|
pool: 2,
|
||||||
|
|
||||||
|
onunlock: () => {
|
||||||
|
if (this.playing) {
|
||||||
|
logger.log("Playing music after manual unlock");
|
||||||
|
this.play();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onload: () => {
|
onload: () => {
|
||||||
resolve();
|
resolve();
|
||||||
},
|
},
|
||||||
|
@ -18,6 +18,7 @@ export const SOUNDS = {
|
|||||||
dialogOk: "ui/dialog_ok.mp3",
|
dialogOk: "ui/dialog_ok.mp3",
|
||||||
swishHide: "ui/ui_swish_hide.mp3",
|
swishHide: "ui/ui_swish_hide.mp3",
|
||||||
swishShow: "ui/ui_swish_show.mp3",
|
swishShow: "ui/ui_swish_show.mp3",
|
||||||
|
badgeNotification: "ui/badge_notification.mp3",
|
||||||
|
|
||||||
levelComplete: "ui/level_complete.mp3",
|
levelComplete: "ui/level_complete.mp3",
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ export const SOUNDS = {
|
|||||||
|
|
||||||
export const MUSIC = {
|
export const MUSIC = {
|
||||||
theme: "theme.mp3",
|
theme: "theme.mp3",
|
||||||
|
menu: "menu.mp3",
|
||||||
};
|
};
|
||||||
|
|
||||||
export class SoundInstanceInterface {
|
export class SoundInstanceInterface {
|
||||||
|
@ -6,6 +6,7 @@ import { ReadWriteProxy } from "../core/read_write_proxy";
|
|||||||
import { BoolSetting, EnumSetting, BaseSetting } from "./setting_types";
|
import { BoolSetting, EnumSetting, BaseSetting } from "./setting_types";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { ExplainedResult } from "../core/explained_result";
|
import { ExplainedResult } from "../core/explained_result";
|
||||||
|
import { THEMES } from "../game/theme";
|
||||||
|
|
||||||
const logger = createLogger("application_settings");
|
const logger = createLogger("application_settings");
|
||||||
|
|
||||||
@ -67,6 +68,18 @@ export const allApplicationSettings = [
|
|||||||
},
|
},
|
||||||
G_IS_STANDALONE
|
G_IS_STANDALONE
|
||||||
),
|
),
|
||||||
|
new EnumSetting("theme", {
|
||||||
|
options: Object.keys(THEMES),
|
||||||
|
valueGetter: theme => theme,
|
||||||
|
textGetter: theme => theme.substr(0, 1).toUpperCase() + theme.substr(1),
|
||||||
|
category: categoryApp,
|
||||||
|
restartRequired: false,
|
||||||
|
changeCb:
|
||||||
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
(app, id) => document.body.setAttribute("data-theme", id),
|
||||||
|
}),
|
||||||
new BoolSetting(
|
new BoolSetting(
|
||||||
"soundsMuted",
|
"soundsMuted",
|
||||||
categoryApp,
|
categoryApp,
|
||||||
@ -100,6 +113,7 @@ class SettingsStorage {
|
|||||||
|
|
||||||
this.soundsMuted = false;
|
this.soundsMuted = false;
|
||||||
this.musicMuted = false;
|
this.musicMuted = false;
|
||||||
|
this.theme = "light";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +124,17 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
// Read and directly write latest data back
|
// Read and directly write latest data back
|
||||||
return this.readAsync().then(() => this.writeAsync());
|
return this.readAsync()
|
||||||
|
.then(() => {
|
||||||
|
// Apply default setting callbacks
|
||||||
|
const settings = this.getAllSettings();
|
||||||
|
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||||
|
const handle = allApplicationSettings[i];
|
||||||
|
handle.apply(this.app, settings[handle.id]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
.then(() => this.writeAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
@ -208,7 +232,7 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentVersion() {
|
getCurrentVersion() {
|
||||||
return 2;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
migrate(data) {
|
migrate(data) {
|
||||||
|
@ -27,6 +27,16 @@ export class BaseSetting {
|
|||||||
this.dialogs = null;
|
this.dialogs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
* @param {any} value
|
||||||
|
*/
|
||||||
|
apply(app, value) {
|
||||||
|
if (this.changeCb) {
|
||||||
|
this.changeCb(app, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Application} app
|
* @param {Application} app
|
||||||
* @param {Element} element
|
* @param {Element} element
|
||||||
|
@ -99,17 +99,6 @@ export class PreloadState extends GameState {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
return this.app.settings.initialize();
|
return this.app.settings.initialize();
|
||||||
})
|
})
|
||||||
.then(() => {
|
|
||||||
// Make sure the app pickups the right size
|
|
||||||
this.app.updateAfterUiScaleChanged();
|
|
||||||
})
|
|
||||||
|
|
||||||
.then(() => {
|
|
||||||
// Initialize fullscreen
|
|
||||||
if (this.app.platformWrapper.getSupportsFullscreen()) {
|
|
||||||
this.app.platformWrapper.setFullscreen(this.app.settings.getIsFullScreen());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
.then(() => this.setStatus("Initializing sounds"))
|
.then(() => this.setStatus("Initializing sounds"))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
Loading…
Reference in New Issue
Block a user