资源加载,bgm和音效播放

This commit is contained in:
unanmed 2023-06-21 17:10:06 +08:00
parent 6f59ea51ac
commit 5aed6393a2
16 changed files with 289 additions and 52 deletions

View File

@ -16,11 +16,25 @@ export default defineConfig({
'resource.zip': [
'autotiles/*',
'tilesets/*',
'materials/*',
'images/*',
'animates/*',
'sounds/*',
'fonts/*'
],
'weather.zip': [
'materials/fog.png',
'materials/cloud.png',
'materials/sun.png'
],
'materials.zip': [
'materials/animates.png',
'materials/enemy48.png',
'materials/enemys.png',
'materials/icons.png',
'materials/items.png',
'materials/npc48.png',
'materials/npcs.png',
'materials/terrains.png'
]
}
});

View File

@ -636,6 +636,13 @@ return '{' + [
mainStyle_m
: '主要样式设置:' '标题界面背景图:' EvalString BGNL? Newline
'竖屏标题界面背景图:' EvalString BGNL? Newline
'标题样式;可写 display: none 隐藏标题' EvalString BGNL? Newline
'标题按钮样式:' EvalString BGNL? Newline
'横屏状态栏背景url(...) 0 0/100% 100% no-repeat 可将图片拉伸自适配' BGNL? Newline EvalString BGNL? Newline
'竖屏状态栏背景:' EvalString BGNL? Newline
'竖屏工具栏背景:' EvalString BGNL? Newline
'楼层切换样式:' EvalString BGNL? Newline
'状态栏颜色' ColorString Colour '边框颜色' ColorString Colour BGNL? Newline
'选中框颜色' ColorString Colour '全局字体' EvalString BEND
@ -645,7 +652,14 @@ tooltip : 主要样式设置
default : ["project/images/bg.jpg", "project/images/bg.jpg", "color: white", "background-color: #32369F; opacity: 0.85; color: #FFFFFF; border: #FFFFFF 2px solid; caret-color: #FFD700;", "url(project/materials/ground.png) repeat", "url(project/materials/ground.png) repeat", "url(project/materials/ground.png) repeat", "background-color: black; color: white", "255,255,255,1", "rgba(255,255,255,1)", "204,204,204,1", "rgba(204,204,204,1)", "255,215,0,1", "rgba(255,215,0,1)", "Verdana"]
helpUrl : /_docs/#/instruction
var code = {
floorChangingStyle: EvalString_0,
startBackground: EvalString_0,
startVerticalBackground: EvalString_1,
startLogoStyle: EvalString_2,
startButtonsStyle: EvalString_3,
statusLeftBackground: EvalString_4,
statusTopBackground: EvalString_5,
toolsBackground: EvalString_6,
floorChangingStyle: EvalString_7,
statusBarColor: JSON.parse('['+ColorString_0+']'),
borderColor: JSON.parse('['+ColorString_1+']'),
selectColor: JSON.parse('['+ColorString_2+']'),

View File

@ -277,7 +277,7 @@ span#hard {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
background: url(project/materials/ground.png) repeat;
background: black;
z-index: 185;
display: none;
top: 0;

View File

@ -56,6 +56,10 @@ const compress = type === 'dist';
await fs.remove('./dist/_server');
await fs.remove('./dist/editor.html');
await fs.remove('./dist/server.cjs');
await fs.remove('./dist/project/materials/airwall.png');
await fs.remove('./dist/project/materials/ground.png');
await fs.remove('./dist/project/materials/icons_old.png');
} catch {}
// 2. 压缩字体

View File

@ -254,7 +254,7 @@ async function writeFile(req: Request, res: Response) {
if (name.endsWith('project/events.js')) doDeclaration('events', value);
if (name.endsWith('project/items.js')) doDeclaration('items', value);
if (name.endsWith('project/maps.js')) doDeclaration('maps', value);
if (name.endsWith('project/data.js')) doDeclaration('data', value);
if (name.endsWith('project/data.js')) writeDevResource(value);
} catch (e) {
console.log(e);
res.end(
@ -315,6 +315,44 @@ async function writeMultiFiles(req: Request, res: Response) {
res.end();
}
async function writeDevResource(data: string) {
try {
const buf = Buffer.from(data, 'base64');
data = buf.toString('utf-8');
const info = JSON.parse(data.split('\n').slice(1).join(''));
const res: string[] = [];
const icons = await fs.readFile('./public/project/icons.js', 'utf-8');
const iconData = JSON.parse(icons.split('\n').slice(1).join(''));
res.push(
...info.main.animates.map((v: any) => `animates.${v}.animate`),
...info.main.bgms.map((v: any) => `bgms.${v}`),
...info.main.fonts.map((v: any) => `fonts.${v}.ttf`),
...info.main.images.map((v: any) => `images.${v}`),
...info.main.sounds.map((v: any) => `sounds.${v}`),
...info.main.tilesets.map((v: any) => `tilesets.${v}`),
...Object.keys(iconData.autotile).map(v => `autotiles.${v}.png`),
...[
'animates',
'cloud',
'enemy48',
'enemys',
'fog',
'icons',
'items',
'keyboard',
'npc48',
'npcs',
'sun',
'terrains'
].map(v => `materials.${v}.png`)
);
const text = JSON.stringify(res, void 0, 4);
await fs.writeFile('./src/data/resource-dev.json', text, 'utf-8');
} catch (e) {
console.log(e);
}
}
/**
*
* @param {string} type

View File

@ -44,6 +44,7 @@ export class AudioPlayer extends EventEmitter<AudioPlayerEvent> {
async update(data: ArrayBuffer) {
this.data = data;
this.buffer = await ac.decodeAudioData(data);
this.emit('update', this.buffer);
}
@ -61,9 +62,10 @@ export class AudioPlayer extends EventEmitter<AudioPlayerEvent> {
*
*/
play(when?: number, offset?: number, duration?: number) {
if (!this.source) return;
this.ready();
this.source?.start(when, offset, duration);
if (!this.source) return;
this.source.start(when, offset, duration);
const source = this.source;
this.source?.addEventListener('ended', ev => {

View File

@ -1,7 +1,7 @@
import { has } from '../../plugin/utils';
import { ResourceController } from '../loader/controller';
class BgmController extends ResourceController<HTMLAudioElement> {
export class BgmController extends ResourceController<HTMLAudioElement> {
playing?: BgmIds;
/**
@ -27,6 +27,7 @@ class BgmController extends ResourceController<HTMLAudioElement> {
const bgm = this.get(id);
bgm.currentTime = when;
bgm.play();
this.playing = id;
}
/**
@ -48,13 +49,6 @@ class BgmController extends ResourceController<HTMLAudioElement> {
}
get(id: BgmIds) {
return this.list[`bgm.${id}`];
return this.list[`bgms.${id}`];
}
}
declare global {
interface AncTe {
bgm: BgmController;
}
}
ancTe.bgm = new BgmController();

View File

@ -132,7 +132,10 @@ export class SoundEffect extends AudioPlayer {
}
}
class SoundController extends ResourceController<ArrayBuffer, SoundEffect> {
export class SoundController extends ResourceController<
ArrayBuffer,
SoundEffect
> {
private seIndex: Record<number, SoundEffect> = {};
/**
@ -196,10 +199,3 @@ class SoundController extends ResourceController<ArrayBuffer, SoundEffect> {
return this.list[`sounds.${sound}`];
}
}
declare global {
interface AncTe {
sound: SoundController;
}
}
ancTe.sound = new SoundController();

View File

@ -1,11 +1,32 @@
import { BgmController } from './audio/bgm';
import { SoundController } from './audio/sound';
import { readyAllResource } from './loader/load';
import { ResourceStore, ResourceType } from './loader/resource';
export {};
declare global {
interface AncTe {}
interface AncTe {
sound: SoundController;
/** 游戏资源 */
resource: ResourceStore<Exclude<ResourceType, 'zip'>>;
zipResource: ResourceStore<'zip'>;
bgm: BgmController;
}
interface Window {
readonly ancTe: AncTe;
ancTe: AncTe;
}
const ancTe: AncTe;
}
// @ts-ignore
window.ancTe = {};
function ready() {
window.ancTe = {
bgm: new BgmController(),
resource: new ResourceStore(),
zipResource: new ResourceStore(),
sound: new SoundController()
};
readyAllResource();
}
ready();

View File

@ -7,7 +7,7 @@ const info = resource;
*
*/
export function readyAllResource() {
if (main.RESOURCE_TYPE === 'dev') return readyDevResource();
/* @__PURE__ */ if (main.RESOURCE_TYPE === 'dev') return readyDevResource();
info.resource.forEach(v => {
const type = getTypeByResource(v);
if (type === 'zip') {
@ -21,4 +21,14 @@ export function readyAllResource() {
/**
*
*/
function readyDevResource() {}
/* @__PURE__ */ async function readyDevResource() {
const loadData = (await import('../../data/resource-dev.json')).default;
loadData.forEach(v => {
const type = getTypeByResource(v);
if (type !== 'zip') {
ancTe.resource.set(v, new Resource(v, type));
}
});
ancTe.resource.forEach(v => v.active());
}

View File

@ -37,12 +37,13 @@ export class Resource<
constructor(resource: string, format: T) {
super(resource);
this.data = this.resolveUrl(resource);
this.format = format;
this.uri = resource;
this.once('active', this.load);
this.once('load', this.onLoad);
this.once('loadstart', this.onLoadStart);
this.once('active', () => this.load());
this.once('load', v => this.onLoad(v));
this.once('loadstart', v => this.onLoadStart(v));
}
protected onLoadStart(v?: ResourceData[T]) {
@ -242,7 +243,10 @@ export class ZippedResource extends EventEmitter<ZippedEvent> {
}
}
class ResourceStore<T extends ResourceType> extends Map<string, Resource<T>> {
export class ResourceStore<T extends ResourceType> extends Map<
string,
Resource<T>
> {
active(key: string[] | string) {
const keys = ensureArray(key);
keys.forEach(v => this.get(v)?.active());
@ -301,14 +305,3 @@ export function getZipFormatByType(type: ResourceType): 'arraybuffer' | 'text' {
if (type === 'text' || type === 'json') return 'text';
else return 'arraybuffer';
}
declare global {
interface AncTe {
/** 游戏资源 */
resource: ResourceStore<Exclude<ResourceType, 'zip'>>;
zipResource: ResourceStore<'zip'>;
}
}
ancTe.resource = new ResourceStore();
ancTe.zipResource = new ResourceStore();

145
src/data/resource-dev.json Normal file
View File

@ -0,0 +1,145 @@
[
"animates.amazed.animate",
"animates.angry.animate",
"animates.angry2.animate",
"animates.bulb.animate",
"animates.emm.animate",
"animates.explosion1.animate",
"animates.explosion2.animate",
"animates.explosion3.animate",
"animates.explosion4.animate",
"animates.fire.animate",
"animates.focus.animate",
"animates.fret.animate",
"animates.hand.animate",
"animates.ice.animate",
"animates.jianji.animate",
"animates.luv.animate",
"animates.magicAtk.animate",
"animates.stone.animate",
"animates.sweat.animate",
"animates.sweat2.animate",
"animates.sword.animate",
"animates.zone.animate",
"bgms.beforeBoss.mp3",
"bgms.cave.mp3",
"bgms.escape.mp3",
"bgms.grass.mp3",
"bgms.mount.mp3",
"bgms.plot1.mp3",
"bgms.road.mp3",
"bgms.title.mp3",
"bgms.tower.mp3",
"bgms.towerBoss.mp3",
"bgms.towerBoss2.mp3",
"bgms.towerBoss3.mp3",
"bgms.winter.mp3",
"bgms.winterTown.mp3",
"fonts.normal.ttf",
"images.IQ.png",
"images.arrow.png",
"images.atk.png",
"images.bg.jpg",
"images.boom.png",
"images.botton.png",
"images.cave2.jpg",
"images.def.png",
"images.exp.png",
"images.hero1.png",
"images.hero2.png",
"images.hp.png",
"images.money.png",
"images.skill.png",
"images.skill0.png",
"images.skill1.png",
"images.skill10.png",
"images.skill11.png",
"images.skill12.png",
"images.skill13.png",
"images.skill14.png",
"images.skill2.png",
"images.skill3.png",
"images.skill4.png",
"images.skill5.png",
"images.skill6.png",
"images.skill7.png",
"images.skill8.png",
"images.skill9.png",
"images.title.jpg",
"images.tower.jpg",
"images.tower7.jpeg",
"images.winskin.png",
"images.winskin2.png",
"images.winskin3.png",
"sounds.008-System08.ogg",
"sounds.015-Jump01.ogg",
"sounds.050-Explosion03.ogg",
"sounds.051-Explosion04.ogg",
"sounds.087-Action02.ogg",
"sounds.094-Attack06.ogg",
"sounds.118-Fire02.ogg",
"sounds.119-Fire03.ogg",
"sounds.120-Ice01.ogg",
"sounds.arrow.mp3",
"sounds.attack.mp3",
"sounds.bomb.mp3",
"sounds.cancel.mp3",
"sounds.centerFly.mp3",
"sounds.chapter.mp3",
"sounds.confirm.mp3",
"sounds.cursor.mp3",
"sounds.danger.mp3",
"sounds.door.mp3",
"sounds.drink.mp3",
"sounds.electron.mp3",
"sounds.equip.mp3",
"sounds.error.mp3",
"sounds.floor.mp3",
"sounds.item.mp3",
"sounds.jump.mp3",
"sounds.load.mp3",
"sounds.open_ui.mp3",
"sounds.paper.mp3",
"sounds.pickaxe.mp3",
"sounds.quake.mp3",
"sounds.recovery.mp3",
"sounds.save.mp3",
"sounds.shake.mp3",
"sounds.shop.mp3",
"sounds.thunder.mp3",
"sounds.tree.mp3",
"sounds.zone.mp3",
"tilesets.magictower.png",
"tilesets.043-Cave01.png",
"tilesets.004-Mountain01.png",
"tilesets.Map-Tower01.png",
"tilesets.Caverna1.png",
"tilesets.map-tower.png",
"tilesets.winter1.png",
"tilesets.snowTown.png",
"tilesets.room.png",
"autotiles.autotile.png",
"autotiles.autotile1.png",
"autotiles.autotile2.png",
"autotiles.autotile3.png",
"autotiles.autotile4.png",
"autotiles.autotile5.png",
"autotiles.autotile6.png",
"autotiles.autotile7.png",
"autotiles.autotile8.png",
"autotiles.autotile9.png",
"autotiles.autotile10.png",
"autotiles.autotile11.png",
"materials.animates.png",
"materials.cloud.png",
"materials.enemy48.png",
"materials.enemys.png",
"materials.fog.png",
"materials.icons.png",
"materials.items.png",
"materials.keyboard.png",
"materials.npc48.png",
"materials.npcs.png",
"materials.sun.png",
"materials.terrains.png"
]

View File

@ -1,6 +1,9 @@
{
"resource": [
"zip.resource.zip",
"zip.weather.zip",
"zip.materials.zip",
"materials.keyboard.png",
"bgms.tower.mp3",
"bgms.cave.mp3",
"bgms.mount.mp3",

View File

@ -4,6 +4,7 @@ import App2 from './App2.vue';
import './styles.less';
import 'ant-design-vue/dist/antd.dark.css';
import './initPlugin';
import './core/index';
createApp(App).mount('#root');
createApp(App2).mount('#root2');

View File

@ -2,7 +2,7 @@ import { message } from 'ant-design-vue';
import { MessageApi } from 'ant-design-vue/lib/message';
import { isNil } from 'lodash-es';
import { Animation, sleep, TimingFn } from 'mutate-animate';
import { ComputedRef, ref } from 'vue';
import { ref } from 'vue';
import { EVENT_KEY_CODE_MAP } from './keyCodes';
import axios from 'axios';
import { decompressFromBase64 } from 'lz-string';
@ -211,14 +211,12 @@ export async function doByInterval(
interval: number,
awaitFirst: boolean = false
) {
if (awaitFirst) {
await sleep(interval);
}
for await (const fn of funcs) {
if (awaitFirst) {
await sleep(interval);
}
fn();
if (!awaitFirst) {
await sleep(interval);
}
await sleep(interval);
}
}

View File

@ -22,7 +22,11 @@ interface Loader {
* @param imgName
* @param callback
*/
loadImage(dir: string, imgName: string, callback?: () => void): void;
loadImage(
dir: string,
imgName: string,
callback?: (name: string, img: HTMLImageElement) => void
): void;
/**
* zip中加载一系列图片