Light Effect & V2.4.1

This commit is contained in:
ckcz123 2018-09-18 18:03:42 +08:00
parent 64e39b8da6
commit 99697ddbbf
13 changed files with 141 additions and 52 deletions

View File

@ -8,8 +8,9 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
* [List / HTML5魔塔游戏列表](https://h5mota.com/)
* [Demo / 样板效果](https://ckcz123.com/games/template/)
* [Docs / 使用文档说明](https://ckcz123.github.io/mota-js/)
<!--
* [Video / 视频教程](http://www.bilibili.com/video/av17608025/)
-->
![样板](./docs/img/sample0.png)
## 目录结构
@ -53,6 +54,19 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明
### 2018.9.18 V2.4.1
* [x] 增加背景层和前景层的图块绘制,多层图块可叠加
* [x] 背景层/前景层图块的显示、隐藏、修改等事件
* [x] 专门的装备页面Q键开启装备系统大改造
* [x] 灯光和漆黑层效果,通过插件函数方式给出
* [x] 将状态栏更新和阻激夹域的计算移动到脚本编辑中
* [x] 增加控制免疫阻激夹域的flag:no_zone等
* [x] 打字机效果时点击显示全部文字
* [x] 修复更改画面色调的Bug
* [x] 修复更改剧情文本属性后读档恢复原样的问题
* [x] 部分细节优化
### 2018.8.28 V2.4
* [x] 大地图的支持
@ -293,7 +307,7 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
- [JS代码压缩工具](http://github.com/ckcz123/JSCompressor/)能对Javascript代码进行压缩和整合从而减少IO请求量。
- [便捷PS工具](http://github.com/ckcz123/ps/)能只用复制和粘贴来快速对素材进行PS操作。
- [地图生成器](http://github.com/ckcz123/map_generator/):能从一张截图识别出来具体的数字数组,方便复刻已有的塔。
- [怪物数据导出器](http://github.com/ckcz123/enemy_export/)能从RMXP中带出怪物数据以供H5使用。
- [怪物数据导出器](http://github.com/ckcz123/enemy_export/)能从RMXP中导出怪物数据以供H5使用。
- [伤害和临界值计算器](http://github.com/ckcz123/magic-tower-calculator/):一个能帮助计算怪物的伤害和临界值的小工具。
## 联系我们

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
# 事件
?> 目前版本**v2.4**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
本章内将对样板所支持的事件进行介绍。

View File

@ -1,6 +1,6 @@
# HTML5 魔塔样板说明文档
?> 目前版本**v2.4**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。
@ -12,9 +12,9 @@
> 这个魔塔样板可以让你在完全不懂任何编程的情况下做出自己的H5魔塔。不会代码没关系只要你想做就能做出来
继续查看文档的详细介绍让你学会如何使用这一个样板来制作属于自己的HTML5魔塔。
<!--
视频教程地址:[http://www.bilibili.com/video/av17608025/](http://www.bilibili.com/video/av17608025/) ,配合本教程观看效果更佳~
-->
==========================================================================================
[继续阅读下一章现在就做出自己的第一部H5魔塔](start)

View File

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

View File

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

View File

@ -567,6 +567,8 @@ ui.prototype.drawTextBox = function(content, showAll) {
////// 绘制一个选项界面 //////
ui.prototype.drawChoices = function(content, choices) {
choices = choices || [];
var background = core.canvas.ui.createPattern(core.material.ground, "repeat");
core.clearMap('ui');
@ -577,7 +579,15 @@ ui.prototype.drawChoices = function(content, choices) {
// Step 1: 计算长宽高
var length = choices.length;
var left=85, width = 416-2*left; // 宽度
// 宽度计算:考虑选项的长度
var width = 416 - 2*85;
core.setFont('ui', "bold 17px Verdana");
for (var i = 0; i < choices.length; i++) {
width = Math.max(width, core.canvas.ui.measureText(core.replaceText(choices[i].text || choices[i])).width + 30);
}
var left=parseInt((416 - width) / 2); // 左边界
// 高度
var height = 32*(length+2), bottom = 208+height/2;
if (length%2==0) bottom+=16;
@ -693,8 +703,9 @@ ui.prototype.drawChoices = function(content, choices) {
content_top = top+55;
var title_offset = left+width/2;
// 动画
if (id=='hero' || core.isset(icon))
title_offset += 22;
title_offset += 12;
if (id == 'hero') {
var heroHeight = core.material.icons.hero.height;
@ -1872,7 +1883,7 @@ ui.prototype.drawEquipbox = function(index) {
// 个数
if (core.itemCount(ownEquip)>1)
core.fillText('ui', core.itemCount(ownEquip), 16*(4*(i%6)+1)+40, 304+Math.floor(i/6)*54+38-ydelta, '#FFFFFF', "bold 14px Verdana");
if (selectId == ownEquip)
if (index>=12 && selectId == ownEquip)
core.strokeRect('ui', 16*(4*(i%6)+1)+1, 304+Math.floor(i/6)*54+1-ydelta, 40, 40, '#FFD700');
}

View File

@ -2,7 +2,7 @@ function main() {
//------------------------ 用户修改内容 ------------------------//
this.version = "2.4"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.version = "2.4.1"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.useCompress = false; // 是否使用压缩文件
// 当你即将发布你的塔时请使用“JS代码压缩工具”将所有js代码进行压缩然后将这里的useCompress改为true。

View File

@ -60,7 +60,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"firstData": {
"title": "魔塔样板",
"name": "template",
"version": "Ver 2.4",
"version": "Ver 2.4.1",
"floorId": "sample0",
"hero": {
"name": "阳光",
@ -200,8 +200,8 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"bombFourDirections": false,
"snowFourDirections": false,
"bigKeyIsBox": false,
"equipment": true,
"equipboxButton": true,
"equipment": false,
"equipboxButton": false,
"enableAddPoint": false,
"enableNegativeDamage": false,
"hatredDecrease": true,

View File

@ -1,7 +1,7 @@
functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
{
"events": {
"initGame": function() {
"events": {
"initGame": function() {
// 游戏开始前的一些初始化操作
// 根据flag来对道具进行修改
@ -32,7 +32,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.material.items.shield5.cls = 'equips';
}
},
"setInitData": function (hard) {
"setInitData": function (hard) {
// 不同难度分别设置初始属性
if (hard=='Easy') { // 简单难度
core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度
@ -52,7 +52,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
}
core.events.afterLoadData();
},
"win": function(reason, norank) {
"win": function(reason, norank) {
// 游戏获胜事件
core.ui.closePanel();
var replaying = core.status.replay.replaying;
@ -71,7 +71,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
})
});
},
"lose": function(reason) {
"lose": function(reason) {
// 游戏失败事件
core.ui.closePanel();
var replaying = core.status.replay.replaying;
@ -84,7 +84,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
});
})
},
"afterChangeFloor": function (floorId, fromLoad) {
"afterChangeFloor": function (floorId, fromLoad) {
// 转换楼层结束的事件
// floorId是切换到的楼层fromLoad若为true则代表是从读档行为造成的楼层切换
if (!core.hasFlag("visited_"+floorId)) {
@ -92,7 +92,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.setFlag("visited_"+floorId, true);
}
},
"addPoint": function (enemy) {
"addPoint": function (enemy) {
// 加点事件
var point = enemy.point;
if (!core.flags.enableAddPoint || !core.isset(point) || point<=0) return [];
@ -114,7 +114,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
}
];
},
"afterBattle": function(enemyId,x,y,callback) {
"afterBattle": function(enemyId,x,y,callback) {
// 战斗结束后触发的事件
var enemy = core.material.enemys[enemyId];
@ -235,7 +235,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
if (core.isset(callback)) callback();
},
"afterOpenDoor": function(doorId,x,y,callback) {
"afterOpenDoor": function(doorId,x,y,callback) {
// 开一个门后触发的事件
var todo = [];
@ -258,7 +258,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
}
if (core.isset(callback)) callback();
},
"afterGetItem": function(itemId,x,y,callback) {
"afterGetItem": function(itemId,x,y,callback) {
// 获得一个道具后触发的事件
var todo = [];
@ -275,11 +275,11 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
if (core.isset(callback)) callback();
},
"afterChangeLight": function(x,y) {
"afterChangeLight": function(x,y) {
// 改变亮灯之后,可以触发的事件
},
"afterPushBox": function () {
"afterPushBox": function () {
// 推箱子后的事件
var noBoxLeft = function () {
@ -302,7 +302,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
*/
}
},
"afterUseBomb": function () {
"afterUseBomb": function () {
// 使用炸弹/圣锤后的事件
// 这是一个使用炸弹也能开门的例子
@ -317,19 +317,19 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
*/
},
"beforeSaveData": function(data) {
"beforeSaveData": function(data) {
// 即将存档前可以执行的操作
},
"afterLoadData": function(data) {
"afterLoadData": function(data) {
// 读档事件后,载入事件前,可以执行的操作
// 怪物数据的动态修改迁移到了“脚本编辑 - updateEnemys”中详见文档说明
core.enemys.updateEnemys();
}
},
"enemys": {
"getSpecials": function() {
},
"enemys": {
"getSpecials": function() {
// 获得怪物的特殊属性,每一行定义一个特殊属性。
// 分为三项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述
// 可以直接写字符串也可以写个function将怪物传进去
@ -360,7 +360,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
[24, "激光", function (enemy) {return "经过怪物同行或同列时自动减生命"+(enemy.value||0)+"点";}]
];
},
"getDamageInfo": function (enemy, hero_hp, hero_atk, hero_def, hero_mdef) {
"getDamageInfo": function (enemy, hero_hp, hero_atk, hero_def, hero_mdef) {
// 获得战斗伤害信息(实际伤害计算函数)
// 怪物生命,怪物攻击、防御、特殊属性
@ -453,7 +453,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
"damage": damage
};
},
"updateEnemys": function () {
"updateEnemys": function () {
// 更新怪物数据,可以在这里对怪物属性和数据进行动态更新,详见文档——事件——怪物数据的动态修改
// 比如下面这个例子如果flag:xxx为真则将绿头怪的攻击设为100金币设为20
/*
@ -464,9 +464,9 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
*/
// 别忘了在事件中调用“更新怪物数据”事件!
}
},
"control": {
"updateStatusBar": function () {
},
"control": {
"updateStatusBar": function () {
// 更新状态栏
// 检查等级
@ -532,7 +532,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 更新全地图显伤
core.updateDamage();
},
"updateCheckBlock": function () {
"updateCheckBlock": function () {
// 领域、夹击、阻击等的伤害值计算
core.status.checkBlock = {};
@ -652,7 +652,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 计算夹击伤害
if (has) {
core.status.checkBlock.betweenAttack[x+core.bigmap.width*y]=true;
// 先扣除该点领域/阻击/激光造成的伤害,再算夹击
// 先扣除该点领域/阻击/激光造成的伤害,再算夹击
var leftHp = core.status.hero.hp - core.status.checkBlock.damage[x+core.bigmap.width*y];
// 1血不夹core.flags.betweenAttackCeil控制向上还是向下
if (leftHp>1)
@ -662,9 +662,9 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
}
}
}
},
"ui": {
"drawAbout": function() {
},
"ui": {
"drawAbout": function() {
// 绘制“关于”界面
if (!core.isPlaying()) {
core.status.event = {'id': null, 'data': null};
@ -691,9 +691,9 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.fillText('ui', 'HTML5魔塔交流群539113091', text_start, top+112+32);
// TODO: 写自己的“关于”页面每次增加32像素即可
}
},
"plugins": {
"plugin": function () {
},
"plugins": {
"plugin": function () {
////// 插件编写,可以在这里写自己额外需要执行的脚本 //////
// 在这里写的代码,在所有模块加载完毕后,游戏开始前会被执行
@ -706,10 +706,74 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 如果不写this的话函数将无法被外部所访问
this.test = function () {
console.log("插件函数执行测试");
};
// 绘制灯光/漆黑层效果。调用方式 core.plugin.drawLight(...)
// 【参数说明】
// color可选灯光以外部分的颜色可以是一个四元数组或者简单的一个0到1之间的数。忽略则默认为0.9。
// 如果是四元数组则代表RGBA值如 [255,255,0,0.2] 就代表 #FFFF00 且不透明度0.2
// 如果是一个数则只是不透明度的值RGB均为0如 0.9 就代表 [0,0,0,0.9]
// lights可选一个数组定义了每个独立的灯光。
// 其中每一项是三元组 [x,y,r] 或者四元组 [x,y,r,o]
// x和y分别为该灯光的横纵坐标r为该灯光的半径o为该灯光中心的不透明度可忽略默认为0。
// lightDec可选0到1之间光从多少百分比才开始衰减在此范围内保持全亮不设置默认为0。
// 比如lightDec为0.5代表每个灯光部分内圈50%的范围全亮50%以后才开始快速衰减。
// 【调用样例】
// core.plugin.drawLight(); // 绘制一个0.9的全图不透明度,等价于更改画面色调为[0,0,0,0.9]。
// core.plugin.drawLight(0.95, [[25,11,46]]); // 全图不透明度0.95,其中在(25,11)点存在一个半径为46的灯光效果。
// core.plugin.drawLight([255,255,0,0.2], [[25,11,46,0.1]]); // 全图为不透明度0.2的黄色,其中在(25,11)点存在一个半径为46的灯光效果灯光中心不透明度0.1。
// core.plugin.drawLight(0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 存在三个灯光效果,分别是中心(25,11)半径46中心(105,121)半径88中心(301,221)半径106。
// core.plugin.drawLight([0,0,255,0.3], [[25,11,46],[105,121,88,0.2]], 0.4); // 存在两个灯光效果它们在内圈40%范围内保持全亮且40%后才开始衰减。
// 【注意事项】
// 此函数会和更改画面色调发生冲突,请只选择一个使用。
this.drawLight = function (color, lights, lightDec) {
// 清空色调层
var ctx = core.canvas.curtain;
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.msImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
core.clearMap('curtain');
core.setOpacity('curtain', 1);
core.setAlpha('curtain', 1);
// 绘制色调层,默认不透明度
if (!core.isset(color)) color = 0.9;
if (typeof color == "number") color = [0,0,0,color];
core.fillRect('curtain', 0, 0, 416, 416,
'rgba('+color[0]+','+color[1]+','+color[2]+','+core.clamp(color[3],0,1)+')');
// 绘制每个灯光效果
if (!core.isset(lights) || lights.length==0) return;
lightDec = core.clamp(lightDec, 0, 1);
lights.forEach(function (light) {
// 坐标,半径,中心不透明度
var x = light[0], y = light[1], r = light[2], o = 255 * (1 - core.clamp(light[3], 0, 1));
// 计算衰减距离
var decDistance = parseInt(r * lightDec), leftDistance = r - decDistance;
// 正方形区域的直径和左上角坐标
var d = r * 2, sx = x - r, sy = y - r;
// 获得正方形区域的颜色信息
var imageData = ctx.getImageData(sx, sy, d, d);
// 对每个像素点进行遍历
for (var i = 0; i < imageData.data.length; i+=4) {
// 当前点的坐标
var index = i / 4, cx = parseInt(index/d), cy = index%d;
// 当前点距离中心点的距离
var dx = r - cx, dy = r - cy, distance = Math.sqrt(dx*dx+dy*dy);
if (distance >= r) continue;
// 计算当前点的alpha值
var alpha = imageData.data[i+3] - (distance<decDistance?1:(r-distance)/leftDistance)*o;
imageData.data[i+3] = core.clamp(alpha, 0, 255);
}
ctx.putImageData(imageData, sx, sy);
});
}
// 可以在任何地方如afterXXX或自定义脚本事件调用函数方法为 core.plugin.xxx();
}
}
}
}

View File

@ -3,7 +3,7 @@
增加背景层和前景层的图块绘制,多层图块可叠加
背景层/前景层图块的显示、隐藏、修改等事件
专门的装备页面Q键开启装备系统大改造
仿RM的灯光效果,通过插件函数方式给出
灯光和漆黑层效果,通过插件函数方式给出
将状态栏更新和阻激夹域的计算移动到脚本编辑中
增加控制免疫阻激夹域的flag:no_zone等
打字机效果时点击显示全部文字