mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-26 00:53:25 +08:00
图片加载
This commit is contained in:
parent
2e0770ae71
commit
e947a1e6e8
@ -19,7 +19,11 @@ function core() {
|
||||
this.__HALF_SIZE__ = Math.floor(this.__SIZE__ / 2);
|
||||
this.material = {
|
||||
animates: {},
|
||||
images: {},
|
||||
images: {
|
||||
images: {},
|
||||
autotile: {},
|
||||
tilesets: {}
|
||||
},
|
||||
bgms: {},
|
||||
sounds: {},
|
||||
items: {},
|
||||
|
@ -115,6 +115,7 @@ loader.prototype._load_async = function (callback) {
|
||||
// ----- 加载资源文件 ------ //
|
||||
|
||||
loader.prototype._loadMaterials_sync = function (callback) {
|
||||
callback();
|
||||
this._setStartLoadTipText('正在加载资源文件...');
|
||||
this.loadImages(
|
||||
'materials',
|
||||
@ -122,7 +123,6 @@ loader.prototype._loadMaterials_sync = function (callback) {
|
||||
core.material.images,
|
||||
function () {
|
||||
core.loader._loadMaterials_afterLoad();
|
||||
callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -154,14 +154,7 @@ loader.prototype._loadMaterials_afterLoad = function () {
|
||||
// ------ 加载使用的图片 ------ //
|
||||
|
||||
loader.prototype._loadExtraImages_sync = function (callback) {
|
||||
core.material.images.images = {};
|
||||
this._setStartLoadTipText('正在加载图片文件...');
|
||||
core.loadImages(
|
||||
'images',
|
||||
core.images,
|
||||
core.material.images.images,
|
||||
callback
|
||||
);
|
||||
callback();
|
||||
};
|
||||
|
||||
loader.prototype._loadExtraImages_async = function (onprogress, onfinished) {
|
||||
@ -196,15 +189,7 @@ loader.prototype._loadExtraImages_async = function (onprogress, onfinished) {
|
||||
// ------ 加载自动元件 ------ //
|
||||
|
||||
loader.prototype._loadAutotiles_sync = function (callback) {
|
||||
core.material.images.autotile = {};
|
||||
var keys = Object.keys(core.material.icons.autotile);
|
||||
var autotiles = {};
|
||||
|
||||
this._setStartLoadTipText('正在加载自动元件...');
|
||||
this.loadImages('autotiles', keys, autotiles, function () {
|
||||
core.loader._loadAutotiles_afterLoad(keys, autotiles);
|
||||
callback();
|
||||
});
|
||||
callback();
|
||||
};
|
||||
|
||||
loader.prototype._loadAutotiles_async = function (onprogress, onfinished) {
|
||||
@ -224,30 +209,12 @@ loader.prototype._loadAutotiles_async = function (onprogress, onfinished) {
|
||||
);
|
||||
};
|
||||
|
||||
loader.prototype._loadAutotiles_afterLoad = function (keys, autotiles) {
|
||||
// autotile需要保证顺序
|
||||
keys.forEach(function (v) {
|
||||
core.material.images.autotile[v] = autotiles[v];
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
core.maps._makeAutotileEdges();
|
||||
});
|
||||
};
|
||||
loader.prototype._loadAutotiles_afterLoad = function (keys, autotiles) {};
|
||||
|
||||
// ------ 加载额外素材 ------ //
|
||||
|
||||
loader.prototype._loadTilesets_sync = function (callback) {
|
||||
core.material.images.tilesets = {};
|
||||
this._setStartLoadTipText('正在加载额外素材...');
|
||||
this.loadImages(
|
||||
'tilesets',
|
||||
core.tilesets,
|
||||
core.material.images.tilesets,
|
||||
function () {
|
||||
callback();
|
||||
}
|
||||
);
|
||||
callback();
|
||||
};
|
||||
|
||||
loader.prototype._loadTilesets_async = function (onprogress, onfinished) {
|
||||
@ -266,26 +233,7 @@ loader.prototype._loadTilesets_async = function (onprogress, onfinished) {
|
||||
// ------ 实际加载一系列图片 ------ //
|
||||
|
||||
loader.prototype.loadImages = function (dir, names, toSave, callback) {
|
||||
if (!names || names.length == 0) {
|
||||
if (callback) callback();
|
||||
return;
|
||||
}
|
||||
var items = 0;
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
this.loadImage(dir, names[i], function (id, image) {
|
||||
core.loader._setStartLoadTipText('正在加载图片 ' + id + '...');
|
||||
if (toSave[id] !== undefined) {
|
||||
if (image != null) toSave[id] = image;
|
||||
return;
|
||||
}
|
||||
toSave[id] = image;
|
||||
items++;
|
||||
core.loader._setStartProgressVal(items * (100 / names.length));
|
||||
if (items == names.length) {
|
||||
if (callback) callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
return callback();
|
||||
};
|
||||
|
||||
loader.prototype.loadImage = function (dir, imgName, callback) {
|
||||
|
@ -336,10 +336,15 @@ main.prototype.loadAsync = async function (mode, callback) {
|
||||
// 加载核心js代码
|
||||
if (main.useCompress) {
|
||||
await main.loadScript(`libs/libs.min.js?v=${main.version}`);
|
||||
main.loading.emit('coreLoaded');
|
||||
} else {
|
||||
await Promise.all(
|
||||
main.loadList.map(v =>
|
||||
main.loadScript(`libs/${v}.js?v=${main.version}`)
|
||||
main.loadScript(`libs/${v}.js?v=${main.version}`).then(vv => {
|
||||
if (v === 'core') {
|
||||
main.loading.emit('coreLoaded');
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -398,6 +403,8 @@ main.prototype.loadAsync = async function (mode, callback) {
|
||||
coreData[t] = main[t];
|
||||
});
|
||||
await core.init(coreData, callback);
|
||||
main.loading.emit('coreInit');
|
||||
|
||||
core.resize();
|
||||
|
||||
main.core = core;
|
||||
|
@ -5,16 +5,19 @@ export interface EmitableEvent {
|
||||
interface Listener<T extends (...params: any) => any> {
|
||||
fn: T;
|
||||
once?: boolean;
|
||||
immediate?: boolean;
|
||||
}
|
||||
|
||||
interface ListenerOptions {
|
||||
once: boolean;
|
||||
immediate: boolean;
|
||||
}
|
||||
|
||||
export class EventEmitter<T extends EmitableEvent = {}> {
|
||||
private events: {
|
||||
[P in keyof T]?: Listener<T[P]>[];
|
||||
} = {};
|
||||
private emitted: (keyof T)[] = [];
|
||||
|
||||
/**
|
||||
* 监听某个事件
|
||||
@ -27,6 +30,16 @@ export class EventEmitter<T extends EmitableEvent = {}> {
|
||||
fn: T[K],
|
||||
options?: Partial<ListenerOptions>
|
||||
) {
|
||||
if (options?.immediate && this.emitted.includes(event)) {
|
||||
fn();
|
||||
if (!options.once) {
|
||||
this.events[event] ??= [];
|
||||
this.events[event]?.push({
|
||||
fn
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.events[event] ??= [];
|
||||
this.events[event]?.push({
|
||||
fn,
|
||||
@ -60,6 +73,9 @@ export class EventEmitter<T extends EmitableEvent = {}> {
|
||||
* @param params 传入的参数
|
||||
*/
|
||||
emit<K extends keyof T>(event: K, ...params: Parameters<T[K]>) {
|
||||
if (!this.emitted.includes(event)) {
|
||||
this.emitted.push(event);
|
||||
}
|
||||
const events = (this.events[event] ??= []);
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const e = events[i];
|
||||
|
@ -3,8 +3,6 @@ import { SoundController } from './audio/sound';
|
||||
import { readyAllResource } from './loader/load';
|
||||
import { ResourceStore, ResourceType } from './loader/resource';
|
||||
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
interface AncTe {
|
||||
sound: SoundController;
|
||||
|
@ -1,6 +1,15 @@
|
||||
import resource from '../../data/resource.json';
|
||||
import { has } from '../../plugin/utils';
|
||||
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
|
||||
import { Resource, getTypeByResource } from './resource';
|
||||
|
||||
interface GameLoadEvent extends EmitableEvent {
|
||||
coreLoaded: () => void;
|
||||
autotileLoaded: () => void;
|
||||
coreInit: () => void;
|
||||
materialLoaded: () => void;
|
||||
}
|
||||
|
||||
const info = resource;
|
||||
|
||||
/**
|
||||
@ -32,3 +41,79 @@ export function readyAllResource() {
|
||||
});
|
||||
ancTe.resource.forEach(v => v.active());
|
||||
}
|
||||
|
||||
class GameLoading extends EventEmitter<GameLoadEvent> {
|
||||
private autotileLoaded: number = 0;
|
||||
private autotileNum?: number;
|
||||
private autotileListened: boolean = false;
|
||||
|
||||
private materialsNum: number = main.materials.length;
|
||||
private materialsLoaded: number = 0;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.on(
|
||||
'coreInit',
|
||||
() => {
|
||||
this.autotileNum = Object.keys(
|
||||
core.material.icons.autotile
|
||||
).length;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
this.on('materialLoaded', () => {
|
||||
core.loader._loadMaterials_afterLoad();
|
||||
});
|
||||
}
|
||||
|
||||
addMaterialLoaded() {
|
||||
this.once('coreInit', () => {
|
||||
this.materialsLoaded++;
|
||||
if (this.materialsLoaded === this.materialsNum) {
|
||||
this.emit('materialLoaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addAutotileLoaded() {
|
||||
this.once('coreInit', () => {
|
||||
this.autotileLoaded++;
|
||||
if (this.autotileLoaded === this.autotileNum) {
|
||||
this.emit('autotileLoaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 当自动原件加载完毕时
|
||||
* @param autotiles 自动原件数组
|
||||
*/
|
||||
onAutotileLoaded(
|
||||
autotiles: Partial<Record<AllIdsOf<'autotile'>, HTMLImageElement>>
|
||||
) {
|
||||
if (this.autotileListened) return;
|
||||
this.autotileListened = true;
|
||||
this.on('autotileLoaded', () => {
|
||||
const keys = Object.keys(
|
||||
core.material.icons.autotile
|
||||
) as AllIdsOf<'autotile'>[];
|
||||
|
||||
keys.forEach(v => {
|
||||
core.material.images.autotile[v] = autotiles[v]!;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
core.maps._makeAutotileEdges();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const loading = new GameLoading();
|
||||
|
||||
declare global {
|
||||
interface Main {
|
||||
loading: EventEmitter<GameLoadEvent>;
|
||||
}
|
||||
}
|
||||
main.loading = loading;
|
||||
|
@ -4,6 +4,7 @@ import { ensureArray } from '../../plugin/utils';
|
||||
import { has } from '../../plugin/utils';
|
||||
import JSZip from 'jszip';
|
||||
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
|
||||
import { loading } from './load';
|
||||
|
||||
interface ResourceData {
|
||||
image: HTMLImageElement;
|
||||
@ -17,6 +18,8 @@ interface ResourceData {
|
||||
export type ResourceType = keyof ResourceData;
|
||||
export type NonZipResource = Exclude<ResourceType, 'zip'>;
|
||||
|
||||
const autotiles: Partial<Record<AllIdsOf<'autotile'>, HTMLImageElement>> = {};
|
||||
|
||||
export class Resource<
|
||||
T extends ResourceType = ResourceType
|
||||
> extends Disposable<string> {
|
||||
@ -59,6 +62,42 @@ export class Resource<
|
||||
document.fonts.add(new FontFace(this.name, v as ArrayBuffer));
|
||||
} else if (this.type === 'sounds') {
|
||||
ancTe.sound.add(this.uri, v as ArrayBuffer);
|
||||
} else if (this.type === 'images') {
|
||||
const name = `${this.name}${this.ext}` as ImageIds;
|
||||
loading.on(
|
||||
'coreLoaded',
|
||||
() => {
|
||||
core.material.images.images[name] = v as HTMLImageElement;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
} else if (this.type === 'materials') {
|
||||
const name = this.name as SelectKey<
|
||||
MaterialImages,
|
||||
HTMLImageElement
|
||||
>;
|
||||
|
||||
loading.on(
|
||||
'coreLoaded',
|
||||
() => {
|
||||
core.material.images[name] = v;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
} else if (this.type === 'autotiles') {
|
||||
const name = this.name as AllIdsOf<'autotile'>;
|
||||
autotiles[name] = v;
|
||||
loading.addAutotileLoaded();
|
||||
loading.onAutotileLoaded(autotiles);
|
||||
} else if (this.type === 'tilesets') {
|
||||
const name = `${this.name}${this.ext}`;
|
||||
loading.on(
|
||||
'coreLoaded',
|
||||
() => {
|
||||
core.material.images.tilesets[name] = v;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
}
|
||||
|
||||
// 资源加载类型处理
|
||||
|
2
src/types/core.d.ts
vendored
2
src/types/core.d.ts
vendored
@ -810,7 +810,7 @@ type CoreStatusBarElements = {
|
||||
readonly [key: string]: HTMLElement;
|
||||
};
|
||||
|
||||
type Materails = [
|
||||
type Materials = [
|
||||
'animates',
|
||||
'enemys',
|
||||
'items',
|
||||
|
2
src/types/loader.d.ts
vendored
2
src/types/loader.d.ts
vendored
@ -64,6 +64,8 @@ interface Loader {
|
||||
* @param name 要释放的bgm的id或名称
|
||||
*/
|
||||
freeBgm(name: BgmIds | NameMapIn<BgmIds>): void;
|
||||
|
||||
_loadMaterials_afterLoad(): void;
|
||||
}
|
||||
|
||||
declare const loader: new () => Loader;
|
||||
|
2
src/types/map.d.ts
vendored
2
src/types/map.d.ts
vendored
@ -1376,6 +1376,8 @@ interface Maps {
|
||||
* @param doCallback 是否执行该动画的回调函数
|
||||
*/
|
||||
stopAnimate(id?: number, doCallback?: boolean): void;
|
||||
|
||||
_makeAutotileEdges(): void;
|
||||
}
|
||||
|
||||
declare const maps: new () => Maps;
|
||||
|
Loading…
Reference in New Issue
Block a user