Merge pull request #258 from ckcz123/v2.0

V2.5.1
This commit is contained in:
Zhang Chen 2018-11-21 23:51:58 +08:00 committed by GitHub
commit 6542c4e845
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 649 additions and 318 deletions

View File

@ -53,6 +53,22 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明
### 2018.11.21 V2.5.1
* [x] 新增事件type:insert可以插入另一个地点的事件执行公共事件
* [x] 可以使用\v来控制剧情文本部分文字的颜色
* [x] 新增事件type:switch多重分歧
* [x] 绘制前景/背景层时淡化其他图层
* [x] 追加素材的自动调整(如白底、不规范的素材)
* [x] 浏览地图时:左上角/V开启显伤右上角/Z查看当前层大地图
* [x] 允许在受到领域夹击等伤害后禁用快捷商店
* [x] 升级的扣除模式,即不显示经验值,只显示升级的所需剩余值
* [x] 装备增加可装备条件判定
* [x] 选项界面可以使用1-9快速选择
* [x] 未开启状态的快捷商店用灰色显示
* [x] 修复不能在背景/前景层绘图的Bug
* [x] 部分其他细节优化
### 2018.10.31 V2.5
* [x] 添加绘图模式支持;可以用户手动绘图和保存

View File

@ -192,6 +192,7 @@ action
| show_s
| hide_s
| trigger_s
| insert_s
| revisit_s
| exit_s
| setBlock_s
@ -481,6 +482,20 @@ var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']},\n';
return code;
*/;
insert_s
: '插入事件' 'x' PosString ',' 'y' PosString '楼层' IdString? Newline
/* insert_s
tooltip : insert: 立即插入另一个地点的事件执行,当前事件不会中断,事件坐标不会改变
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6
default : ["0","0",""]
colour : this.eventColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
var code = '{"type": "insert", "loc": ['+PosString_0+','+PosString_1+']'+IdString_0+'},\n';
return code;
*/;
revisit_s
: '重启当前事件' Newline
@ -1966,6 +1981,10 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['trigger_s'].xmlText([
data.loc[0],data.loc[1],this.next]);
break;
case "insert": // 强制插入另一个点的事件在当前事件列表执行,当前坐标和楼层不会改变
this.next = MotaActionBlocks['insert_s'].xmlText([
data.loc[0],data.loc[1],data.floorId||'',this.next]);
break;
case "playSound":
this.next = MotaActionBlocks['playSound_s'].xmlText([
data.name,this.next]);

View File

@ -49,28 +49,35 @@ comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_type": "textarea",
"_string": true,
"_lint": true,
"_data": "cls为items的即捡即用类物品的效果。"
"_data": "即捡即用类物品的效果仅对cls为items有效。"
},
"itemEffectTip": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_data": "cls为items的即捡即用类物品在获得时左上角额外显示的文字。"
"_data": "即捡即用类物品在获得时提示的文字仅对cls为items有效。"
},
"useItemEffect": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_data": "cls为tools或constants时的使用物品效果。"
"_data": "道具效果仅对cls为tools或constants有效。"
},
"canUseItemEffect": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_data": "cls为tools或constants时对当前能否使用该物品的判断。"
"_data": "当前能否使用该道具仅对cls为tools或constants有效。"
},
"canEquip":{
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_data": "当前能否装备某个装备仅对cls为equips有效。\n与canUseItemEffect不同这里null代表可以装备。"
}
}
},
@ -119,54 +126,54 @@ comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==null || thiseval instanceof Array || (thiseval==~~thiseval && thiseval>=0)",
"_data": "特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌,21:退化,22:固伤,23:重生,24:激光\n\n多个属性例如用[1,4,11]表示先攻2连击吸血\n模仿怪的攻防设为0就好"
"_data": "特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌,21:退化,22:固伤,23:重生,24:激光,25:光环\n\n多个属性例如用[1,4,11]表示先攻2连击吸血"
},
"value": {
"_leaf": true,
"_type": "textarea",
"_data": "特殊属性的数值\n领域怪需要加value表示领域伤害的数值\n吸血怪需要在后面添加value代表吸血比例"
"_data": "特殊属性的数值\n如:领域/阻激/激光怪的伤害值;吸血怪的吸血比例;光环怪增加生命的比例"
},
"zoneSquare": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "领域怪zoneSquare代表是否九宫格伤害"
"_data": "领域怪是否九宫格伤害"
},
"range": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
"_data": "range可选代表领域伤害的范围不加默认为1"
"_data": "领域伤害的范围不加默认为1"
},
"notBomb": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "加入 \"notBomb\": true 代表该怪物不可被炸弹或圣锤炸掉"
"_data": "该怪物不可被炸"
},
"n": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
"_data": "多连击需要在后面指定n代表是几连击"
"_data": "多连击的连击数"
},
"add": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "代表吸血后是否加到自身"
"_data": "吸血后是否加到自身;光环是否叠加"
},
"atkValue": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval||thiseval==null",
"_data": "退化时勇士下降的攻击力点数"
"_data": "退化时勇士下降的攻击力点数;光环怪增加攻击的比例"
},
"defValue": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval||thiseval==null",
"_data": "退化时勇士下降的防御力点数"
"_data": "退化时勇士下降的防御力点数;光环怪增加防御的比例"
},
"damage": {
"_leaf": true,

View File

@ -1079,19 +1079,33 @@ editor.prototype.listen = function () {
editor.brushMod=brushMod3.value;
}
var bgc = document.getElementById('bg'), fgc = document.getElementById('fg'),
evc = document.getElementById('event'), ev2c = document.getElementById('event2');
var layerMod=document.getElementById('layerMod');
layerMod.onchange=function(){
editor.layerMod=layerMod.value;
[bgc,fgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 1;
});
}
var layerMod2=document.getElementById('layerMod2');
if(layerMod2)layerMod2.onchange=function(){
editor.layerMod=layerMod2.value;
[fgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
bgc.style.opacity = 1;
}
var layerMod3=document.getElementById('layerMod3');
if(layerMod3)layerMod3.onchange=function(){
editor.layerMod=layerMod3.value;
[bgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
fgc.style.opacity = 1;
}
var viewportButtons=document.getElementById('viewportButtons');

View File

@ -108,10 +108,10 @@ editor_blockly = function () {
],
'事件控制':[
MotaActionBlocks['if_s'].xmlText(),
MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别", "caseList": [
MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别", "caseList": [
{"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]},
{"action": []},
{"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行事件"}]},
{"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]},
]}),
MotaActionBlocks['while_s'].xmlText(),
MotaActionBlocks['break_s'].xmlText(),
@ -126,6 +126,7 @@ editor_blockly = function () {
MotaActionBlocks['hideBgFgMap_s'].xmlText(),
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
MotaActionBlocks['trigger_s'].xmlText(),
MotaActionBlocks['insert_s'].xmlText(),
MotaActionBlocks['move_s'].xmlText(),
MotaActionBlocks['jump_s'].xmlText(),
MotaActionBlocks['disableShop_s'].xmlText(),

View File

@ -556,6 +556,90 @@ editor_mode = function (editor) {
}
selectAppend.onchange();
var getPixel=function(imgData, x, y) {
var offset = (x + y * imgData.width) * 4;
var r = imgData.data[offset+0];
var g = imgData.data[offset+1];
var b = imgData.data[offset+2];
var a = imgData.data[offset+3];
return [r,g,b,a];
}
var setPixel=function(imgData, x, y, rgba) {
var offset = (x + y * imgData.width) * 4;
imgData.data[offset+0]=rgba[0];
imgData.data[offset+1]=rgba[1];
imgData.data[offset+2]=rgba[2];
imgData.data[offset+3]=rgba[3];
}
var autoAdjust = function (image, callback) {
var changed = false;
// Step 1: 检测白底
var tempCanvas = document.createElement('canvas').getContext('2d');
tempCanvas.canvas.width = image.width;
tempCanvas.canvas.height = image.height;
tempCanvas.mozImageSmoothingEnabled = false;
tempCanvas.webkitImageSmoothingEnabled = false;
tempCanvas.msImageSmoothingEnabled = false;
tempCanvas.imageSmoothingEnabled = false;
tempCanvas.drawImage(image, 0, 0);
var imgData = tempCanvas.getImageData(0, 0, image.width, image.height);
var trans = 0, white = 0;
for (var i=0;i<image.width;i++) {
for (var j=0;j<image.height;j++) {
var pixel = getPixel(imgData, i, j);
if (pixel[3]==0) trans++;
if (pixel[0]==255 && pixel[1]==255 && pixel[2]==255 && pixel[3]==255) white++;
}
}
if (white>trans*10 && confirm("看起来这张图片是以白色为底色,是否自动调整为透明底色?")) {
for (var i=0;i<image.width;i++) {
for (var j=0;j<image.height;j++) {
var pixel = getPixel(imgData, i, j);
if (pixel[0]==255 && pixel[1]==255 && pixel[2]==255 && pixel[3]==255) {
setPixel(imgData, i, j, [0,0,0,0]);
}
}
}
tempCanvas.clearRect(0, 0, image.width, image.height);
tempCanvas.putImageData(imgData, 0, 0);
changed = true;
}
// Step 2: 检测长宽比
var ysize = selectAppend.value.indexOf('48') === -1 ? 32 : 48;
if ((image.width%32!=0 || image.height%ysize!=0) && (image.width<=128 && image.height<=ysize*4)
&& confirm("目标长宽不符合条件,是否自动进行调整?")) {
var ncanvas = document.createElement('canvas').getContext('2d');
ncanvas.canvas.width = 128;
ncanvas.canvas.height = 4*ysize;
ncanvas.mozImageSmoothingEnabled = false;
ncanvas.webkitImageSmoothingEnabled = false;
ncanvas.msImageSmoothingEnabled = false;
ncanvas.imageSmoothingEnabled = false;
var w = image.width / 4, h = image.height / 4;
for (var i=0;i<4;i++) {
for (var j=0;j<4;j++) {
ncanvas.drawImage(tempCanvas.canvas, i*w, j*h, w, h, i*32 + (32-w)/2, j*ysize + (ysize-h)/2, w, h);
}
}
tempCanvas = ncanvas;
changed = true;
}
if (!changed) {
callback(image);
}
else {
var nimg = new Image();
nimg.onload = function () {
callback(nimg);
};
nimg.src = tempCanvas.canvas.toDataURL();
}
}
var selectFileBtn = document.getElementById('selectFileBtn');
selectFileBtn.onclick = function () {
var loadImage = function (content, callback) {
@ -576,48 +660,50 @@ editor_mode = function (editor) {
}
core.readFile(function (content) {
loadImage(content, function (image) {
editor_mode.appendPic.img = image;
editor_mode.appendPic.width = image.width;
editor_mode.appendPic.height = image.height;
autoAdjust(image, function (image) {
editor_mode.appendPic.img = image;
editor_mode.appendPic.width = image.width;
editor_mode.appendPic.height = image.height;
if (selectAppend.value == 'autotile') {
for (var ii = 0; ii < 3; ii++) {
var newsprite = appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = image.width) / ratio + 'px';
newsprite.style.height = (newsprite.height = image.height) / ratio + 'px';
if (selectAppend.value == 'autotile') {
for (var ii = 0; ii < 3; ii++) {
var newsprite = appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = image.width) / ratio + 'px';
newsprite.style.height = (newsprite.height = image.height) / ratio + 'px';
}
sprite_ctx.clearRect(0, 0, sprite.width, sprite.height);
sprite_ctx.drawImage(image, 0, 0);
}
sprite_ctx.clearRect(0, 0, sprite.width, sprite.height);
sprite_ctx.drawImage(image, 0, 0);
}
else {
var ysize = selectAppend.value.indexOf('48') === -1 ? 32 : 48;
for (var ii = 0; ii < 3; ii++) {
var newsprite = appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = Math.floor(image.width / 32) * 32) / ratio + 'px';
newsprite.style.height = (newsprite.height = Math.floor(image.height / ysize) * ysize) / ratio + 'px';
else {
var ysize = selectAppend.value.indexOf('48') === -1 ? 32 : 48;
for (var ii = 0; ii < 3; ii++) {
var newsprite = appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = Math.floor(image.width / 32) * 32) / ratio + 'px';
newsprite.style.height = (newsprite.height = Math.floor(image.height / ysize) * ysize) / ratio + 'px';
}
}
}
//画灰白相间的格子
var bgc = bg.getContext('2d');
var colorA = ["#f8f8f8", "#cccccc"];
var colorIndex;
var sratio = 4;
for (var ii = 0; ii < image.width / 32 * sratio; ii++) {
colorIndex = 1 - ii % 2;
for (var jj = 0; jj < image.height / 32 * sratio; jj++) {
bgc.fillStyle = colorA[colorIndex];
colorIndex = 1 - colorIndex;
bgc.fillRect(ii * 32 / sratio, jj * 32 / sratio, 32 / sratio, 32 / sratio);
//画灰白相间的格子
var bgc = bg.getContext('2d');
var colorA = ["#f8f8f8", "#cccccc"];
var colorIndex;
var sratio = 4;
for (var ii = 0; ii < image.width / 32 * sratio; ii++) {
colorIndex = 1 - ii % 2;
for (var jj = 0; jj < image.height / 32 * sratio; jj++) {
bgc.fillStyle = colorA[colorIndex];
colorIndex = 1 - colorIndex;
bgc.fillRect(ii * 32 / sratio, jj * 32 / sratio, 32 / sratio, 32 / sratio);
}
}
}
//把导入的图片画出
source_ctx.drawImage(image, 0, 0);
editor_mode.appendPic.sourceImageData=source_ctx.getImageData(0,0,image.width,image.height);
//把导入的图片画出
source_ctx.drawImage(image, 0, 0);
editor_mode.appendPic.sourceImageData=source_ctx.getImageData(0,0,image.width,image.height);
//重置临时变量
selectAppend.onchange();
//重置临时变量
selectAppend.onchange();
});
});
}, null, 'img');
@ -630,21 +716,6 @@ editor_mode = function (editor) {
var imgData=editor_mode.appendPic.sourceImageData;
var nimgData=new ImageData(imgData.width,imgData.height);
// ImageData .data 形如一维数组,依次排着每个点的 R(0~255) G(0~255) B(0~255) A(0~255)
var getPixel=function(imgData, x, y) {
var offset = (x + y * imgData.width) * 4;
var r = imgData.data[offset+0];
var g = imgData.data[offset+1];
var b = imgData.data[offset+2];
var a = imgData.data[offset+3];
return [r,g,b,a];
}
var setPixel=function(imgData, x, y, rgba) {
var offset = (x + y * imgData.width) * 4;
imgData.data[offset+0]=rgba[0];
imgData.data[offset+1]=rgba[1];
imgData.data[offset+2]=rgba[2];
imgData.data[offset+3]=rgba[3];
}
var convert=function(rgba,delta){
var round=Math.round;
// rgbToHsl hue2rgb hslToRgb from https://github.com/carloscabo/colz.git

View File

@ -1,6 +1,6 @@
# V2.0版本介绍
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
目前样板已经更新到V2.0版本以上本章将对V2.0的一些内容进行介绍。

View File

@ -1,6 +1,6 @@
# 附录: API列表
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
**这里只列出所有可能会被造塔者用到的常用API更多的有关内容请在代码内进行查询。**

View File

@ -1,6 +1,6 @@
# 元件说明
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。
@ -262,6 +262,17 @@ floorId指定的是目标楼层的唯一标识符ID
**从2.1.1开始,楼层属性中提供了`upFloor`和`downFloor`两项。如果设置此项(比如`"upFloor": [2,3]`则写stair:upFloor或者楼传器的落点将用此点来替换楼梯位置即类似于RM中的上箭头。**
## 剧情文本控制
在写剧情文本时,可以:
- 使用`\t[...]`来给文字加上标题和图标。如`\t[老人,man]`。
- 使用`\b[...]`来制作对话框效果,如`\b[up,3,2]`。
- 使用`\v[...]`来动态修改局部文本的颜色,如`\v[red]`。
- 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。
详细信息请参见[剧情文本控制](event#text显示一段文字剧情)中的说明。
## 大地图
从V2.4开始H5魔塔开始支持大地图。

View File

@ -1,6 +1,6 @@
# 事件
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
本章内将对样板所支持的事件进行介绍。
@ -237,6 +237,15 @@
!> `\t[...]`必须在`\b[...]`前面!不然两者都无法正常显示。
还可以使用`\v[...]`来调整剧情文本的颜色。
``` js
"x,y": [ // 实际执行的事件列表
"这句话是默认颜色,\v[red]将颜色变成红色,\v[blue]将颜色变成蓝色",
"\v[#FF00FF]还可以使用RGB值来控制颜色\v如果不加中括号则回到默认颜色",
"\t[hero]\b[up,hero]啊啊啊,别过来,\v[red]别过来!!!\n\v你到底是什么东西"
]
```
另外值得一提的是,我们是可以在文字中计算一个表达式的值的。只需要将表达式用 `${ }`整个括起来就可以。
@ -468,6 +477,32 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。
### insert插入另一个地点的事件
`{"type":"insert"}` 会插入另一个地点的事件执行。
其基本写法如下:
``` js
"x,y": [ // 实际执行的事件列表
{"type": "insert", "loc": [3,6]}, // 插入[3,6]点的事件并执行
{"type": "insert", "loc": [10,10], "floorId": "MT1"}, // 插入MT1层[10,10]点的事件并执行
"上面的插入事件执行完毕后会接着继续执行后面的事件"
]
```
loc是必须的代表另一个地点的坐标。
floorId可选代表另一个地点所在的楼层如果不写则默认为当前层。
和`type:trigger`不同的是,**`type:trigger`是立刻将当前事件结束剩下所有内容都忽略然后重新启动另一个地点的action事件。**
但是`type:insert`不会结束当前事件,而是直接将另一个地点的事件列表“插入”到当前事件列表中执行。
**这个过程中,当前事件不会被结束,当前的楼层和事件坐标不会发生改变。** 插入的事件执行完毕后,会继续执行接下来的内容。
我们某个事件写在某个角落的墙上然后远程调用,从而达到“公共事件”的效果。
### revisit立即重启当前事件
revisit和trigger完全相同只不过是立刻触发的还是本地点的事件
@ -1215,11 +1250,11 @@ text为提示文字可以在这里给输入提示文字。这里同样可以
]
```
我们可以在condition中给出一个表达式能将`status:xxx, item:xxx, flag:xxx`来作为参数),并计算它的值
我们可以在condition中给出一个表达式能将`status:xxx`, `item:xxx`, `flag:xxx`来作为参数),并计算它的值
如果某条件中的值与其相等,则将执行其对应的列表事件内容。
如果没有符合的值,则将执行`"default"`中的列表事件内容。
如果没有符合的值,则将执行`default`中的列表事件内容。
例如下面这个例子,将检查当前游戏难度并赠送不同属性。
@ -1248,7 +1283,7 @@ text为提示文字可以在这里给输入提示文字。这里同样可以
需要额外注意的几点:
- 各个条件分支的判断是顺序执行的,因此若多个分支的条件都满足,将只执行最靠前的分支,同理,请不要在`"default"`分支后添加分支,这些分支将不可能被执行。
-`"default"`分支并不是必要的,如果删除,则在没有满足条件的分支时将不执行任何事件。
- `default`分支并不是必要的,如果删除,则在没有满足条件的分支时将不执行任何事件。
- 即使某个场合不执行事件对应的action数组也需要存在不过简单的留空就好。
- switch可以不断进行嵌套一层套一层如某条件成立的场合再进行另一个switch判断等。
- switch语句内的内容执行完毕后将接着其后面的语句继续执行。

View File

@ -1,6 +1,6 @@
# HTML5 魔塔样板说明文档
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。

View File

@ -1,6 +1,6 @@
# 个性化
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
@ -521,6 +521,15 @@ case 89: // 使用该按键的keyCode比如Y键就是89
## 公共事件
从2.5.1开始H5提供了`{"type":"insert"}`事件,完美支持了公共事件的写法。
我们只需要将需要的公共事件放在某个角落的墙上(或者甚至单独弄一层专门摆放公共事件),并使用“插入事件”,即可进行调用。
具体详见[插入另一个地点的事件](event#insert插入另一个地点的事件)。
当然,继续使用**插件**的写法也是可以的。具体参见“脚本编辑 - 插件编写”。
<!--
在RM中存在公共事件的说法也就是通过某个指令来调用一系列事件的触发。
在H5中我们可以使用“插件”的形式来达成这个效果。具体参见“脚本编辑 - 插件编写”。
@ -547,7 +556,7 @@ this.myfunc = function(x) {
然后比如我们在某个道具的使用效果 `useItemEffect` 中写 `core.plugin.myfunc(2)` 即可调用此公共事件(插件)。也可以在战后事件或自定义脚本等位置来写。
通过这种将脚本和自定义事件混用的方式可以达到和RM中公共事件类似的效果即一个调用触发一系列事件。
-->
## 自定义状态栏(新增显示项)
在V2.2以后,我们可以自定义状态栏背景图(全塔属性 - statusLeftBackground等等。

View File

@ -1,6 +1,6 @@
# 快速上手
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5.1**,上次更新时间:* {docsify-updated} *
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!

View File

@ -767,6 +767,12 @@ actions.prototype.clickAction = function (x,y) {
////// 自定义事件时,按下某个键的操作 //////
actions.prototype.keyDownAction = function (keycode) {
// 视为无效
var startTime = core.status.event.data.startTime||0;
if (startTime>0 && new Date().getTime()-startTime<250)
return;
core.status.event.data.startTime = 0;
if (core.status.event.data.type=='choices') {
var data = core.status.event.data.current;
var choices = data.choices;
@ -809,6 +815,15 @@ actions.prototype.keyUpAction = function (keycode) {
core.insertAction(choices[core.status.event.selection].action);
core.doAction();
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
core.status.route.push("choices:"+index);
core.insertAction(choices[index].action);
core.doAction();
}
}
}
}
}
@ -930,6 +945,16 @@ actions.prototype.clickViewMaps = function (x,y) {
core.ui.drawMaps(index, cx, cy);
return;
}
if (x==0 && y==12) {
core.status.event.data.paint = !core.status.event.data.paint;
core.ui.drawMaps(index, cx, cy);
return;
}
if (x==12 && y==0) {
core.status.event.data.all = !core.status.event.data.all;
core.ui.drawMaps(index, cx, cy);
return;
}
if (x>=2 && x<=10 && y<=1 && mh>13) {
core.ui.drawMaps(index, cx, cy-1);
@ -1002,6 +1027,11 @@ actions.prototype.keyUpViewMaps = function (keycode) {
core.ui.drawMaps(core.status.event.data);
return;
}
if (keycode==90) {
core.status.event.data.all = !core.status.event.data.all;
core.ui.drawMaps(core.status.event.data);
return;
}
if (keycode==77) {
core.status.event.data.paint = !core.status.event.data.paint;
core.ui.drawMaps(core.status.event.data);
@ -1122,6 +1152,14 @@ actions.prototype.keyUpShop = function (keycode) {
var topIndex = 6 - parseInt(choices.length / 2);
this.clickShop(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<=choices.length) {
var topIndex = 6 - parseInt(choices.length / 2);
this.clickShop(6, topIndex+index);
}
}
return;
}
@ -1169,6 +1207,13 @@ actions.prototype.keyUpQuickShop = function (keycode) {
var topIndex = 6 - parseInt(keys.length / 2);
this.clickQuickShop(6, topIndex+core.status.event.selection);
}
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<=keys.length) {
var topIndex = 6 - parseInt(keys.length / 2);
this.clickQuickShop(6, topIndex+index);
}
}
return;
}
@ -1811,6 +1856,14 @@ actions.prototype.keyUpSwitchs = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSwitchs(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSwitchs(6, topIndex+index);
}
}
}
@ -1891,6 +1944,14 @@ actions.prototype.keyUpSettings = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSettings(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSettings(6, topIndex+index);
}
}
}
////// 同步存档界面时的点击操作 //////
@ -1969,7 +2030,7 @@ actions.prototype.clickSyncSave = function (x,y) {
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify({
'name': core.firstData.name,
'hard': core.status.hard,
'seed': core.getFlag('seed'),
'seed': core.getFlag('__seed__'),
'route': core.encodeRoute(core.status.route)
}));
break;
@ -2011,6 +2072,14 @@ actions.prototype.keyUpSyncSave = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSyncSave(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSyncSave(6, topIndex+index);
}
}
}
////// 同步存档选择界面时的点击操作 //////
@ -2060,6 +2129,14 @@ actions.prototype.keyUpSyncSelect = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSyncSelect(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickSyncSelect(6, topIndex+index);
}
}
}
////// 存档下载界面时的点击操作 //////
@ -2133,6 +2210,14 @@ actions.prototype.keyUpLocalSaveSelect = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickLocalSaveSelect(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickLocalSaveSelect(6, topIndex+index);
}
}
}
////// 存档删除界面时的点击操作 //////
@ -2219,6 +2304,14 @@ actions.prototype.keyUpStorageRemove = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickStorageRemove(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickStorageRemove(6, topIndex+index);
}
}
}
////// 回放选择界面时的点击操作 //////
@ -2234,7 +2327,7 @@ actions.prototype.clickReplay = function (x, y) {
case 0:
{
core.ui.closePanel();
var hard=core.status.hard, seed = core.getFlag('seed');
var hard=core.status.hard, seed = core.getFlag('__seed__');
core.startGame(hard, seed, core.clone(core.status.route));
break;
}
@ -2258,7 +2351,7 @@ actions.prototype.clickReplay = function (x, y) {
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify({
'name': core.firstData.name,
'hard': core.status.hard,
'seed': core.getFlag('seed'),
'seed': core.getFlag('__seed__'),
'route': core.encodeRoute(core.status.route)
}));
break;
@ -2293,6 +2386,14 @@ actions.prototype.keyUpReplay = function (keycode) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickReplay(6, topIndex+core.status.event.selection);
}
// 数字键快速选择
if (keycode>=49 && keycode<=57) {
var index = keycode-49;
if (index<choices.length) {
var topIndex = 6 - parseInt((choices.length - 1) / 2);
this.clickReplay(6, topIndex+index);
}
}
}
////// “虚拟键盘”界面时的点击操作 //////

View File

@ -1519,7 +1519,9 @@ control.prototype.updateDamage = function (floorId, canvas) {
core.clearMap('damage');
}
// if (!core.isset(core.status.thisMap) || !core.isset(core.status.thisMap.blocks)) return;
// 正在开始游戏中
if (core.status.isStarting) return;
// 更新显伤
var mapBlocks = core.status.maps[floorId].blocks;
// 没有怪物手册
@ -1598,7 +1600,7 @@ control.prototype.updateDamage = function (floorId, canvas) {
}
}
// 如果是领域&夹击
if (core.flags.displayExtraDamage) {
if (core.flags.displayExtraDamage && core.isset((core.status.checkBlock||{}).damage)) {
canvas.textAlign = 'center';
// 临时改变
@ -2254,7 +2256,7 @@ control.prototype.doSL = function (id, type) {
if (data.version != core.firstData.version) {
// core.drawTip("存档版本不匹配");
if (confirm("存档版本不匹配!\n你想回放此存档的录像吗\n可以随时停止录像播放以继续游戏。")) {
core.startGame(data.hard, data.hero.flags.seed, core.decodeRoute(data.route));
core.startGame(data.hard, data.hero.flags.__seed__, core.decodeRoute(data.route));
}
return;
}
@ -2293,7 +2295,7 @@ control.prototype.doSL = function (id, type) {
return;
}
var route = core.subarray(core.status.route, core.decodeRoute(data.route));
if (!core.isset(route) || data.hero.flags.seed!=core.getFlag('seed')) {
if (!core.isset(route) || data.hero.flags.__seed__!=core.getFlag('__seed__')) {
core.drawTip("无法从此存档回放录像");
return;
}
@ -2794,6 +2796,8 @@ control.prototype.resize = function(clientWidth, clientHeight) {
if (!core.flags.enableMana) count--;
if (!core.flags.enableSkill) count--;
if (count>12) alert("当前状态栏数目("+count+")大于12请调整到不超过12以避免手机端出现显示问题。");
var statusLineHeight = BASE_LINEHEIGHT * 9 / count;
var statusLineFontSize = DEFAULT_FONT_SIZE;
if (count>9) statusLineFontSize = statusLineFontSize * 9 / count;

View File

@ -148,7 +148,7 @@ function core() {
},
'textAttribute': {
'position': "center",
"offset": 20,
"offset": 0,
"title": [255,215,0,1],
"background": [0,0,0,0.85],
"text": [255,255,255,1],
@ -203,6 +203,11 @@ core.prototype.init = function (coreData, callback) {
document.getElementById("startLogo").innerHTML = core.firstData.title;
core.material.items = core.clone(core.items.getItems());
core.material.enemys = core.clone(core.enemys.getEnemys());
if (main.mode == 'play') {
for (var enemyId in core.material.enemys) {
core.material.enemys[enemyId].id = enemyId;
}
}
core.material.icons = core.icons.getIcons();
core.material.events = core.events.getEvents();

View File

@ -88,8 +88,8 @@ events.prototype.startGame = function (hard, seed, route, callback) {
core.status.isStarting = true;
if (core.isset(seed)) {
core.setFlag('seed', seed);
core.setFlag('rand', seed);
core.setFlag('__seed__', seed);
core.setFlag('__rand__', seed);
}
else core.utils.__init_seed();
@ -195,7 +195,7 @@ events.prototype.gameOver = function (ending, fromReplay, norank) {
'name': core.firstData.name,
'version': core.firstData.version,
'hard': core.status.hard,
'seed': core.getFlag('seed'),
'seed': core.getFlag('__seed__'),
'route': core.encodeRoute(core.status.route)
}
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify(obj));
@ -238,7 +238,7 @@ events.prototype.gameOver = function (ending, fromReplay, norank) {
formData.append('experience', core.status.hero.experience);
formData.append('steps', core.status.hero.steps);
formData.append('norank', norank||0);
formData.append('seed', core.getFlag('seed'));
formData.append('seed', core.getFlag('__seed__'));
formData.append('totalTime', Math.floor(core.status.hero.statistics.totalTime/1000));
formData.append('route', core.encodeRoute(core.status.route));
formData.append('base64', 1);
@ -316,7 +316,7 @@ events.prototype.doEvents = function (list, x, y, callback) {
core.status.event = {'id': 'action', 'data': {
'list': [
{"todo": core.clone(list), "total": core.clone(list), "condition": "false"}
], 'x': x, 'y': y, 'callback': callback
], 'x': x, 'y': y, 'callback': callback, 'startTime': new Date().getTime()
}}
// 停止勇士
@ -702,12 +702,12 @@ events.prototype.doAction = function() {
case "setFg": // 颜色渐变
if (data.async) {
core.setFg(data.color, data.time);
core.setFlag('color', data.color||null);
core.setFlag('__color__', data.color||null);
this.doAction();
}
else {
core.setFg(data.color, data.time, function() {
core.setFlag('color', data.color||null);
core.setFlag('__color__', data.color||null);
core.events.doAction();
});
}
@ -715,8 +715,8 @@ events.prototype.doAction = function() {
case "setWeather": // 更改天气
core.setWeather(data.name, data.level);
if (core.isset(data.name))
core.setFlag('weather', [data.name, data.level]);
else core.setFlag('weather', null);
core.setFlag('__weather__', [data.name, data.level]);
else core.setFlag('__weather__', null);
this.doAction();
break;
case "openDoor": // 开一个门,包括暗墙
@ -774,6 +774,15 @@ events.prototype.doAction = function() {
this.doAction();
break;
}
case "insert":
{
var toX=core.calValue(data.loc[0]), toY=core.calValue(data.loc[1]);
var floorId = data.floorId || core.status.floorId;
var event = core.floors[floorId].events[toX+","+toY];
if (core.isset(event)) core.insertAction(event);
this.doAction();
break;
}
case "playSound":
if (!core.status.replay.replaying)
core.playSound(data.name);
@ -910,7 +919,7 @@ events.prototype.doAction = function() {
case "switch": // 条件选择
var key = core.calValue(data.condition)
for (var i = 0; i < data.caseList.length; i++) {
if (core.calValue(data.caseList[i].case) == key || core.calValue(data.caseList[i].case) == "default") {
if (data.caseList[i].case=="default" || core.calValue(data.caseList[i].case) == key) {
core.events.insertAction(data.caseList[i].action);
break;
}
@ -1336,7 +1345,7 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback
}
// 不存在事件时,更改画面色调
var color = core.getFlag('color', null);
var color = core.getFlag('__color__', null);
if (!core.isset(color) && core.isset(core.status.maps[floorId].color)) {
color = core.status.maps[floorId].color;
}
@ -1356,7 +1365,7 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback
}
// 更改天气
var weather = core.getFlag('weather', null);
var weather = core.getFlag('__weather__', null);
if (!core.isset(weather) && core.isset(core.status.maps[floorId].weather)) {
weather = core.status.maps[floorId].weather;
}
@ -1641,8 +1650,8 @@ events.prototype.openShop = function(shopId, needVisited) {
var choice = shop.choices[i];
var text = choice.text;
if (core.isset(choice.need))
text += ""+eval(choice.need)+use+""
choices.push(text);
text += ""+eval(choice.need)+use+"";
choices.push({"text": text, "color":shop.visited?null:"#999999"});
}
choices.push("离开");
core.ui.drawChoices(content, choices);
@ -1912,7 +1921,7 @@ events.prototype.uploadCurrent = function (username) {
formData.append('money', core.status.hero.money);
formData.append('experience', core.status.hero.experience);
formData.append('steps', core.status.hero.steps);
formData.append('seed', core.getFlag('seed'));
formData.append('seed', core.getFlag('__seed__'));
formData.append('totalTime', Math.floor(core.status.hero.statistics.totalTime/1000));
formData.append('route', core.encodeRoute(core.status.route));
formData.append('deler', 'current');

View File

@ -9,6 +9,10 @@ items.prototype.init = function () {
this.itemEffectTip = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.itemEffectTip;
this.useItemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.useItemEffect;
this.canUseItemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canUseItemEffect;
if (!core.isset(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip))
items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip = {};
this.canEquip = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip;
//delete(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a);
}
@ -162,13 +166,21 @@ items.prototype.loadEquip = function (equipId, callback) {
if (!core.isset(core.status.hero.equipment)) core.status.hero.equipment = [];
core.playSound('equip.mp3');
var loadEquip = core.material.items[equipId];
if (!core.isset(loadEquip)) {
if (core.isset(callback)) callback();
return;
}
var can = this.canEquip[equipId];
if (core.isset(can) && !eval(can)) {
core.drawTip("当前不可换上"+loadEquip.name);
if (core.isset(callback)) callback();
return;
}
core.playSound('equip.mp3');
var loadEquipType = loadEquip.equip.type;
var unloadEquipId = core.status.hero.equipment[loadEquipType];
@ -285,9 +297,19 @@ items.prototype.quickLoadEquip = function (index) {
for (var i=0;i<equipSize;i++) {
var v = current[i];
if (core.isset(v) && !core.hasItem(v) && !core.hasEquip(v)) {
core.drawTip("你当前没有"+((core.material.items[v]||{}).name||"未知装备")+",无法换装");
return;
}
if (core.isset(v)) {
if (!core.hasItem(v) && !core.hasEquip(v)) {
core.drawTip("你当前没有"+((core.material.items[v]||{}).name||"未知装备")+",无法换装");
return;
}
var can = this.canEquip[v];
if (core.isset(can) && !eval(can)) {
core.drawTip("当前不可换上"+((core.material.items[v]||{}).name||"未知装备"));
return;
}
}
}
// 快速换装
if (!core.isset(core.status.hero.equipment)) core.status.hero.equipment = [];

View File

@ -386,7 +386,7 @@ maps.prototype.getBgFgMapArray = function (floorId, name) {
var width = core.floors[floorId].width || 13;
var height = core.floors[floorId].height || 13;
if (core.isset(core.status[name+"maps"][floorId]))
if (main.mode!='editor' && core.isset(core.status[name+"maps"][floorId]))
return core.status[name+"maps"][floorId];
var arr = core.clone(core.floors[floorId][name+"map"] || []);
@ -409,18 +409,12 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
var width = core.floors[floorId].width || 13;
var height = core.floors[floorId].height || 13;
var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground";
var blockIcon = core.material.icons.terrains[groundId];
var blockImage = core.material.images.terrains;
if (!core.isset(core.status[name+"maps"]))
core.status[name+"maps"] = {};
var arr = this.getBgFgMapArray(floorId, name);
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
if (name=='bg')
canvas.drawImage(blockImage, 0, blockIcon * 32, 32, 32, x * 32, y * 32, 32, 32);
if (arr[y][x]>0) {
var block = core.maps.initBlock(x, y, arr[y][x]);
if (core.isset(block.event)) {
@ -454,9 +448,16 @@ maps.prototype.drawMap = function (mapName, callback) {
core.removeGlobalAnimate(null, null, true);
var drawBg = function(){
var width = core.floors[mapName].width || 13;
var height = core.floors[mapName].height || 13;
core.maps.drawBgFgMap(mapName, core.canvas.bg, "bg");
core.maps.drawBgFgMap(mapName, core.canvas.fg, "fg");
var groundId = (core.status.maps||core.floors)[mapName].defaultGround || "ground";
var blockIcon = core.material.icons.terrains[groundId];
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
core.canvas.bg.drawImage(core.material.images.terrains, 0, blockIcon * 32, 32, 32, x * 32, y * 32, 32, 32);
}
}
var images = [];
if (core.isset(core.status.maps[mapName].images)) {
@ -466,6 +467,7 @@ maps.prototype.drawMap = function (mapName, callback) {
}
}
images.forEach(function (t) {
if (typeof t == 'string') t = [0,0,t];
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2];
if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+mapName+"_"+dx+"_"+dy) &&
@ -496,7 +498,10 @@ maps.prototype.drawMap = function (mapName, callback) {
32*dx, 32*dy + image.height - 32, image.width, 32);
}
}
})
});
core.maps.drawBgFgMap(mapName, core.canvas.bg, "bg");
core.maps.drawBgFgMap(mapName, core.canvas.fg, "fg");
}
if (main.mode=='editor'){

View File

@ -283,6 +283,64 @@ ui.prototype.drawText = function (contents, callback) {
// core.drawTextBox(content);
}
ui.prototype.getTitleAndIcon = function (content) {
var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null;
var getInfo = function (v) {
["enemy48", "enemys", "npc48", "npcs"].forEach(function (x) {
if (core.isset(core.material.icons[x][v])) {
image = core.material.images[x];
icon = core.material.icons[x][v];
if (x.indexOf("48")>=0) {
iconHeight = 48;
animate = 4;
}
else {
iconHeight = 32;
animate = 2;
}
}
});
};
if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) {
var index = content.indexOf("]");
if (index>=0) {
var str=content.substring(2, index);
if (content.indexOf("\\t[")==0) str=content.substring(3, index);
content=content.substring(index+1);
var ss=str.split(",");
if (ss.length==1) {
id=ss[0];
if (id=='hero') name = core.status.hero.name;
else if (core.isset(core.material.enemys[id])) {
name = core.material.enemys[id].name;
getInfo(id);
}
else {
name=id;
id='npc';
}
}
else {
name=ss[0];
id = 'npc';
if (ss[1]=='hero') id = 'hero';
else getInfo(ss[1]);
}
}
}
return {
"content": content,
"id": id,
"name": name,
"image": image,
"icon": icon,
"iconHeight": iconHeight,
"animate": animate
};
}
////// 绘制一个对话框 //////
ui.prototype.drawTextBox = function(content, showAll) {
@ -294,78 +352,9 @@ ui.prototype.drawTextBox = function(content, showAll) {
core.status.event.interval = null;
// 获得name, image, icon
var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null;
if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) {
var index = content.indexOf("]");
if (index>=0) {
var str=content.substring(2, index);
if (content.indexOf("\\t[")==0) str=content.substring(3, index);
content=content.substring(index+1);
var ss=str.split(",");
if (ss.length==1) {
// id
id=ss[0];
if (id=='hero') {
name = core.status.hero.name;
}
else {
if (core.isset(core.material.enemys[id])) {
name = core.material.enemys[id].name;
if (core.isset(core.material.icons.enemy48[id])) {
image = core.material.images.enemy48;
icon = core.material.icons.enemy48[id];
iconHeight = 48;
animate=4;
}
else {
image = core.material.images.enemys;
icon = core.material.icons.enemys[id];
iconHeight = 32;
animate=2;
}
}
else {
name=id;
id='npc';
image=null;
icon=null;
}
}
}
else {
name=ss[0];
id = 'npc';
if (ss[1]=='hero') {
id = 'hero';
}
else if (core.isset(core.material.icons.npc48[ss[1]])) {
image = core.material.images.npc48;
icon = core.material.icons.npc48[ss[1]];
iconHeight = 48;
animate=4;
}
else if (core.isset(core.material.icons.npcs[ss[1]])){
image = core.material.images.npcs;
icon = core.material.icons.npcs[ss[1]];
iconHeight = 32;
animate=2;
}
else if (core.isset(core.material.icons.enemy48[ss[1]])) {
image = core.material.images.enemy48;
icon = core.material.icons.enemy48[ss[1]];
iconHeight = 48;
animate=4;
}
else if (core.isset(core.material.icons.enemys[ss[1]])) {
image = core.material.images.enemys;
icon = core.material.icons.enemys[ss[1]];
iconHeight = 32;
animate=2;
}
}
}
}
var info = this.getTitleAndIcon(content);
content = info.content;
var id=info.id, name=info.name, image=info.image, icon=info.icon, iconHeight=info.iconHeight, animate=info.animate;
// 获得位置信息
@ -415,16 +404,17 @@ ui.prototype.drawTextBox = function(content, showAll) {
// var contents = content.split('\n');
// var contents = core.splitLines('ui', content, );
var left=10, right=416-2*left;
var left=7, right=416-2*left;
var content_left = left + 25;
if (id=='hero' || core.isset(icon)) content_left=left+63;
var validWidth = right-(content_left-left)-13;
var font = textfont + 'px Verdana';
if (textAttribute.bold) font = "bold "+font;
var contents = core.splitLines("ui", content, validWidth, font);
var realContent = content.replace(/(\v|\\v)(\[.*?])?/g, "");
var height = 20 + (textfont+5)*(contents.length+1) + (id=='hero'?core.material.icons.hero.height-10:core.isset(name)?iconHeight-10:0);
var height = 20 + (textfont+5)*(core.splitLines("ui", realContent, validWidth, font).length+1)
+ (id=='hero'?core.material.icons.hero.height-10:core.isset(name)?iconHeight-10:0);
var xoffset = 6, yoffset = 22;
@ -434,20 +424,16 @@ ui.prototype.drawTextBox = function(content, showAll) {
top = parseInt((416 - height) / 2);
}
else if (position=='up') {
if (px==null || py==null) {
if (px==null || py==null)
top = 5 + offset;
}
else {
else
top = 32 * py - height - ydelta - yoffset;
}
}
else if (position=='down') {
if (px==null || py==null) {
if (px==null || py==null)
top = 416 - height - 5 - offset;
}
else {
else
top = 32 * py + 32 + yoffset;
}
}
// var left = 97, top = 64, right = 416 - 2 * left, bottom = 416 - 2 * top;
@ -459,11 +445,10 @@ ui.prototype.drawTextBox = function(content, showAll) {
core.setFillStyle('ui', core.arrayToRGB(textAttribute.background));
core.setStrokeStyle('ui', borderColor);
core.fillRect('ui', left, top, right, height);
core.strokeRect('ui', left - 1, top - 1, right + 1, height + 1, borderColor, 2);
var xoffset = 9;
var xoffset = 10;
// draw triangle
if (position=='up' && core.isset(px) && core.isset(py)) {
@ -534,32 +519,66 @@ ui.prototype.drawTextBox = function(content, showAll) {
}
}
var defaultColor = core.arrayToRGB(textAttribute.text);
var offsetx = content_left, offsety = content_top;
core.setFont('ui', font);
core.setAlpha('ui', textAttribute.text[3]);
core.setFillStyle('ui', defaultColor);
var index = 0, currcolor = defaultColor, changed = false;
var drawContent = function (content) {
core.clearMap("ui", content_left, content_top - 18, validWidth, top + height - content_top + 10);
core.setAlpha('ui', textAttribute.background[3]);
core.setFillStyle('ui', core.arrayToRGB(textAttribute.background));
core.fillRect("ui", content_left, content_top - 18, validWidth, top + height - content_top + 11);
core.setAlpha('ui', textAttribute.text[3]);
core.setFillStyle('ui', core.arrayToRGB(textAttribute.text));
var contents = core.splitLines("ui", content, validWidth, font);
for (var i=0;i<contents.length;i++) {
core.fillText('ui', contents[i], content_left, content_top + (textfont+5)*i, null, font);
var drawNext = function () {
if (index >= content.length) return false;
if (changed) {
core.setFillStyle('ui', currcolor);
changed = false;
}
}
// get next character
var char = content.charAt(index++);
// \n, \\n
if (char == '\n' || (char=='\\' && content.charAt(index)=='n')) {
offsetx = content_left;
offsety += textfont+5;
if (char=='\\') index++;
return drawNext();
}
// \v, \\v
if (char == '\v' || (char=='\\' && content.charAt(index)=='v')) {
if (char == '\\') index++;
changed = true;
// 检查是不是 []
var index2;
if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) {
// 变色
var str = content.substring(index+1, index2);
if (str=="") currcolor = defaultColor;
else currcolor = str;
index = index2+1;
}
else currcolor = defaultColor;
return drawNext();
}
// 检查是不是自动换行
var charwidth = core.canvas.ui.measureText(char).width;
if (offsetx + charwidth > content_left + validWidth) {
index--;
offsetx = content_left;
offsety += textfont+5;
return drawNext();
}
// 输出
core.fillText('ui', char, offsetx, offsety);
offsetx += charwidth;
return true;
};
if (showAll || textAttribute.time<=0 || core.status.event.id!='action') {
drawContent(content);
while (drawNext());
}
else {
var index=0;
core.status.event.interval = setInterval(function () {
drawContent(content.substring(0, ++index));
if (index==content.length) {
changed = true;
if (!drawNext()) {
clearInterval(core.status.event.interval);
core.status.event.interval = null;
}
@ -604,82 +623,13 @@ ui.prototype.drawChoices = function(content, choices) {
if (core.isset(content)) {
// 获得name, image, icon
if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) {
var index = content.indexOf("]");
if (index>=0) {
var str=content.substring(2, index);
if (content.indexOf("\\t[")==0) str=content.substring(3, index);
content=content.substring(index+1);
var ss=str.split(",");
if (ss.length==1) {
// id
id=ss[0];
if (id=='hero') {
name = core.status.hero.name;
}
else {
if (core.isset(core.material.enemys[id])) {
name = core.material.enemys[id].name;
if (core.isset(core.material.icons.enemy48[id])) {
image = core.material.images.enemy48;
icon = core.material.icons.enemy48[id];
iconHeight = 48;
animate=4;
}
else {
image = core.material.images.enemys;
icon = core.material.icons.enemys[id];
iconHeight = 32;
animate=2;
}
}
else {
name=id;
id='npc';
image=null;
icon=null;
}
}
}
else {
name=ss[0];
id = 'npc';
if (ss[1]=='hero') {
id = 'hero';
}
else if (core.isset(core.material.icons.npc48[ss[1]])) {
image = core.material.images.npc48;
icon = core.material.icons.npc48[ss[1]];
iconHeight = 48;
animate=4;
}
else if (core.isset(core.material.icons.npcs[ss[1]])){
image = core.material.images.npcs;
icon = core.material.icons.npcs[ss[1]];
iconHeight = 32;
animate=2;
}
else if (core.isset(core.material.icons.enemy48[ss[1]])) {
image = core.material.images.enemy48;
icon = core.material.icons.enemy48[ss[1]];
iconHeight = 48;
animate=4;
}
else if (core.isset(core.material.icons.enemys[ss[1]])) {
image = core.material.images.enemys;
icon = core.material.icons.enemys[ss[1]];
iconHeight = 32;
animate=2;
}
}
}
}
content = core.replaceText(content);
// 获得name, image, icon
var info = this.getTitleAndIcon(content);
content = core.replaceText(info.content);
id=info.id; name=info.name; image=info.image;
icon=info.icon; iconHeight=info.iconHeight; animate=info.animate;
if (id=='hero' || core.isset(icon))
content_left = left+60;
contents = core.splitLines('ui', content, width-(content_left-left)-10, 'bold 15px Verdana');
// content部分高度
@ -746,7 +696,8 @@ ui.prototype.drawChoices = function(content, choices) {
// 选项
core.canvas.ui.textAlign = "center";
for (var i = 0; i < choices.length; i++) {
core.fillText('ui', core.replaceText(choices[i].text || choices[i]), 208, choice_top + 32 * i, "#FFFFFF", "bold 17px Verdana");
core.setFillStyle('ui', choices[i].color || "#FFFFFF");
core.fillText('ui', core.replaceText(choices[i].text || choices[i]), 208, choice_top + 32 * i, null, "bold 17px Verdana");
}
if (choices.length>0) {
@ -846,7 +797,9 @@ ui.prototype.drawQuickShop = function () {
core.status.event.id = 'selectShop';
var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {return shopList[shopId].visited || !shopList[shopId].mustEnable});
var choices = keys.map(function (shopId) {return shopList[shopId].textInList});
var choices = keys.map(function (shopId) {
return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"};
});
choices.push("返回游戏");
this.drawChoices(null, choices);
@ -1618,6 +1571,13 @@ ui.prototype.drawMaps = function (index, x, y) {
core.fillText('ui', "上移地图 [W]", 208, 38, '#FFD700', '20px Arial');
core.fillText('ui', "下移地图 [S]", 208, 390);
core.strokeRect('ui', 2, 2, 28, 28);
core.fillText('ui', 'V', 16, 24);
core.strokeRect('ui', 2, 416-30, 28, 28);
core.fillText('ui', 'M', 16, 408);
core.strokeRect('ui', 416-30, 2, 28, 28);
core.fillText('ui', 'Z', 400, 24);
var top = 150;
core.fillText('ui', "左", 32, top);
core.fillText('ui', "移", 32, top+32);
@ -1635,6 +1595,7 @@ ui.prototype.drawMaps = function (index, x, y) {
core.fillText('ui', "退出 [ESC / ENTER]", 208, 208+8);
core.fillText('ui', "[X] 可查看怪物手册", 285, 208+40, null, '13px Arial');
return;
}
@ -1642,8 +1603,10 @@ ui.prototype.drawMaps = function (index, x, y) {
core.setOpacity('animate', 1);
var damage = (core.status.event.data||{}).damage, paint = (core.status.event.data||{}).paint;
var all = (core.status.event.data||{}).all;
if (core.isset(index.damage)) damage=index.damage;
if (core.isset(index.paint)) paint=index.paint;
if (core.isset(index.all)) all=index.all;
if (core.isset(index.index)) {
x=index.x;
@ -1661,7 +1624,7 @@ ui.prototype.drawMaps = function (index, x, y) {
if (y<6) y=6;
if (y>mh-7) y=mh-7;
core.status.event.data = {"index": index, "x": x, "y": y, "damage": damage, "paint": paint};
core.status.event.data = {"index": index, "x": x, "y": y, "damage": damage, "paint": paint, "all": all};
clearTimeout(core.interval.tipAnimate);
core.clearMap('ui');
@ -1683,7 +1646,7 @@ ui.prototype.drawMaps = function (index, x, y) {
core.setFont('data', '16px Arial');
var text = core.status.maps[floorId].title;
if (mw>13 || mh>13) text+=" ["+(x-6)+","+(y-6)+"]";
if (!all && (mw>13 || mh>13)) text+=" ["+(x-6)+","+(y-6)+"]";
var textX = 16, textY = 18, width = textX + core.canvas.data.measureText(text).width + 16, height = 42;
core.fillRect('data', 5, 5, width, height, '#000');
core.setOpacity('data', 0.4);
@ -2112,8 +2075,13 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
tempCanvas.canvas.height = tempHeight;
tempCanvas.clearRect(0, 0, tempWidth, tempHeight);
// background map
core.maps.drawBgFgMap(floorId, tempCanvas, "bg");
var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground";
var blockIcon = core.material.icons.terrains[groundId];
for (var i = 0; i < mw; i++) {
for (var j = 0; j < mh; j++) {
tempCanvas.drawImage(core.material.images.terrains, 0, blockIcon * 32, 32, 32, i * 32, j * 32, 32, 32);
}
}
// background image
var images = [];
@ -2124,6 +2092,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
}
}
images.forEach(function (t) {
if (typeof t == 'string') t = [0,0,t];
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2];
if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
@ -2136,6 +2105,10 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
32 * dx, 32 * dy + image.height - 32, image.width, 32);
}
})
// background map
core.maps.drawBgFgMap(floorId, tempCanvas, "bg");
// draw block
var mapArray = core.maps.getMapArray(blocks,mw,mh);
for (var b in blocks) {
@ -2171,8 +2144,6 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
var height = core.material.images.images[heroIcon].height/4;
tempCanvas.drawImage(core.material.images.images[heroIcon], icon.stop * 32, icon.loc * height, 32, height, 32*heroLoc.x, 32*heroLoc.y+32-height, 32, height);
}
// foreground map
core.maps.drawBgFgMap(floorId, tempCanvas, "fg");
// draw fg
images.forEach(function (t) {
@ -2189,6 +2160,9 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
}
})
// foreground map
core.maps.drawBgFgMap(floorId, tempCanvas, "fg");
// draw damage
if (core.status.event.id=='viewMaps' && (core.status.event.data||{}).damage)
core.control.updateDamage(floorId, tempCanvas);
@ -2198,9 +2172,28 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
if (!core.isset(centerX)) centerX=parseInt(mw/2);
if (!core.isset(centerY)) centerY=parseInt(mh/2);
var offsetX = core.clamp(centerX-6, 0, mw-13), offsetY = core.clamp(centerY-6, 0, mh-13);
// offsetX~offsetX+12; offsetY~offsetY+12
core.canvas[canvas].drawImage(tempCanvas.canvas, offsetX*32, offsetY*32, 416, 416, x, y, size, size);
// 如果是浏览地图的全模式
if (core.status.event.id=='viewMaps' && (core.status.event.data||{}).all) {
if (tempWidth<=tempHeight) {
var realHeight = 416, realWidth = realHeight * tempWidth / tempHeight;
var side = (416 - realWidth) / 2;
core.fillRect(canvas, 0, 0, side, realHeight, '#000000');
core.fillRect(canvas, 416-side, 0, side, realHeight);
core.canvas[canvas].drawImage(tempCanvas.canvas, 0, 0, tempWidth, tempHeight, side, 0, realWidth, realHeight);
}
else {
var realWidth = 416, realHeight = realWidth * tempHeight / tempWidth;
var side = (416 - realHeight) / 2;
core.fillRect(canvas, 0, 0, realWidth, side, '#000000');
core.fillRect(canvas, 0, 416-side, realWidth, side);
core.canvas[canvas].drawImage(tempCanvas.canvas, 0, 0, tempWidth, tempHeight, 0, side, realWidth, realHeight);
}
}
else {
var offsetX = core.clamp(centerX-6, 0, mw-13), offsetY = core.clamp(centerY-6, 0, mh-13);
// offsetX~offsetX+12; offsetY~offsetY+12
core.canvas[canvas].drawImage(tempCanvas.canvas, offsetX*32, offsetY*32, 416, 416, x, y, size, size);
}
}
ui.prototype.drawKeyBoard = function () {

View File

@ -13,7 +13,7 @@ utils.prototype.init = function () {
////// 将文字中的${和}(表达式)进行替换 //////
utils.prototype.replaceText = function (text) {
return text.replace(/\${([^}]+)}/g, function (word, value) {
return text.replace(/\${(.*?)}/g, function (word, value) {
return core.calValue(value);
});
}
@ -486,8 +486,8 @@ utils.prototype.__init_seed = function () {
rand = this.__next_rand(rand);
rand = this.__next_rand(rand);
rand = this.__next_rand(rand);
core.setFlag('seed', rand);
core.setFlag('rand', rand);
core.setFlag('__seed__', rand);
core.setFlag('__rand__', rand);
}
utils.prototype.__next_rand = function (_rand) {
@ -497,9 +497,9 @@ utils.prototype.__next_rand = function (_rand) {
}
utils.prototype.rand = function (num) {
var rand = core.getFlag('rand');
var rand = core.getFlag('__rand__');
rand = this.__next_rand(rand);
core.setFlag('rand', rand);
core.setFlag('__rand__', rand);
var ans = rand/2147483647;
if (core.isset(num) && num>0)
return Math.floor(ans*num);

11
main.js
View File

@ -2,7 +2,7 @@ function main() {
//------------------------ 用户修改内容 ------------------------//
this.version = "2.5"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.version = "2.5.1"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.useCompress = false; // 是否使用压缩文件
// 当你即将发布你的塔时请使用“JS代码压缩工具”将所有js代码进行压缩然后将这里的useCompress改为true。
@ -420,15 +420,6 @@ main.statusBar.image.fly.onclick = function () {
return;
}
// 浏览地图时
if (main.core.isPlaying() && (core.status.event||{}).id=='viewMaps') {
if (core.isset(core.status.event.data)) {
core.status.event.data.paint = !core.status.event.data.paint;
core.ui.drawMaps(core.status.event.data);
}
return;
}
if (main.core.isPlaying()) {
if (!main.core.flags.equipboxButton) {
main.core.useFly(true);

View File

@ -68,7 +68,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"firstData": {
"title": "魔塔样板",
"name": "template",
"version": "Ver 2.5",
"version": "Ver 2.5.1",
"floorId": "sample0",
"hero": {
"name": "阳光",

View File

@ -594,7 +594,7 @@ main.floors.sample1=
]
},
{
"case": "'default'",
"case": "default",
"action": [
{
"type": "comment",

View File

@ -1,4 +1,22 @@
HTML5魔塔样板V2.5
HTML5魔塔样板V2.5.1
新增事件type:insert可以插入另一个地点的事件执行公共事件
可以使用\v来控制剧情文本部分文字的颜色
新增事件type:switch多重分歧
绘制前景/背景层时淡化其他图层
追加素材的自动调整(如白底、不规范的素材)
浏览地图时:左上角/V开启显伤右上角/Z查看当前层大地图
允许在受到领域夹击等伤害后禁用快捷商店
升级的扣除模式,即不显示经验值,只显示升级的所需剩余值
装备增加可装备条件判定
选项界面可以使用1-9快速选择
未开启状态的快捷商店用灰色显示
修复不能在背景/前景层绘图的Bug
部分其他细节优化
-----------------------------------------------------------------------
HTML5魔塔样板V2.5
添加绘图模式支持;可以用户手动绘图和保存
内置主动技能:二倍斩的支持,可以仿照制作其他主动技能