react-simple-game-engine
Version:
[WIP] not able to use in currently. <!-- Document cumming soon... -->
606 lines (605 loc) • 26.3 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { WorldManagement } from "./world-management";
import { copyProperties, createAssetImage, createAssetSound, parallel, tick, } from "../utils";
import { Sound } from "./sound";
import { SoundType } from "../export-enums";
var MAX_ASSET_PARALLEL_LOAD = 4;
var Scene = /** @class */ (function () {
function Scene() {
this.nativeEventsUnsubscribes = function () { };
this.entityPropsChangeListeners = {};
this.soundBackgroundOptionsChangeListeners = [];
this.soundOnceOptionsChangeListeners = [];
this.processStateChangeListeners = [];
this.joystickActionListeners = [];
this.prefabs = [];
this.sounds = [];
this.sprites = [];
this.sessionId = "".concat(Math.random(), "-").concat(new Date().getTime());
this.assetsDelay = 0;
this.tag = this.constructor.tag;
this.ui = this.constructor.ui;
this.soundsDecor = this.__proto__.soundsDecor || [];
this.spritesDecor = this.__proto__.spritesDecor || [];
this._loadedAssets = false;
this.onBorn();
}
Object.defineProperty(Scene.prototype, "renderer", {
get: function () {
return this._renderer;
},
set: function (_renderer) {
if (this._renderer) {
console.warn("Not allow to change renderer of scene");
return;
}
this._renderer = _renderer;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scene.prototype, "worldManagement", {
get: function () {
return this._worldManagement;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scene.prototype, "renderAssetsFail", {
get: function () {
return this._renderAssetsFail;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scene.prototype, "UI", {
get: function () {
var Ui = this.ui || (function () { return null; });
return Ui;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scene.prototype, "soundBackgroundOptions", {
get: function () {
return Sound.Management[SoundType.BACKGROUND];
},
set: function (options) {
copyProperties(Sound.Management[SoundType.BACKGROUND], options);
for (var _i = 0, _a = this.soundBackgroundOptionsChangeListeners; _i < _a.length; _i++) {
var listener = _a[_i];
listener(Sound.Management[SoundType.BACKGROUND]);
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scene.prototype, "soundOnceOptions", {
get: function () {
return Sound.Management[SoundType.ONCE];
},
set: function (options) {
copyProperties(Sound.Management[SoundType.ONCE], options);
for (var _i = 0, _a = this.soundOnceOptionsChangeListeners; _i < _a.length; _i++) {
var listener = _a[_i];
listener(Sound.Management[SoundType.ONCE]);
}
},
enumerable: false,
configurable: true
});
Scene.prototype.bootSoundOptions = function () {
var options = this.getSoundOptions();
copyProperties(Sound.Management[SoundType.ONCE], options[SoundType.ONCE] || {});
copyProperties(Sound.Management[SoundType.BACKGROUND], options[SoundType.BACKGROUND] || {});
};
Scene.prototype.getSoundOptions = function () {
return {};
};
Scene.prototype.onBorn = function () { };
Scene.prototype.getComponents = function (simpleCamera) {
return [];
};
Scene.prototype.getUIProps = function () {
return {};
};
Scene.prototype.getInitialConfigs = function () {
return {};
};
Object.defineProperty(Scene.prototype, "loadedAssets", {
get: function () {
return this._loadedAssets;
},
set: function (loadedAssets) {
var _a;
this._loadedAssets = loadedAssets;
(_a = this.loadAssetsListener) === null || _a === void 0 ? void 0 : _a.call(this, loadedAssets);
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scene.prototype, "loadedAssetsError", {
set: function (errors) {
var _a;
(_a = this.loadAssetsListener) === null || _a === void 0 ? void 0 : _a.call(this, this._loadedAssets, errors);
},
enumerable: false,
configurable: true
});
Scene.prototype.onProcessStateChangeListener = function (func) {
var listeners = this.processStateChangeListeners;
listeners.push(func);
return function () {
var index = listeners.indexOf(func);
if (index > -1) {
listeners.splice(index, 1);
}
};
};
Scene.prototype.onSoundOnceOptionsChange = function (func) {
var listeners = this.soundOnceOptionsChangeListeners;
listeners.push(func);
return function () {
var index = listeners.indexOf(func);
if (index > -1) {
listeners.splice(index, 1);
}
};
};
Scene.prototype.onSoundBackgroundOptionsChange = function (func) {
var listeners = this.soundBackgroundOptionsChangeListeners;
listeners.push(func);
return function () {
var index = listeners.indexOf(func);
if (index > -1) {
listeners.splice(index, 1);
}
};
};
Scene.prototype.onJoystickAction = function (func) {
var listeners = this.joystickActionListeners;
listeners.push(func);
return function () {
var index = listeners.indexOf(func);
if (index > -1) {
listeners.splice(index, 1);
}
};
};
Scene.prototype.onEntityPropsChange = function (name, func) {
var listeners = (this.entityPropsChangeListeners[name] =
this.entityPropsChangeListeners[name] || []);
listeners.push(func);
return function () {
var index = listeners.indexOf(func);
if (index > -1) {
listeners.splice(index, 1);
}
};
};
Scene.prototype.emitJoystickActionEvent = function (data) {
var listeners = this.joystickActionListeners;
for (var _i = 0, listeners_1 = listeners; _i < listeners_1.length; _i++) {
var listener = listeners_1[_i];
listener(data);
}
};
Scene.prototype.emitProcessStateChangeEvent = function (isForeground) {
var listeners = this.processStateChangeListeners;
for (var _i = 0, listeners_2 = listeners; _i < listeners_2.length; _i++) {
var listener = listeners_2[_i];
listener(isForeground);
}
};
Scene.prototype.emitEntityPropsChangeEvent = function (name, value) {
var listeners = this.entityPropsChangeListeners[name] || [];
for (var _i = 0, listeners_3 = listeners; _i < listeners_3.length; _i++) {
var listener = listeners_3[_i];
listener(value);
}
};
Scene.prototype.onLoadAssetNotify = function (func) {
this.loadAssetsListener = func;
};
Scene.prototype.destructor = function () {
this.nativeEventsUnsubscribes();
this._worldManagement.destructor();
for (var _i = 0, _a = this.sounds; _i < _a.length; _i++) {
var sound = _a[_i];
sound.stop();
}
};
Scene.prototype.switchToScene = function (tag) {
this.manager.gotoScene(tag);
};
Scene.prototype.loadSprites = function () {
return __awaiter(this, void 0, void 0, function () {
var _this_1 = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, parallel(this.spritesDecor, function (decor) { return __awaiter(_this_1, void 0, void 0, function () {
var sprite;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!decor.src) return [3 /*break*/, 2];
return [4 /*yield*/, createAssetImage(decor.src)];
case 1:
sprite = _a.sent();
this[decor.propertyKey] = sprite;
this.sprites.push(sprite);
_a.label = 2;
case 2: return [2 /*return*/];
}
});
}); }, MAX_ASSET_PARALLEL_LOAD)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Scene.prototype.loadSounds = function () {
return __awaiter(this, void 0, void 0, function () {
var _i, _a, decor, sound;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_i = 0, _a = this.soundsDecor;
_b.label = 1;
case 1:
if (!(_i < _a.length)) return [3 /*break*/, 4];
decor = _a[_i];
if (!decor.src) return [3 /*break*/, 3];
return [4 /*yield*/, createAssetSound(decor.src, decor.type)];
case 2:
sound = _b.sent();
if (decor.volume) {
sound.volume = decor.volume;
}
this[decor.propertyKey] = sound;
this.sounds.push(sound);
_b.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
});
};
Scene.prototype.createSprites = function () {
var _this_1 = this;
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
return parallel(sources, function (source) { return __awaiter(_this_1, void 0, void 0, function () {
var src, sprite;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
src = (typeof source === "string" ? { src: source } : source).src;
return [4 /*yield*/, createAssetImage(src)];
case 1:
sprite = _a.sent();
this.sprites.push(sprite);
return [2 /*return*/, sprite];
}
});
}); }, MAX_ASSET_PARALLEL_LOAD);
};
Scene.prototype.createSounds = function () {
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var sounds, _a, sources_1, source, _b, volume, src, _c, type, sound;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
sounds = [];
_a = 0, sources_1 = sources;
_d.label = 1;
case 1:
if (!(_a < sources_1.length)) return [3 /*break*/, 4];
source = sources_1[_a];
_b = typeof source === "string"
? { src: source, volume: undefined, type: undefined }
: source, volume = _b.volume, src = _b.src, _c = _b.type, type = _c === void 0 ? SoundType.ONCE : _c;
return [4 /*yield*/, createAssetSound(src, type)];
case 2:
sound = _d.sent();
if (volume) {
sound.volume = volume;
}
sounds.push(sound);
this.sounds.push(sound);
_d.label = 3;
case 3:
_a++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, sounds];
}
});
});
};
Scene.prototype.mapSprites = function () {
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var spritesDecor;
var _this_1 = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
spritesDecor = this.spritesDecor.filter(function (decor) { return !decor.src; });
return [4 /*yield*/, parallel(sources, function (src, _a) {
var realIndex = _a.realIndex;
return __awaiter(_this_1, void 0, void 0, function () {
var decor, sprite;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
decor = spritesDecor[realIndex];
if (!decor) return [3 /*break*/, 2];
return [4 /*yield*/, createAssetImage(src)];
case 1:
sprite = _b.sent();
this[decor.propertyKey] = sprite;
this.sprites.push(sprite);
_b.label = 2;
case 2: return [2 /*return*/];
}
});
});
}, MAX_ASSET_PARALLEL_LOAD)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
Scene.prototype.mapSounds = function () {
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
var soundsDecor, index, _a, soundsDecor_1, decor, src, sound;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
soundsDecor = this.soundsDecor.filter(function (decor) { return !decor.src; });
index = 0;
_a = 0, soundsDecor_1 = soundsDecor;
_b.label = 1;
case 1:
if (!(_a < soundsDecor_1.length)) return [3 /*break*/, 4];
decor = soundsDecor_1[_a];
src = sources[index++];
return [4 /*yield*/, createAssetSound(src, decor.type)];
case 2:
sound = _b.sent();
if (decor.volume) {
sound.volume = decor.volume;
}
this[decor.propertyKey] = sound;
this.sounds.push(sound);
_b.label = 3;
case 3:
_a++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
});
};
Scene.prototype.loadAssets = function (delay, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.skip, skip = _c === void 0 ? false : _c, render = _b.render;
return __awaiter(this, void 0, void 0, function () {
var resultLoadSound, result, hasErrors, errors_1;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
if (delay != null) {
this.assetsDelay = delay;
}
// if delay less than 0, it will wait forever
return [4 /*yield*/, tick(this.assetsDelay < 0 ? undefined : this.assetsDelay)];
case 1:
// if delay less than 0, it will wait forever
_d.sent();
this.loadedAssets = false;
return [4 /*yield*/, this.loadSounds().catch(function (err) {
return {
error: true,
type: "load-sound",
detail: err,
};
})];
case 2:
resultLoadSound = _d.sent();
if ((resultLoadSound === null || resultLoadSound === void 0 ? void 0 : resultLoadSound.error) && !skip) {
this._renderAssetsFail = function () {
return render ? render([resultLoadSound]) : [resultLoadSound];
};
this.loadedAssetsError = [resultLoadSound];
return [2 /*return*/];
}
return [4 /*yield*/, Promise.all([
this.loadSprites().catch(function (err) {
return {
error: true,
type: "load-sprite",
detail: err,
};
}),
this.onLoadAssets().catch(function (err) {
return {
error: true,
type: "load-extends",
detail: err,
};
}),
])];
case 3:
result = _d.sent();
hasErrors = result.some(function (rs) { return rs === null || rs === void 0 ? void 0 : rs.error; });
if (hasErrors && !skip) {
errors_1 = result.filter(function (rs) { return !!(rs === null || rs === void 0 ? void 0 : rs.error); });
// this.loadedAssets = false;
this._renderAssetsFail = function () {
return render ? render(errors_1) : errors_1;
};
this.loadedAssetsError = errors_1;
}
else {
// when don't have error or skip error
this.loadedAssets = true;
}
return [2 /*return*/];
}
});
});
};
Scene.prototype.onLoadAssets = function () {
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/];
}); });
};
Scene.prototype.getPrefab = function (Class) {
return this.prefabs.find(function (pf) { return pf instanceof Class; });
};
Scene.prototype.listenNativeEvents = function () {
var _this = this;
function onVisibilitychange() {
_this.emitProcessStateChangeEvent(window.Renderer.isForeground);
}
window.document.addEventListener("visibilitychange", onVisibilitychange);
this.nativeEventsUnsubscribes = function () {
window.document.removeEventListener("visibilitychange", onVisibilitychange);
};
};
Scene.prototype.onBootstrapDone = function (simpleCamera) { };
Scene.prototype.bootstrapDone = function (simpleCamera) {
this.onBootstrapDone(simpleCamera);
};
Scene.prototype.bootstrap = function (simpleCamera) {
var _this_1 = this;
this._renderer = window.Renderer;
this.listenNativeEvents();
this.bootSoundOptions();
this.onProcessStateChangeListener(function (isForeground) {
if (isForeground) {
if (window.Renderer.running) {
for (var _i = 0, _a = _this_1.sounds; _i < _a.length; _i++) {
var sound = _a[_i];
// only resume background sounds
if (sound.type === SoundType.BACKGROUND) {
sound.resume();
}
}
}
}
else {
// pause all sounds
for (var _b = 0, _c = _this_1.sounds; _b < _c.length; _b++) {
var sound = _c[_b];
sound.pause();
}
}
});
this._worldManagement = new WorldManagement(simpleCamera, this);
var components = this.getComponents(simpleCamera);
var layerIndex = 0;
for (var _i = 0, components_1 = components; _i < components_1.length; _i++) {
var component = components_1[_i];
component.worldManagement = this._worldManagement;
component.layerIndex = layerIndex++;
if (component.isPrefab) {
this.prefabs.push(component);
}
else {
var entity = component.output();
this._worldManagement.addEntity(entity);
}
}
this._worldManagement.bootstrapCompleted();
this.bootstrapDone(simpleCamera);
};
Scene.prototype.onDraw = function () { };
Scene.prototype.onUpdate = function () { };
Scene.prototype.mouseMove = function () {
if (this._worldManagement) {
this._worldManagement.iterateEntities(function (entity) {
entity.onMouseMove();
});
}
};
Scene.prototype.mousePressed = function () {
if (this._worldManagement) {
this._worldManagement.iterateEntities(function (entity) {
entity.onMousePressed();
});
}
};
Scene.prototype.mouseRelease = function () {
if (this._worldManagement) {
this._worldManagement.iterateEntities(function (entity) {
entity.onMouseRelease();
});
}
};
Scene.prototype.action = function () {
if (Renderer.running && Renderer.isForeground) {
this.onUpdate();
this._worldManagement.update();
}
Renderer.background(41, 41, 41);
this.onDraw();
this._worldManagement.draw();
};
return Scene;
}());
export { Scene };