Merge pull request #250 from ckcz123/v2.0

V2.5
This commit is contained in:
Zhang Chen 2018-10-31 23:40:01 +08:00 committed by GitHub
commit 3c3811c2e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 344 additions and 161 deletions

View File

@ -53,6 +53,31 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明
### 2018.10.31 V2.5
* [x] 添加绘图模式支持;可以用户手动绘图和保存
* [x] 内置主动技能:二倍斩的支持,可以仿照制作其他主动技能
* [x] 将按键处理移动到脚本编辑中
* [x] Alt+0\~9保存和读取当前套装
* [x] 图块属性的cannotOut和cannotIn控制可通行方向来造成悬崖效果
* [x] 支持动态Autotile自动元件仅在事件层有效
* [x] 允许快捷商店使用共用的times
* [x] 未启用的快捷商店可以隐藏或预览
* [x] 开始剧情startText可以执行任意事件
* [x] 对话窗口可以任意调节位置(上中下、距离顶部/底部的像素值)
* [x] 楼层转换界面可以设置背景图片文字颜色等
* [x] 数据统计进行分段描写,剑盾显示数值
* [x] 现在可以在事件编辑器中注释内容了
* [x] 存读档界面显示该存档的属性
* [x] F7键可以开启debug模式
* [x] R键可以从本地选取录像文件从头播放
* [x] 吸血属性的显伤增加^;仇恨怪显示仇恨伤害
* [x] 4键默认使用破冰稿或冰冻徽章或地震卷轴或上下楼器依次判断是否存在
* [x] 血瓶的道具化选项;黄宝石增加加点选项
* [x] 破炸飞增加默认音效
* [x] 修复单击瞬移的拖动打怪问题
* [x] 其他细节优化
### 2018.10.27 V2.4.4
* [x] tilesets可以设置图块属性如可通行状态

View File

@ -63,19 +63,20 @@ return code;
*/;
shopsub
: '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND
: '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '未开启状态则不显示在列表中' Bool BGNL? NewLine '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND
/* shopsub
tooltip : 全局商店,消耗填-1表示每个选项的消耗不同,正数表示消耗数值
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97
default : ["shop1","贪婪之神","blueShop","1F金币商店",false,null,"20+10*times*(times+1)","勇敢的武士啊, 给我${need}金币就可以:"]
default : ["shop1","贪婪之神","blueShop","1F金币商店",false,false,null,"20+10*times*(times+1)","勇敢的武士啊, 给我${need}金币就可以:"]
var code = {
'id': IdString_0,
'name': EvalString_0,
'icon': IdString_1,
'textInList': EvalString_1,
'commonTimes': Bool_0,
'mustEnable': Bool_1,
'use': ShopUse_List_0,
'need': EvalString_2,
'text': EvalString_3,
@ -182,6 +183,7 @@ return code;
action
: text_0_s
| text_1_s
| comment_s
| autoText_s
| setText_s
| tip_s
@ -282,6 +284,19 @@ var code = '"'+title+EvalString_1+EvalString_2+'",\n';
return code;
*/;
comment_s
: '添加注释' ':' EvalString Newline
/* comment_s
tooltip : comment添加一段会被游戏跳过的注释内容
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=comment%ef%bc%9a%e6%b7%bb%e5%8a%a0%e6%b3%a8%e9%87%8a
default : ["可以在这里写添加任何注释内容"]
colour : this.commentColor
var code = '{"type": "comment", "text": "'+EvalString_0+'"},\n';
return code;
*/;
autoText_s
: '自动剧情文本: 标题' EvalString? '图像' IdString? '对话框效果' EvalString? '时间' Int BGNL? EvalString Newline
@ -1575,6 +1590,7 @@ this.evisitor.printColor=70;
this.evisitor.dataColor=130;
this.evisitor.eventColor=220;
this.evisitor.soundColor=20;
this.evisitor.commentColor=285;
*/
/* Function_1
@ -1639,7 +1655,7 @@ ActionParser.prototype.parse = function (obj,type) {
choice.text,choice.need||'',text_effect,text_choices]);
}
return MotaActionBlocks['shopsub'].xmlText([
obj.id,obj.name,obj.icon,obj.textInList,obj.commonTimes,obj.use,obj.need,parser.EvalString(obj.text),text_choices,next
obj.id,obj.name,obj.icon,obj.textInList,obj.commonTimes,obj.mustEnable,obj.use,obj.need,parser.EvalString(obj.text),text_choices,next
]);
}
var next=null;
@ -1704,6 +1720,9 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['autoText_s'].xmlText([
'','','',data.time,this.EvalString(data.text),this.next]);
break;
case "comment": // 注释
this.next = MotaActionBlocks['comment_s'].xmlText([data.text,this.next]);
break;
case "setText": // 设置剧情文本的属性
var setTextfunc = function(a){return a?JSON.stringify(a).slice(1,-1):null;}
data.title=setTextfunc(data.title);

View File

@ -257,7 +257,7 @@ data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_type": "event",
"_event": "firstArrive",
"_range": "thiseval==null || thiseval instanceof Array",
"_data": "游戏开始前剧情。\n可以双击进入事件编辑器。\n如果无剧情直接留一个空数组即可。"
"_data": "游戏开始前剧情,可以执行任意自定义事件。\n双击进入事件编辑器。\n如果无剧情直接留一个空数组即可。"
},
"shops": {
"_leaf": true,
@ -606,6 +606,12 @@ data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_bool": "bool",
"_data": "是否允许瞬间移动"
},
"enableDisabledShop": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "是否允许查看未开启状态的快捷商店内容;如果此项为真,则对于未开启状态的商店允许查看其内容(但不能购买)"
},
}
}
}

View File

@ -390,7 +390,7 @@ editor.prototype.drawInitData = function (icons) {
if (img == 'autotile') {
var autotiles = images[img];
for (var im in autotiles) {
dc.drawImage(autotiles[im], nowx, nowy);
dc.drawImage(autotiles[im], 0, 0, 96, 128, nowx, nowy, 96, 128);
nowy += autotiles[im].height;
}
nowx += 3 * 32;

View File

@ -56,6 +56,7 @@ editor_blockly = function () {
'显示文字':[
MotaActionBlocks['text_0_s'].xmlText(),
MotaActionBlocks['text_1_s'].xmlText(),
MotaActionBlocks['comment_s'].xmlText(),
MotaActionFunctions.actionParser.parseList({"type": "choices", "text": "是否跳过剧情", "choices": [
{"text": "是", "action": []},
{"text": "否", "action": [
@ -484,6 +485,7 @@ document.getElementById('blocklyDiv').onmousewheel = function(e){
'text_0_s': 'EvalString_0',
'text_1_s': 'EvalString_2',
'autoText_s': 'EvalString_2',
'comment_s': 'EvalString_0',
'choices_s': 'EvalString_0',
'function_s': 'RawEvalString_0',
'shopsub': 'EvalString_3',

View File

@ -805,10 +805,18 @@ editor_mode = function (editor) {
var confirmAutotile = function () {
if (sprite.width != 96 || sprite.height != 128) {
printe("不合法的Autotile图片");
if (sprite.height==128 && sprite.width%96==0) {
printe("这里只能导入单帧的自动元件,多帧的动画请先导入单帧自动元件再同名替换素材即可。");
}
else {
printe("不合法的Autotile图片");
}
return;
}
var imgbase64 = source.toDataURL().split(',')[1];
var imgData = source_ctx.getImageData(0,0,sprite.width,sprite.height);
sprite_ctx.putImageData(imgData, 0, 0);
var imgbase64 = sprite.toDataURL().split(',')[1];
// Step 1: List文件名
fs.readdir('./project/images', function (err, data) {

View File

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

View File

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

View File

@ -1,6 +1,6 @@
# 元件说明
?> 目前版本**v2.4.4**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。

View File

@ -1,6 +1,6 @@
# 事件
?> 目前版本**v2.4.4**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
本章内将对样板所支持的事件进行介绍。
@ -327,6 +327,18 @@ time为可选项表示文字添加的速度。若此项设置为0将直接全
值得注意的是提示的text内容也是可以使用`${ }`来计算表达式的值的。
### comment添加注释
使用`{"type": "comment"}`可以添加一段注释
``` js
"x,y": [ // 实际执行的事件列表
{"type": "comment", "text": "这是一段会被跳过的注释内容"}
]
```
这个事件将在运行时被游戏跳过。
### setValue设置勇士的某个属性、道具个数或某个变量/Flag的值
`{"type": "setValue"}` 能修改勇士的某个属性、道具个数、或某个自定义变量或`Flag`的值。
@ -1587,6 +1599,8 @@ core.insertAction([
"icon": "blueShop", // 商店图标blueShop为蓝色商店pinkShop为粉色商店
"textInList": "1F金币商店", // 在快捷商店栏中显示的名称
"use": "money", // 商店所要使用的。只能是"money"或"experience"。
"commonTimes": true, // 是否使用全局次数
"mustEnable": true, // 如果未开启则不显示在状态栏中
"need": "20+10*times*(times+1)", // 商店需要的金币/经验数值可以是一个表达式以times作为参数计算。
// 这里用到的times为该商店的已经的访问次数。首次访问该商店时times的值为0。
// 上面的例子是50层商店的计算公式。你也可以写任意其他的计算公式只要以times作为参数即可。
@ -1634,6 +1648,8 @@ core.insertAction([
- icon 为商店的图标在icons.js的npcs中定义。如woman可代表一个商人。
- textInList 为其在快捷商店栏中显示的名称,如"3楼金币商店"等
- use 为消耗的类型是金币money还是经验experience
- commonTimes 是否使用全局次数如果为true则可以多个快捷商店共享相同的次数
- mustEnable 是否必须是只在开启状态才在列表显示如果此项为true则未开启的快捷商店不予显示
- need 是一个表达式,计算商店所需要用到的数值。
- 可以将times作为参数times为该商店已经访问过的次数第一次访问时times是0。
- 如果对于每个选项都需要不同的数值,这里设为"-1";可参见下面经验商店的例子。
@ -1873,8 +1889,6 @@ core.insertAction([
它将显示全塔属性中的startText内容可以修改成自己的提供战斗动画开启选择设置初始福利并正式开始游戏。
全塔属性的startText只能使用纯文本类型其他的事件均无效。
我们可以修改脚本编辑`setInitData`函数来对于不同难度分别设置初始属性。
其参数hard分为对应全塔属性中levelChooseButtons中的第二项分别对应不同的难度并会在游戏中传输在状态栏显示。

View File

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

View File

@ -1,6 +1,6 @@
# 个性化
?> 目前版本**v2.4.4**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.5**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。

View File

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

View File

@ -1028,6 +1028,18 @@ actions.prototype.clickShop = function(x,y) {
var topIndex = 6 - parseInt(choices.length / 2);
if (y>=topIndex && y<topIndex+choices.length) {
// 检查能否使用快捷商店
var reason = core.events.canUseQuickShop(shop.id);
if (core.isset(reason)) {
core.drawText(reason);
return false;
}
if (!shop.visited) {
if (shop.times==0) core.drawTip("该商店尚未开启");
else core.drawTip("该商店已失效");
return;
}
core.status.event.selection=y-topIndex;
var money = core.getStatus('money'), experience = core.getStatus('experience');
@ -1117,12 +1129,12 @@ actions.prototype.keyUpShop = function (keycode) {
////// 快捷商店界面时的点击操作 //////
actions.prototype.clickQuickShop = function(x, y) {
var shopList = core.status.shops, keys = Object.keys(shopList);
var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {return shopList[shopId].visited || !shopList[shopId].mustEnable});
if (x >= 5 && x <= 7) {
var topIndex = 6 - parseInt(keys.length / 2);
if (y>=topIndex && y<topIndex+keys.length) {
var reason = core.events.canUseQuickShop(keys[y - topIndex]);
if (core.isset(reason)) {
if (!core.flags.enableDisabledShop && core.isset(reason)) {
core.drawText(reason);
return;
}
@ -1154,7 +1166,7 @@ actions.prototype.keyUpQuickShop = function (keycode) {
core.ui.closePanel();
return;
}
var shopList = core.status.shops, keys = Object.keys(shopList);
var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) {return shopList[shopId].visited || !shopList[shopId].mustEnable});
if (keycode==13 || keycode==32 || keycode==67) {
var topIndex = 6 - parseInt(keys.length / 2);
this.clickQuickShop(6, topIndex+core.status.event.selection);
@ -1554,7 +1566,7 @@ actions.prototype.clickSL = function(x,y) {
if (x>=10 && x<=12 && y==12) {
core.ui.closePanel();
if (!core.isPlaying()) {
core.showStartAnimate();
core.showStartAnimate(true);
}
return;
}
@ -1666,7 +1678,7 @@ actions.prototype.keyUpSL = function (keycode) {
if (keycode==27 || keycode==88 || (core.status.event.id == 'save' && keycode==83) || (core.status.event.id == 'load' && keycode==68)) {
core.ui.closePanel();
if (!core.isPlaying()) {
core.showStartAnimate();
core.showStartAnimate(true);
}
return;
}
@ -1760,7 +1772,7 @@ actions.prototype.clickSwitchs = function (x,y) {
core.ui.drawSwitchs();
break;
case 7:
core.setFlag('bigmapMoveDirectly', !core.getFlag('bigmapMoveDirectly', false));
core.setFlag('clickMove', !core.getFlag('clickMove', true));
core.ui.drawSwitchs();
break;
case 8:
@ -2141,11 +2153,15 @@ actions.prototype.clickStorageRemove = function (x, y) {
localforage.clear(function () {
core.ui.closePanel();
core.drawText("\t[操作成功]你的所有存档已被清空。");
core.status.saveIndex = 1;
core.setLocalStorage('saveIndex2', 1);
});
}
else {
localStorage.clear();
core.drawText("\t[操作成功]你的所有存档已被清空。");
core.status.saveIndex = 1;
core.setLocalStorage('saveIndex2', 1);
}
break;
case 1:
@ -2158,6 +2174,8 @@ actions.prototype.clickStorageRemove = function (x, y) {
core.removeLocalForage("autoSave", function() {
core.ui.closePanel();
core.drawText("\t[操作成功]当前塔的存档已被清空。");
core.status.saveIndex = 1;
core.setLocalStorage('saveIndex2', 1);
});
}
else {
@ -2167,6 +2185,8 @@ actions.prototype.clickStorageRemove = function (x, y) {
}
core.removeLocalStorage("autoSave");
core.drawText("\t[操作成功]当前塔的存档已被清空。");
core.status.saveIndex = 1;
core.setLocalStorage('saveIndex2', 1);
}
break;
case 2:
@ -2216,15 +2236,8 @@ actions.prototype.clickReplay = function (x, y) {
case 0:
{
core.ui.closePanel();
var hard=core.status.hard, route=core.clone(core.status.route);
var seed = core.getFlag('seed');
core.resetStatus(core.firstData.hero, hard, core.firstData.floorId, null, core.initStatus.maps);
core.events.setInitData(hard);
core.setFlag('seed', seed);
core.setFlag('rand', seed);
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() {
core.startReplay(route);
}, true);
var hard=core.status.hard, seed = core.getFlag('seed');
core.startGame(hard, seed, core.clone(core.status.route));
break;
}
case 1:
@ -2290,6 +2303,15 @@ actions.prototype.clickKeyBoard = function (x, y) {
core.ui.closePanel();
core.keyUp(112+x-1); // F1-F12: 112-122
}
if (y==3 && x==12) {
var val = prompt();
if (val!=null) {
try {
eval(val);
}
catch (e) {}
}
}
if (y==4 && x>=1 && x<=10) {
core.ui.closePanel();
core.keyUp(x==10?48:48+x); // 1-9: 49-57; 0: 48
@ -2456,6 +2478,12 @@ actions.prototype.setPaintMode = function (mode) {
core.drawTip("进入"+(core.status.event.data.erase?"擦除":"绘图")+"模式");
}
actions.prototype.clearPaint = function () {
core.clearMap('route');
core.paint[core.status.floorId] = null;
core.drawTip("已清空绘图内容");
}
actions.prototype.savePaint = function () {
var data = {};
for (var floorId in core.paint) {
@ -2498,7 +2526,6 @@ actions.prototype.exitPaint = function () {
core.clearMap('route');
core.ui.closePanel();
core.statusBar.image.shop.style.opacity = 1;
core.statusBar.image.toolbox.style.opacity = 1;
core.updateStatusBar();
core.drawTip("退出绘图模式");
}

View File

@ -79,6 +79,13 @@ control.prototype.setRequestAnimationFrame = function () {
core.drawBlock(obj, obj.status);
}
if ((core.status.autotileAnimateObjs.blocks||[]).length>0) {
core.status.autotileAnimateObjs.status++;
core.status.autotileAnimateObjs.blocks.forEach(function (block) {
core.drawAutotile(core.canvas.event, core.status.autotileAnimateObjs.map, block, 32, 0, 0, core.status.autotileAnimateObjs.status);
})
}
core.animateFrame.globalTime = timestamp;
}
}
@ -201,7 +208,7 @@ control.prototype.setRequestAnimationFrame = function () {
}
////// 显示游戏开始界面 //////
control.prototype.showStartAnimate = function (callback) {
control.prototype.showStartAnimate = function (noAnimate, callback) {
core.dom.startPanel.style.opacity=1;
core.dom.startPanel.style.display="block";
core.dom.startTop.style.opacity=1;
@ -213,18 +220,27 @@ control.prototype.showStartAnimate = function (callback) {
core.clearStatus();
core.clearMap('all');
var opacityVal = 1;
var startAnimate = window.setInterval(function () {
opacityVal -= 0.03;
if (opacityVal < 0) {
clearInterval(startAnimate);
core.dom.startTop.style.display = 'none';
// core.playGame();
core.dom.startButtonGroup.style.display = 'block';
if (core.isset(callback)) callback();
}
core.dom.startTop.style.opacity = opacityVal;
}, 20);
if(noAnimate) {
core.dom.startTop.style.display = 'none';
// core.playGame();
core.dom.startButtonGroup.style.display = 'block';
if (core.isset(callback)) callback();
}
else {
var opacityVal = 1;
var startAnimate = window.setInterval(function () {
opacityVal -= 0.03;
if (opacityVal < 0) {
clearInterval(startAnimate);
core.dom.startTop.style.display = 'none';
// core.playGame();
core.dom.startButtonGroup.style.display = 'block';
if (core.isset(callback)) callback();
}
core.dom.startTop.style.opacity = opacityVal;
}, 20);
}
}
////// 隐藏游戏开始界面 //////
@ -318,35 +334,9 @@ control.prototype.resetStatus = function(hero, hard, floorId, route, maps, value
core.status.played = true;
}
////// 开始游戏 //////
control.prototype.startGame = function (hard, callback) {
console.log('开始游戏');
this.resetStatus(core.firstData.hero, hard, core.firstData.floorId, null, core.initStatus.maps);
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() {
if (core.isset(callback)) callback();
}, true);
setTimeout(function () {
// Upload
var formData = new FormData();
formData.append('type', 'people');
formData.append('name', core.firstData.name);
formData.append('version', core.firstData.version);
formData.append('platform', core.platform.isPC?"PC":core.platform.isAndroid?"Android":core.platform.isIOS?"iOS":"");
formData.append('hard', core.encodeBase64(hard));
formData.append('hardCode', core.getFlag('hard', 0));
formData.append('base64', 1);
core.utils.http("POST", "/games/upload.php", formData);
})
}
////// 重新开始游戏;此函数将回到标题页面 //////
control.prototype.restart = function() {
this.showStartAnimate();
this.showStartAnimate(true);
if (core.bgms.length>0)
core.playBgm(core.bgms[0]);
}
@ -473,7 +463,7 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) {
// 单击瞬间移动
if (core.status.heroStop) {
if (core.control.tryMoveDirectly(destX, destY))
if (stepPostfix.length<=1 && core.getFlag('clickMove', true) && core.control.tryMoveDirectly(destX, destY))
return;
}
@ -1041,7 +1031,7 @@ control.prototype.updateViewport = function() {
////// 绘制勇士 //////
control.prototype.drawHero = function (direction, x, y, status, offset) {
if (!core.isPlaying()) return;
if (!core.isPlaying() || core.status.isStarting) return;
var scan = {
'up': {'x': 0, 'y': -1},
@ -1679,14 +1669,7 @@ control.prototype.chooseReplayFile = function () {
return;
}
core.dom.startPanel.style.display = 'none';
core.resetStatus(core.firstData.hero, obj.hard, core.firstData.floorId, null, core.initStatus.maps);
core.setFlag('seed', obj.seed);
core.setFlag('rand', obj.seed);
core.events.setInitData(obj.hard);
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() {
core.startReplay(core.decodeRoute(obj.route));
}, true);
core.startGame(obj.hard, obj.seed, core.decode(obj.route));
}, function () {
})
@ -2263,15 +2246,7 @@ control.prototype.doSL = function (id, type) {
if (data.version != core.firstData.version) {
// core.drawTip("存档版本不匹配");
if (confirm("存档版本不匹配!\n你想回放此存档的录像吗\n可以随时停止录像播放以继续游戏。")) {
core.dom.startPanel.style.display = 'none';
var seed = data.hero.flags.seed;
core.resetStatus(core.firstData.hero, data.hard, core.firstData.floorId, null, core.initStatus.maps);
core.events.setInitData(data.hard);
core.setFlag('seed', seed);
core.setFlag('rand', seed);
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() {
core.startReplay(core.decodeRoute(data.route));
}, true);
core.startGame(data.hard, data.hero.flags.seed, core.decodeRoute(data.route));
}
return;
}

View File

@ -164,6 +164,7 @@ function core() {
// 动画
'globalAnimateObjs': [],
'boxAnimateObjs': [],
'autotileAnimateObjs': {},
'animateObjs': [],
};
this.status = {};
@ -331,8 +332,8 @@ core.prototype.setRequestAnimationFrame = function () {
}
////// 显示游戏开始界面 //////
core.prototype.showStartAnimate = function (callback) {
core.control.showStartAnimate(callback);
core.prototype.showStartAnimate = function (noAnimate, callback) {
core.control.showStartAnimate(noAnimate, callback);
}
////// 隐藏游戏开始界面 //////
@ -356,8 +357,8 @@ core.prototype.resetStatus = function(hero, hard, floorId, route, maps, values)
}
////// 开始游戏 //////
core.prototype.startGame = function (hard, callback) {
core.control.startGame(hard, callback);
core.prototype.startGame = function (hard, seed, route, callback) {
core.events.startGame(hard, seed, route, callback);
}
////// 重新开始游戏;此函数将回到标题页面 //////
@ -661,8 +662,8 @@ core.prototype.drawMap = function (mapName, callback) {
}
////// 绘制Autotile //////
core.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top){
core.maps.drawAutotile(ctx, mapArr, block, size, left, top);
core.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top, status){
core.maps.drawAutotile(ctx, mapArr, block, size, left, top, status);
}
////// 某个点是否不可通行 //////

View File

@ -76,38 +76,83 @@ events.prototype.initGame = function () {
}
////// 游戏开始事件 //////
events.prototype.startGame = function (hard) {
events.prototype.startGame = function (hard, seed, route, callback) {
if (core.status.isStarting) return;
core.status.isStarting = true;
core.hideStartAnimate(function() {
core.drawText(core.clone(core.firstData.startText), function() {
if (core.flags.showBattleAnimateConfirm) { // 是否提供“开启战斗动画”的选择项
var start = function () {
console.log('开始游戏');
core.resetStatus(core.firstData.hero, hard, core.firstData.floorId, null, core.initStatus.maps);
core.status.isStarting = true;
if (core.isset(seed)) {
core.setFlag('seed', seed);
core.setFlag('rand', seed);
}
else core.utils.__init_seed();
core.events.setInitData(hard);
core.clearMap('all');
core.clearStatusBar();
var post_start = function () {
core.status.isStarting = false;
core.changeFloor(core.status.floorId, null, core.status.hero.loc, null, function() {
if (core.isset(callback)) callback();
}, true);
setTimeout(function () {
// Upload
var formData = new FormData();
formData.append('type', 'people');
formData.append('name', core.firstData.name);
formData.append('version', core.firstData.version);
formData.append('platform', core.platform.isPC?"PC":core.platform.isAndroid?"Android":core.platform.isIOS?"iOS":"");
formData.append('hard', core.encodeBase64(hard));
formData.append('hardCode', core.getFlag('hard', 0));
formData.append('base64', 1);
core.utils.http("POST", "/games/upload.php", formData);
})
}
core.insertAction(core.clone(core.firstData.startText), null, null, function() {
if (!core.status.replay.replaying && core.flags.showBattleAnimateConfirm) { // 是否提供“开启战斗动画”的选择项
core.status.event.selection = core.flags.battleAnimate ? 0 : 1;
core.ui.drawConfirmBox("你想开启战斗动画吗?\n之后可以在菜单栏中开启或关闭。\n强烈建议新手开启此项", function () {
core.data.flags.battleAnimate = true;
core.flags.battleAnimate = true;
core.setLocalStorage('battleAnimate', true);
core.startGame(hard);
core.utils.__init_seed();
core.events.setInitData(hard);
post_start();
}, function () {
core.data.flags.battleAnimate = false;
core.flags.battleAnimate = false;
core.setLocalStorage('battleAnimate', false);
core.startGame(hard);
core.utils.__init_seed();
core.events.setInitData(hard);
post_start();
});
}
else {
core.startGame(hard);
core.utils.__init_seed();
core.events.setInitData(hard);
post_start();
}
});
})
if (core.isset(route)) {
core.startReplay(route);
}
}
if (core.isset(route)) {
core.dom.startPanel.style.display = 'none';
start();
}
else {
core.hideStartAnimate(function() {
start();
})
}
}
////// 不同难度分别设置初始属性 //////
@ -347,6 +392,9 @@ events.prototype.doAction = function() {
}, data.time || 3000);
}
break;
case "comment":
this.doAction();
break;
case "setText": // 设置文本状态
["position", "offset", "bold", "titlefont", "textfont", "time"].forEach(function (t) {
if (core.isset(data[t])) core.status.textAttribute[t]=data[t];
@ -589,11 +637,8 @@ events.prototype.doAction = function() {
this.doAction();
break;
case "showImage": // 显示图片
if (core.isset(data.loc) && core.isset(core.material.images.images[data.name])) {
core.canvas.image.drawImage(core.material.images.images[data.name],
core.calValue(data.loc[0]), core.calValue(data.loc[1]));
}
else core.clearMap('image');
if (!core.isset(data.loc)) data.loc=[];
core.events.showImage(data.name, data.loc[0], data.loc[1]);
this.doAction();
break;
case "animateImage": // 淡入淡出图片
@ -1361,6 +1406,14 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback
}, 25);
}
////// 绘制图片 //////
events.prototype.showImage = function (name, x, y) {
if (core.isset(name) && core.isset(x) && core.isset(y) && core.isset(core.material.images.images[name])) {
core.canvas.image.drawImage(core.material.images.images[name], x, y);
}
else core.clearMap('image');
}
////// 图片淡入/淡出 //////
events.prototype.animateImage = function (type, image, loc, time, keep, callback) {
time = time||0;
@ -1535,12 +1588,18 @@ events.prototype.openShop = function(shopId, needVisited) {
if (shop.commonTimes)
shop.times = core.getFlag('commonTimes', 0);
shop.visited = shop.visited || false;
if (needVisited && !shop.visited) {
if (shop.times==0) core.drawTip("该商店尚未开启");
else core.drawTip("该商店已失效");
return;
if (!core.flags.enableDisabledShop) {
if (shop.times==0) core.drawTip("该商店尚未开启");
else core.drawTip("该商店已失效");
return;
}
else {
core.drawTip("该商店尚未开启,只能浏览不可使用");
}
}
shop.visited = true;
else shop.visited = true;
var selection = core.status.event.selection;
var actions = [];

View File

@ -310,12 +310,6 @@ maps.prototype.canMoveDirectly = function (destX,destY) {
var fromX = core.getHeroLoc('x'), fromY = core.getHeroLoc('y');
if (fromX==destX&&fromY==destY) return 0;
// 大地图且会改变左上角坐标,不能
var sx = core.clamp(fromX-6,0,core.bigmap.width-13), sy = core.clamp(fromY-6,0,core.bigmap.height-13),
ex = core.clamp(destX-6,0,core.bigmap.width-13), ey = core.clamp(destY-6,0,core.bigmap.height-13);
if (!core.hasFlag('bigmapMoveDirectly') && (sx!=ex || sy!=ey)) return -1;
// 无视起点事件
var nowBlockId = core.getBlockId(fromX, fromY);
if ((nowBlockId!=null&&nowBlockId!='upFloor'&&nowBlockId!='downFloor'&&nowBlockId!='portal'
@ -458,6 +452,7 @@ maps.prototype.drawMap = function (mapName, callback) {
mapName = mapName || core.status.floorId;
core.clearMap('all');
core.removeGlobalAnimate(null, null, true);
var drawBg = function(){
core.maps.drawBgFgMap(mapName, core.canvas.bg, "bg");
@ -520,6 +515,8 @@ maps.prototype.drawMap = function (mapName, callback) {
core.status.floorId = mapName;
core.status.thisMap = core.status.maps[mapName];
var drawEvent = function(){
core.status.autotileAnimateObjs = {"status": 0, "blocks": [], "map": null};
var mapData = core.status.maps[core.status.floorId];
var mapBlocks = mapData.blocks;
@ -530,6 +527,7 @@ maps.prototype.drawMap = function (mapName, callback) {
if (core.isset(block.event) && !block.disable) {
if (block.event.cls == 'autotile') {
core.drawAutotile(core.canvas.event, mapArray, block, 32, 0, 0);
core.status.autotileAnimateObjs.blocks.push(core.clone(block));
}
else {
core.drawBlock(block);
@ -537,6 +535,7 @@ maps.prototype.drawMap = function (mapName, callback) {
}
}
}
core.status.autotileAnimateObjs.map = core.clone(mapArray);
}
if (main.mode=='editor'){
@ -561,7 +560,7 @@ maps.prototype.drawMap = function (mapName, callback) {
}
////// 绘制Autotile //////
maps.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top){
maps.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top, status){
var indexArrs = [ //16种组合的图块索引数组; // 将autotile分割成48块16*16的小块; 数组索引即对应各个小块
// +----+----+----+----+----+----+
[10, 9, 4, 3 ], //0 bin:0000 | 1 | 2 | 3 | 4 | 5 | 6 |
@ -584,7 +583,9 @@ maps.prototype.drawAutotile = function(ctx, mapArr, block, size, left, top){
var drawBlockByIndex = function(ctx, dx, dy, autotileImg, index, size){ //index为autotile的图块索引1-48
var sx = 16*((index-1)%6), sy = 16*(~~((index-1)/6));
ctx.drawImage(autotileImg, sx, sy, 16, 16, dx, dy, size/2, size/2);
status = status || 0;
status %= parseInt(autotileImg.width/96);
ctx.drawImage(autotileImg, sx + 96*status, sy, 16, 16, dx, dy, size/2, size/2);
}
var getAutotileAroundId = function(currId, x, y) {
if(x<0 || y<0 || x>=mapArr[0].length || y>=mapArr.length) return 1;
@ -1195,15 +1196,18 @@ maps.prototype.removeGlobalAnimate = function (x, y, all) {
if (all) {
core.status.globalAnimateObjs = [];
core.status.autotileAnimateObjs = {};
return;
}
for (var t = 0; t < core.status.globalAnimateObjs.length; t++) {
if (core.status.globalAnimateObjs[t].x == x && core.status.globalAnimateObjs[t].y == y) {
core.status.globalAnimateObjs.splice(t, 1);
return;
}
core.status.globalAnimateObjs = core.status.globalAnimateObjs.filter(function (block) {return block.x!=x || block.y!=y;});
// 检查Autotile
if (core.isset(core.status.autotileAnimateObjs.blocks)) {
core.status.autotileAnimateObjs.blocks = core.status.autotileAnimateObjs.blocks.filter(function (block) {return block.x!=x || block.y!=y;});
core.status.autotileAnimateObjs.map[y][x] = 0;
}
}
////// 设置全局动画的显示效果 //////
@ -1219,6 +1223,9 @@ maps.prototype.syncGlobalAnimate = function () {
core.status.globalAnimateObjs.forEach(function (t) {
t.status=0;
})
if (core.isset(core.status.autotileAnimateObjs.status)) {
core.status.autotileAnimateObjs.status = 0;
}
}
////// 绘制UI层的box动画 //////

View File

@ -823,7 +823,7 @@ ui.prototype.drawSwitchs = function() {
"临界显伤: "+(core.flags.displayCritical ? "[ON]" : "[OFF]"),
"领域显伤: "+(core.flags.displayExtraDamage ? "[ON]" : "[OFF]"),
"新版存档: "+(core.platform.useLocalForage ? "[ON]":"[OFF]"),
"大地图瞬移:"+(core.hasFlag('bigmapMoveDirectly') ? "[ON]":"[OFF]"),
"单击瞬移: "+(core.getFlag('clickMove', true) ? "[ON]":"[OFF]"),
"查看工程",
"下载离线版本",
"返回主菜单"
@ -845,12 +845,9 @@ ui.prototype.drawQuickShop = function () {
core.status.event.id = 'selectShop';
var shopList = core.status.shops, keys = Object.keys(shopList);
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 = [];
for (var i=0;i<keys.length;i++) {
choices.push(shopList[keys[i]].textInList);
}
choices.push("返回游戏");
this.drawChoices(null, choices);
}
@ -2048,27 +2045,35 @@ ui.prototype.drawSLPanel = function(index, refresh) {
core.status.event.ui[i] = data;
var id=5*page+i;
if (i<3) {
core.fillText('ui', i==0?"自动存档":name+id, (2*i+1)*u, 35, '#FFFFFF', "bold 17px Verdana");
core.strokeRect('ui', (2*i+1)*u-size/2, 50, size, size, i==offset?strokeColor:'#FFFFFF', i==offset?6:2);
core.fillText('ui', i==0?"自动存档":name+id, (2*i+1)*u, 30, '#FFFFFF', "bold 17px Verdana");
core.strokeRect('ui', (2*i+1)*u-size/2, 45, size, size, i==offset?strokeColor:'#FFFFFF', i==offset?6:2);
if (core.isset(data) && core.isset(data.floorId)) {
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i+1)*u-size/2, 50, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
core.fillText('ui', core.formatDate(new Date(data.time)), (2*i+1)*u, 65+size, data.hero.flags.consoleOpened?'#FF6A6A':'#FFFFFF', '10px Verdana');
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i+1)*u-size/2, 45, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
var v = core.formatBigNumber(data.hero.hp)+"/"+core.formatBigNumber(data.hero.atk)+"/"+core.formatBigNumber(data.hero.def);
var v2 = "/"+core.formatBigNumber(data.hero.mdef);
if (v.length+v2.length<=21) v+=v2;
core.fillText('ui', v, (2*i+1)*u, 60+size, '#FFD700', '10px Verdana');
core.fillText('ui', core.formatDate(new Date(data.time)), (2*i+1)*u, 73+size, data.hero.flags.consoleOpened?'#FF6A6A':'#FFFFFF');
}
else {
core.fillRect('ui', (2*i+1)*u-size/2, 50, size, size, '#333333', 2);
core.fillText('ui', '空', (2*i+1)*u, 117, '#FFFFFF', 'bold 30px Verdana');
core.fillRect('ui', (2*i+1)*u-size/2, 45, size, size, '#333333', 2);
core.fillText('ui', '空', (2*i+1)*u, 112, '#FFFFFF', 'bold 30px Verdana');
}
}
else {
core.fillText('ui', name+id, (2*i-5)*u, 230, '#FFFFFF', "bold 17px Verdana");
core.strokeRect('ui', (2*i-5)*u-size/2, 245, size, size, i==offset?strokeColor:'#FFFFFF', i==offset?6:2);
core.fillText('ui', name+id, (2*i-5)*u, 218, '#FFFFFF', "bold 17px Verdana");
core.strokeRect('ui', (2*i-5)*u-size/2, 233, size, size, i==offset?strokeColor:'#FFFFFF', i==offset?6:2);
if (core.isset(data) && core.isset(data.floorId)) {
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i-5)*u-size/2, 245, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
core.fillText('ui', core.formatDate(new Date(data.time)), (2*i-5)*u, 260+size, data.hero.flags.consoleOpened?'#FF6A6A':'#FFFFFF', '10px Verdana');
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i-5)*u-size/2, 233, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
var v = core.formatBigNumber(data.hero.hp)+"/"+core.formatBigNumber(data.hero.atk)+"/"+core.formatBigNumber(data.hero.def);
var v2 = "/"+core.formatBigNumber(data.hero.mdef);
if (v.length+v2.length<=21) v+=v2;
core.fillText('ui', v, (2*i-5)*u, 248+size, '#FFD700', '10px Verdana');
core.fillText('ui', core.formatDate(new Date(data.time)), (2*i-5)*u, 261+size, data.hero.flags.consoleOpened?'#FF6A6A':'#FFFFFF', '10px Verdana');
}
else {
core.fillRect('ui', (2*i-5)*u-size/2, 245, size, size, '#333333', 2);
core.fillText('ui', '空', (2*i-5)*u, 245+70, '#FFFFFF', 'bold 30px Verdana');
core.fillRect('ui', (2*i-5)*u-size/2, 233, size, size, '#333333', 2);
core.fillText('ui', '空', (2*i-5)*u, 297, '#FFFFFF', 'bold 30px Verdana');
}
}
};
@ -2323,7 +2328,7 @@ ui.prototype.drawStatistics = function () {
}
else {
// 装备
if (id.indexOf('sword')==0 || id.indexOf('shield')==0) {
if (cls[id]=='equips') {
var values = core.material.items[id].equip||{};
atk = values.atk||0;
def = values.def||0;
@ -2331,7 +2336,7 @@ ui.prototype.drawStatistics = function () {
}
}
if (id.indexOf('sword')==0 || id.indexOf('shield')==0) {
if (id.indexOf('sword')==0 || id.indexOf('shield')==0 || cls[id]=='equips') {
var t = "";
if (atk>0) t+=atk+"攻";
if (def>0) t+=def+"防";
@ -2460,10 +2465,10 @@ ui.prototype.drawPaint = function () {
core.setStrokeStyle('route', '#FF0000');
core.statusBar.image.shop.style.opacity = 0;
core.statusBar.image.toolbox.style.opacity = 0;
core.statusBar.image.book.src = core.statusBar.icons.paint.src;
core.statusBar.image.fly.src = core.statusBar.icons.erase.src;
core.statusBar.image.toolbox.src = core.statusBar.icons.delete.src;
core.statusBar.image.settings.src = core.statusBar.icons.exit.src;
core.statusBar.image.book.style.opacity = 1;
core.statusBar.image.fly.style.opacity = 1;

View File

@ -20,6 +20,7 @@ utils.prototype.replaceText = function (text) {
////// 计算表达式的值 //////
utils.prototype.calValue = function (value) {
if (!core.isset(value)) return value;
if (typeof value == 'number') {
return value;
}

10
main.js
View File

@ -2,7 +2,7 @@ function main() {
//------------------------ 用户修改内容 ------------------------//
this.version = "2.4.4"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.version = "2.5"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.useCompress = false; // 是否使用压缩文件
// 当你即将发布你的塔时请使用“JS代码压缩工具”将所有js代码进行压缩然后将这里的useCompress改为true。
@ -130,7 +130,8 @@ function main() {
'skill': 25,
'paint': 26,
'erase': 27,
'exit': 28,
'delete': 28,
'exit': 29,
},
'floor': document.getElementById('floor'),
'name': document.getElementById('name'),
@ -451,6 +452,11 @@ main.statusBar.image.toolbox.onclick = function () {
return;
}
if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
core.actions.clearPaint();
return;
}
if (main.core.isPlaying()) {
main.core.openToolbox(core.status.event.id != 'equipbox');
}

View File

@ -68,7 +68,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"firstData": {
"title": "魔塔样板",
"name": "template",
"version": "Ver 2.4.4",
"version": "Ver 2.5",
"floorId": "sample0",
"hero": {
"name": "阳光",
@ -231,6 +231,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"potionWhileRouting": false,
"portalWithoutTrigger": true,
"canGoDeadZone": false,
"enableMoveDirectly": true
"enableMoveDirectly": true,
"enableDisabledShop": true
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,4 +1,31 @@
HTML5魔塔样板V2.4.4
HTML5魔塔样板V2.5
添加绘图模式支持;可以用户手动绘图和保存
内置主动技能:二倍斩的支持,可以仿照制作其他主动技能
将按键处理移动到脚本编辑中
Alt+0\~9保存和读取当前套装
图块属性的cannotOut和cannotIn控制可通行方向来造成悬崖效果
支持动态Autotile自动元件仅在事件层有效
允许快捷商店使用共用的times
未启用的快捷商店可以隐藏或预览
开始剧情startText可以执行任意事件
对话窗口可以任意调节位置(上中下、距离顶部/底部的像素值)
楼层转换界面可以设置背景图片文字颜色等
数据统计进行分段描写,剑盾显示数值
现在可以在事件编辑器中注释内容了
存读档界面显示该存档的属性
F7键可以开启debug模式
R键可以从本地选取录像文件从头播放
吸血属性的显伤增加^;仇恨怪显示仇恨伤害
4键默认使用破冰稿或冰冻徽章或地震卷轴或上下楼器等等
血瓶的道具化选项;黄宝石增加加点选项
破炸飞增加默认音效
修复单击瞬移的拖动打怪问题
其他细节优化
-----------------------------------------------------------------------
HTML5魔塔样板V2.4.4
tilesets可以设置图块属性如可通行状态
追加素材时可以更改图片色调