diff --git a/_docs/api.md b/_docs/api.md
index 2bfd3918..3f40d96f 100644
--- a/_docs/api.md
+++ b/_docs/api.md
@@ -503,6 +503,13 @@ registerResize: fn(name: string, func: fn(obj: ?))
name: 名称,可供注销使用
func: 可以是一个函数,或者是插件中的函数名;可以接受obj参数,详见resize函数。
+registerWeather: fn(name: string, initFunc: fn(level: number), frameFunc?: fn(timestamp: number, level: number))
+注册一个天气
+name: 要注册的天气名
+initFunc: 当切换到此天气时的初始化;接受level(天气等级)为参数;可用于创建多个节点(如初始化雪花)
+frameFunc: 每帧的天气效果变化;可接受timestamp(从页面加载完毕到当前所经过的时间)和level(天气等级)作为参数
+天气应当仅在weather层进行绘制,推荐使用core.animateFrame.weather.nodes用于节点信息。
+
removeFlag: fn(name: string)
删除某个flag/变量
@@ -698,6 +705,9 @@ unregisterReplayAction: fn(name: string)
unregisterResize: fn(name: string)
注销一个resize函数
+unregisterWeather: fn(name: string)
+注销一个天气
+
updateCheckBlock: fn(floorId?: string)
更新领域、夹击、阻击的伤害地图
diff --git a/_docs/script.md b/_docs/script.md
index 3ba53acd..3c94be54 100644
--- a/_docs/script.md
+++ b/_docs/script.md
@@ -480,6 +480,53 @@ core.registerReplayAction('commonEvent', function (action) {
});
```
+### registerWeather
+
+```
+registerWeather: fn(name: string, initFunc: fn(level: number), frameFunc?: fn(timestamp: number, level: number))
+注册一个天气
+name: 要注册的天气名
+initFunc: 当切换到此天气时的初始化;接受level(天气等级)为参数;可用于创建多个节点(如初始化雪花)
+frameFunc: 每帧的天气效果变化;可接受timestamp(从页面加载完毕到当前所经过的时间)和level(天气等级)作为参数
+天气应当仅在weather层进行绘制,推荐使用core.animateFrame.weather.nodes用于节点信息。
+```
+
+`registerWeather`允许你注册一个天气。
+
+在游戏时,楼层属性中可以设置天气如 `["snow", 5]`,或者脚本 `core.setWeather("snow", 5)` 来切换天气。
+
+下面是一个例子:
+
+```js
+// 注册一个”血“天气,每200ms就随机在界面上的绘制红色斑点
+core.registerWeather('blood', function (level) {
+ // 切换到此天气时应当执行的脚本吗,如播放一个音效
+ core.playSound('blood.mp3');
+}, function (timestamp, level) {
+ // 我们希望每200ms就界面上随机绘制 level^2 个红点,半径在0~32像素之间
+
+ // 检查是否经过了200ms
+ if (timestamp - core.animateFrame.weather.time < 200) return;
+ // 当且仅当在weather层上绘制
+ core.clearMap('weather');
+ for (var i = 0; i < level * level; ++i) {
+ // 随机界面中的一个点,半径在0~32之间
+ var px = Math.random() * core.__PIXELS__;
+ var py = Math.random() * core.__PIXELS__;
+ var r = Math.random() * 32;
+ core.fillCircle('weather', px, py, r, 'red');
+ }
+ // 设置本次天气调用的时间
+ core.animateFrame.weather.time = timestamp;
+});
+```
+
+值得注意的是,天气当且仅当在`weather`层进行绘制,推荐使用或设置`core.animateFrame.weather.time`作为上次天气调用的时间避免太过于频繁的调用。
+
+推荐使用`core.animateFrame.weather.nodes`来存储天气的节点,这样会在取消天气时自动被移除。
+
+样板的云`cloud`和雾`fog`均由多个图片叠加移动实现;如果你想实现类似效果,可直接使用`core.control.__animateFrame_weather_image`作为`frameFunc`,详见样板的云雾实现。
+
### registerSystemEvent
```
diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js
index 8d522deb..f8c363e8 100644
--- a/_server/CodeMirror/defs.js
+++ b/_server/CodeMirror/defs.js
@@ -2324,6 +2324,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!doc": "注销一个录像行为",
"!type": "fn(name: string)"
},
+ "unregisterWeather": {
+ "!doc": "注销一个天气",
+ "!type": "fn(name: string)"
+ },
"setBuff": {
"!doc": "设置主角某个属性的百分比修正倍率,初始值为1,
倍率存放在flag: '__'+name+'_buff__' 中
例如:core.setBuff('atk', 0.5); // 主角能发挥出的攻击力减半
name: 属性的英文名,请注意只能用于数值类属性哦,否则随后的乘法会得到NaN
value: 新的百分比修正倍率,不填(效果上)视为1",
"!type": "fn(name: string, value: number)"
@@ -2460,6 +2464,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [
"!doc": "注册一个resize函数
name: 名称,可供注销使用
func: 可以是一个函数,或者是插件中的函数名;可以接受obj参数,详见resize函数。",
"!type": "fn(name: string, func: fn(obj: ?))"
},
+ "registerWeather": {
+ "!doc": "注册一个天气
name: 要注册的天气名
initFunc: 当切换到此天气时的初始化;接受level(天气等级)为参数;可用于创建多个节点(如初始化雪花)
frameFunc: 每帧的天气效果变化;可接受timestamp(从页面加载完毕到当前所经过的时间)和level(天气等级)作为参数
天气应当仅在weather层进行绘制,推荐使用core.animateFrame.weather.nodes用于节点信息。",
+ "!type": "fn(name: string, initFunc: fn(level: number), frameFunc?: fn( timestamp: number, level: number))"
+ },
"stopReplay": {
"!doc": "停止播放",
"!type": "fn(force?: bool)"
diff --git a/libs/control.js b/libs/control.js
index e4b899bb..913b5b29 100644
--- a/libs/control.js
+++ b/libs/control.js
@@ -16,6 +16,7 @@ control.prototype._init = function () {
this.controldata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.control;
this.renderFrameFuncs = [];
this.replayActions = [];
+ this.weathers = {};
this.resizes = [];
// --- 注册系统的animationFrame
this.registerAnimationFrame("totalTime", false, this._animationFrame_totalTime);
@@ -26,6 +27,12 @@ control.prototype._init = function () {
this.registerAnimationFrame("weather", true, this._animationFrame_weather);
this.registerAnimationFrame("tip", true, this._animateFrame_tip);
this.registerAnimationFrame("parallelDo", false, this._animationFrame_parallelDo);
+ // --- 注册系统的天气
+ this.registerWeather("rain", this._weather_rain, this._animationFrame_weather_rain);
+ this.registerWeather("snow", this._weather_snow, this._animationFrame_weather_snow);
+ this.registerWeather("fog", this._weather_fog, this.__animateFrame_weather_image);
+ this.registerWeather("cloud", this._weather_cloud, this.__animateFrame_weather_image);
+ this.registerWeather("sun", this._weather_sun, this._animationFrame_weather_sun);
// --- 注册系统的replay
this.registerReplayAction("move", this._replayAction_move);
this.registerReplayAction("item", this._replayAction_item);
@@ -199,13 +206,19 @@ control.prototype._animationFrame_heroMoving = function (timestamp) {
}
control.prototype._animationFrame_weather = function (timestamp) {
- var weather = core.animateFrame.weather;
- if (timestamp - weather.time <= 30 || !core.dymCanvas.weather) return;
- core.control["_animationFrame_weather_"+weather.type]();
- weather.time = timestamp;
+ var weather = core.animateFrame.weather, type = weather.type;
+ if (!core.dymCanvas.weather || !core.control.weathers[type] || !core.control.weathers[type].frameFunc) return;
+ try {
+ core.doFunc(core.control.weathers[type].frameFunc, core.control, timestamp, core.animateFrame.weather.level);
+ } catch (e) {
+ main.log(e);
+ main.log("ERROR in weather["+type+"]:已自动注销该项。");
+ core.unregisterWeather(type);
+ }
}
-control.prototype._animationFrame_weather_rain = function () {
+control.prototype._animationFrame_weather_rain = function (timestamp, level) {
+ if (timestamp - core.animateFrame.weather.time < 30) return;
var ctx = core.dymCanvas.weather, ox = core.bigmap.offsetX, oy = core.bigmap.offsetY;
core.clearMap('weather');
ctx.strokeStyle = 'rgba(174,194,224,0.8)';
@@ -228,9 +241,11 @@ control.prototype._animationFrame_weather_rain = function () {
});
ctx.fill();
+ core.animateFrame.weather.time = timestamp;
}
-control.prototype._animationFrame_weather_snow = function () {
+control.prototype._animationFrame_weather_snow = function (timestamp, level) {
+ if (timestamp - core.animateFrame.weather.time < 30) return;
var ctx = core.dymCanvas.weather, ox = core.bigmap.offsetX, oy = core.bigmap.offsetY;
core.clearMap('weather');
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
@@ -260,11 +275,15 @@ control.prototype._animationFrame_weather_snow = function () {
}
});
ctx.fill();
+ core.animateFrame.weather.time = timestamp;
}
-control.prototype.__animateFrame_weather_image = function (image) {
- if (!image) return;
+control.prototype.__animateFrame_weather_image = function (timestamp, level) {
+ if (timestamp - core.animateFrame.weather.time < 30) return;
var node = core.animateFrame.weather.nodes[0];
+ var image = node.image;
+ if (!image) return;
+ core.clearMap('weather');
core.setAlpha('weather', node.level / 500);
var wind = 1.5;
var width = image.width, height = image.height;
@@ -296,20 +315,18 @@ control.prototype.__animateFrame_weather_image = function (image) {
}
}
core.setAlpha('weather',1);
+ core.animateFrame.weather.time = timestamp;
}
-control.prototype._animationFrame_weather_fog = function () {
- core.clearMap('weather');
- this.__animateFrame_weather_image(core.animateFrame.weather.fog);
-}
-
-control.prototype._animationFrame_weather_cloud = function () {
- core.clearMap('weather');
- this.__animateFrame_weather_image(core.animateFrame.weather.cloud);
-}
-
-control.prototype._animationFrame_weather_sun = function () {
- // do nothing here.
+control.prototype._animationFrame_weather_sun = function (timestamp, level) {
+ if (timestamp - core.animateFrame.weather.time < 30) return;
+ var node = core.animateFrame.weather.nodes[0];
+ var opacity = node.opacity + node.delta;
+ if (opacity > level / 10 + 0.3 || opacity < level / 10 - 0.3)
+ node.delta = -node.delta;
+ node.opacity = opacity;
+ core.setOpacity('weather', core.clamp(opacity, 0, 1));
+ core.animateFrame.weather.time = timestamp;
}
control.prototype._animateFrame_tip = function (timestamp) {
@@ -2542,7 +2559,7 @@ control.prototype.getMappedName = function (name) {
////// 更改天气效果 //////
control.prototype.setWeather = function (type, level) {
// 非雨雪
- if (type == null) {
+ if (type == null || !this.weathers[type]) {
core.deleteCanvas('weather')
core.animateFrame.weather.type = null;
core.animateFrame.weather.nodes = [];
@@ -2555,72 +2572,98 @@ control.prototype.setWeather = function (type, level) {
// 计算当前的宽高
core.createCanvas('weather', 0, 0, core.__PIXELS__, core.__PIXELS__, 80);
+ core.setOpacity('weather', 1.0);
core.animateFrame.weather.type = type;
core.animateFrame.weather.level = level;
core.animateFrame.weather.nodes = [];
- this._setWeather_createNodes(type, level);
+ try {
+ core.doFunc(this.weathers[type].initFunc, this, level);
+ } catch (e) {
+ main.log(e);
+ main.log("ERROR in weather["+type+"]:已自动注销该项。");
+ core.unregisterWeather(type);
+ }
}
-control.prototype._setWeather_createNodes = function (type, level) {
- var number = level * parseInt(20*core.bigmap.width*core.bigmap.height/(core.__SIZE__*core.__SIZE__));
- switch (type) {
- case 'rain':
- for (var a=0;a void, frameFunc?: (timestamp: number, level: number) => void): void
+
+ /** 注销一个天气 */
+ unregisterWeather(name: string) : void;
+
/**
* 更改画面色调,不计入存档。如需长期生效请使用core.events._action_setCurtain()函数
* @example core.setCurtain(); // 恢复画面色调,用时四分之三秒