diff --git a/README.md b/README.md index 68a5c0d2..bf22c60d 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! │ └─ *.png # 对应的某个具体的图片素材 ├── /libs/ # JS源代码目录 │ ├─ /floors/ # 剧本文件,记录了每个地图的数据和事件 +│ ├─ /thirdparty/ # 游戏所用到的第三方库文件 │ ├─ core.js # 系统核心文件 │ ├─ data.js # 记录了勇士的初始化信息、各个全局变量和全局Flag值 │ ├─ enemys.js # 记录了怪物的信息,包括怪物的数据和特殊属性、伤害计算公式、临界值计算等。 @@ -47,6 +48,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! ### 2017.12.31 V1.3 * [x] 支持全键盘操作。 +* [x] 支持将某个图片作为某层的背景素材。 * [x] 便捷PS工具支持更改图片色相。 * [x] 支持经验升级(进阶/境界塔)。 * [x] 打败怪物可以进行加点(加点塔)。 diff --git a/_server/css/editor.css b/_server/css/editor.css new file mode 100644 index 00000000..02b25b10 --- /dev/null +++ b/_server/css/editor.css @@ -0,0 +1,297 @@ + +html,body,div,img{margin:0;padding:0;} +body{ + font-family: Roboto,"Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;; + background-color: #F5F5F5; +} +/* ::-webkit-scrollbar { + width: 5px; +} */ +.main { + max-width: 100%; + min-height: 500px; + margin: 0 auto; +} +#left, #mid, #right{ + border-radius: 2px; + box-sizing: border-box; + box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12); +} +#left{ + position: absolute; + left: 5px; + top: 10px; + width: 435px; + height: 630px; +} + +#editArea{ + position: absolute; + width: 100%; + height: 70%; + left: 0; + top: 0; + /* padding: 10px 5px; */ + box-sizing: border-box; +} +#pout{ + display: block; + width: 410px; + height: 100%; + box-sizing: border-box; + margin-left: 22px; + margin-top: 23px; + line-height: 20px; + font-size: 12.3px; + font-family: 'Lucida Console', Monaco, monospace; + white-space: pre; + border: 1px solid #ddd; + border-radius: 2px; +} +#editTip{ + position: absolute; + width: 100%; + height: 80px; + bottom:10px; + left: 10px; +} +#editArea p{ + margin: 10px; + display: block; + width: 70%; + line-height: 20px; + text-align: left; + font-size: 14px; +} +#editTip .btn{ + float: right; + margin-right: 20px; + margin-top: 5px; +} + +#mid{ + position: absolute; + left: 448px; + top: 10px; + width: 440px; + height: 630px; +} +.map { + position: absolute; + left: 20px; + top: 21px; + width: 416px; + height: 416px; +} +#mid .tools{ + position: absolute; + width: 425px; + height: 180px; + left: 0; + bottom: 0; + border-top: 1px solid #ccc; + padding: 10px 5px; + margin-left: 8px;; + box-sizing: border-box; +} +#tip{ + float: right; + width: 50%; + height: 95%; + padding: 5px 10px 10px 10px; + margin-right: 0; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 2px; + font-size: 15px; + line-height: 14px; +} +.files { + width: 50%; + height: 120px; + /* padding: 10px; */ + margin-top: 15px; +} +.input{ + display: block; + max-width: 150px; + height: 20px; + padding: 6px 12px; + font-size: 14px; + margin-top: 10px; + color: #555; + background-color: #fff; + border: 1px solid #ccc; + border-radius: 3px; + box-shadow: inset 0 1px 1px rgba(0,0,0,.075); +} +#bgSelect{ + width: 50%; + height: 100px; + margin-top: 10px; +} +#bgSelect span{ + /* display: block; */ + font-size: 14px; + line-height: 30px; +} +#printOut{ + margin-top: 10px; + height: 20px; + +} +.btn { + width: 80px; + border-radius: 2px; + line-height: 30px; + margin: 0; + min-width: 50px; + padding: 0 5px; + display: inline-block; + margin-top: 5px; + font-size: 14px; + font-weight: 400; + /* text-transform: uppercase; */ + letter-spacing: 0; + overflow: hidden; + cursor: pointer; + text-decoration: none; + text-align: center; + vertical-align: middle; + border: 0; + background: rgba(158,158,158,.2); + box-shadow: 0 1px 1px 0 rgba(0,0,0,.14), 0 2px 1px -1px rgba(0,0,0,.2), 0 1px 3px 0 rgba(0,0,0,.12); + color: #fff; + background-color: #26A69A; +} +.btn:hover { + background-color: #009688; + box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12); +} +#right{ + position: absolute; + left: 900px; + top: 10px; + width: 440px; + height: 630px; + /* border: 1px solid rgb(238, 13, 13); */ +} +#iconLib{ + position: absolute; + width: 435px; + height: 620px; + left: 5px; + top: 5px; + overflow: auto; +} +.gameCanvas { + position: absolute; +} +#dataSelection{ + position: absolute; + /* top:0; + left:320px; */ + z-index:75; + width:26px; + height:26px; + margin: 3px 0 0 3px; + padding:0; + /* display: none; */ + box-sizing: border-box; + background-color:rgba(255, 255, 255, 0.0); + border: 1px solid #000; + box-shadow: 0 0 0 2px #fff, + 0 0 0 3px #000; +} +.warnText{ + color: #D50000; + font-weight: 700; + font-size: 14px; +} +.infoText{ + color: #2196F3; +} +.successText{ + color: #00897B +} + +table, td { + border: 1px solid #fff; + color: #fff; + cursor:crosshair; +} +table.col{ + position: relative; + + text-align: center; + border-collapse: collapse; +} +table.col td{ + background-color: #4DB6AC; +} +#arrColMark td{ + width: 16px; +} +#arrColMark { + top: 2px; + left: 36px; + width: 385px; + height: 16px; + font-size: 13px; +} +#mapColMark { + top: 2px; + left: 19px; + width: 418px; + height: 16px; + font-size: 13px; +} +#mapColMark td{ + width: 29px; +} +#mapColMark td:hover .colBlock{ + position: absolute; + top: 19px; + height: 416px; + width: 32px; + z-index: 100; + background-color: rgba(38,166,154,.5); +} +table.row{ + position: relative; + text-align: right; + vertical-align:middle; + border-collapse: collapse; +} +table.row td{ + background-color: #4C221B; +} +#arrRowMark{ + top: 5px; + left: 2px; + width: 16px; + height: 262px; + font-size: 12px; +} +#mapRowMark{ + top: 1px; + left: 2px; + width: 16px; + height: 416px; + font-size: 12px; +} +#mapRowMark td{ + height: 29px; +} +#mapRowMark td:hover .rowBlock{ + position: absolute; + left: 18px; + height: 32px; + width: 416px; + z-index: 100; + background-color: rgba(76,34,27,.5); +} +/* for vue dom */ +[v-cloak] { + display: none !important; +} diff --git a/_server/vm.js b/_server/vm.js index e198d040..4c1644bf 100644 --- a/_server/vm.js +++ b/_server/vm.js @@ -187,7 +187,7 @@ var tip = new Vue({ isClearBlock: false, geneMapSuccess: false, timer: null, - msgs: [ //分别编号1,2,3,4,5,6,7,8;奇数警告,偶数成功 + msgs: [ //分别编号1,2,3,4,5,6,7,8,9,10;奇数警告,偶数成功 "当前未选择任何图块,请先在右边选择要画的图块!", "生成地图成功!可点击复制按钮复制地图数组到剪切板", "生成失败! 地图中有未定义的图块,建议先用其他有效图块覆盖或点击清除地图!", @@ -195,7 +195,9 @@ var tip = new Vue({ "复制失败!", "复制成功!可直接粘贴到楼层文件的地图数组中。", "复制失败!当前还没有数据", - "修改成功!可点击复制按钮复制地图数组到剪切板" + "修改成功!可点击复制按钮复制地图数组到剪切板", + "选择背景图片失败!文件名格式错误或图片不存在!", + "更新背景图片成功!", ], mapMsg: '', whichShow: 0, @@ -255,12 +257,31 @@ var bgSelect = new Vue({ el: '#bgSelect', data: { bgs: {}, - selectedBg: 'ground' + selectedBg: 'ground', + imgname: '' }, watch:{ selectedBg: function(){ editor.bgY = this.bgs.indexOf(this.selectedBg); editor.drawMapBg(); } + }, + methods: { + updatebg: function(){ + tip.whichShow = 0; + var regx = /\S+\.(png|bmp|jpg|jpeg|gif)$/i; + if(regx.test(this.imgname)){ + var url = 'images/'+this.imgname; + editor.loadImg(url).then(function(img){ + editor.drawMapBg(img); + tip.whichShow = 10; + }).catch(function(err){ + console.log(err); + tip.whichShow = 9; + }); + }else{ + tip.whichShow = 9; + } + } } }) \ No newline at end of file diff --git a/docs/event.md b/docs/event.md index a1525c3c..2f283b69 100644 --- a/docs/event.md +++ b/docs/event.md @@ -29,6 +29,7 @@ "x,y": { "trigger": "action", // 触发的trigger, action代表自定义事件 "enable": true, // 该事件初始状态下是否处于启用状态 + "noPass": true, // 该点是否不可通行。true代表不可通行,false代表可通行。 "data": [ // 实际执行的事件列表 // 事件1 // 事件2 @@ -53,6 +54,7 @@ "x,y": { // 除非你要覆盖该点已存在的系统默认事件,否则"trigger": "action"可以省略 "enable": true, // 该事件初始状态下是否处于启用状态 + "noPass": true, // 该点是否不可通行。true代表不可通行,false代表可通行。 "data": [ // 实际执行的事件列表 // 事件1 // 事件2 @@ -71,6 +73,28 @@ "x,y": { // 除非你要覆盖该点已存在的系统默认事件,否则"trigger": "action"可以省略 // 该事件初始状态下是启用状态,则可以省略"enable": true;如果是禁用状态则必须加上"enable": false + "noPass": true, // 该点是否不可通行。true代表不可通行,false代表可通行。 + "data": [ // 实际执行的事件列表 + // 事件1 + // 事件2 + // ... + ] + } +} +``` + +`"noPass"`为该点是否可通行的标记。`true`代表该点不可通行,`false`代表该点可通行。 + +对于目前所有的素材,都存在默认的是否可通行状态。如果你在该点指定`noPass`,则原本的可通行状态会被覆盖。 + +因此,除非你想覆盖默认的可通行选项(比如将一个空地设为不可通行),否则该项可以忽略。 + +``` js +"events": { // 该楼的所有可能事件列表 + "x,y": { + // 除非你要覆盖该点已存在的系统默认事件,否则"trigger": "action"可以省略 + // 该事件初始状态下是启用状态,则可以省略"enable": true;如果是禁用状态则必须加上"enable": false + // 除非你想覆盖系统默认的可通行状态,否则"noPass"项可以忽略 "data": [ // 实际执行的事件列表 // 事件1 // 事件2 @@ -86,7 +110,7 @@ ``` js "events": { // 该楼的所有可能事件列表 - // 如果大括号里只有"data"项(没有"action"或"enable"),则可以省略到只剩下中括号 + // 如果大括号里只有"data"项(没有"action", "enable"或"noPass"),则可以省略到只剩下中括号 "x,y": [ // 实际执行的事件列表 // 事件1 // 事件2 @@ -97,7 +121,7 @@ 这种简写方式可以极大方便地造塔者进行造塔。 -!> **请注意:如果该点初始的`enable`为`false`,或者该点本身有系统默认事件且需要覆盖(`trigger`),则必须采用上面那种大括号写的方式来定义。** +!> **请注意:如果该点初始的`enable`为`false`,或者该点本身有系统默认事件且需要覆盖(`trigger`),或者你想覆盖该点的默认通行状态,则必须采用上面那种大括号写的方式来定义。**   diff --git a/docs/personalization.md b/docs/personalization.md index d63c4883..8e5eca3f 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -21,6 +21,41 @@ 如果你需要某个素材已经存在,则可以直接将其覆盖images目录下的同名文件,就能看到效果。 +### 使用自己的图片作为某层楼的背景素材 + +由于HTML5功能(素材)有限,导致了对很多比较复杂的素材(比如房子内)等无法有着较好的绘图方式。 + +为了解决这个问题,我们允许用户自己放置一张图片作为某一层的背景素材。 + +要启用这个功能,我们首先需要在`main.js`中将可能的图片进行加载。 + +``` js +this.pngs = [ // 在此存放所有可能的背景图片;背景图片最好是416*416像素,其他分辨率会被强制缩放成416*416 + // 建议对于较大的图片,在网上使用在线的“图片压缩工具”来进行压缩,以节省流量 + "bg.png", // "yewai.png", +]; +``` + +!> 背景素材只支持png格式,且会被强制缩放到416*416。 + +!> 请使用网上的一些[在线图片压缩工具](http://www.asqql.com/gifzip/)对png图片进行压缩,以节省流量。一张500KB的png图片可以被压缩到20-30KB,显示效果不会有太大差异。 + +之后,我们可以在每层剧本的`"png": "xxx"`里来定义该层的默认背景图片素材。 + +``` js +"png": "bg.png", // 背景图;你可以选择一张png图片来作为背景素材。 +``` + +你的图片背景素材将会覆盖原来本身的背景层。 + +**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。 + +``` js +"events": { + "x,y": {"noPass": true} // (x,y)点不可通行 +} +``` + ### 使用便捷PS工具生成素材 如果我们有更多的素材要求,我们可以使用“便捷PS工具”进行处理。 @@ -52,7 +87,6 @@ 如果需要添加一个素材到游戏,则必须为其分配一个唯一标识符,并同时修改`icons.js`和`maps.js`两个文件。 - #### 新添加自定义地形(路面、墙壁等) 如果你在terrains.png中新增了一行: diff --git a/drawMapGUI.html b/drawMapGUI.html index 1b76a04a..0ea0b61f 100644 --- a/drawMapGUI.html +++ b/drawMapGUI.html @@ -2,304 +2,7 @@ - +
@@ -349,14 +52,19 @@
+
+ 当前地板: - 当前地板: {{ selectedBg }} +
+ + +
@@ -396,14 +104,9 @@