优化BGMA连续播放与通关音量压低并强化节点缩放
This commit is contained in:
@@ -5,13 +5,14 @@ export function browserAudio(report){
|
||||
setInnerAudioOption(){},
|
||||
createInnerAudioContext(){
|
||||
const player=new Audio();player.preload='auto';players.add(player);
|
||||
let errorHandler=()=>{},playHandler=()=>{},generation=0;
|
||||
let errorHandler=()=>{},playHandler=()=>{},endedHandler=()=>{},generation=0;
|
||||
const error=reason=>{
|
||||
if(disposed||reason?.name==='AbortError')return;
|
||||
report('音效播放失败:'+(reason?.message||'请检查页面声音权限'));
|
||||
errorHandler({errMsg:reason?.message||'浏览器音频加载失败'});
|
||||
};
|
||||
player.addEventListener('error',()=>error(player.error));
|
||||
player.addEventListener('ended',()=>{if(!disposed)endedHandler();});
|
||||
return {
|
||||
set src(path){player.src=new URL('../'+path,location.href).href;},
|
||||
set loop(value){player.loop=value;},
|
||||
@@ -19,6 +20,8 @@ export function browserAudio(report){
|
||||
set obeyMuteSwitch(value){},
|
||||
onError(callback){errorHandler=callback;},
|
||||
onPlay(callback){playHandler=callback;},
|
||||
onEnded(callback){endedHandler=callback;},
|
||||
offEnded(callback){if(endedHandler===callback)endedHandler=()=>{};},
|
||||
stop(){generation++;player.pause();if(player.readyState)player.currentTime=0;},
|
||||
play(){
|
||||
const current=generation;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import fs from 'node:fs';import vm from 'node:vm';import assert from 'node:assert/strict';import path from 'node:path';import {fileURLToPath} from 'node:url';
|
||||
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');const pack=JSON.parse(fs.readFileSync(path.join(root,'src/upstream/levels.json'))),ordered=pack.playOrder.map(id=>pack.levels.find(l=>l.id===id));
|
||||
export function boot(storage = new Map(), width = 375, height = 812) {
|
||||
const handlers = {}, frames = new Map(), played=[],vibrated=[];
|
||||
const handlers = {}, frames = new Map(), played=[],vibrated=[],audioContexts=[];
|
||||
let frameId = 0,now=100000;
|
||||
class Clock extends Date {static now(){return now;}}
|
||||
const text = [],images=[];
|
||||
const ctx = new Proxy({ drawImage:(image,x,y,w,h)=>images.push({source:image.source||null,x,y,w,h}),measureText: s => ({ width: [...String(s)].reduce((n,c)=>n+(/[^\x00-\x7f]/.test(c)?1:.55),0)*(Number(/([\d.]+)px/.exec(ctx.font)?.[1])||16) }), fillText: (s, x, y) => text.push({ s, x, y }) }, { get: (o, k) => o[k] ?? (() => { }), set: (o, k, v) => (o[k] = v, true) });
|
||||
const wx = {createImage:()=>({set src(value){const b=fs.readFileSync(path.join(root,value));this.width=b.readUInt32BE(16);this.height=b.readUInt32BE(20);this.source=value;this.onload?.();}}),vibrateShort:o=>vibrated.push({type:o.type,at:now}),setInnerAudioOption:()=>{},createInnerAudioContext:()=>({stop(){},onError(){},play(){assert.ok(fs.existsSync(path.join(root,this.src)),this.src);played.push(this.src);}}), createCanvas: () => ({ getContext: () => ctx }), getWindowInfo: () => ({ windowWidth: width, windowHeight: height, pixelRatio: 2, safeArea: { top: 44, bottom: height - 34 } }), getMenuButtonBoundingClientRect: () => ({ bottom: 80 }), getStorageSync: k => storage.get(k) || '', setStorageSync: (k, v) => storage.set(k, v), removeStorageSync: k => storage.delete(k), getPerformance: () => ({ now: () => Date.now() }), showModal: () => { }, env: { USER_DATA_PATH: '/user' } };
|
||||
const wx = {createImage:()=>({set src(value){const b=fs.readFileSync(path.join(root,value));this.width=b.readUInt32BE(16);this.height=b.readUInt32BE(20);this.source=value;this.onload?.();}}),vibrateShort:o=>vibrated.push({type:o.type,at:now}),setInnerAudioOption:()=>{},createInnerAudioContext:()=>{const a={stop(){},onError(fn){this.error=fn;},onEnded(fn){this.ended=fn;},offEnded(fn){if(this.ended===fn)this.ended=null;},play(){assert.ok(fs.existsSync(path.join(root,this.src)),this.src);played.push(this.src);}};audioContexts.push(a);return a;}, createCanvas: () => ({ getContext: () => ctx }), getWindowInfo: () => ({ windowWidth: width, windowHeight: height, pixelRatio: 2, safeArea: { top: 44, bottom: height - 34 } }), getMenuButtonBoundingClientRect: () => ({ bottom: 80 }), getStorageSync: k => storage.get(k) || '', setStorageSync: (k, v) => storage.set(k, v), removeStorageSync: k => storage.delete(k), getPerformance: () => ({ now: () => Date.now() }), showModal: () => { }, env: { USER_DATA_PATH: '/user' } };
|
||||
wx.loadFont=p=>{assert.ok(fs.existsSync(path.join(root,p)),'字体必须随包提供 '+p);return path.basename(p,'.ttf');};
|
||||
for (const name of ['TouchStart', 'TouchMove', 'TouchEnd', 'TouchCancel', 'Hide', 'Show', 'WindowResize'])
|
||||
wx['on' + name] = cb => handlers[name] = cb;
|
||||
@@ -25,5 +25,5 @@ export function boot(storage = new Map(), width = 375, height = 812) {
|
||||
assert.ok(++steps < 25);
|
||||
} button(api.buttons().some(b => b.label === label) ? label : label + ' ✓'); if (api.buttons().some(b => b.label === '返回游戏'))
|
||||
button('返回游戏'); assert.equal(api.snapshot().level, ordered[i].id); };
|
||||
return { advance(ms){now+=ms;tick();}, api, button, cell, select, tick, handlers, frames, storage, text, played,images,vibrated };
|
||||
return { advance(ms){now+=ms;tick();}, api, button, cell, select, tick, handlers, frames, storage, text, played,images,vibrated,audioContexts };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user