mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 20:16:16 -04:00
Game state now contains a map of sounds to play next, for better perf
This commit is contained in:
parent
efa634cd8f
commit
581ee412d4
10 changed files with 1326 additions and 1153 deletions
|
@ -23,7 +23,6 @@ There's also an easy mode for kids (slower ball).
|
||||||
|
|
||||||
# Next
|
# Next
|
||||||
|
|
||||||
|
|
||||||
- extract sound logic, only set the params as a gamestate object
|
- extract sound logic, only set the params as a gamestate object
|
||||||
- separate particles by type
|
- separate particles by type
|
||||||
- reuse coins and particles
|
- reuse coins and particles
|
||||||
|
|
33
dist/PWA/sw-b71.js
vendored
33
dist/PWA/sw-b71.js
vendored
|
@ -1,2 +1,33 @@
|
||||||
function e(e,t,n,r,a,i,c){try{var o=e[i](c),u=o.value}catch(e){n(e);return}o.done?t(u):Promise.resolve(u).then(r,a)}function t(t){return function(){var n=this,r=arguments;return new Promise(function(a,i){var c=t.apply(n,r);function o(t){e(c,a,i,o,u,"next",t)}function u(t){e(c,a,i,o,u,"throw",t)}o(void 0)})}}function n(e,t){var n,r,a,i,c={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return i={next:o(0),throw:o(1),return:o(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function o(i){return function(o){return function(i){if(n)throw TypeError("Generator is already executing.");for(;c;)try{if(n=1,r&&(a=2&i[0]?r.return:i[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,i[1])).done)return a;switch(r=0,a&&(i=[2&i[0],a.value]),i[0]){case 0:case 1:a=i;break;case 4:return c.label++,{value:i[1],done:!1};case 5:c.label++,r=i[1],i=[0];continue;case 7:i=c.ops.pop(),c.trys.pop();continue;default:if(!(a=(a=c.trys).length>0&&a[a.length-1])&&(6===i[0]||2===i[0])){c=0;continue}if(3===i[0]&&(!a||i[1]>a[0]&&i[1]<a[3])){c.label=i[1];break}if(6===i[0]&&c.label<a[1]){c.label=a[1],a=i;break}if(a&&c.label<a[2]){c.label=a[2],c.ops.push(i);break}a[2]&&c.ops.pop(),c.trys.pop();continue}i=t.call(e,c)}catch(e){i=[6,e],r=0}finally{n=a=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,o])}}}var r="breakout-71-".concat("29036807"),a=["/"];self.addEventListener("install",function(e){e.waitUntil(t(function(){return n(this,function(e){switch(e.label){case 0:return[4,caches.open(r)];case 1:return e.sent().addAll(a),[2]}})})())}),self.addEventListener("activate",function(e){e.waitUntil(t(function(){return n(this,function(e){switch(e.label){case 0:return[4,caches.keys()];case 1:return[4,Promise.all(e.sent().map(function(e){if(e!==r)return caches.delete(e)}))];case 2:return e.sent(),[4,clients.claim()];case 3:return e.sent(),[2]}})})())}),self.addEventListener("fetch",function(e){if("navigate"===e.request.mode&&e.request.url.endsWith("/index.html?isPWA=true")){e.respondWith(caches.match("/"));return}});
|
// The version of the cache.
|
||||||
|
const VERSION = "29036807";
|
||||||
|
// The name of the cache
|
||||||
|
const CACHE_NAME = `breakout-71-${VERSION}`;
|
||||||
|
// The static resources that the app needs to function.
|
||||||
|
const APP_STATIC_RESOURCES = [
|
||||||
|
"/"
|
||||||
|
];
|
||||||
|
// On install, cache the static resources
|
||||||
|
self.addEventListener("install", (event)=>{
|
||||||
|
event.waitUntil((async ()=>{
|
||||||
|
const cache = await caches.open(CACHE_NAME);
|
||||||
|
cache.addAll(APP_STATIC_RESOURCES);
|
||||||
|
})());
|
||||||
|
});
|
||||||
|
// delete old caches on activate
|
||||||
|
self.addEventListener("activate", (event)=>{
|
||||||
|
event.waitUntil((async ()=>{
|
||||||
|
const names = await caches.keys();
|
||||||
|
await Promise.all(names.map((name)=>{
|
||||||
|
if (name !== CACHE_NAME) return caches.delete(name);
|
||||||
|
}));
|
||||||
|
await clients.claim();
|
||||||
|
})());
|
||||||
|
});
|
||||||
|
self.addEventListener("fetch", (event)=>{
|
||||||
|
if (event.request.mode === "navigate" && event.request.url.endsWith("/index.html?isPWA=true")) {
|
||||||
|
event.respondWith(caches.match("/"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//# sourceMappingURL=sw-b71.js.map
|
//# sourceMappingURL=sw-b71.js.map
|
||||||
|
|
2
dist/PWA/sw-b71.js.map
vendored
2
dist/PWA/sw-b71.js.map
vendored
File diff suppressed because one or more lines are too long
140
dist/index.html
vendored
140
dist/index.html
vendored
|
@ -765,6 +765,7 @@ function tick() {
|
||||||
(0, _render.render)(gameState);
|
(0, _render.render)(gameState);
|
||||||
}
|
}
|
||||||
if (gameState.running) (0, _recording.recordOneFrame)(gameState);
|
if (gameState.running) (0, _recording.recordOneFrame)(gameState);
|
||||||
|
if ((0, _options.isOptionOn)('sound')) (0, _sounds.playPendingSounds)(gameState);
|
||||||
requestAnimationFrame(tick);
|
requestAnimationFrame(tick);
|
||||||
}
|
}
|
||||||
window.addEventListener("visibilitychange", ()=>{
|
window.addEventListener("visibilitychange", ()=>{
|
||||||
|
@ -1185,7 +1186,7 @@ window.stressTest = ()=>restart({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
},{"./loadGameData":"l1B4x","./sounds":"dQKPV","./game_utils":"cEeac","./PWA/sw_loader":"2n0gK","./i18n/i18n":"eNPRm","./settings":"5blfu","./gameStateMutators":"9ZeQl","./render":"9AS2t","./recording":"godmD","./newGameState":"aQN6X","./asyncAlert":"rSqLY","./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3","./getLevelBackground":"7OIPf"}],"l1B4x":[function(require,module,exports,__globalThis) {
|
},{"./loadGameData":"l1B4x","./sounds":"dQKPV","./game_utils":"cEeac","./PWA/sw_loader":"2n0gK","./i18n/i18n":"eNPRm","./settings":"5blfu","./gameStateMutators":"9ZeQl","./render":"9AS2t","./recording":"godmD","./newGameState":"aQN6X","./asyncAlert":"rSqLY","./options":"d5NoS","./getLevelBackground":"7OIPf","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"l1B4x":[function(require,module,exports,__globalThis) {
|
||||||
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
||||||
parcelHelpers.defineInteropFlag(exports);
|
parcelHelpers.defineInteropFlag(exports);
|
||||||
parcelHelpers.export(exports, "appVersion", ()=>appVersion);
|
parcelHelpers.export(exports, "appVersion", ()=>appVersion);
|
||||||
|
@ -1756,49 +1757,62 @@ function levelIconHTML(bricks, levelSize, color) {
|
||||||
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"dQKPV":[function(require,module,exports,__globalThis) {
|
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"dQKPV":[function(require,module,exports,__globalThis) {
|
||||||
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
||||||
parcelHelpers.defineInteropFlag(exports);
|
parcelHelpers.defineInteropFlag(exports);
|
||||||
|
parcelHelpers.export(exports, "playPendingSounds", ()=>playPendingSounds);
|
||||||
parcelHelpers.export(exports, "sounds", ()=>sounds);
|
parcelHelpers.export(exports, "sounds", ()=>sounds);
|
||||||
parcelHelpers.export(exports, "getAudioContext", ()=>getAudioContext);
|
parcelHelpers.export(exports, "getAudioContext", ()=>getAudioContext);
|
||||||
parcelHelpers.export(exports, "getAudioRecordingTrack", ()=>getAudioRecordingTrack);
|
parcelHelpers.export(exports, "getAudioRecordingTrack", ()=>getAudioRecordingTrack);
|
||||||
var _game = require("./game");
|
|
||||||
var _options = require("./options");
|
var _options = require("./options");
|
||||||
|
let lastPlay = Date.now();
|
||||||
|
function playPendingSounds(gameState) {
|
||||||
|
if (lastPlay > Date.now() - 60) return;
|
||||||
|
lastPlay = Date.now();
|
||||||
|
for(let key in gameState.aboutToPlaySound){
|
||||||
|
const soundName = key;
|
||||||
|
const ex = gameState.aboutToPlaySound[soundName];
|
||||||
|
if (ex.vol) {
|
||||||
|
sounds[soundName](Math.min(2, ex.vol), pixelsToPan(gameState, ex.x), gameState.combo);
|
||||||
|
ex.vol = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const sounds = {
|
const sounds = {
|
||||||
wallBeep: (pan)=>{
|
wallBeep: (vol, pan, combo)=>{
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
createSingleBounceSound(800, pixelsToPan(pan));
|
createSingleBounceSound(800, pan, vol);
|
||||||
},
|
},
|
||||||
comboIncreaseMaybe: (combo, x, volume)=>{
|
comboIncreaseMaybe: (volume, pan, combo)=>{
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
let delta = 0;
|
let delta = 0;
|
||||||
if (!isNaN(lastComboPlayed)) {
|
if (!isNaN(lastComboPlayed)) {
|
||||||
if (lastComboPlayed < combo) delta = 1;
|
if (lastComboPlayed < combo) delta = 1;
|
||||||
if (lastComboPlayed > combo) delta = -1;
|
if (lastComboPlayed > combo) delta = -1;
|
||||||
}
|
}
|
||||||
playShepard(delta, pixelsToPan(x), volume);
|
playShepard(delta, pan, volume);
|
||||||
lastComboPlayed = combo;
|
lastComboPlayed = combo;
|
||||||
},
|
},
|
||||||
comboDecrease () {
|
comboDecrease (volume, pan, combo) {
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
playShepard(-1, 0.5, 0.5);
|
playShepard(-1, pan, volume);
|
||||||
},
|
},
|
||||||
coinBounce: (pan, volume)=>{
|
coinBounce: (volume, pan, combo)=>{
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
createSingleBounceSound(1200, pan, volume, 0.1, "triangle");
|
||||||
},
|
},
|
||||||
explode: (pan)=>{
|
explode: (volume, pan, combo)=>{
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
createExplosionSound(pixelsToPan(pan));
|
createExplosionSound(pan);
|
||||||
},
|
},
|
||||||
lifeLost (pan) {
|
lifeLost (volume, pan, combo) {
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
createShatteredGlassSound(pixelsToPan(pan));
|
createShatteredGlassSound(pan);
|
||||||
},
|
},
|
||||||
coinCatch (pan) {
|
coinCatch (volume, pan, combo) {
|
||||||
if (!(0, _options.isOptionOn)("sound")) return;
|
if (!(0, _options.isOptionOn)("sound")) return;
|
||||||
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
createSingleBounceSound(900, pan, volume, 0.1, "triangle");
|
||||||
},
|
},
|
||||||
colorChange (pan, volume) {
|
colorChange (volume, pan, combo) {
|
||||||
createSingleBounceSound(400, pixelsToPan(pan), volume, 0.5, "sine");
|
createSingleBounceSound(400, pan, volume, 0.5, "sine");
|
||||||
createSingleBounceSound(800, pixelsToPan(pan), volume * 0.5, 0.2, "square");
|
createSingleBounceSound(800, pan, volume * 0.5, 0.2, "square");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// How to play the code on the leftconst context = new window.AudioContext();
|
// How to play the code on the leftconst context = new window.AudioContext();
|
||||||
|
@ -1879,8 +1893,8 @@ function createExplosionSound(pan = 0.5) {
|
||||||
// Stop the noise source after the sound has played
|
// Stop the noise source after the sound has played
|
||||||
noiseSource.stop(context.currentTime + 1);
|
noiseSource.stop(context.currentTime + 1);
|
||||||
}
|
}
|
||||||
function pixelsToPan(pan) {
|
function pixelsToPan(gameState, pan) {
|
||||||
return Math.max(0, Math.min(1, (pan - (0, _game.gameState).offsetXRoundedDown) / (0, _game.gameState).gameZoneWidthRoundedUp));
|
return Math.max(0, Math.min(1, (pan - gameState.offsetXRoundedDown) / gameState.gameZoneWidthRoundedUp));
|
||||||
}
|
}
|
||||||
let lastComboPlayed = NaN, shepard = 6;
|
let lastComboPlayed = NaN, shepard = 6;
|
||||||
function playShepard(delta, pan, volume) {
|
function playShepard(delta, pan, volume) {
|
||||||
|
@ -1935,7 +1949,7 @@ function createOscillator(context, frequency, type) {
|
||||||
return oscillator;
|
return oscillator;
|
||||||
}
|
}
|
||||||
|
|
||||||
},{"./game":"edeGs","./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"d5NoS":[function(require,module,exports,__globalThis) {
|
},{"./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"d5NoS":[function(require,module,exports,__globalThis) {
|
||||||
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
||||||
parcelHelpers.defineInteropFlag(exports);
|
parcelHelpers.defineInteropFlag(exports);
|
||||||
parcelHelpers.export(exports, "options", ()=>options);
|
parcelHelpers.export(exports, "options", ()=>options);
|
||||||
|
@ -2001,6 +2015,7 @@ parcelHelpers.export(exports, "isTelekinesisActive", ()=>isTelekinesisActive);
|
||||||
parcelHelpers.export(exports, "findLast", ()=>findLast);
|
parcelHelpers.export(exports, "findLast", ()=>findLast);
|
||||||
parcelHelpers.export(exports, "distance2", ()=>distance2);
|
parcelHelpers.export(exports, "distance2", ()=>distance2);
|
||||||
parcelHelpers.export(exports, "distanceBetween", ()=>distanceBetween);
|
parcelHelpers.export(exports, "distanceBetween", ()=>distanceBetween);
|
||||||
|
parcelHelpers.export(exports, "defaultSounds", ()=>defaultSounds);
|
||||||
var _loadGameData = require("./loadGameData");
|
var _loadGameData = require("./loadGameData");
|
||||||
function getMajorityValue(arr) {
|
function getMajorityValue(arr) {
|
||||||
const count = {};
|
const count = {};
|
||||||
|
@ -2058,6 +2073,44 @@ function distance2(a, b) {
|
||||||
function distanceBetween(a, b) {
|
function distanceBetween(a, b) {
|
||||||
return Math.sqrt(distance2(a, b));
|
return Math.sqrt(distance2(a, b));
|
||||||
}
|
}
|
||||||
|
function defaultSounds() {
|
||||||
|
return {
|
||||||
|
aboutToPlaySound: {
|
||||||
|
wallBeep: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
comboIncreaseMaybe: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
comboDecrease: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
coinBounce: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
explode: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
lifeLost: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
coinCatch: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
colorChange: {
|
||||||
|
vol: 0,
|
||||||
|
x: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
},{"./loadGameData":"l1B4x","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"2n0gK":[function(require,module,exports,__globalThis) {
|
},{"./loadGameData":"l1B4x","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"2n0gK":[function(require,module,exports,__globalThis) {
|
||||||
if ("serviceWorker" in navigator && window.location.search.includes("isPWA=true")) // @ts-ignore
|
if ("serviceWorker" in navigator && window.location.search.includes("isPWA=true")) // @ts-ignore
|
||||||
|
@ -2115,6 +2168,7 @@ parcelHelpers.export(exports, "spawnExplosion", ()=>spawnExplosion);
|
||||||
parcelHelpers.export(exports, "explodeBrick", ()=>explodeBrick);
|
parcelHelpers.export(exports, "explodeBrick", ()=>explodeBrick);
|
||||||
parcelHelpers.export(exports, "dontOfferTooSoon", ()=>dontOfferTooSoon);
|
parcelHelpers.export(exports, "dontOfferTooSoon", ()=>dontOfferTooSoon);
|
||||||
parcelHelpers.export(exports, "pickRandomUpgrades", ()=>pickRandomUpgrades);
|
parcelHelpers.export(exports, "pickRandomUpgrades", ()=>pickRandomUpgrades);
|
||||||
|
parcelHelpers.export(exports, "schedulGameSound", ()=>schedulGameSound);
|
||||||
parcelHelpers.export(exports, "addToScore", ()=>addToScore);
|
parcelHelpers.export(exports, "addToScore", ()=>addToScore);
|
||||||
parcelHelpers.export(exports, "setLevel", ()=>setLevel);
|
parcelHelpers.export(exports, "setLevel", ()=>setLevel);
|
||||||
parcelHelpers.export(exports, "rainbowColor", ()=>rainbowColor);
|
parcelHelpers.export(exports, "rainbowColor", ()=>rainbowColor);
|
||||||
|
@ -2122,7 +2176,6 @@ parcelHelpers.export(exports, "repulse", ()=>repulse);
|
||||||
parcelHelpers.export(exports, "attract", ()=>attract);
|
parcelHelpers.export(exports, "attract", ()=>attract);
|
||||||
parcelHelpers.export(exports, "gameStateTick", ()=>gameStateTick);
|
parcelHelpers.export(exports, "gameStateTick", ()=>gameStateTick);
|
||||||
parcelHelpers.export(exports, "ballTick", ()=>ballTick);
|
parcelHelpers.export(exports, "ballTick", ()=>ballTick);
|
||||||
var _sounds = require("./sounds");
|
|
||||||
var _gameUtils = require("./game_utils");
|
var _gameUtils = require("./game_utils");
|
||||||
var _i18N = require("./i18n/i18n");
|
var _i18N = require("./i18n/i18n");
|
||||||
var _loadGameData = require("./loadGameData");
|
var _loadGameData = require("./loadGameData");
|
||||||
|
@ -2208,7 +2261,7 @@ function resetCombo(gameState, x, y) {
|
||||||
if (prev > gameState.combo && gameState.perks.soft_reset) gameState.combo += Math.floor((prev - gameState.combo) * (gameState.perks.soft_reset * 10) / 100);
|
if (prev > gameState.combo && gameState.perks.soft_reset) gameState.combo += Math.floor((prev - gameState.combo) * (gameState.perks.soft_reset * 10) / 100);
|
||||||
const lost = Math.max(0, prev - gameState.combo);
|
const lost = Math.max(0, prev - gameState.combo);
|
||||||
if (lost) {
|
if (lost) {
|
||||||
for(let i = 0; i < lost && i < 8; i++)setTimeout(()=>(0, _sounds.sounds).comboDecrease(), i * 100);
|
for(let i = 0; i < lost && i < 8; i++)setTimeout(()=>schedulGameSound(gameState, 'comboDecrease', x, 1), i * 100);
|
||||||
if (typeof x !== "undefined" && typeof y !== "undefined") gameState.flashes.push({
|
if (typeof x !== "undefined" && typeof y !== "undefined") gameState.flashes.push({
|
||||||
type: "text",
|
type: "text",
|
||||||
text: "-" + lost,
|
text: "-" + lost,
|
||||||
|
@ -2227,7 +2280,7 @@ function decreaseCombo(gameState, by, x, y) {
|
||||||
gameState.combo = Math.max(baseCombo(gameState), gameState.combo - by);
|
gameState.combo = Math.max(baseCombo(gameState), gameState.combo - by);
|
||||||
const lost = Math.max(0, prev - gameState.combo);
|
const lost = Math.max(0, prev - gameState.combo);
|
||||||
if (lost) {
|
if (lost) {
|
||||||
(0, _sounds.sounds).comboDecrease();
|
schedulGameSound(gameState, 'comboDecrease', x, 1);
|
||||||
if (typeof x !== "undefined" && typeof y !== "undefined") gameState.flashes.push({
|
if (typeof x !== "undefined" && typeof y !== "undefined") gameState.flashes.push({
|
||||||
type: "text",
|
type: "text",
|
||||||
text: "-" + lost,
|
text: "-" + lost,
|
||||||
|
@ -2263,7 +2316,7 @@ function explodeBrick(gameState, index, ball, isExplosion) {
|
||||||
if (color === "black") {
|
if (color === "black") {
|
||||||
delete gameState.bricks[index];
|
delete gameState.bricks[index];
|
||||||
const x = (0, _gameUtils.brickCenterX)(gameState, index), y = (0, _gameUtils.brickCenterY)(gameState, index);
|
const x = (0, _gameUtils.brickCenterX)(gameState, index), y = (0, _gameUtils.brickCenterY)(gameState, index);
|
||||||
(0, _sounds.sounds).explode(ball.x);
|
schedulGameSound(gameState, 'explode', ball.x, 1);
|
||||||
const col = index % gameState.gridSize;
|
const col = index % gameState.gridSize;
|
||||||
const row = Math.floor(index / gameState.gridSize);
|
const row = Math.floor(index / gameState.gridSize);
|
||||||
const size = 1 + gameState.perks.bigger_explosions;
|
const size = 1 + gameState.perks.bigger_explosions;
|
||||||
|
@ -2346,13 +2399,13 @@ function explodeBrick(gameState, index, ball, isExplosion) {
|
||||||
// color change
|
// color change
|
||||||
if ((gameState.perks.picky_eater || gameState.perks.pierce_color) && color !== gameState.ballsColor && color) {
|
if ((gameState.perks.picky_eater || gameState.perks.pierce_color) && color !== gameState.ballsColor && color) {
|
||||||
if (gameState.perks.picky_eater) resetCombo(gameState, ball.x, ball.y);
|
if (gameState.perks.picky_eater) resetCombo(gameState, ball.x, ball.y);
|
||||||
(0, _sounds.sounds).colorChange(ball.x, 0.8);
|
schedulGameSound(gameState, 'colorChange', ball.x, 0.8);
|
||||||
gameState.lastExplosion = gameState.levelTime;
|
gameState.lastExplosion = gameState.levelTime;
|
||||||
gameState.ballsColor = color;
|
gameState.ballsColor = color;
|
||||||
if (!(0, _options.isOptionOn)("basic")) gameState.balls.forEach((ball)=>{
|
if (!(0, _options.isOptionOn)("basic")) gameState.balls.forEach((ball)=>{
|
||||||
spawnExplosion(gameState, 7, ball.previousX, ball.previousY, color, 150, 15);
|
spawnExplosion(gameState, 7, ball.previousX, ball.previousY, color, 150, 15);
|
||||||
});
|
});
|
||||||
} else (0, _sounds.sounds).comboIncreaseMaybe(gameState.combo, ball.x, 1);
|
} else schedulGameSound(gameState, 'comboIncreaseMaybe', ball.x, 1);
|
||||||
}
|
}
|
||||||
gameState.flashes.push({
|
gameState.flashes.push({
|
||||||
type: "ball",
|
type: "ball",
|
||||||
|
@ -2390,6 +2443,14 @@ function pickRandomUpgrades(gameState, count) {
|
||||||
help: u.help(gameState.perks[u.id] + 1)
|
help: u.help(gameState.perks[u.id] + 1)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
function schedulGameSound(gameState, sound, x, vol) {
|
||||||
|
if (!vol) return;
|
||||||
|
x ??= gameState.offsetX + gameState.gameZoneWidth / 2;
|
||||||
|
const ex = gameState.aboutToPlaySound[sound];
|
||||||
|
if (ex.vol) console.log('Combined sounds for ' + sound);
|
||||||
|
ex.x = (x * vol + ex.x * ex.vol) / (vol + ex.vol);
|
||||||
|
ex.vol += vol;
|
||||||
|
}
|
||||||
function addToScore(gameState, coin) {
|
function addToScore(gameState, coin) {
|
||||||
coin.destroyed = true;
|
coin.destroyed = true;
|
||||||
gameState.score += coin.points;
|
gameState.score += coin.points;
|
||||||
|
@ -2413,7 +2474,7 @@ function addToScore(gameState, coin) {
|
||||||
});
|
});
|
||||||
if (Date.now() - gameState.lastPlayedCoinGrab > 16) {
|
if (Date.now() - gameState.lastPlayedCoinGrab > 16) {
|
||||||
gameState.lastPlayedCoinGrab = Date.now();
|
gameState.lastPlayedCoinGrab = Date.now();
|
||||||
(0, _sounds.sounds).coinCatch(coin.x);
|
schedulGameSound(gameState, 'coinCatch', coin.x, 1);
|
||||||
}
|
}
|
||||||
gameState.runStatistics.score += coin.points;
|
gameState.runStatistics.score += coin.points;
|
||||||
}
|
}
|
||||||
|
@ -2553,7 +2614,6 @@ frames = 1) {
|
||||||
score: gameState.score
|
score: gameState.score
|
||||||
}));
|
}));
|
||||||
} else if (gameState.running || gameState.levelTime) {
|
} else if (gameState.running || gameState.levelTime) {
|
||||||
let playedCoinBounce = false;
|
|
||||||
const coinRadius = Math.round(gameState.coinSize / 2);
|
const coinRadius = Math.round(gameState.coinSize / 2);
|
||||||
gameState.coins.forEach((coin)=>{
|
gameState.coins.forEach((coin)=>{
|
||||||
if (coin.destroyed) return;
|
if (coin.destroyed) return;
|
||||||
|
@ -2585,17 +2645,14 @@ frames = 1) {
|
||||||
if (gameState.bricks[hitBrick] && coin.color !== gameState.bricks[hitBrick] && gameState.bricks[hitBrick] !== "black" && !coin.coloredABrick) {
|
if (gameState.bricks[hitBrick] && coin.color !== gameState.bricks[hitBrick] && gameState.bricks[hitBrick] !== "black" && !coin.coloredABrick) {
|
||||||
gameState.bricks[hitBrick] = coin.color;
|
gameState.bricks[hitBrick] = coin.color;
|
||||||
coin.coloredABrick = true;
|
coin.coloredABrick = true;
|
||||||
(0, _sounds.sounds).colorChange(coin.x, 0.3);
|
schedulGameSound(gameState, 'colorChange', coin.x, 0.3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof hitBrick !== "undefined" || hitBorder) {
|
if (typeof hitBrick !== "undefined" || hitBorder) {
|
||||||
coin.vx *= 0.8;
|
coin.vx *= 0.8;
|
||||||
coin.vy *= 0.8;
|
coin.vy *= 0.8;
|
||||||
coin.sa *= 0.9;
|
coin.sa *= 0.9;
|
||||||
if (speed > 20 && !playedCoinBounce) {
|
if (speed > 20) schedulGameSound(gameState, 'coinBounce', coin.x, 0.2);
|
||||||
playedCoinBounce = true;
|
|
||||||
(0, _sounds.sounds).coinBounce(coin.x, 0.2);
|
|
||||||
}
|
|
||||||
if (Math.abs(coin.vy) < 3) coin.vy = 0;
|
if (Math.abs(coin.vy) < 3) coin.vy = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2739,7 +2796,7 @@ function ballTick(gameState, ball, delta) {
|
||||||
if (gameState.perks.left_is_lava && borderHitCode % 2 && ball.x < gameState.offsetX + gameState.gameZoneWidth / 2) resetCombo(gameState, ball.x, ball.y);
|
if (gameState.perks.left_is_lava && borderHitCode % 2 && ball.x < gameState.offsetX + gameState.gameZoneWidth / 2) resetCombo(gameState, ball.x, ball.y);
|
||||||
if (gameState.perks.right_is_lava && borderHitCode % 2 && ball.x > gameState.offsetX + gameState.gameZoneWidth / 2) resetCombo(gameState, ball.x, ball.y);
|
if (gameState.perks.right_is_lava && borderHitCode % 2 && ball.x > gameState.offsetX + gameState.gameZoneWidth / 2) resetCombo(gameState, ball.x, ball.y);
|
||||||
if (gameState.perks.top_is_lava && borderHitCode >= 2) resetCombo(gameState, ball.x, ball.y + gameState.ballSize);
|
if (gameState.perks.top_is_lava && borderHitCode >= 2) resetCombo(gameState, ball.x, ball.y + gameState.ballSize);
|
||||||
(0, _sounds.sounds).wallBeep(ball.x);
|
schedulGameSound(gameState, 'wallBeep', ball.x, 1);
|
||||||
gameState.levelWallBounces++;
|
gameState.levelWallBounces++;
|
||||||
gameState.runStatistics.wall_bounces++;
|
gameState.runStatistics.wall_bounces++;
|
||||||
}
|
}
|
||||||
|
@ -2752,11 +2809,11 @@ function ballTick(gameState, ball, delta) {
|
||||||
const angle = Math.atan2(-gameState.puckWidth / 2, (ball.x - gameState.puckPosition) * (gameState.perks.concave_puck ? -0.5 : 1));
|
const angle = Math.atan2(-gameState.puckWidth / 2, (ball.x - gameState.puckPosition) * (gameState.perks.concave_puck ? -0.5 : 1));
|
||||||
ball.vx = speed * Math.cos(angle);
|
ball.vx = speed * Math.cos(angle);
|
||||||
ball.vy = speed * Math.sin(angle);
|
ball.vy = speed * Math.sin(angle);
|
||||||
(0, _sounds.sounds).wallBeep(ball.x);
|
schedulGameSound(gameState, 'wallBeep', ball.x, 1);
|
||||||
} else {
|
} else {
|
||||||
ball.vy *= -1;
|
ball.vy *= -1;
|
||||||
gameState.perks.extra_life = Math.max(0, gameState.perks.extra_life - 1);
|
gameState.perks.extra_life = Math.max(0, gameState.perks.extra_life - 1);
|
||||||
(0, _sounds.sounds).lifeLost(ball.x);
|
schedulGameSound(gameState, 'lifeLost', ball.x, 1);
|
||||||
if (!(0, _options.isOptionOn)("basic")) for(let i = 0; i < 10; i++)gameState.flashes.push({
|
if (!(0, _options.isOptionOn)("basic")) for(let i = 0; i < 10; i++)gameState.flashes.push({
|
||||||
type: "particle",
|
type: "particle",
|
||||||
ethereal: false,
|
ethereal: false,
|
||||||
|
@ -2831,7 +2888,7 @@ function ballTick(gameState, ball, delta) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sturdyBounce) {
|
if (sturdyBounce) {
|
||||||
(0, _sounds.sounds).wallBeep(x);
|
schedulGameSound(gameState, 'wallBeep', x, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof hitBrick !== "undefined") {
|
if (typeof hitBrick !== "undefined") {
|
||||||
|
@ -2863,7 +2920,7 @@ function ballTick(gameState, ball, delta) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
},{"./sounds":"dQKPV","./game_utils":"cEeac","./i18n/i18n":"eNPRm","./loadGameData":"l1B4x","./settings":"5blfu","./render":"9AS2t","./gameOver":"caCAf","./game":"edeGs","./recording":"godmD","./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"9AS2t":[function(require,module,exports,__globalThis) {
|
},{"./game_utils":"cEeac","./i18n/i18n":"eNPRm","./loadGameData":"l1B4x","./settings":"5blfu","./render":"9AS2t","./gameOver":"caCAf","./game":"edeGs","./recording":"godmD","./options":"d5NoS","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"9AS2t":[function(require,module,exports,__globalThis) {
|
||||||
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
|
||||||
parcelHelpers.defineInteropFlag(exports);
|
parcelHelpers.defineInteropFlag(exports);
|
||||||
parcelHelpers.export(exports, "gameCanvas", ()=>gameCanvas);
|
parcelHelpers.export(exports, "gameCanvas", ()=>gameCanvas);
|
||||||
|
@ -3742,7 +3799,8 @@ function newGameState(params) {
|
||||||
levelTime: 0,
|
levelTime: 0,
|
||||||
levelWallBounces: 0,
|
levelWallBounces: 0,
|
||||||
needsRender: true,
|
needsRender: true,
|
||||||
autoCleanUses: 0
|
autoCleanUses: 0,
|
||||||
|
...(0, _gameUtils.defaultSounds)()
|
||||||
};
|
};
|
||||||
(0, _gameStateMutators.resetBalls)(gameState);
|
(0, _gameStateMutators.resetBalls)(gameState);
|
||||||
if (!(0, _gameUtils.sumOfKeys)(gameState.perks)) {
|
if (!(0, _gameUtils.sumOfKeys)(gameState.perks)) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
RunParams,
|
RunParams,
|
||||||
Upgrade,
|
Upgrade,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import { getAudioContext } from "./sounds";
|
import {getAudioContext, playPendingSounds} from "./sounds";
|
||||||
import {
|
import {
|
||||||
currentLevelInfo,
|
currentLevelInfo,
|
||||||
getRowColIndex,
|
getRowColIndex,
|
||||||
|
@ -429,7 +429,6 @@ export function bordersHitCheck(
|
||||||
|
|
||||||
return hhit + vhit * 2;
|
return hhit + vhit * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tick() {
|
export function tick() {
|
||||||
const currentTick = performance.now();
|
const currentTick = performance.now();
|
||||||
const timeDeltaMs = currentTick - gameState.lastTick;
|
const timeDeltaMs = currentTick - gameState.lastTick;
|
||||||
|
@ -458,6 +457,9 @@ export function tick() {
|
||||||
if (gameState.running) {
|
if (gameState.running) {
|
||||||
recordOneFrame(gameState);
|
recordOneFrame(gameState);
|
||||||
}
|
}
|
||||||
|
if(isOptionOn('sound') ){
|
||||||
|
playPendingSounds(gameState)
|
||||||
|
}
|
||||||
requestAnimationFrame(tick);
|
requestAnimationFrame(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
import { Ball, GameState, PerkId, PerksMap } from "./types";
|
import {Ball, GameState, PerkId, PerksMap} from "./types";
|
||||||
import { icons, upgrades } from "./loadGameData";
|
import {icons, upgrades} from "./loadGameData";
|
||||||
|
|
||||||
export function getMajorityValue(arr: string[]): string {
|
export function getMajorityValue(arr: string[]): string {
|
||||||
const count: { [k: string]: number } = {};
|
const count: { [k: string]: number } = {};
|
||||||
|
@ -99,3 +99,18 @@ export function distanceBetween(
|
||||||
) {
|
) {
|
||||||
return Math.sqrt(distance2(a, b));
|
return Math.sqrt(distance2(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function defaultSounds() {
|
||||||
|
return {
|
||||||
|
aboutToPlaySound: {
|
||||||
|
wallBeep: {vol: 0, x: 0},
|
||||||
|
comboIncreaseMaybe: {vol: 0, x: 0},
|
||||||
|
comboDecrease: {vol: 0, x: 0},
|
||||||
|
coinBounce: {vol: 0, x: 0},
|
||||||
|
explode: {vol: 0, x: 0},
|
||||||
|
lifeLost: {vol: 0, x: 0},
|
||||||
|
coinCatch: {vol: 0, x: 0},
|
||||||
|
colorChange: {vol: 0, x: 0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,9 @@
|
||||||
import { GameState, RunParams } from "./types";
|
import {GameState, RunParams} from "./types";
|
||||||
import { getTotalScore } from "./settings";
|
import {getTotalScore} from "./settings";
|
||||||
import { allLevels, upgrades } from "./loadGameData";
|
import {allLevels, upgrades} from "./loadGameData";
|
||||||
import {
|
import {defaultSounds, getPossibleUpgrades, makeEmptyPerksMap, sumOfKeys,} from "./game_utils";
|
||||||
getPossibleUpgrades,
|
import {dontOfferTooSoon, resetBalls} from "./gameStateMutators";
|
||||||
makeEmptyPerksMap,
|
import {isOptionOn} from "./options";
|
||||||
sumOfKeys,
|
|
||||||
} from "./game_utils";
|
|
||||||
import { dontOfferTooSoon, resetBalls } from "./gameStateMutators";
|
|
||||||
import { isOptionOn } from "./options";
|
|
||||||
|
|
||||||
export function newGameState(params: RunParams): GameState {
|
export function newGameState(params: RunParams): GameState {
|
||||||
const totalScoreAtRunStart = getTotalScore();
|
const totalScoreAtRunStart = getTotalScore();
|
||||||
|
@ -91,6 +87,7 @@ export function newGameState(params: RunParams): GameState {
|
||||||
levelWallBounces: 0,
|
levelWallBounces: 0,
|
||||||
needsRender: true,
|
needsRender: true,
|
||||||
autoCleanUses: 0,
|
autoCleanUses: 0,
|
||||||
|
...defaultSounds()
|
||||||
};
|
};
|
||||||
resetBalls(gameState);
|
resetBalls(gameState);
|
||||||
|
|
||||||
|
@ -109,3 +106,4 @@ export function newGameState(params: RunParams): GameState {
|
||||||
}
|
}
|
||||||
return gameState;
|
return gameState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,48 +1,65 @@
|
||||||
import { gameState } from "./game";
|
|
||||||
|
|
||||||
import { isOptionOn } from "./options";
|
import { isOptionOn } from "./options";
|
||||||
|
import {GameState} from "./types";
|
||||||
|
|
||||||
|
let lastPlay = Date.now()
|
||||||
|
|
||||||
|
export function playPendingSounds(gameState:GameState){
|
||||||
|
if(lastPlay>Date.now()-60){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastPlay=Date.now()
|
||||||
|
for(let key in gameState.aboutToPlaySound){
|
||||||
|
const soundName = key as keyof GameState["aboutToPlaySound"]
|
||||||
|
const ex = gameState.aboutToPlaySound[soundName] as {vol:number, x:number}
|
||||||
|
if(ex.vol){
|
||||||
|
sounds[soundName](Math.min(2,ex.vol),pixelsToPan(gameState, ex.x), gameState.combo)
|
||||||
|
ex.vol=0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
export const sounds = {
|
export const sounds = {
|
||||||
wallBeep: (pan: number) => {
|
wallBeep: (vol:number, pan: number, combo:number) => {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
createSingleBounceSound(800, pixelsToPan(pan));
|
createSingleBounceSound(800, pan, vol);
|
||||||
},
|
},
|
||||||
|
|
||||||
comboIncreaseMaybe: (combo: number, x: number, volume: number) => {
|
comboIncreaseMaybe: ( volume: number,pan: number,combo: number, ) => {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
let delta = 0;
|
let delta = 0;
|
||||||
if (!isNaN(lastComboPlayed)) {
|
if (!isNaN(lastComboPlayed)) {
|
||||||
if (lastComboPlayed < combo) delta = 1;
|
if (lastComboPlayed < combo) delta = 1;
|
||||||
if (lastComboPlayed > combo) delta = -1;
|
if (lastComboPlayed > combo) delta = -1;
|
||||||
}
|
}
|
||||||
playShepard(delta, pixelsToPan(x), volume);
|
playShepard(delta, pan, volume);
|
||||||
lastComboPlayed = combo;
|
lastComboPlayed = combo;
|
||||||
},
|
},
|
||||||
|
|
||||||
comboDecrease() {
|
comboDecrease(volume: number,pan: number,combo: number) {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
playShepard(-1, 0.5, 0.5);
|
playShepard(-1, pan, volume);
|
||||||
},
|
},
|
||||||
coinBounce: (pan: number, volume: number) => {
|
coinBounce: (volume: number,pan: number,combo: number) => {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
createSingleBounceSound(1200, pan, volume, 0.1, "triangle");
|
||||||
},
|
},
|
||||||
explode: (pan: number) => {
|
explode: (volume: number,pan: number,combo: number) => {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
createExplosionSound(pixelsToPan(pan));
|
createExplosionSound(pan);
|
||||||
},
|
},
|
||||||
lifeLost(pan: number) {
|
lifeLost(volume: number,pan: number,combo: number) {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
createShatteredGlassSound(pixelsToPan(pan));
|
createShatteredGlassSound(pan);
|
||||||
},
|
},
|
||||||
|
|
||||||
coinCatch(pan: number) {
|
coinCatch(volume: number,pan: number,combo: number) {
|
||||||
if (!isOptionOn("sound")) return;
|
if (!isOptionOn("sound")) return;
|
||||||
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
createSingleBounceSound(900, (pan), volume, 0.1, "triangle");
|
||||||
},
|
},
|
||||||
colorChange(pan: number, volume: number) {
|
colorChange(volume: number,pan: number,combo: number) {
|
||||||
createSingleBounceSound(400, pixelsToPan(pan), volume, 0.5, "sine");
|
createSingleBounceSound(400, pan, volume, 0.5, "sine");
|
||||||
createSingleBounceSound(800, pixelsToPan(pan), volume * 0.5, 0.2, "square");
|
createSingleBounceSound(800, pan, volume * 0.5, 0.2, "square");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,7 +175,7 @@ function createExplosionSound(pan = 0.5) {
|
||||||
noiseSource.stop(context.currentTime + 1);
|
noiseSource.stop(context.currentTime + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pixelsToPan(pan: number) {
|
function pixelsToPan(gameState:GameState, pan: number) {
|
||||||
return Math.max(
|
return Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(
|
Math.min(
|
||||||
|
|
10
src/types.d.ts
vendored
10
src/types.d.ts
vendored
|
@ -237,6 +237,16 @@ export type GameState = {
|
||||||
levelTime: number;
|
levelTime: number;
|
||||||
levelWallBounces: number;
|
levelWallBounces: number;
|
||||||
autoCleanUses: number;
|
autoCleanUses: number;
|
||||||
|
aboutToPlaySound:{
|
||||||
|
wallBeep:{vol:number, x:number},
|
||||||
|
comboIncreaseMaybe:{vol:number, x:number},
|
||||||
|
comboDecrease:{vol:number, x:number},
|
||||||
|
coinBounce:{vol:number, x:number},
|
||||||
|
explode:{vol:number, x:number},
|
||||||
|
lifeLost:{vol:number, x:number},
|
||||||
|
coinCatch:{vol:number, x:number},
|
||||||
|
colorChange:{vol:number, x:number},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RunParams = {
|
export type RunParams = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue