Paint Mode

This commit is contained in:
oc 2018-10-30 02:26:18 +08:00
parent 6488b355e8
commit de972f87f4
6 changed files with 239 additions and 46 deletions

View File

@ -369,6 +369,20 @@ HTML5魔塔一大亮点就是存在录像系统可以很方便进行录像回
如果录像出现问题请加群539113091找小艾反馈Bug。
## 绘图模式
从V2.5开始,样板提供了绘图模式,可以让玩家在画布上任意进行绘制,标记等。
使用M键或在菜单栏中可以进入绘图模式。
**绘图的内容会自动保存,且以页面为生命周期,和存读档无关,返回标题并重新开始游戏后绘制的内容仍有效,但刷新页面就会消失。**
你可以将绘制内容保存到文件,也可以从文件读取保存的绘制内容。
绘图模式下,状态栏的图标也会相应改变,铅笔为绘制模式,橡皮为擦除模式,存读档为保存和读取绘图文件,退出为返回默认值。
在浏览地图页面中也可以按楼传按钮或M键来开启/关闭该层的绘图显示。
## 操作说明
本塔主要支持鼠标(触摸屏)操作和键盘操作。
@ -397,10 +411,15 @@ HTML5魔塔一大亮点就是存在录像系统可以很方便进行录像回
- **[B]** 打开数据统计
- **[H]** 打开帮助页面
- **[R]** 回放录像
- **[E]** 显示光标
- **[SPACE]** 轻按(仅在轻按开关打开时有效)
- **[M]** 绘图模式
- **[PgUp/PgDn]** 浏览地图
- **[1]** 快捷使用破墙镐
- **[2]** 快捷使用炸弹/圣锤
- **[3]** 快捷使用中心对称飞行器
- **[4]** 快捷使用其他道具
- **[Alt+0~9]** 快捷换装
以上快捷键也能在游戏菜单中的操作说明中看到。

View File

@ -282,6 +282,9 @@ actions.prototype.keyUp = function(keyCode, altKey) {
this.keyUpCenterFly(keyCode);
return;
}
if (core.status.event.id=='paint') {
this.keyUpPaint(keyCode);
}
return;
}
@ -1137,10 +1140,17 @@ actions.prototype.keyUpViewMaps = function (keycode) {
core.clearMap('data');
core.setOpacity('data', 1);
core.ui.closePanel();
return;
}
if (keycode==86) {
core.status.event.data.damage = !core.status.event.data.damage;
core.ui.drawMaps(core.status.event.data.index, core.status.event.data.x, core.status.event.data.y);
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);
return;
}
if (keycode==88 || (core.status.replay.replaying && keycode==67)) {
if (core.isset(core.status.replay)&&core.status.replay.replaying) {
@ -1148,6 +1158,7 @@ actions.prototype.keyUpViewMaps = function (keycode) {
} else {
core.openBook(false);
}
return;
}
return;
}
@ -2531,17 +2542,28 @@ actions.prototype.clickAbout = function () {
core.restart();
}
actions.prototype.ondownPaint = function (x, y) {
console.log("ondown: ("+x+","+y+")");
core.canvas.route.beginPath();
core.canvas.route.moveTo(x+core.bigmap.offsetX, y+core.bigmap.offsetY);
////// 绘图相关 //////
actions.prototype.ondownPaint = function (x, y) {
x+=core.bigmap.offsetX;
y+=core.bigmap.offsetY;
if (!core.status.event.data.erase) {
core.canvas.route.beginPath();
core.canvas.route.moveTo(x, y);
}
core.status.event.data.x = x;
core.status.event.data.y = y;
}
actions.prototype.onmovePaint = function (x, y) {
if (core.status.event.data.x==null) return;
x+=core.bigmap.offsetX;
y+=core.bigmap.offsetY;
if (core.status.event.data.erase) {
core.clearMap('route', x-10, y-10, 20, 20);
return;
}
var midx = (core.status.event.data.x+x)/2, midy = (core.status.event.data.y+y)/2;
core.canvas.route.quadraticCurveTo(midx, midy, x, y);
core.canvas.route.stroke();
@ -2550,13 +2572,83 @@ actions.prototype.onmovePaint = function (x, y) {
}
actions.prototype.onupPaint = function (x,y) {
console.log("onup: ("+x+","+y+")");
var midx = (core.status.event.data.x+x)/2, midy = (core.status.event.data.y+y)/2;
core.canvas.route.quadraticCurveTo(midx, midy, x, y);
core.canvas.route.stroke();
x+=core.bigmap.offsetX;
y+=core.bigmap.offsetY;
if (core.status.event.data.erase) {
core.clearMap('route', x-5, y-5, 10, 10);
}
else if (core.status.event.data.x!=null) {
var midx = (core.status.event.data.x+x)/2, midy = (core.status.event.data.y+y)/2;
core.canvas.route.quadraticCurveTo(midx, midy, x, y);
core.canvas.route.stroke();
}
core.status.event.data.x = null;
core.status.event.data.y = null;
// 保存
core.paint[core.status.floorId] = LZString.compress(core.utils.encodeCanvas(core.canvas.route).join(","));
}
actions.prototype.setPaintMode = function (mode) {
if (mode == 'paint') core.status.event.data.erase = false;
else if (mode == 'erase') core.status.event.data.erase = true;
else return;
core.drawTip("进入"+(core.status.event.data.erase?"擦除":"绘图")+"模式");
}
actions.prototype.savePaint = function () {
var data = {};
for (var floorId in core.paint) {
if (core.isset(core.paint[floorId]))
data[floorId] = LZString.decompress(core.paint[floorId]);
}
core.download(core.firstData.name+".h5paint", JSON.stringify({
'name': core.firstData.name,
'paint': data
}));
}
actions.prototype.loadPaint = function () {
core.readFile(function (obj) {
if (obj.name!=core.firstData.name) {
alert("绘图文件和游戏不一致!");
return;
}
if (!core.isset(obj.paint)) {
alert("无效的绘图文件!");
return;
}
core.paint = {};
for (var floorId in obj.paint) {
if (core.isset(obj.paint[floorId]))
core.paint[floorId] = LZString.compress(obj.paint[floorId]);
}
core.clearMap('route');
var value = core.paint[core.status.floorId];
if (core.isset(value)) value = LZString.decompress(value).split(",");
core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
core.canvas.route.drawImage(core.bigmap.tempCanvas.canvas, 0, 0);
core.drawTip("读取绘图文件成功");
})
}
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("退出绘图模式");
}
actions.prototype.keyUpPaint = function (keycode) {
if (keycode==27 || keycode==88 || keycode==77 || keycode==13 || keycode==32 || keycode==67) {
this.exitPaint();
return;
}
}
////// 绘图相关 END //////

View File

@ -1645,6 +1645,10 @@ ui.prototype.drawMaps = function (index, x, y) {
core.clearMap('animate');
core.setOpacity('animate', 1);
var damage = (core.status.event.data||{}).damage, paint = (core.status.event.data||{}).paint;
if (core.isset(index.damage)) damage=index.damage;
if (core.isset(index.paint)) paint=index.paint;
if (core.isset(index.index)) {
x=index.x;
y=index.y;
@ -1661,19 +1665,27 @@ 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": (core.status.event.data||{"damage":false}).damage};
core.status.event.data = {"index": index, "x": x, "y": y, "damage": damage, "paint": paint};
clearTimeout(core.interval.tipAnimate);
core.clearMap('ui');
core.setAlpha('ui', 1);
this.drawThumbnail(floorId, 'ui', core.status.maps[floorId].blocks, 0, 0, 416, x, y);
// 绘图
if (core.status.event.data.paint) {
var offsetX = core.clamp(x-6, 0, mw-13), offsetY = core.clamp(y-6, 0, mh-13);
var value = core.paint[floorId];
if (core.isset(value)) value = LZString.decompress(value).split(",");
core.utils.decodeCanvas(value, 32*mw, 32*mh);
core.canvas.ui.drawImage(core.bigmap.tempCanvas.canvas, offsetX*32, offsetY*32, 416, 416, 0, 0, 416, 416);
}
core.clearMap('data');
core.setOpacity('data', 0.2);
core.canvas.data.textAlign = 'left';
core.setFont('data', '16px Arial');
var text = core.status.maps[floorId].title;
if (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;
@ -2420,52 +2432,61 @@ ui.prototype.drawAbout = function () {
////// 绘制“画图”界面 //////
ui.prototype.drawPaint = function () {
console.log("drawPaint");
core.drawText(
"\t[进入绘图模式]你可以在此页面上任意进行绘图和标记操作。\nM键可以进入或退出此模式。\n\n"+
"绘图的内容会自动保存,且以页面为生命周期,和存读档无关,重新开始游戏或读档后绘制的内容仍有效,但刷新页面就会消失。\n"+
"你可以将绘制内容保存到文件,也可以从文件读取保存的绘制内容。\n"+
"浏览地图页面可以按楼传按钮或M键来开启/关闭该层的绘图显示。\n\n更多功能请详见文档-元件-绘图模式。",
function () {
core.drawTip("打开绘图模式,现在可以任意在界面上绘图标记");
core.drawTip("打开绘图模式,现在可以任意在界面上绘图标记");
core.lockControl();
core.status.event.id = 'paint';
core.status.event.data = {"x": null, "y": null, "erase": false};
core.lockControl();
core.status.event.id = 'paint';
core.status.event.data = {"x": null, "y": null, "erase": false};
core.clearMap('ui');
core.clearMap('route');
core.clearMap('ui');
core.clearMap('route');
core.setAlpha('route', 1);
core.setOpacity('route', 1);
core.setAlpha('route', 1);
core.setOpacity('route', 1);
// 将已有的内容绘制到route上
var value = core.paint[core.status.floorId];
if (core.isset(value)) value = LZString.decompress(value).split(",");
core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
core.canvas.route.drawImage(core.bigmap.tempCanvas.canvas, 0, 0);
// 将已有的内容绘制到route上
var value = core.paint[core.status.floorId];
if (core.isset(value) && typeof value == 'string') value = LZString.decompress(value).split(",");
core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
core.canvas.route.drawImage(core.bigmap.tempCanvas.canvas, 0, 0);
core.setLineWidth('route', 3);
core.setStrokeStyle('route', '#FF0000');
core.setLineWidth('route', 3);
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.settings.src = core.statusBar.icons.exit.src;
core.statusBar.image.book.style.opacity = 1;
core.statusBar.image.fly.style.opacity = 1;
}
);
}
////// 绘制帮助页面 //////
ui.prototype.drawHelp = function () {
core.drawText([
"\t[键盘快捷键列表]"+
"[CTRL] 跳过对话\n" +
"[Z] 转向\n" +
"[X] 打开/关闭怪物手册\n" +
"[G] 打开/关闭楼层传送器\n" +
"[A] 读取自动存档(回退)\n" +
"[CTRL] 跳过对话 [Z] 转向\n" +
"[X] 怪物手册 [G] 楼层传送\n" +
"[A] 读取自动存档 [S/D] 存读档页面\n" +
"[S/D] 打开/关闭存/读档页面\n" +
"[K/V] 打开/关闭快捷商店选择列表\n" +
"[T] 打开/关闭工具栏\n" +
"[ESC] 打开/关闭系统菜单\n" +
"[B] 打开数据统计\n" +
// "[E] 显示光标\n" +
"[H] 打开帮助页面\n"+
"[R] 回放\n"+
"[SPACE] 轻按(仅在轻按开关打开时有效)\n" +
"[K/V] 快捷商店 [ESC] 系统菜单\n" +
"[T] 道具页面 [Q] 装备页面\n" +
"[B] 数据统计 [H] 帮助页面\n" +
"[R] 回放录像 [E] 显示光标\n" +
"[SPACE] 轻按 [M] 绘图模式\n" +
"[PgUp/PgDn] 浏览地图\n"+
"[1] 快捷使用破墙镐\n" +
"[2] 快捷使用炸弹/圣锤\n" +
"[3] 快捷使用中心对称飞行器",
"[1~4] 快捷使用破炸飞和其他道具\n"+
"[Alt+0~9] 快捷换装",
"\t[鼠标操作]"+
"点状态栏中图标: 进行对应的操作\n"+
"点任意块: 寻路并移动\n"+
@ -2473,7 +2494,7 @@ ui.prototype.drawHelp = function () {
"双击空地: 瞬间移动\n"+
"单击勇士: 转向\n"+
"双击勇士: 轻按(仅在轻按开关打开时有效)\n"+
"长按任意位置:跳过剧情对话或打开虚拟键盘\n"
"长按任意位置:跳过剧情对话或打开虚拟键盘"
]);
}

View File

@ -253,14 +253,14 @@ utils.prototype.cropImage = function (image, size) {
////// 格式化时间为字符串 //////
utils.prototype.formatDate = function(date) {
if (!core.isset(date)) return "";
return date.getFullYear()+"-"+core.setTwoDigits(date.getMonth()+1)+"-"+core.setTwoDigits(date.getDate())+" "
return ""+date.getFullYear()+"-"+core.setTwoDigits(date.getMonth()+1)+"-"+core.setTwoDigits(date.getDate())+" "
+core.setTwoDigits(date.getHours())+":"+core.setTwoDigits(date.getMinutes())+":"+core.setTwoDigits(date.getSeconds());
}
////// 格式化时间为最简字符串 //////
utils.prototype.formatDate2 = function (date) {
if (!core.isset(date)) return "";
return date.getFullYear()+core.setTwoDigits(date.getMonth()+1)+core.setTwoDigits(date.getDate())
return ""+date.getFullYear()+core.setTwoDigits(date.getMonth()+1)+core.setTwoDigits(date.getDate())
+core.setTwoDigits(date.getHours())+core.setTwoDigits(date.getMinutes())+core.setTwoDigits(date.getSeconds());
}
@ -460,6 +460,26 @@ utils.prototype.decodeBase64 = function (str) {
}).join(''));
}
////// 任意进制转换 //////
utils.prototype.convertBase = function (str, fromBase, toBase) {
var map = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+={}[]\\|:;<>,.?/";
if (fromBase==toBase) return str;
var len = str.length, ans="";
var t = [];
for (var i=0;i<len;i++) t[i]=map.indexOf(str.charAt(i));
t[len]=0;
while (len>0) {
for (var i=len; i>=1; i--) {
t[i-1]+=t[i]%toBase*fromBase;
t[i]=parseInt(t[i]/toBase);
}
ans+=map.charAt(t[0]%toBase);
t[0]=parseInt(t[0]/toBase);
while (len>0 && t[len-1]==0) len--;
}
return ans;
}
utils.prototype.__init_seed = function () {
var rand = new Date().getTime()%34834795 + 3534;
rand = this.__next_rand(rand);

41
main.js
View File

@ -122,6 +122,11 @@ function main() {
'speedUp': 21,
'rewind': 22,
'equipbox': 23,
'mana': 24,
'skill': 25,
'paint': 26,
'erase': 27,
'exit': 28,
},
'floor': document.getElementById('floor'),
'name': document.getElementById('name'),
@ -389,6 +394,11 @@ main.statusBar.image.book.onclick = function () {
return;
}
if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
core.actions.setPaintMode('paint');
return;
}
if (main.core.isPlaying())
main.core.openBook(true);
}
@ -396,11 +406,27 @@ main.statusBar.image.book.onclick = function () {
////// 点击状态栏中的楼层传送器/装备栏时 //////
main.statusBar.image.fly.onclick = function () {
// 播放录像时
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.stopReplay();
return;
}
// 绘图模式
if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
core.actions.setPaintMode('erase');
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);
@ -457,6 +483,11 @@ main.statusBar.image.save.onclick = function () {
return;
}
if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
core.actions.savePaint();
return;
}
if (main.core.isPlaying())
main.core.save(true);
}
@ -469,6 +500,11 @@ main.statusBar.image.load.onclick = function () {
return;
}
if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
core.actions.loadPaint();
return;
}
if (main.core.isPlaying())
main.core.load(true);
}
@ -481,6 +517,11 @@ main.statusBar.image.settings.onclick = function () {
return;
}
if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
core.actions.exitPaint();
return;
}
if (main.core.isPlaying())
main.core.openSettings(true);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 22 KiB