Merge pull request #322 from ckcz123/v2.0

V2.0
This commit is contained in:
Zhang Chen 2019-02-26 02:15:46 +08:00 committed by GitHub
commit 9e02f57cb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1030 additions and 909 deletions

View File

@ -59,9 +59,11 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
* [x] 存档方式优化,大幅降低单个存档的占用空间
* [x] 脚本编辑器增加代码格式化的选项
* [x] 事件和脚本编辑器中Ctrl+S可以进行保存
* [x] 显示选择项提供颜色控制
* [x] 事件的移动勇士增加前进和后退两个操作
* [x] 事件编辑器的下拉框增加滚动条
* [x] 通关后将询问是否进行评分
* [x] 录像播放失败后可以回退到上个节点
* [x] 修复已知的所有Bug大量细节优化
### 2019.2.4 V2.5.4

View File

@ -176,6 +176,7 @@ core.openDoor(id, x, y, needKey, callback) [异步]
尝试开门操作。id为目标点的IDx和y为坐标needKey表示是否需要使用钥匙callback为开门完毕后的回调函数。
id可为null代表使用地图上的值。
例如core.openDoor('yellowDoor', 10, 3, false, function() {console.log("1")})
此函数返回true代表成功开门并将执行callback回调返回false代表无法开门且不会执行回调函数。
core.battle(id, x, y, force, callback) [异步]

View File

@ -1529,6 +1529,7 @@ choices是一个很麻烦的事件它将弹出一个列表供用户进行选
``` js
"x,y": [ // 实际执行的事件列表
{"type": "choices", "text": "...", // 提示文字
"color": [255,0,0,1], // 颜色
"choices": [
{"text": "选项1文字", "action": [
// 选项1执行的事件
@ -1544,11 +1545,15 @@ choices是一个很麻烦的事件它将弹出一个列表供用户进行选
]
```
其中最外面的"text"为提示文本。同上面的`"type":"text"`一样,支持`${}`表达式的计算,和\t显示名称、图标。text可省略如果省略将不显示任何提示文字。
其中最外面的"text"为提示文本。同上面的`"type":"text"`一样,支持`${}`表达式的计算,和\t显示名称、图标\r更改颜色。text可省略如果省略将不显示任何提示文字。
choices为一个数组其中每一项都是一个选项列表。
每一项的text为显示在屏幕上的选项名也支持${}的表达式计算,但不支持`\t[]`的显示。action为当用户选择了该选项时将执行的事件。
每一项的text为显示在屏幕上的选项名也支持${}的表达式计算,但不支持`\t[]`的显示。
action为当用户选择了该选项时将执行的事件。
color为可选的可以是一个字符串#FF0000或者一个RGBA数组[255,0,0,1])。
选项可以有任意多个但一般不要超过6个否则屏幕可能塞不下。
@ -1577,7 +1582,7 @@ choices为一个数组其中每一项都是一个选项列表。
"false": [ // 否则,显示选择页面
{"type": "choices", "text": "\t[老人,woman]少年,你需要钥匙吗?\n我这里有大把的", // 显示一个卖钥匙的选择页面
"choices": [ // 提供四个选项:黄钥匙、蓝钥匙、红钥匙、离开。前三个选项显示需要的金额
{"text": "黄钥匙(${9+flag:woman_times}金币)", "action": [ // 第一个选项,黄钥匙
{"text": "黄钥匙(${9+flag:woman_times}金币)", "color": [255,255,0,1], "action": [ // 第一个选项,黄钥匙
// 选择该选项的执行内容
{"type": "if", "condition": "status:money>=9+flag:woman_times", // 条件判断:钱够不够
"true": [
@ -1591,10 +1596,10 @@ choices为一个数组其中每一项都是一个选项列表。
]
}
]},
{"text": "蓝钥匙(${18+2*flag:woman_times}金币)", "action": [ // 第二个选项:蓝钥匙
{"text": "蓝钥匙(${18+2*flag:woman_times}金币)", "color": [0,0,255,1], "action": [ // 第二个选项:蓝钥匙
// 逻辑和上面黄钥匙完全相同,略
]},
{"text": "红钥匙(${36+4*flag:woman_times}金币)", "action": [ // 第三个选项:红钥匙
{"text": "红钥匙(${36+4*flag:woman_times}金币)", "color": [255,0,0,1], "action": [ // 第三个选项:红钥匙
// 逻辑和上面黄钥匙完全相同,略
]},
{"text": "离开", "action": [ // 第四个选项:离开

View File

@ -1528,15 +1528,22 @@ return code;
*/;
choicesContext
: '子选项' EvalString BGNL? Newline action+
: '子选项' EvalString '颜色' EvalString? Colour BGNL? Newline action+
/* choicesContext
tooltip : 选项的选择
helpUrl : https://h5mota.com/games/template/docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9
default : ["提示文字:红钥匙"]
default : ["提示文字:红钥匙",""]
colour : this.subColor
var code = '{"text": "'+EvalString_0+'", "action": [\n'+action_0+']},\n';
if (EvalString_1) {
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
if (colorRe.test(EvalString_1))
EvalString_1 = ', "color": ['+EvalString_1+']';
else
EvalString_1 = ', "color": "'+EvalString_1+'"';
}
var code = '{"text": "'+EvalString_0+'"'+EvalString_1+', "action": [\n'+action_0+']},\n';
return code;
*/;
@ -2095,7 +2102,9 @@ ActionParser.prototype.parseAction = function() {
if (!/^\w+\.png$/.test(data.background))
data.background=setTextfunc(data.background);
this.next = MotaActionBlocks['setText_s'].xmlText([
data.position,data.offset,data.title,`rgba(${data.title})`,data.text,`rgba(${data.text})`,data.background,`rgba(${data.background})`,data.bold,data.titlefont,data.textfont,data.time,this.next]);
data.position,data.offset,data.title,'rgba('+data.title+')',
data.text,'rgba('+data.text+')',data.background,'rgba('+data.background+')',
data.bold,data.titlefont,data.textfont,data.time,this.next]);
break;
case "tip":
this.next = MotaActionBlocks['tip_s'].xmlText([
@ -2267,7 +2276,7 @@ ActionParser.prototype.parseAction = function() {
case "setFg": // 颜色渐变
if(this.isset(data.color)){
this.next = MotaActionBlocks['setFg_0_s'].xmlText([
data.color,`rgba(${data.color})`,data.time||0,data.async||false,this.next]);
data.color,'rgba('+data.color+')',data.time||0,data.async||false,this.next]);
} else {
this.next = MotaActionBlocks['setFg_1_s'].xmlText([
data.time||0,data.async||false,this.next]);
@ -2275,7 +2284,7 @@ ActionParser.prototype.parseAction = function() {
break;
case "screenFlash": // 画面闪烁
this.next = MotaActionBlocks['screenFlash_s'].xmlText([
data.color,`rgba(${data.color})`,data.time||500,data.times||1,data.async||false,this.next]);
data.color,'rgba('+data.color+')',data.time||500,data.times||1,data.async||false,this.next]);
break;
case "setWeather": // 更改天气
this.next = MotaActionBlocks['setWeather_s'].xmlText([
@ -2402,7 +2411,7 @@ ActionParser.prototype.parseAction = function() {
var text_choices = null;
for(var ii=data.choices.length-1,choice;choice=data.choices[ii];ii--) {
text_choices=MotaActionBlocks['choicesContext'].xmlText([
choice.text,this.insertActionList(choice.action),text_choices]);
choice.text,choice.color,'rgba('+choice.color+')',this.insertActionList(choice.action),text_choices]);
}
this.next = MotaActionBlocks['choices_s'].xmlText([
this.isset(data.text)?this.EvalString(data.text):null,'','',text_choices,this.next]);

View File

@ -153,8 +153,8 @@ editor.prototype.idsInit = function (maps, icons) {
if(img.width%32 || img.height%32){
alert(imgName+'的长或宽不是32的整数倍, 请修改后刷新页面');
}
if(img.width*img.height > 32*32*1000){
alert(imgName+'上的图块数量超过了1000请修改后刷新页面');
if(img.width*img.height > 32*32*3000){
alert(imgName+'上的图块数量超过了3000请修改后刷新页面');
}
for (var id=startOffset; id<startOffset+width*height;id++) {
var x = (id-startOffset)%width, y = parseInt((id-startOffset)/width);
@ -645,12 +645,6 @@ editor.prototype.listen = function () {
if(clickpath.length>=2 && clickpath[0].indexOf('id_')===0){editor.lastClickId=clickpath[0]}
}
var iconLib=document.getElementById('iconLib');
iconLib.onmousedown = function (e) {
console.log("iconLib: ("+e.clientX+","+e.clientY+")");
e.stopPropagation();
}
var eui=document.getElementById('eui');
var uc = eui.getContext('2d');
@ -797,9 +791,6 @@ editor.prototype.listen = function () {
currDrawData.info = JSON.parse(JSON.stringify(editor.info));
reDo = null;
// console.log(stepPostfix);
if (editor.layerMod!='map' && editor.info.images && editor.info.images.indexOf('48')!==-1){
printe('前景/背景不支持48的图块');
} else {
if(editor.brushMod==='tileset' && core.tilesets.indexOf(editor.info.images)!==-1){
var imgWidth=~~(core.material.images.tilesets[editor.info.images].width/32);
var x0=stepPostfix[0].x;
@ -816,7 +807,6 @@ editor.prototype.listen = function () {
for (var ii = 0; ii < stepPostfix.length; ii++)
editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.info;
}
}
// console.log(editor.map);
editor.updateMap();
holdingPath = 0;
@ -975,9 +965,38 @@ editor.prototype.listen = function () {
}
}
var getScrollBarHeight = function () {
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
// force scrollbars
outer.style.overflow = "scroll";
// add innerdiv
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
// remove divs
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
}
var scrollBarHeight = getScrollBarHeight();
console.log(scrollBarHeight);
var dataSelection = document.getElementById('dataSelection');
var iconLib=document.getElementById('iconLib');
iconLib.onmousedown = function (e) {
e.stopPropagation();
if (!editor.isMobile && e.clientY>=(635 - 5 - scrollBarHeight)) return;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var loc = {

View File

@ -64,9 +64,9 @@ editor_blockly = function () {
MotaActionBlocks['lose_s'].xmlText(),
MotaActionBlocks['choices_s'].xmlText([
'选择剑或者盾','流浪者','man',MotaActionBlocks['choicesContext'].xmlText([
'剑',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
'剑','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
MotaActionBlocks['choicesContext'].xmlText([
'盾',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]),
'盾','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]),
])
])
]),
@ -137,7 +137,7 @@ editor_blockly = function () {
MotaActionBlocks['setWeather_s'].xmlText(),
MotaActionBlocks['playBgm_s'].xmlText(),
MotaActionBlocks['pauseBgm_s'].xmlText(),
// MotaActionBlocks['resumeBgm_s'].xmlText(),
MotaActionBlocks['resumeBgm_s'].xmlText(),
MotaActionBlocks['loadBgm_s'].xmlText(),
MotaActionBlocks['freeBgm_s'].xmlText(),
MotaActionBlocks['playSound_s'].xmlText(),
@ -175,7 +175,7 @@ editor_blockly = function () {
MotaActionFunctions.actionParser.parse([
{"type": "choices", "text": "\t[老人,man]少年,你需要钥匙吗?\n我这里有大把的",
"choices": [
{"text": "黄钥匙(\${9+flag:shop_times}金币)", "action": [
{"text": "黄钥匙(\${9+flag:shop_times}金币)", "color": [255,255,0,1], "action": [
{"type": "if", "condition": "status:money>=9+flag:shop_times",
"true": [
{"type": "setValue", "name": "status:money", "value": "status:money-(9+flag:shop_times)"},
@ -187,7 +187,7 @@ editor_blockly = function () {
]
}
]},
{"text": "蓝钥匙(\${18+2*flag:shop_times}金币)", "action": [
{"text": "蓝钥匙(\${18+2*flag:shop_times}金币)", "color": [0,0,255,1], "action": [
]},
{"text": "离开", "action": [
{"type": "exit"}

View File

@ -734,7 +734,9 @@ actions.prototype.keyDownCtrl = function () {
//////
actions.prototype.clickCenterFly = function(x, y) {
if (x==core.status.event.data.poxX && y==core.status.event.data.posY) {
var posX = core.status.event.data.posX, posY = core.status.event.data.posY;
core.ui.closePanel();
if (x==posX&& y==posY) {
if (core.canUseItem('centerFly')) {
core.useItem('centerFly');
}
@ -742,10 +744,10 @@ actions.prototype.clickCenterFly = function(x, y) {
core.drawTip('当前不能使用中心对称飞行器');
}
}
core.ui.closePanel();
}
actions.prototype.keyUpCenterFly = function (keycode) {
core.ui.closePanel();
if (keycode==51 || keycode==13 || keycode==32 || keycode==67) {
if (core.canUseItem('centerFly')) {
core.useItem('centerFly');
@ -754,7 +756,6 @@ actions.prototype.keyUpCenterFly = function (keycode) {
core.drawTip('当前不能使用中心对称飞行器');
}
}
core.ui.closePanel();
}
@ -2062,6 +2063,7 @@ actions.prototype.clickSyncSave = function (x,y) {
core.removeLocalForage("save"+i);
}
}
core.ui.closePanel();
core.drawText("读取成功!\n你的本地所有存档均已被覆盖。");
}, function () {
core.status.event.selection=0;

View File

@ -1654,7 +1654,7 @@ control.prototype.setReplaySpeed = function (speed) {
control.prototype.stopReplay = function () {
if (!core.isPlaying()) return;
if (core.status.event.id=='save' || (core.status.event.id||"").indexOf('book')==0 || core.status.event.id=='viewMaps') return;
if (!core.isReplaying()) return;
// if (!core.isReplaying()) return;
core.status.replay.toReplay = [];
core.status.replay.totalList = [];
core.status.replay.replaying=false;
@ -1962,8 +1962,27 @@ control.prototype.replay = function () {
return;
}
// core.stopReplay();
// core.insertAction("录像文件出错");
core.status.replay.replaying = false;
main.log("录像文件出错,当前操作:"+action+
"\n接下来10个操作是"+core.status.replay.toReplay.slice(0, 10).toString());
core.ui.drawConfirmBox("录像文件出错,你想回到上个节点吗?", function () {
core.ui.closePanel();
if (core.status.replay.save.length > 0) {
core.status.replay.replaying = true;
core.status.replay.pausing = true;
core.rewindReplay();
}
else {
core.drawTip("无法回到上一个节点");
core.stopReplay();
core.insertAction("录像文件出错");
}
}, function () {
core.ui.closePanel();
core.stopReplay();
});
}
@ -2151,6 +2170,9 @@ control.prototype.autosave = function (removeLast) {
/////// 实际进行自动存档 //////
control.prototype.checkAutosave = function () {
if (!core.animateFrame || !core.saves || !core.saves.autosave) return;
core.setLocalStorage('totalTime', core.animateFrame.totalTime);
if (core.saves.autosave.data == null || !core.saves.autosave.updated) return;
@ -2347,6 +2369,7 @@ control.prototype.syncLoad = function () {
core.removeLocalForage("save"+i);
}
}
core.ui.closePanel();
core.drawText("同步成功!\n你的本地所有存档均已被覆盖。");
}, function () {
core.status.event.selection=0;
@ -2581,6 +2604,7 @@ control.prototype.playBgm = function (bgm) {
if (!core.musicStatus.bgmStatus) {
try {
core.musicStatus.playingBgm = bgm;
core.musicStatus.lastBgm = bgm;
core.material.bgms[bgm].pause();
}
catch (e) {
@ -2614,6 +2638,7 @@ control.prototype.playBgm = function (bgm) {
core.material.bgms[bgm].currentTime = 0;
core.material.bgms[bgm].play();
core.musicStatus.playingBgm = bgm;
core.musicStatus.lastBgm = bgm;
}
catch (e) {
console.log("无法播放BGM "+bgm);
@ -2644,7 +2669,7 @@ control.prototype.resumeBgm = function () {
// 恢复BGM
try {
core.playBgm(core.musicStatus.playingBgm);
core.playBgm(core.musicStatus.playingBgm || core.musicStatus.lastBgm);
}
catch (e) {
console.log("无法恢复BGM");
@ -2765,7 +2790,8 @@ control.prototype.updateStatusBar = function () {
core.statusBar.image.toolbox.src = core.statusBar.icons.rewind.src;
core.statusBar.image.keyboard.src = core.statusBar.icons.book.src;
core.statusBar.image.shop.style.opacity = 0;
core.statusBar.image.shop.src = core.statusBar.icons.floor.src;
core.statusBar.image.save.src = core.statusBar.icons.speedDown.src;
@ -2790,7 +2816,8 @@ control.prototype.updateStatusBar = function () {
core.statusBar.image.toolbox.src = core.statusBar.icons.toolbox.src;
core.statusBar.image.keyboard.src = core.statusBar.icons.keyboard.src;
core.statusBar.image.shop.style.opacity = 1;
core.statusBar.image.shop.src = core.statusBar.icons.shop.src;
core.statusBar.image.save.src = core.statusBar.icons.save.src;

View File

@ -53,6 +53,7 @@ function core() {
'bgmStatus': false, // 是否播放BGM
'soundStatus': true, // 是否播放SE
'playingBgm': null, // 正在播放的BGM
'lastBgm': null, // 上次播放的bgm
'gainNode': null,
'playingSounds': {}, // 正在播放的SE
'volume': 1.0, // 音量
@ -622,7 +623,7 @@ core.prototype.nearHero = function (x, y) {
////// 开门 //////
core.prototype.openDoor = function (id, x, y, needKey, callback) {
core.events.openDoor(id, x, y, needKey, callback);
return core.events.openDoor(id, x, y, needKey, callback);
}
////// 战斗 //////

View File

@ -184,8 +184,9 @@ enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
var info = this.getDamageInfo(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
if (info == null) {
if (core.status.hero.atk<=enemy.def) {
return [[enemy.def+1-core.status.hero.atk,'?']];
info = this.getEnemyInfo(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
if (core.status.hero.atk<=info.def) {
return [[info.def+1-core.status.hero.atk,'?']];
}
return [];
}

View File

@ -109,6 +109,7 @@ events.prototype.startGame = function (hard, seed, route, callback) {
core.clearStatusBar();
var post_start = function () {
core.ui.closePanel();
core.control.triggerStatusBar('show');
core.dom.musicBtn.style.display = 'none';
@ -277,7 +278,7 @@ events.prototype.gameOver = function (ending, fromReplay, norank) {
var doUpload = function(username) {
var hp = core.status.hero.hp;
if (username==undefined) hp = 1;
core.ui.closePanel();
// upload
var formData = new FormData();
formData.append('type', 'score');
@ -863,11 +864,15 @@ events.prototype.doAction = function() {
y = core.calValue(data.loc[1], prefix);
}
var floorId=data.floorId || core.status.floorId;
if (floorId==core.status.floorId)
core.openDoor(null, x, y, data.needKey, function() {
if (floorId==core.status.floorId) {
var _callback = function () {
core.lockControl();
core.events.doAction();
})
}
if (!core.openDoor(null, x, y, data.needKey, _callback)) {
_callback();
}
}
else {
core.removeBlock(x, y, floorId);
this.doAction();
@ -966,12 +971,10 @@ events.prototype.doAction = function() {
core.pauseBgm();
this.doAction();
break
/*
case "resumeBgm":
core.resumeBgm();
this.doAction();
break
*/
case "loadBgm":
if (core.platform.isPC)
core.loadBgm(data.name);
@ -1424,8 +1427,7 @@ events.prototype.openDoor = function (id, x, y, needKey, callback) {
// 是否存在门
if (!core.terrainExists(x, y, id) || !(id.endsWith("Door") || id.endsWith("Wall"))
|| !core.isset(core.material.icons.animates[id])) {
if (core.isset(callback)) callback();
return;
return false;
}
if (core.status.automaticRoute.moveStepBeforeStop.length==0) {
core.status.automaticRoute.moveStepBeforeStop=core.status.automaticRoute.autoStepRoutes.slice(core.status.automaticRoute.autoStep-1,core.status.automaticRoute.autoStepRoutes.length);
@ -1441,8 +1443,7 @@ events.prototype.openDoor = function (id, x, y, needKey, callback) {
core.drawTip("你没有" + ((core.material.items[key]||{}).name||"钥匙"));
else core.drawTip("无法开启此门");
core.clearContinueAutomaticRoute();
if (core.isset(callback)) callback();
return;
return false;
}
core.autosave(true);
core.removeItem(key);
@ -1470,7 +1471,9 @@ events.prototype.openDoor = function (id, x, y, needKey, callback) {
}
core.clearMap('event', 32 * x, 32 * y, 32, 32);
core.drawImage('event', core.material.images.animates, 32 * state, 32 * door, 32, 32, 32 * x, 32 * y, 32, 32);
}, speed / core.status.replay.speed)
}, speed / core.status.replay.speed);
return true;
}
////// 战斗 //////
@ -1811,7 +1814,7 @@ events.prototype.moveImage = function (code, to, opacityVal, time, callback) {
var animate = setInterval(function () {
step++;
moveStep();
if (step > steps) {
if (step == steps) {
if (core.isset(opacityVal))
core.setOpacity(name, opacityVal);
delete core.animateFrame.asyncId[animate];
@ -2047,7 +2050,7 @@ events.prototype.useItem = function(itemId) {
core.ui.drawThumbnail(core.status.floorId, 'ui', core.status.thisMap.blocks, 0, 0, 416, toX, toY, core.status.hero.loc, core.getFlag('heroIcon', "hero.png"));
var offsetX = core.clamp(toX-6, 0, core.bigmap.width-13), offsetY = core.clamp(toY-6, 0, core.bigmap.height-13);
core.fillRect('ui',(toX-offsetX)*32,(toY-offsetY)*32,32,32,fillstyle);
core.status.event.data = {"x": toX, "y": toY, "poxX": toX-offsetX, "posY": toY-offsetY};
core.status.event.data = {"x": toX, "y": toY, "posX": toX-offsetX, "posY": toY-offsetY};
core.drawTip("请确认当前中心对称飞行器的位置");
return;
}

View File

@ -62,8 +62,8 @@ loader.prototype.load = function (callback) {
if (img.width%32!=0 || img.height%32!=0) {
console.warn("警告!"+imgName+"的宽或高不是32的倍数");
}
if (img.width * img.height > 32*32*1000) {
console.warn("警告!"+imgName+"上的图块素材个数大于1000");
if (img.width * img.height > 32*32*3000) {
console.warn("警告!"+imgName+"上的图块素材个数大于3000");
}
}

View File

@ -178,20 +178,42 @@ maps.prototype.initMaps = function (floorIds) {
return maps;
}
maps.prototype.__initFloorMap = function (floorId) {
var map = core.clone(core.floors[floorId].map);
var mw = core.floors[floorId].width || 13;
var mh = core.floors[floorId].height || 13;
for (var x=0;x<mh;x++) {
if (!core.isset(map[x])) map[x] = [];
for (var y=0;y<mw;y++) {
if (!core.isset(map[x][y])) map[x][y]=0;
// check "disable"
var event = core.floors[floorId].events[y+","+x];
if (core.isset(event) && event.enable === false && main.mode == 'play') {
map[x][y] += ":f";
}
}
}
return map;
}
////// 压缩地图
maps.prototype.compressMap = function (mapArr, floorId) {
if (core.utils.same(mapArr, core.floors[floorId].map)) return null;
var floorMap = this.__initFloorMap(floorId);
if (core.utils.same(mapArr, floorMap)) return null;
var mw = core.floors[floorId].width || 13;
var mh = core.floors[floorId].height || 13;
for (var x=0;x<mh;x++) {
if (core.utils.same(mapArr[x], core.floors[floorId].map[x]||[])) {
if (core.utils.same(mapArr[x], floorMap[x])) {
// 没有改变的行直接删掉记成0
mapArr[x] = 0;
}
else {
for (var y=0;y<mw;y++) {
if (mapArr[x][y] === (core.floors[floorId].map[x]||[])[y]) {
if (mapArr[x][y] === floorMap[x][y]) {
// 没有改变的数据记成-1
mapArr[x][y] = -1;
}
@ -203,18 +225,19 @@ maps.prototype.compressMap = function (mapArr, floorId) {
////// 解压缩地图
maps.prototype.decompressMap = function (mapArr, floorId) {
if (!core.isset(mapArr)) return core.clone(core.floors[floorId].map);
var floorMap = this.__initFloorMap(floorId);
if (!core.isset(mapArr)) return floorMap;
var mw = core.floors[floorId].width || 13;
var mh = core.floors[floorId].height || 13;
for (var x=0;x<mh;x++) {
if (mapArr[x] === 0) {
mapArr[x] = core.clone(core.floors[floorId].map[x]);
mapArr[x] = floorMap[x];
}
else {
for (var y=0;y<mw;y++) {
if (mapArr[x][y] === -1) {
mapArr[x][y] = core.floors[floorId].map[x][y];
mapArr[x][y] = floorMap[x][y];
}
}
}
@ -432,11 +455,16 @@ maps.prototype.drawBlock = function (block, animate, dx, dy) {
if (!blockInfo.isTileset) x = (animate||0)%(block.event.animate||1);
if (core.isset(block.name)) {
core.clearMap(block.name, block.x * 32, block.y * 32, 32, 32);
core.clearMap(block.name, block.x * 32, block.y * 32 + 32 - height, 32, height);
if (block.name == 'bg') {
if (height>32) {
core.clearMap(block.name, block.x * 32, block.y * 32 - 32, 32, 32);
core.drawImage('bg', core.material.groundCanvas.canvas, block.x * 32, block.y * 32 - 32);
}
core.drawImage('bg', core.material.groundCanvas.canvas, block.x * 32, block.y * 32);
}
core.drawImage(block.name, image, x * 32, y * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
core.drawImage(block.name, image, x * 32, y * height, 32, height,
block.x * 32, block.y * 32 + 32 - height, 32, height);
return;
}

View File

@ -503,6 +503,72 @@ ui.prototype.calTextBoxWidth = function (canvas, content, min_width, max_width)
}
}
ui.prototype.__drawText = function (canvas, content, content_left, content_top, valid_width,
color, per_height, time) {
core.setTextAlign(canvas, 'left');
var offsetx = content_left, offsety = content_top;
core.setFillStyle(canvas, color);
var index = 0, currcolor = color, changed = false;
var drawNext = function () {
if (index >= content.length) return false;
if (changed) {
core.setFillStyle(canvas, currcolor);
changed = false;
}
// get next character
var ch = content.charAt(index++);
// \n, \\n
if (ch == '\n' || (ch=='\\' && content.charAt(index)=='n')) {
offsetx = content_left;
offsety += per_height;
if (ch=='\\') index++;
return drawNext();
}
// \r, \\r
if (ch == '\r' || (ch=='\\' && content.charAt(index)=='r')) {
if (ch == '\\') index++;
changed = true;
// 检查是不是 []
var index2;
if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) {
// 变色
var str = content.substring(index+1, index2);
if (str=="") currcolor = color;
else currcolor = str;
index = index2+1;
}
else currcolor = color;
return drawNext();
}
// 检查是不是自动换行
var charwidth = core.calWidth(canvas, ch);
if (core.isset(valid_width) && offsetx + charwidth > content_left + valid_width) {
index--;
offsetx = content_left;
offsety += per_height;
return drawNext();
}
// 输出
core.fillText(canvas, ch, offsetx, offsety);
offsetx += charwidth;
return true;
};
if (!core.isset(time) || time<=0) while (drawNext());
else {
core.status.event.interval = setInterval(function () {
changed = true;
if (!drawNext()) {
clearInterval(core.status.event.interval);
core.status.event.interval = null;
}
}, time);
}
}
////// 绘制一个对话框 //////
ui.prototype.drawTextBox = function(content, showAll) {
@ -729,69 +795,10 @@ ui.prototype.drawTextBox = function(content, showAll) {
core.drawImage('ui', image, 0, 0, image.width, image.height, left+10, top+10, 70, 70);
}
var offsetx = content_left, offsety = content_top;
core.setFont('ui', font);
core.setFillStyle('ui', textColor);
var index = 0, currcolor = textColor, changed = false;
var drawNext = function () {
if (index >= content.length) return false;
if (changed) {
core.setFillStyle('ui', currcolor);
changed = false;
}
// get next character
var ch = content.charAt(index++);
// \n, \\n
if (ch == '\n' || (ch=='\\' && content.charAt(index)=='n')) {
offsetx = content_left;
offsety += textfont+5;
if (ch=='\\') index++;
return drawNext();
}
// \r, \\r
if (ch == '\r' || (ch=='\\' && content.charAt(index)=='r')) {
if (ch == '\\') index++;
changed = true;
// 检查是不是 []
var index2;
if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) {
// 变色
var str = content.substring(index+1, index2);
if (str=="") currcolor = textColor;
else currcolor = str;
index = index2+1;
}
else currcolor = textColor;
return drawNext();
}
// 检查是不是自动换行
var charwidth = core.calWidth('ui', ch);
if (offsetx + charwidth > content_left + validWidth) {
index--;
offsetx = content_left;
offsety += textfont+5;
return drawNext();
}
// 输出
core.fillText('ui', ch, offsetx, offsety);
offsetx += charwidth;
return true;
};
if (showAll || textAttribute.time<=0 || core.status.event.id!='action') {
while (drawNext());
}
else {
core.status.event.interval = setInterval(function () {
changed = true;
if (!drawNext()) {
clearInterval(core.status.event.interval);
core.status.event.interval = null;
}
}, textAttribute.time);
}
this.__drawText('ui', content, content_left, content_top, validWidth, textColor, textfont + 5,
(showAll || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time);
}
@ -812,7 +819,8 @@ ui.prototype.drawScrollText = function (content, time, callback) {
var font = textfont+"px "+core.status.globalAttribute.font;
if (textAttribute.bold) font = "bold "+font;
var contents = core.splitLines('ui', content), lines = contents.length;
var realContent = content.replace(/(\r|\\r)(\[.*?])?/g, "");
var contents = core.splitLines('ui', realContent), lines = contents.length;
// 计算总高度按1.4倍行距计算
var width = 416, height = textfont * 1.4 * lines;
@ -821,15 +829,8 @@ ui.prototype.drawScrollText = function (content, time, callback) {
tempCanvas.canvas.height = height;
tempCanvas.clearRect(0, 0, width, height);
tempCanvas.font = font;
tempCanvas.fillStyle = textColor;
// 全部绘制
var currH = textfont;
for (var i = 0; i < lines; ++i) {
var text = contents[i];
tempCanvas.fillText(text, offset, currH);
currH += 1.4 * textfont;
}
this.__drawText(tempCanvas, content, offset, textfont, null, textColor, 1.4*textfont, 0);
// 开始绘制到UI上
core.clearMap('ui');
@ -891,17 +892,19 @@ ui.prototype.drawChoices = function(content, choices) {
var contents = null;
var content_left = left + 15;
var validWidth = width-(content_left-left)-10;
if (core.isset(content)) {
// 获得name, image, icon
// 获得name, image, icon
var info = this.getTitleAndIcon(content);
content = core.replaceText(info.content);
var realContent = content.replace(/(\r|\\r)(\[.*?])?/g, "");
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 '+globalFont);
validWidth = width-(content_left-left)-10
contents = core.splitLines('ui', realContent, validWidth, 'bold 15px '+globalFont);
// content部分高度
var cheight=0;
@ -963,17 +966,16 @@ ui.prototype.drawChoices = function(content, choices) {
}
}
core.setTextAlign('ui', 'left');
for (var i=0;i<contents.length;i++) {
core.fillText('ui', contents[i], content_left, content_top, textColor, 'bold 15px '+globalFont);
content_top+=20;
}
core.setFont('ui', 'bold 15px '+globalFont);
this.__drawText('ui', content, content_left, content_top, validWidth, textColor, 20, 0);
}
// 选项
core.setTextAlign('ui', 'center');
for (var i = 0; i < choices.length; i++) {
core.setFillStyle('ui', choices[i].color || textColor);
var color = choices[i].color || textColor;
if (color instanceof Array) color = core.arrayToRGBA(color);
core.setFillStyle('ui', color);
core.fillText('ui', core.replaceText(choices[i].text || choices[i]), 208, choice_top + 32 * i, null, "bold 17px "+globalFont);
}

View File

@ -462,7 +462,9 @@ utils.prototype.encodeRoute = function (route) {
ans+=lastMove.substring(0,1).toUpperCase();
if (cnt>1) ans+=cnt;
}
return ans;
// return ans;
// 压缩
return LZString.compressToBase64(ans);
}
////// 解密路线 //////
@ -470,6 +472,14 @@ utils.prototype.decodeRoute = function (route) {
if (!core.isset(route)) return route;
// 解压缩
try {
var v = LZString.decompressFromBase64(route);
if (core.isset(v) && /^[a-zA-Z0-9+\/=:]+$/.test(v)) {
route = v;
}
} catch (e) {}
var ans=[], index=0;
var getNumber = function (noparse) {

10
main.js
View File

@ -316,7 +316,7 @@ main.prototype.setMainTipsText = function (text) {
main.prototype.log = function (e) {
if (e) {
if (main.core && main.core.platform && !main.core.platform.isPC) {
console.log((e.stack || e.toString()).replace("\n", " --- "));
console.log((e.stack || e.toString()));
}
else {
console.log(e);
@ -490,7 +490,6 @@ main.statusBar.image.toolbox.ondblclick = function (e) {
e.stopPropagation();
if (core.isReplaying()) {
core.rewindReplay();
return;
}
@ -516,6 +515,11 @@ main.statusBar.image.keyboard.onclick = function (e) {
main.statusBar.image.shop.onclick = function (e) {
e.stopPropagation();
if (core.isReplaying()) {
core.viewMapReplay();
return;
}
if (main.core.isPlaying())
main.core.openQuickShop(true);
}
@ -664,7 +668,9 @@ main.dom.musicBtn.onclick = function () {
window.onblur = function () {
if (main.core && main.core.control) {
try {
main.core.control.checkAutosave();
} catch (e) {main.log(e);}
}
}

View File

@ -1,25 +1,25 @@
main.floors.sample1=
{
"floorId": "sample1",
"title": "样板 1 层",
"name": "1",
"canFlyTo": true,
"canUseQuickShop": true,
"defaultGround": "grass",
"images": [
"floorId": "sample1",
"title": "样板 1 层",
"name": "1",
"canFlyTo": true,
"canUseQuickShop": true,
"defaultGround": "grass",
"images": [
[
0,
0,
"bg.jpg",
0
]
],
"weather": [
],
"weather": [
"snow",
6
],
"item_ratio": 1,
"map": [
],
"item_ratio": 1,
"map": [
[ 7,131, 8,152, 9,130, 10,152,166,165,132,165,166],
[ 0, 0, 0, 0, 0, 0, 0,152,165,164, 0,162,165],
[152,152,152,152,121,152,152,152, 0, 0,229, 0, 0],
@ -34,8 +34,8 @@ main.floors.sample1=
[ 1, 0,123, 1, 0, 20,124, 0,121, 0,122, 0,126],
[ 1, 0, 0, 1, 88, 20, 86, 0, 0, 0, 0, 0,122]
],
"firstArrive": [],
"events": {
"firstArrive": [],
"events": {
"4,10": [
"\t[样板提示]本层楼将会对各类事件进行介绍。",
"左边是一个仿50层的陷阱做法上方是商店、快捷商店的使用方法右上是一个典型的杀怪开门的例子右下是各类可能的NPC事件。",
@ -606,6 +606,7 @@ main.floors.sample1=
"choices": [
{
"text": "黄钥匙(${9+flag:woman_times}金币)",
"color": [255,255,0,1],
"action": [
{
"type": "if",
@ -633,6 +634,7 @@ main.floors.sample1=
},
{
"text": "蓝钥匙(${18+2*flag:woman_times}金币)",
"color": [0,0,255,1],
"action": [
{
"type": "if",
@ -660,6 +662,7 @@ main.floors.sample1=
},
{
"text": "红钥匙(${36+4*flag:woman_times}金币)",
"color": [255,0,0,1],
"action": [
{
"type": "if",
@ -708,8 +711,8 @@ main.floors.sample1=
"type": "revisit"
}
]
},
"changeFloor": {
},
"changeFloor": {
"4,12": {
"floorId": "sample0",
"loc": [
@ -723,8 +726,8 @@ main.floors.sample1=
"direction": "up"
},
"10,12": null
},
"afterBattle": {
},
"afterBattle": {
"9,6": [
{
"type": "setValue",
@ -768,14 +771,14 @@ main.floors.sample1=
}
],
"10,12": null
},
"afterGetItem": {},
"afterOpenDoor": {},
"cannotMove": {},
"bgmap": [
},
"afterGetItem": {},
"afterOpenDoor": {},
"cannotMove": {},
"bgmap": [
],
"fgmap": [
"fgmap": [
],
]
}

View File

@ -4,9 +4,11 @@
存档方式优化,大幅降低单个存档的占用空间
脚本编辑器增加代码格式化的选项
事件和脚本编辑器中Ctrl+S可以进行保存
显示选择项提供颜色控制
事件的移动勇士增加前进和后退两个操作
事件编辑器的下拉框增加滚动条
通关后将询问是否进行评分
录像播放失败后可以回退到上个节点
修复已知的所有Bug大量细节优化
-----------------------------------------------------------------------