Support Animate

This commit is contained in:
oc 2018-02-06 13:36:18 +08:00
parent 99463c6e5e
commit d02f9df848
18 changed files with 285 additions and 78 deletions

File diff suppressed because one or more lines are too long

1
animates/hand.animate Normal file

File diff suppressed because one or more lines are too long

1
animates/sword.animate Normal file
View File

@ -0,0 +1 @@
{"ratio":2,"bitmaps":["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAD6SURBVHhe7dQ9SsVAFAXg+MNTeAhaWCrWLsHGUlCwsHMXgo2NjZ31a1yBVtaCrSvQ1i24hSSegbuEBAS/Dw7M3JnqZEgHAAAAAAAAAAAAAP/NOI5rySI5GobhNDlJ9uuYqaXo9RR83Pf9U/KevGV/kxwkW+2D1FWmkmKXKfYuZf8k38lrZpeZHSaLusaU2ktOyRcp+zP5Sl6yv858t53VNaaWcrdT9mPSXvpHskrxO3XMnNpvJYW3F/+Q9XmNmVv7raT055R+n/VejZlbyt5M6VfJbdYbNWZureyUvkzOagQAAAAAAAAAAAAAAAAAAAAAAAAAAADwd3XdL135q9NaPZ6+AAAAAElFTkSuQmCC","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJ4SURBVHhe7de7alRRFMbx3DSIgqiNIBJsBUUESyutBAsLO9/CWtL4BtorlgFBRGIEEQwxMSBiMWouGo2TCyaTC0lmJjM5ey+/HVfeYPZB8P+DNefsS/WdxZ5zugAAAAAAAAAAAAAAAAAAAID/lZkdVnX7ELmkkA+C1rU3xngthHBf1xsa9+1vQmcdhK7qUdAXFPh4URSjur+r6vdt6DQP/ZDqkkL/ZlZs6jqh8WnfghzU1UcOQlclmop3fBk5KPA+hXxRYb9LiWtsujR0Oe5b0Gke+hUF/TaFLtHrh29BDgr9jEJOoReqeur2RPfTvgWdpnzTG8yAQm6oYgq8uWfWLvaD1y+vkNko3G6FPJ9CT7ZbZpVVs9m1/Ydw3bchB3X9+dTxqVLwk4tmH1T1VnjlW5CDGj11/XDq+HTgfFwye/rVbKpmNjzDx1N2Cn8jhb+qF8mRObOX381m1sPww4od8y3IQZn3KPzdogjNyorZ8xmzaXX9cjOe8y3IxcNvNtq2OV41ezFrttYMv30ZOSn8dOavqBrjC3+PnfVGvOfLyE0P4HH6qhr9Zfbmp7p/Lg74EnJT+LdbeyGk4F/PhfhgMp7yJeSm9/yTavza2HyIYwuhPTRkvb6E3NT5fQr/2cRS2HhfDfVB/Qn7EnJLf7rq/pvTq6H9uRa2fBplSOGrTixvhdrUWqj7NMqi8HsV/shsLez5FMq004qXq+th14cok879/upO+FKp2GGfQll09PSsNOLVxXq85VMoUzr7F7fDIx+iTOnNR8fP2UGOnvKl8NPx8+RTPOpTKFt6CH4LAAAAAAAAAAAAAAAAAAAAAAAAAACAf1RX1x9x4x3SPdhnTAAAAABJRU5ErkJggg==","","","","","","","","","","","","","","","","","",""],"frame_max":5,"frames":[[[0,8,32,30,100]],[[0,-16,32,50,130]],[[0,-24,40,80,150]],[[0,-48,24,90,180],[1,-8,40,100,255]],[[0,-56,24,100,200],[1,-8,24,100,255]]]}

1
animates/thunder.animate Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
animates/zone.animate Normal file

File diff suppressed because one or more lines are too long

View File

@ -149,6 +149,42 @@ floorId指定的是目标楼层的唯一标识符ID
可以指定time指定后切换动画时长为指定的数值。
## 动画和天气系统
现在我们的H5魔塔支持播放动画也支持天气系统了。
要播放动画你需要先使用“RM动画导出器”将动画导出放在animates目录下然后在main.js中定义。
``` js
this.animates = [// 在此存放所有可能使用的动画必须是animate格式在这里不写后缀名
// 动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符
"hand", "sword", "zone", "yongchang", "thunder" // 根据需求自行添加
]
```
!> 动画必须是animate格式名称不能使用中文不能带空格或特殊字符。
目前暂时不支持带旋转和翻转的帧。
导出动画时可能会进行一些压缩以节省流量,因此清晰度可能不如原版。
动画播放时是按照每秒20帧的速度即50ms/帧)。
定义完毕后,我们可以调用`animate`事件来播放该动画,有关事件的详细介绍请参见[事件](event)。
!> 播放录像时,将默认忽略所有动画。
目前天气系统只支持雨和雪两种天气。
在每层楼的剧本文件里存在一个weather选项表示该层楼的默认天气。
``` js
// 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
"weather": ["snow",5]
```
我们也可以使用`setWeather`事件来设置当前天气,有关事件的详细介绍请参见[事件](event)。
## 背景音乐
本塔支持BGM和SE的播放。

View File

@ -530,21 +530,43 @@ time为可选的指定的话将作为楼层切换动画的时间。
使用disableShop可以永久禁用全局商店直到再次被openShop打开为止。有关全局商店的说明可参见[全局商店](#全局商店)。
### animate显示动画
我们可以使用 `{"type": "animate"}` 来显示一段动画。
有关动画的详细介绍可参见[动画和天气系统](element#动画和天气系统)。
``` js
"x,y": [ // 实际执行的事件列表
{"type": "animate", "name": "yongchang", "loc": [1,3]}, // 在(1,3)显示“咏唱魔法”动画
{"type": "animate", "name": "zone", "loc": "hero"}, // 在勇士位置显示“领域”动画
{"type": "animate", "name": "hand"} // 可以不指定loc则默认为当前事件点
]
```
name为动画名**请确保动画在main.js中的this.animates中被定义过。**
loc为动画的位置可以是`[x,y]`表示在(x,y)点显示,也可以是字符串`"hero"`表示在勇士点显示。
loc可忽略如果忽略则显示为事件当前点。
在动画播放结束后才会继续执行下一个事件。
### showImage显示图片
我们可以使用 `{"type": "showImage"}` 来显示一张图片。
``` js
"x,y": [ // 实际执行的事件列表
{"type": "showImage", "name": "bg.png", "x": 231, "y": 297}, // 在(231,297)显示bg.png
{"type": "showImage", "name": "1.png", "x": 109, "y": 167}, // 在(109,167)显示1.png
{"type": "showImage", "name": "bg", "loc": [231,297]}, // 在(231,297)显示bg.png
{"type": "showImage", "name": "1", "loc": [109,167]}, // 在(109,167)显示1.png
{"type": "showImage"} // 如果不指定name则清除所有图片。
]
```
name为图片名。**请确保图片在main.js中的this.pngs中被定义过。**
x和y为图片左上角坐标以像素为单位进行计算。
loc为图片左上角坐标,以像素为单位进行计算。
如果不指定name则清除所有显示的图片。

View File

@ -32,22 +32,24 @@
要启用这个功能,我们首先需要在`main.js`中将可能的图片进行加载。
``` js
this.pngs = [ // 在此存放所有可能的背景图片背景图片最好是416*416像素其他分辨率会被强制缩放成416*416
// 建议对于较大的图片,在网上使用在线的“图片压缩工具”来进行压缩,以节省流量
"bg.png", // "yewai.png",
this.pngs = [ // 在此存放所有可能使用的图片只能是png格式可以不写后缀名
// 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。
// 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
// 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量
"bg", // 依次向后添加
];
```
!> 背景素材只支持png格式。
!> 请使用网上的一些[在线图片压缩工具](http://www.asqql.com/gifzip/)对png图片进行压缩以节省流量。一张500KB的png图片可以被压缩到20-30KB显示效果不会有太大差异。
!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对png图片进行压缩以节省流量。一张500KB的png图片可以被压缩到20-30KB显示效果不会有太大差异。
之后,我们可以在每层剧本的`"png"`里来定义该层的默认背景图片素材。
``` js
"png": [[x,y,"bg.png"]], // 背景图你可以选择一张或多张png图片来作为背景素材。
"png": [[x,y,"bg"]], // 背景图你可以选择一张或多张png图片来作为背景素材。
"png": [], // 无任何背景图
"png": [[1,1,"house.png"], [6,7,"house2.png"]] // 在(1,1)放一个house.png且(6,7)放house2.png
"png": [[1,1,"house"], [6,7,"house2"]] // 在(1,1)放一个house.png且(6,7)放house2.png
```
png为一个数组代表当前层所有作为背景素材的图片信息。

View File

@ -3,17 +3,8 @@
*/
function core() {
this.dom = {};
this.statusBar = {};
this.canvas = {};
this.images = [];
this.pngs = [];
this.bgms = [];
this.sounds = [];
this.floorIds = [];
this.floors = {};
this.firstData = {};
this.material = {
'animates': {},
'images': {},
'bgms': {},
'sounds': {},
@ -31,7 +22,8 @@ function core() {
'heroMoveTriggerInterval': null,
'heroMoveInterval': null,
"tipAnimate": null,
'openDoorAnimate': null
'openDoorAnimate': null,
'animateInterval': null,
}
this.animateFrame = {
'background': null,
@ -147,22 +139,12 @@ function core() {
'boxAnimateObjs': [],
};
this.status = {};
this.flags = {};
}
/////////// 系统事件相关 ///////////
////// 初始化 //////
core.prototype.init = function (dom, statusBar, canvas, images, pngs, bgms, sounds, floorIds, floors, coreData) {
core.dom = dom;
core.statusBar = statusBar;
core.canvas = canvas;
core.images = images;
core.pngs = pngs;
core.bgms = bgms;
core.sounds = sounds;
core.floorIds = floorIds;
core.floors = floors;
core.prototype.init = function (coreData) {
for (var key in coreData) {
core[key] = coreData[key];
}
@ -187,7 +169,7 @@ core.prototype.init = function (dom, statusBar, canvas, images, pngs, bgms, soun
document.title = core.firstData.title + " - HTML5魔塔";
document.getElementById("startLogo").innerHTML = core.firstData.title;
core.material.items = core.items.getItems();
core.initStatus.maps = core.maps.initMaps(floorIds);
core.initStatus.maps = core.maps.initMaps(core.floorIds);
core.material.enemys = core.clone(core.enemys.getEnemys());
core.material.icons = core.icons.getIcons();
core.material.events = core.events.getEvents();
@ -386,7 +368,7 @@ core.prototype.setRequestAnimationFrame = function () {
// weather
if (core.isPlaying() && timestamp-core.animateFrame.weather.time>30) {
if (core.animateFrame.weather.type=='rain' && core.animateFrame.weather.level>0) {
if (core.animateFrame.weather.type == 'rain' && core.animateFrame.weather.level > 0) {
core.clearMap('weather', 0, 0, 416, 416);
@ -402,8 +384,8 @@ core.prototype.setRequestAnimationFrame = function () {
p.x += p.xs;
p.y += p.ys;
if (p.x>416 || p.y>416) {
p.x = Math.random()*416;
if (p.x > 416 || p.y > 416) {
p.x = Math.random() * 416;
p.y = -10;
}
@ -412,7 +394,7 @@ core.prototype.setRequestAnimationFrame = function () {
core.canvas.weather.fill();
}
else if (core.animateFrame.weather.type=='snow' && core.animateFrame.weather.level>0) {
else if (core.animateFrame.weather.type == 'snow' && core.animateFrame.weather.level > 0) {
core.clearMap('weather', 0, 0, 416, 416);
@ -421,30 +403,30 @@ core.prototype.setRequestAnimationFrame = function () {
if (!core.isset(core.animateFrame.weather.data))
core.animateFrame.weather.data = 0;
core.animateFrame.weather.data+=0.01;
core.animateFrame.weather.data += 0.01;
var angle = core.animateFrame.weather.data;
core.animateFrame.weather.nodes.forEach(function (p) {
core.canvas.weather.moveTo(p.x, p.y);
core.canvas.weather.arc(p.x, p.y, p.r, 0, Math.PI*2, true);
core.canvas.weather.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);
// update
p.x += Math.sin(angle) * 2;
p.y += Math.cos(angle+p.d) + 1 + p.r/2;
p.y += Math.cos(angle + p.d) + 1 + p.r / 2;
if (p.x>416+5 || p.x<-5 || p.y>416) {
if (Math.random()>1/3) {
p.x = Math.random()*416;
if (p.x > 416 + 5 || p.x < -5 || p.y > 416) {
if (Math.random() > 1 / 3) {
p.x = Math.random() * 416;
p.y = -10;
}
else {
if (Math.sin(angle)>0) {
if (Math.sin(angle) > 0) {
p.x = -5;
p.y = Math.random()*416;
p.y = Math.random() * 416;
}
else {
p.x = 416+5;
p.y=Math.random()*416;
p.x = 416 + 5;
p.y = Math.random() * 416;
}
}
}
@ -457,20 +439,11 @@ core.prototype.setRequestAnimationFrame = function () {
core.animateFrame.weather.time = timestamp;
}
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);
}
////// 显示游戏开始界面 //////
core.prototype.showStartAnimate = function (callback) {
core.dom.startPanel.style.opacity=1;
@ -564,7 +537,7 @@ core.prototype.loadAutotile = function (callback) {
core.material.images.autotile={};
var autotileIds = Object.keys(core.material.icons.autotile);
if (autotileIds.length==0) {
core.loadMusic(callback);
core.loadAnimates(callback);
return;
}
for (var x=0;x<autotileIds.length;x++) {
@ -572,8 +545,8 @@ core.prototype.loadAutotile = function (callback) {
core.material.images.autotile[autotileId]=image;
if (Object.keys(core.material.images.autotile).length==autotileIds.length) {
// 最后加载音频
core.loadMusic(callback);
// 加载动画
core.loadAnimates(callback);
}
})
}
@ -601,6 +574,70 @@ core.prototype.loadImage = function (imgName, callback) {
}
}
////// 加载动画 //////
core.prototype.loadAnimates = function (callback) {
core.animates.forEach(function (t) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'animates/' + t + ".animate", true);
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.onload = function (e) {
var content = this.responseText;
try {
content = JSON.parse(content);
var data = {};
data.ratio = content.ratio;
data.images = [];
content.bitmaps.forEach(function (t2) {
if (!core.isset(t2) || t2=="") {
data.images.push(null);
}
else {
try {
var image = new Image();
image.src = t2;
data.images.push(image);
} catch (e) {
data.images.push(null);
}
}
})
data.frame = content.frame_max;
data.frames = [];
content.frames.forEach(function (t2) {
var info = [];
t2.forEach(function (t3) {
info.push({
'index': t3[0],
'x': t3[1],
'y': t3[2],
'zoom': t3[3],
'opacity': t3[4]
})
})
data.frames.push(info);
})
core.material.animates[t] = data;
}
catch (ee) {
console.log(ee);
core.material.animates[t]=null;
}
}
xhr.ontimeout = function(e) {
console.log(e);
core.material.animates[t]=null;
}
xhr.onerror = function (e) {
console.log(e);
core.material.animates[t]=null;
}
xhr.send();
})
core.loadMusic(callback);
}
////// 加载音频 //////
core.prototype.loadMusic = function (callback) {
@ -2212,7 +2249,16 @@ core.prototype.battle = function (id, x, y, force, callback) {
});
}
else {
core.playSound('attack.ogg');
if (core.flags.equipment && core.getFlag('sword', 'sword0')!='sword0') {
core.playSound('zone.ogg');
core.drawAnimate('sword', x, y);
}
else {
core.playSound('attack.ogg');
core.drawAnimate('hand', x, y);
}
core.afterBattle(id, x, y, callback);
}
}
@ -2917,7 +2963,8 @@ core.prototype.showBlock = function(x, y, floodId) {
blockImage = core.material.images[block.event.cls];
core.canvas.event.drawImage(core.material.images[block.event.cls], 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
core.addGlobalAnimate(block.event.animate, block.x * 32, block.y * 32, blockIcon, blockImage);
core.setGlobalAnimate(core.values.animateSpeed);
// core.setGlobalAnimate(core.values.animateSpeed);
core.syncGlobalAnimate();
}
}
}
@ -3066,6 +3113,59 @@ core.prototype.drawBoxAnimate = function () {
}
}
////// 绘制动画 //////
core.prototype.drawAnimate = function (name, x, y, callback) {
// 正在播放录像:不显示动画
if (core.isset(core.status.replay) && core.status.replay.replaying) {
if (core.isset(callback)) callback();
return;
}
// 检测动画是否存在
if (!core.isset(core.material.animates[name]) || !core.isset(x) || !core.isset(y)) {
if (core.isset(callback)) callback();
return;
}
// 清空animate层
clearInterval(core.interval.animateInterval);
core.clearMap('animate', 0, 0, 416, 416);
// 开始绘制
var animate = core.material.animates[name];
var ratio = animate.ratio;
var centerX = 32*x+16, centerY = 32*y+16;
var index=0;
var draw = function (index) {
core.clearMap('animate', 0, 0, 416, 416);
var frame = animate.frames[index];
frame.forEach(function (t) {
var image = animate.images[t.index];
if (!core.isset(image)) return;
var realWidth = image.width * ratio * t.zoom / 100;
var realHeight = image.height * ratio * t.zoom / 100;
core.setAlpha('animate', t.opacity / 255);
core.canvas.animate.drawImage(image, centerX+t.x-realWidth/2, centerY+t.y-realHeight/2, realWidth, realHeight);
})
}
draw(index++);
core.interval.animateInterval = setInterval(function (t) {
if (index == animate.frames.length) {
clearInterval(core.interval.animateInterval);
core.clearMap('animate', 0, 0, 416, 416);
core.setAlpha('animate', 1);
if (core.isset(callback)) callback();
return;
}
draw(index++);
}, 50);
}
////// 更新领域、夹击、阻击的伤害地图 //////
core.prototype.updateCheckBlock = function() {
core.status.checkBlock = {};
@ -3197,6 +3297,10 @@ core.prototype.checkBlock = function () {
else if (damage>0) {
core.drawTip('受到领域伤害'+damage+'点');
}
core.playSound('zone.ogg');
core.drawAnimate("zone", x, y);
if (core.status.hero.hp<=0) {
core.status.hero.hp=0;
core.updateStatusBar();

View File

@ -334,6 +334,21 @@ events.prototype.doAction = function() {
}
else this.doAction();
break;
case "animate": // 显示动画
if (core.isset(data.loc)) {
if (data.loc == 'hero') {
x=core.getHeroLoc('x');
y=core.getHeroLoc('y');
}
else if (data.loc instanceof Array) {
x=data.loc[0];
y=data.loc[1];
}
}
core.drawAnimate(data.name, x, y, function () {
core.events.doAction();
})
break;
case "move": // 移动事件
if (core.isset(data.loc)) {
x=data.loc[0];
@ -367,8 +382,8 @@ events.prototype.doAction = function() {
this.doAction();
break;
case "showImage": // 显示图片
if (core.isset(data.name) && core.isset(data.x) && core.isset(data.y) && core.isset(core.material.images.pngs[data.name])) {
core.canvas.animate.drawImage(core.material.images.pngs[data.name], data.x, data.y);
if (core.isset(data.loc) && core.isset(core.material.images.pngs[data.name])) {
core.canvas.animate.drawImage(core.material.images.pngs[data.name], data.loc[0], data.loc[1]);
}
else core.clearMap('animate', 0, 0, 416, 416);
this.doAction();

View File

@ -10,7 +10,7 @@ main.floors.MT0 = {
"defaultGround": "ground", // 默认地面的图块IDterrains中
"png": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
// "color": [0,0,0,0.3], // 该层的默认画面色调。本项可不写代表无色调如果写需要是一个RGBA数组。
// "weather": ["snow",5], // 该层的默认天气。本项可不写,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
// "weather": ["snow",5], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
// "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。
"map": [ // 地图数据需要是13x13建议使用地图生成器来生成

View File

@ -10,7 +10,7 @@ main.floors.sample0 = {
"defaultGround": "ground", // 默认地面的图块IDterrains中
"png": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
// "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写代表无色调如果写需要是一个RGBA数组。
// "weather": ["snow",5], // 该层的默认天气。本项可不写,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
// "weather": ["snow",5], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
"bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。
"map": [ // 地图数据需要是13x13建议使用地图生成器来生成
[0, 0, 220, 0, 0, 20, 87, 3, 65, 64, 44, 43, 42],

View File

@ -8,9 +8,9 @@ main.floors.sample1 = {
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
"canUseQuickShop": true, // 该层是否允许使用快捷商店
"defaultGround": "grass", // 默认地面的图块IDterrains中
"png": [[0,0,"bg.png"]], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
"png": [[0,0,"bg"]], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
// "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写代表无色调如果写需要是一个RGBA数组。
"weather": ["snow",6], // 该层的默认天气。本项可不写,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
"weather": ["snow",6], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
// "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。
"map": [ // 地图数据需要是13x13建议使用地图生成器来生成
[7, 131, 8, 152, 9, 130, 10, 152, 166, 165, 132, 165, 166],
@ -35,8 +35,8 @@ main.floors.sample1 = {
"4,10": [ // 走到中间时的提示
"\t[样板提示]本层楼将会对各类事件进行介绍。",
"左边是一个仿50层的陷阱做法上方是商店、快捷商店的使用方法右上是一个典型的杀怪开门的例子右下是各类可能的NPC事件。",
"本样板目前支持的事件列表大致有:\ntext: 显示一段文字(比如你现在正在看到的)\ntip: 左上角显示提示\nshow: 使一个事件有效(可见、可被交互)\nhide: 使一个事件失效(不可见、不可被交互)\ntrigger: 触发另一个地点的事件\nbattle: 强制和某怪物战斗\nopenDoor: 无需钥匙开门(例如机关门、暗墙)",
"openShop: 打开一个全局商店\ndisableShop: 禁用一个全局商店\nchangeFloor: 传送勇士到某层某位置\nchangePos: 传送勇士到当层某位置;转向\nsetFg: 更改画面色调\nmove: 移动事件效果\nmoveHero: 移动勇士效果\nplayBgm: 播放某个背景音乐\npauseBgm: 暂停背景音乐\nresumeBgm: 恢复背景音乐的播放\nplaySound: 播放某个音频",
"本样板目前支持的事件列表大致有:\ntext: 显示一段文字(比如你现在正在看到的)\ntip: 左上角显示提示\nshow: 使一个事件有效(可见、可被交互)\nhide: 使一个事件失效(不可见、不可被交互)\ntrigger: 触发另一个地点的事件\nanimate: 显示动画\nbattle: 强制和某怪物战斗\nopenDoor: 无需钥匙开门(例如机关门、暗墙)",
"openShop: 打开一个全局商店\ndisableShop: 禁用一个全局商店\nchangeFloor: 传送勇士到某层某位置\nchangePos: 传送勇士到当层某位置;转向\nshowImage: 显示图片\nsetFg: 更改画面色调\nsetWeather: 更改天气\nmove: 移动事件效果\nmoveHero: 移动勇士效果\nplayBgm: 播放某个背景音乐\npauseBgm: 暂停背景音乐\nresumeBgm: 恢复背景音乐的播放\nplaySound: 播放某个音频",
"if: 条件判断\nchoices: 提供选项\nsetValue: 设置勇士属性道具,或某个变量/flag\nupdate: 更新状态栏和地图显伤\nwin: 获得胜利(游戏通关)\nlose: 游戏失败\nsleep: 等待多少毫秒\nexit: 立刻结束当前事件\nrevisit: 立刻结束事件并重新触发\nfunction: 自定义JS脚本\n\n更多支持的事件还在编写中欢迎您宝贵的意见。",
"有关各事件的样例可参见本层一些NPC的写法。\n所有事件样例本层都有介绍。\n\n一个自定义事件处理完后需要调用{\"type\": \"hide\"}该事件才不会再次出现。",
{"type": "hide"}

View File

@ -10,7 +10,7 @@ main.floors.sample2 = {
"defaultGround": "snowGround", // 默认地面的图块IDterrains中
"png": [], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
"color": [255,0,0,0.3], // 该层的默认画面色调。本项可不写代表无色调如果写需要是一个RGBA数组。
"weather": ["rain",10], // 该层的默认天气。本项可不写,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
"weather": ["rain",10], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪第二项为1-10之间的数代表强度。
"bgm": "qianjin.mid", // 到达该层后默认播放的BGM。本项可忽略。
"map": [ // 地图数据需要是13x13建议使用地图生成器来生成
[5, 5, 5, 5, 5, 5, 87, 5, 5, 5, 5, 5, 5],
@ -28,8 +28,7 @@ main.floors.sample2 = {
[5, 5, 5, 5, 5, 5, 88, 5, 5, 5, 5, 5, 5],
],
"firstArrive": [ // 第一次到该楼层触发的事件
"\t[实战!]本楼将尝试复刻《宿命的旋律》40F剧情。",
"由于暂不支持一些动画效果,例如雷电、振动、天气渲染等等,因此做出来的效果远远比不上原版。\n\n不过作为抛砖引玉还是能展示一下H5的能力。\n开音效食用更加"
"\t[实战!]本楼将尝试复刻《宿命的旋律》40F剧情。"
],
"events": { // 该楼的所有可能事件列表
@ -182,6 +181,7 @@ main.floors.sample2 = {
{"type": "show", "loc": [8,3], "time": 500}, // 依次显示四个角的法师
{"type": "sleep", "time": 500},
"\t[blackMagician]感受绝望吧!冥顽不化的蠢货!",
/*
{"type": "hide", "loc": [4,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
{"type": "show", "loc": [4,3], "time": 150},
{"type": "hide", "loc": [4,6], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
@ -190,8 +190,14 @@ main.floors.sample2 = {
{"type": "show", "loc": [8,6], "time": 150},
{"type": "hide", "loc": [8,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
{"type": "show", "loc": [8,3], "time": 150},
*/
{"type": "animate", "name": "yongchang", "loc": [4,3]},
{"type": "animate", "name": "yongchang", "loc": [4,6]},
{"type": "animate", "name": "yongchang", "loc": [8,6]},
{"type": "animate", "name": "yongchang", "loc": [8,3]},
{"type": "sleep", "time": 200},
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效
{"type": "animate", "name": "thunder", "loc": "hero"},
{"type": "sleep", "time": 200},
"\t[hero]唔……!!(吐血)",
{"type": "playSound", "name": "item.ogg"},
@ -267,6 +273,7 @@ main.floors.sample2 = {
"\t[小妖精,fairy]别小瞧咱!咱好歹也是妖精族里实力数一数二的存在!",
{"type": "playSound", "name": "item.ogg"},
"\t[blackMagician]只会耍嘴皮子的恼人苍蝇!我倒要看看一块焦炭会不会说话!\n——招雷弹",
/*
{"type": "hide", "loc": [4,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
{"type": "show", "loc": [4,3], "time": 150},
{"type": "hide", "loc": [4,6], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
@ -275,9 +282,17 @@ main.floors.sample2 = {
{"type": "show", "loc": [8,6], "time": 150},
{"type": "hide", "loc": [8,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
{"type": "show", "loc": [8,3], "time": 150},
*/
{"type": "animate", "name": "yongchang", "loc": [4,3]},
{"type": "animate", "name": "yongchang", "loc": [4,6]},
{"type": "animate", "name": "yongchang", "loc": [8,6]},
{"type": "animate", "name": "yongchang", "loc": [8,3]},
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效
/*
{"type": "hide", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害
{"type": "show", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害
*/
{"type": "animate", "name": "thunder", "loc": [6,6]},
{"type": "sleep", "time": 500}, // 等待500毫秒
"\t[小妖精,fairy]切,这点伤痛跟他刚才经历的身心地狱相比根本就不算什么。",
{"type": "playSound", "name": "item.ogg"},

21
main.js
View File

@ -12,10 +12,15 @@ function main() {
this.floorIds = [ // 在这里按顺序放所有的楼层;其顺序直接影响到楼层传送器的顺序和上楼器/下楼器的顺序
"sample0", "sample1", "sample2"
];
this.pngs = [ // 在此存放所有可能的背景图片背景图片最好是416*416像素其他分辨率会被强制缩放成416*416
// 建议对于较大的图片,在网上使用在线的“图片压缩工具”来进行压缩,以节省流量
// 有关使用自定义背景图,请参见文档的“自定义素材”说明
"bg.png", // 依次向后添加
this.pngs = [ // 在此存放所有可能使用的图片只能是png格式可以不写后缀名
// 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。
// 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
// 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量
"bg", // 依次向后添加
];
this.animates = [ // 在此存放所有可能使用的动画必须是animate格式在这里不写后缀名
// 动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符
"hand", "sword", "zone", "yongchang", // "thunder" // 根据需求自行添加
];
this.bgms = [ // 在此存放所有的bgm和文件名一致。第一项为默认播放项
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
@ -23,7 +28,7 @@ function main() {
];
this.sounds = [ // 在此存放所有的SE和文件名一致
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg',
'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg', 'zone.ogg'
];
//------------------------ 用户修改内容 END ------------------------//
@ -149,7 +154,11 @@ main.prototype.init = function () {
coreData[name] = main[name];
}
main.loaderFloors(function() {
main.core.init(main.dom, main.statusBar, main.canvas, main.images, main.pngs, main.bgms, main.sounds, main.floorIds, main.floors, coreData);
["dom", "statusBar", "canvas", "images", "pngs",
"animates", "bgms", "sounds", "floorIds", "floors"].forEach(function (t) {
coreData[t] = main[t];
})
main.core.init(coreData);
main.core.resize(main.dom.body.clientWidth, main.dom.body.clientHeight);
})
});

BIN
sounds/zone.ogg Normal file

Binary file not shown.

Binary file not shown.