Support Animate
This commit is contained in:
parent
99463c6e5e
commit
d02f9df848
File diff suppressed because one or more lines are too long
1
animates/hand.animate
Normal file
1
animates/hand.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/sword.animate
Normal file
1
animates/sword.animate
Normal 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
1
animates/thunder.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/yongchang.animate
Normal file
1
animates/yongchang.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/zone.animate
Normal file
1
animates/zone.animate
Normal file
File diff suppressed because one or more lines are too long
@ -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的播放。
|
||||
|
||||
@ -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则清除所有显示的图片。
|
||||
|
||||
|
||||
@ -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为一个数组,代表当前层所有作为背景素材的图片信息。
|
||||
|
||||
206
libs/core.js
206
libs/core.js
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -10,7 +10,7 @@ main.floors.MT0 = {
|
||||
"defaultGround": "ground", // 默认地面的图块ID(terrains中)
|
||||
"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,建议使用地图生成器来生成
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ main.floors.sample0 = {
|
||||
"defaultGround": "ground", // 默认地面的图块ID(terrains中)
|
||||
"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],
|
||||
|
||||
@ -8,9 +8,9 @@ main.floors.sample1 = {
|
||||
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
|
||||
"canUseQuickShop": true, // 该层是否允许使用快捷商店
|
||||
"defaultGround": "grass", // 默认地面的图块ID(terrains中)
|
||||
"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"}
|
||||
|
||||
@ -10,7 +10,7 @@ main.floors.sample2 = {
|
||||
"defaultGround": "snowGround", // 默认地面的图块ID(terrains中)
|
||||
"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
21
main.js
@ -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
BIN
sounds/zone.ogg
Normal file
Binary file not shown.
BIN
常用工具/RM动画导出器.exe
BIN
常用工具/RM动画导出器.exe
Binary file not shown.
Loading…
Reference in New Issue
Block a user