commit
91077ebf15
@ -62,7 +62,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏!
|
||||
* [x] \r[red]可以动态调整剧情文本的颜色
|
||||
* [x] 升级事件改用事件编辑器完成
|
||||
* [x] 每层楼都增添该层的并行事件处理
|
||||
* [x] 新增快捷键:N返回标题;P查看评论;O打开工程
|
||||
* [x] 新增快捷键:N返回标题;P游戏主页;O打开工程
|
||||
* [x] 新增事件:设置全局属性或全局数值
|
||||
* [x] 新增事件:隐藏/显示状态栏
|
||||
* [x] 道具可以设置是否在回放时绘制道具栏或直接使用
|
||||
|
||||
@ -270,6 +270,7 @@ action
|
||||
| showGif_1_s
|
||||
| setFg_0_s
|
||||
| setFg_1_s
|
||||
| screenFlash_s
|
||||
| setWeather_s
|
||||
| move_s
|
||||
| moveHero_s
|
||||
@ -1155,6 +1156,29 @@ var code = '{"type": "setFg"'+Int_0 +async+'},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
screenFlash_s
|
||||
: '画面闪烁' Number ',' Number ',' Number '强度' Number '单次时间' Int '执行次数' Int? '不等待执行完毕' Bool Newline
|
||||
|
||||
/* screenFlash_s
|
||||
tooltip : screenFlash: 画面闪烁,动画时间可不填
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=screenFlash%EF%BC%9A%E7%94%BB%E9%9D%A2%E9%97%AA%E7%83%81
|
||||
default : [255,255,255,1,500,1,false]
|
||||
colour : this.soundColor
|
||||
var limit = function(v,min,max) {
|
||||
if(v>max) return max;
|
||||
if(v<min) return min;
|
||||
return v;
|
||||
}
|
||||
Number_0 = limit(Number_0,0,255);
|
||||
Number_1 = limit(Number_1,0,255);
|
||||
Number_2 = limit(Number_2,0,255);
|
||||
Number_3 = limit(Number_3,0,1);
|
||||
Int_1 = Int_1!=='' ?(', "times": '+Int_1):'';
|
||||
var async = Bool_0?', "async": true':'';
|
||||
var code = '{"type": "screenFlash", "color": ['+Number_0+','+Number_1+','+Number_2+','+Number_3+'], "time": '+Int_0 +Int_1+async+'},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
setWeather_s
|
||||
: '更改天气' Weather_List '强度' Int Newline
|
||||
|
||||
@ -2140,6 +2164,10 @@ ActionParser.prototype.parseAction = function() {
|
||||
data.time||0,data.async||false,this.next]);
|
||||
}
|
||||
break;
|
||||
case "screenFlash": // 画面闪烁
|
||||
this.next = MotaActionBlocks['screenFlash_s'].xmlText([
|
||||
data.color[0],data.color[1],data.color[2],data.color[3]||1,data.time||500,data.times||1,data.async||false,this.next]);
|
||||
break;
|
||||
case "setWeather": // 更改天气
|
||||
this.next = MotaActionBlocks['setWeather_s'].xmlText([
|
||||
data.name||'无',data.level||1,this.next]);
|
||||
|
||||
@ -838,6 +838,11 @@ editor.prototype.listen = function () {
|
||||
var reDo = null;
|
||||
var shortcut = core.getLocalStorage('shortcut',{48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0});
|
||||
document.body.onkeydown = function (e) {
|
||||
|
||||
// 如果是开启事件/脚本编辑器状态,则忽略
|
||||
if (editor_multi.id!="" || editor_blockly.id!="")
|
||||
return;
|
||||
|
||||
// 禁止快捷键的默认行为
|
||||
if (e.ctrlKey && [89, 90, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1)
|
||||
e.preventDefault();
|
||||
@ -898,15 +903,18 @@ editor.prototype.listen = function () {
|
||||
printf('已保存该快捷图块, ctrl + '+(e.keyCode-48)+' 使用.')
|
||||
core.setLocalStorage('shortcut',shortcut);
|
||||
}
|
||||
// wasd平移大地图
|
||||
if (e.keyCode==87)
|
||||
editor.moveViewport(0,-1)
|
||||
else if (e.keyCode==65)
|
||||
editor.moveViewport(-1,0)
|
||||
else if (e.keyCode==83)
|
||||
editor.moveViewport(0,1);
|
||||
else if (e.keyCode==68)
|
||||
editor.moveViewport(1,0);
|
||||
var focusElement = document.activeElement;
|
||||
if (!focusElement || focusElement.tagName.toLowerCase()=='body') {
|
||||
// wasd平移大地图
|
||||
if (e.keyCode==87)
|
||||
editor.moveViewport(0,-1)
|
||||
else if (e.keyCode==65)
|
||||
editor.moveViewport(-1,0)
|
||||
else if (e.keyCode==83)
|
||||
editor.moveViewport(0,1);
|
||||
else if (e.keyCode==68)
|
||||
editor.moveViewport(1,0);
|
||||
}
|
||||
}
|
||||
|
||||
var dataSelection = document.getElementById('dataSelection');
|
||||
|
||||
@ -140,6 +140,7 @@ editor_blockly = function () {
|
||||
MotaActionBlocks['hideStatusBar_s'].xmlText(),
|
||||
MotaActionBlocks['setFg_0_s'].xmlText(),
|
||||
MotaActionBlocks['setFg_1_s'].xmlText(),
|
||||
MotaActionBlocks['screenFlash_s'].xmlText(),
|
||||
MotaActionBlocks['setWeather_s'].xmlText(),
|
||||
MotaActionBlocks['playBgm_s'].xmlText(),
|
||||
MotaActionBlocks['pauseBgm_s'].xmlText(),
|
||||
|
||||
13
docs/api.md
13
docs/api.md
@ -467,25 +467,24 @@ core.maps.removeBlockByIds(floorId, ids)
|
||||
ui.js主要用来进行UI窗口的绘制,比如对话框、怪物手册、楼传器、存读档界面等等。
|
||||
|
||||
|
||||
core.ui.getContextByName(name)
|
||||
core.ui.getContextByName(canvas)
|
||||
根据画布名找到一个画布的context;支持系统画布和自定义画布。如果不存在画布返回null。
|
||||
也可以传画布的context自身,则返回自己。
|
||||
|
||||
|
||||
core.clearMap(name)
|
||||
清空某个画布图层。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。(下同)
|
||||
如果name也可以是'all',若为all则为清空所有系统画布。
|
||||
|
||||
|
||||
core.ui.fillText(name, text, x, y, style, font)
|
||||
在某个画布上绘制一段文字。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名。(下同)
|
||||
text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。
|
||||
text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。(下同)
|
||||
|
||||
|
||||
core.ui.fillBoldText(canvas, text, style, x, y, font)
|
||||
core.ui.fillBoldText(name, text, style, x, y, font)
|
||||
在某个画布上绘制一个描黑边的文字。
|
||||
canvas为要绘制的画布的context,text为文本,style为颜色样式,x,y坐标,font可选为要绘制的字体。
|
||||
|
||||
|
||||
core.ui.fillRect(name, x, y, width, height, style)
|
||||
@ -531,7 +530,7 @@ font可选,如果存在则会先设置该画布上的字体。
|
||||
|
||||
core.ui.drawImage(name, image, x, y, w, h, x1, y1, w1, h1)
|
||||
在一个画布上绘制图片。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。
|
||||
image为要绘制的图片,可以是一个全塔属性中定义的图片名(会从images中去获取),图片本身,或者一个画布。
|
||||
后面的8个坐标参数与canvas的drawImage的八个参数完全相同。
|
||||
请查看 http://www.w3school.com.cn/html5/canvas_drawimage.asp 了解更多。
|
||||
|
||||
@ -473,7 +473,7 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回
|
||||
- **[G]** 打开/关闭楼层传送器
|
||||
- **[A]** 读取自动存档
|
||||
- **[S/D]** 打开/关闭存/读档页面
|
||||
- **[K/V]** 打开/关闭快捷商店选择列表
|
||||
- **[V]** 打开/关闭快捷商店选择列表
|
||||
- **[T]** 打开/关闭工具栏
|
||||
- **[Q]** 打开/关闭装备栏
|
||||
- **[ESC]** 打开/关闭系统菜单
|
||||
|
||||
@ -1061,6 +1061,27 @@ time为可选的,如果指定,则会作为更改画面色调的时间。
|
||||
|
||||
async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。
|
||||
|
||||
### screenFlash:画面闪烁
|
||||
|
||||
我们可以使用 `{"type": "screenFlash"}` 来进行画面闪烁。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
{"type": "screenFlash", "color": [255,255,255,0.6], "time": 500, "times": 1}, // 闪光为白色,不透明度0.6,动画时间1000毫秒
|
||||
{"type": "screenFlash", "color": [255,0,0,1], "time": 100, "times": 2, "async": true}, // 闪光为红色,强度最大,动画时间100毫秒,闪烁两次且异步执行
|
||||
]
|
||||
```
|
||||
|
||||
color为闪光的颜色。它是一个数组,分别指定目标颜色的R,G,B,A值。
|
||||
- 常见RGB颜色: 纯黑[0,0,0],纯白[255,255,255],纯红[255,0,0],等等。
|
||||
A即闪光的不透明度,为一个0到1之间的数,值越高闪烁效果越强。默认为1
|
||||
|
||||
time为闪烁时间,默认值为500
|
||||
|
||||
times为闪烁次数,两次闪烁会连续进行,默认值为1
|
||||
|
||||
async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。
|
||||
|
||||
### setWeather:更改天气
|
||||
|
||||
我们可以使用 `{"type": "setWeather"}` 来更改天气。
|
||||
|
||||
@ -196,10 +196,14 @@ actions.prototype.keyUp = function(keyCode, altKey, fromReplay) {
|
||||
if (!fromReplay && core.isset(core.status.replay)&&core.status.replay.replaying
|
||||
&&core.status.event.id!='save'&&(core.status.event.id||"").indexOf('book')!=0&&core.status.event.id!='viewMaps') return;
|
||||
|
||||
var ok = function (keycode) {
|
||||
return keycode==27 || keycode==88 || keycode==13 || keycode==32 || keycode==67;
|
||||
}
|
||||
|
||||
if (core.status.lockControl) {
|
||||
core.status.holdingKeys = [];
|
||||
// 全键盘操作部分
|
||||
if (core.status.event.id == 'text' && (keyCode==13 || keyCode==32 || keyCode==67)) {
|
||||
if (core.status.event.id == 'text' && ok(keyCode)) {
|
||||
core.drawText();
|
||||
return;
|
||||
}
|
||||
@ -211,15 +215,19 @@ actions.prototype.keyUp = function(keyCode, altKey, fromReplay) {
|
||||
this.keyUpAction(keyCode);
|
||||
return;
|
||||
}
|
||||
if (core.status.event.id=='about' && (keyCode==13 || keyCode==32 || keyCode==67)) {
|
||||
if (core.status.event.id=='about' && ok(keyCode)) {
|
||||
this.clickAbout();
|
||||
return;
|
||||
}
|
||||
if (core.status.event.id=='help' && ok(keyCode)) {
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
if (core.status.event.id=='book') {
|
||||
this.keyUpBook(keyCode);
|
||||
return;
|
||||
}
|
||||
if (core.status.event.id=='book-detail' && (keyCode==13 || keyCode==32 || keyCode==67)) {
|
||||
if (core.status.event.id=='book-detail' && ok(keyCode)) {
|
||||
this.clickBookDetail();
|
||||
return;
|
||||
}
|
||||
@ -251,6 +259,10 @@ actions.prototype.keyUp = function(keyCode, altKey, fromReplay) {
|
||||
this.keyUpSL(keyCode);
|
||||
return;
|
||||
}
|
||||
if (core.status.event.id == 'keyBoard' && ok(keyCode)) {
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
if (core.status.event.id=='switchs') {
|
||||
this.keyUpSwitchs(keyCode);
|
||||
return;
|
||||
@ -551,6 +563,11 @@ actions.prototype.onclick = function (x, y, stepPostfix) {
|
||||
this.clickAbout(x,y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (core.status.event.id == 'help') {
|
||||
this.clickHelp(x,y);
|
||||
return;
|
||||
}
|
||||
|
||||
if (core.status.event.id == 'action') {
|
||||
this.clickAction(x,y);
|
||||
@ -2604,6 +2621,10 @@ actions.prototype.clickAbout = function () {
|
||||
core.restart(true);
|
||||
}
|
||||
|
||||
////// “帮助”界面时的点击操作 //////
|
||||
actions.prototype.clickHelp = function () {
|
||||
core.ui.closePanel();
|
||||
}
|
||||
|
||||
////// 绘图相关 //////
|
||||
|
||||
|
||||
@ -76,15 +76,13 @@ control.prototype.setRequestAnimationFrame = function () {
|
||||
}
|
||||
|
||||
if ((core.status.autotileAnimateObjs.blocks||[]).length>0) {
|
||||
var groundId = (core.status.maps||core.floors)[core.status.floorId].defaultGround || "ground";
|
||||
var blockIcon = core.material.icons.terrains[groundId];
|
||||
core.status.autotileAnimateObjs.status++;
|
||||
core.status.autotileAnimateObjs.blocks.forEach(function (block) {
|
||||
var cv = core.isset(block.name)?core.canvas[block.name]:core.canvas.event;
|
||||
cv.clearRect(block.x * 32, block.y * 32, 32, 32);
|
||||
if (core.isset(block.name)) {
|
||||
if (block.name == 'bg') {
|
||||
core.drawImage('bg', core.material.images.terrains, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
|
||||
core.drawImage('bg', core.material.groundCanvas.canvas, block.x * 32, block.y * 32);
|
||||
}
|
||||
core.drawAutotile(cv, core.status.autotileAnimateObjs[block.name+"map"], block, 32, 0, 0, core.status.autotileAnimateObjs.status);
|
||||
}
|
||||
@ -1335,7 +1333,7 @@ control.prototype.setFg = function(color, time, callback) {
|
||||
core.status.curtainColor = [0,0,0,0];
|
||||
}
|
||||
|
||||
var fromColor = core.status.curtainColor;
|
||||
var nowColor = core.status.curtainColor;
|
||||
|
||||
if (!core.isset(color))
|
||||
color = [0,0,0,0];
|
||||
@ -1351,19 +1349,20 @@ control.prototype.setFg = function(color, time, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
var per_time = 10, step=0, steps = parseInt(time / per_time);
|
||||
var per_time = 10, step = parseInt(time / per_time);
|
||||
|
||||
var changeAnimate = setInterval(function() {
|
||||
step++;
|
||||
|
||||
var nowA = fromColor[3]+(color[3]-fromColor[3])*step/steps;
|
||||
var nowR = parseInt(fromColor[0]+(color[0]-fromColor[0])*step/steps);
|
||||
var nowG = parseInt(fromColor[1]+(color[1]-fromColor[1])*step/steps);
|
||||
var nowB = parseInt(fromColor[2]+(color[2]-fromColor[2])*step/steps);
|
||||
nowColor = [
|
||||
parseInt(nowColor[0]*(step-1)+color[0])/step,
|
||||
parseInt(nowColor[1]*(step-1)+color[1])/step,
|
||||
parseInt(nowColor[2]*(step-1)+color[2])/step,
|
||||
(nowColor[3]*(step-1)+color[3])/step,
|
||||
];
|
||||
core.clearMap('curtain');
|
||||
core.fillRect('curtain', 0, 0, 416, 416, core.arrayToRGBA([nowR,nowG,nowB,nowA]));
|
||||
core.fillRect('curtain', 0, 0, 416, 416, core.arrayToRGBA(nowColor));
|
||||
step--;
|
||||
|
||||
if (step>=steps) {
|
||||
if (step <= 0) {
|
||||
delete core.animateFrame.asyncId[changeAnimate];
|
||||
clearInterval(changeAnimate);
|
||||
core.status.curtainColor = color;
|
||||
@ -1375,6 +1374,22 @@ control.prototype.setFg = function(color, time, callback) {
|
||||
core.animateFrame.asyncId[changeAnimate] = true;
|
||||
}
|
||||
|
||||
////// 画面闪烁 //////
|
||||
control.prototype.screenFlash = function (color, time, times, callback) {
|
||||
times = times || 1;
|
||||
time = time/3;
|
||||
var nowColor = core.clone(core.status.curtainColor);
|
||||
core.setFg(color, time, function() {
|
||||
core.setFg(nowColor, time * 2, function() {
|
||||
if (times > 1)
|
||||
core.screenFlash(color, time * 3, times - 1, callback);
|
||||
else {
|
||||
if (core.isset(callback)) callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
////// 更新全地图显伤 //////
|
||||
control.prototype.updateDamage = function (floorId, canvas) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
@ -2077,10 +2092,10 @@ control.prototype.doSL = function (id, type) {
|
||||
}, function(err) {
|
||||
console.info(err);
|
||||
if (core.platform.useLocalForage) {
|
||||
alert("存档失败,请将控制台的报错信息反馈给管理员。");
|
||||
alert("存档失败,错误信息:\n"+err);
|
||||
}
|
||||
else {
|
||||
alert("存档空间不足,请先使用垃圾存档清理工具进行清理!");
|
||||
alert("存档失败,错误信息:\n"+err+"\n建议使用垃圾存档清理工具进行清理!");
|
||||
}
|
||||
})
|
||||
return;
|
||||
@ -2094,7 +2109,9 @@ control.prototype.doSL = function (id, type) {
|
||||
return;
|
||||
}
|
||||
if (core.isset(data.hashCode) && data.hashCode != core.utils.hashCode(data.hero)) {
|
||||
alert("存档校验失败,请勿修改存档文件!");
|
||||
if (confirm("存档校验失败,请勿修改存档文件!\n你想回放此存档的录像吗?")) {
|
||||
core.startGame(data.hard, data.hero.flags.__seed__, core.decodeRoute(data.route));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (data.version != core.firstData.version) {
|
||||
|
||||
27
libs/core.js
27
libs/core.js
@ -333,11 +333,9 @@ core.prototype.init = function (coreData, callback) {
|
||||
core.flags.displayCritical = core.getLocalStorage('critical', core.flags.displayCritical);
|
||||
core.flags.displayExtraDamage = core.getLocalStorage('extraDamage', core.flags.displayExtraDamage);
|
||||
|
||||
core.material.ground = new Image();
|
||||
core.material.ground.onload = function () {
|
||||
core.material.groundPattern = core.canvas.ui.createPattern(core.material.ground, "repeat");
|
||||
}
|
||||
core.material.ground.src = "project/images/ground.png";
|
||||
core.material.groundCanvas = document.createElement('canvas').getContext('2d');
|
||||
core.material.groundCanvas.canvas.width = core.material.groundCanvas.canvas.height = 32;
|
||||
core.material.groundPattern = core.material.groundCanvas.createPattern(core.material.groundCanvas.canvas, 'repeat');
|
||||
|
||||
core.animateFrame.weather.fog = new Image();
|
||||
core.animateFrame.weather.fog.onerror = function () {
|
||||
@ -345,6 +343,12 @@ core.prototype.init = function (coreData, callback) {
|
||||
}
|
||||
core.animateFrame.weather.fog.src = "project/images/fog.png";
|
||||
|
||||
core.material.images.keyboard = new Image();
|
||||
core.material.images.keyboard.onerror = function () {
|
||||
core.material.images.keyboard = null;
|
||||
}
|
||||
core.material.images.keyboard.src = "project/images/keyboard.png";
|
||||
|
||||
core.bigmap.tempCanvas = document.createElement('canvas').getContext('2d');
|
||||
|
||||
core.loader.load(function () {
|
||||
@ -632,8 +636,8 @@ core.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback,
|
||||
}
|
||||
|
||||
////// 从名字获得画布 //////
|
||||
core.prototype.getContextByName = function (name) {
|
||||
return core.ui.getContextByName(name);
|
||||
core.prototype.getContextByName = function (canvas) {
|
||||
return core.ui.getContextByName(canvas);
|
||||
}
|
||||
|
||||
////// 清除地图 //////
|
||||
@ -647,8 +651,8 @@ core.prototype.fillText = function (name, text, x, y, style, font) {
|
||||
}
|
||||
|
||||
////// 在某个canvas上绘制一段描边文字 //////
|
||||
core.prototype.fillBoldText = function (canvas, text, style, x, y, font) {
|
||||
core.ui.fillBoldText(canvas, text, style , x, y, font);
|
||||
core.prototype.fillBoldText = function (name, text, style, x, y, font) {
|
||||
core.ui.fillBoldText(name, text, style , x, y, font);
|
||||
}
|
||||
|
||||
////// 在某个canvas上绘制一个矩形 //////
|
||||
@ -923,6 +927,11 @@ core.prototype.setFg = function(color, time, callback) {
|
||||
core.control.setFg(color, time, callback);
|
||||
}
|
||||
|
||||
////// 画面闪烁 //////
|
||||
core.prototype.screenFlash = function (color, time, times, callback) {
|
||||
core.control.screenFlash(color, time, times, callback);
|
||||
}
|
||||
|
||||
////// 更新全地图显伤 //////
|
||||
core.prototype.updateDamage = function () {
|
||||
core.control.updateDamage();
|
||||
|
||||
@ -822,6 +822,17 @@ events.prototype.doAction = function() {
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "screenFlash": // 画面闪烁
|
||||
if (data.async) {
|
||||
core.screenFlash(data.color, data.time, data.times);
|
||||
this.doAction();
|
||||
}
|
||||
else {
|
||||
core.screenFlash(data.color, data.time, data.times, function() {
|
||||
core.events.doAction();
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "setWeather": // 更改天气
|
||||
core.setWeather(data.name, data.level);
|
||||
if (core.isset(data.name))
|
||||
|
||||
14
libs/maps.js
14
libs/maps.js
@ -377,9 +377,7 @@ maps.prototype.drawBlock = function (block, animate, dx, dy) {
|
||||
if (core.isset(block.name)) {
|
||||
core.canvas[block.name].clearRect(block.x * 32, block.y * 32, 32, 32);
|
||||
if (block.name == 'bg') {
|
||||
var groundId = (core.status.maps||core.floors)[core.status.floorId].defaultGround || "ground";
|
||||
var blockIcon = core.material.icons.terrains[groundId];
|
||||
core.drawImage('bg', core.material.images.terrains, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
|
||||
core.drawImage('bg', core.material.groundCanvas.canvas, block.x * 32, block.y * 32);
|
||||
}
|
||||
core.canvas[block.name].drawImage(image, x * 32, y * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
|
||||
return;
|
||||
@ -477,18 +475,22 @@ maps.prototype.drawMap = function (floorId, callback) {
|
||||
}
|
||||
core.clearMap('all');
|
||||
|
||||
var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground";
|
||||
core.material.groundCanvas.clearRect(0, 0, 32, 32);
|
||||
core.material.groundCanvas.drawImage(core.material.images.terrains, 0, 32*core.material.icons.terrains[groundId], 32, 32, 0, 0, 32, 32);
|
||||
core.material.groundPattern = core.material.groundCanvas.createPattern(core.material.groundCanvas.canvas, 'repeat');
|
||||
|
||||
var drawBg = function(){
|
||||
var width = core.floors[floorId].width || 13;
|
||||
var height = core.floors[floorId].height || 13;
|
||||
|
||||
var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground";
|
||||
var blockIcon = core.material.icons.terrains[groundId];
|
||||
for (var x = 0; x < width; x++) {
|
||||
for (var y = 0; y < height; y++) {
|
||||
core.drawImage('bg', core.material.images.terrains, 0, blockIcon * 32, 32, 32, x * 32, y * 32, 32, 32);
|
||||
core.drawImage('bg', core.material.groundCanvas.canvas, 32*x, 32*y);
|
||||
}
|
||||
}
|
||||
|
||||
// 获得image
|
||||
var images = [];
|
||||
if (core.isset(core.status.maps[floorId].images)) {
|
||||
images = core.status.maps[floorId].images;
|
||||
|
||||
200
libs/ui.js
200
libs/ui.js
@ -17,11 +17,16 @@ ui.prototype.init = function () {
|
||||
|
||||
////////////////// 地图设置
|
||||
|
||||
ui.prototype.getContextByName = function (name) {
|
||||
if (core.isset(core.canvas[name]))
|
||||
return core.canvas[name];
|
||||
if (core.isset(core.dymCanvas[name]))
|
||||
return core.dymCanvas[name];
|
||||
ui.prototype.getContextByName = function (canvas) {
|
||||
if (typeof canvas == 'string') {
|
||||
if (core.isset(core.canvas[canvas]))
|
||||
canvas = core.canvas[canvas];
|
||||
else if (core.isset(core.dymCanvas[canvas]))
|
||||
canvas = core.dymCanvas[canvas];
|
||||
}
|
||||
if (core.isset(canvas) && core.isset(canvas.canvas)) {
|
||||
return canvas;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -53,15 +58,17 @@ ui.prototype.fillText = function (name, text, x, y, style, font) {
|
||||
}
|
||||
|
||||
////// 在某个canvas上绘制粗体 //////
|
||||
ui.prototype.fillBoldText = function (canvas, text, style, x, y, font) {
|
||||
if (core.isset(font)) canvas.font = font;
|
||||
canvas.fillStyle = '#000000';
|
||||
canvas.fillText(text, x-1, y-1);
|
||||
canvas.fillText(text, x-1, y+1);
|
||||
canvas.fillText(text, x+1, y-1);
|
||||
canvas.fillText(text, x+1, y+1);
|
||||
canvas.fillStyle = style;
|
||||
canvas.fillText(text, x, y);
|
||||
ui.prototype.fillBoldText = function (name, text, style, x, y, font) {
|
||||
var ctx = this.getContextByName(name);
|
||||
if (!ctx) return;
|
||||
if (core.isset(font)) ctx.font = font;
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.fillText(text, x-1, y-1);
|
||||
ctx.fillText(text, x-1, y+1);
|
||||
ctx.fillText(text, x+1, y-1);
|
||||
ctx.fillText(text, x+1, y+1);
|
||||
ctx.fillStyle = style;
|
||||
ctx.fillText(text, x, y);
|
||||
}
|
||||
|
||||
////// 在某个canvas上绘制一个矩形 //////
|
||||
@ -94,12 +101,11 @@ ui.prototype.drawLine = function (name, x1, y1, x2, y2, style, lineWidth) {
|
||||
core.setLineWidth(name, lineWidth);
|
||||
}
|
||||
var ctx = this.getContextByName(name);
|
||||
if (ctx) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.lineTo(x2, y2);
|
||||
ctx.stroke();
|
||||
}
|
||||
if (!ctx) return;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.lineTo(x2, y2);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
////// 在某个canvas上绘制一个箭头 //////
|
||||
@ -112,18 +118,17 @@ ui.prototype.drawArrow = function (name, x1, y1, x2, y2, style, lineWidth) {
|
||||
core.setLineWidth(name, lineWidth);
|
||||
}
|
||||
var ctx = this.getContextByName(name);
|
||||
if (ctx) {
|
||||
var head = 10;
|
||||
var dx = x2-x1, dy=y2-y1;
|
||||
var angle = Math.atan2(dy,dx);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1,y1);
|
||||
ctx.lineTo(x2, y2);
|
||||
ctx.lineTo(x2-head*Math.cos(angle-Math.PI/6),y2-head*Math.sin(angle-Math.PI/6));
|
||||
ctx.moveTo(x2, y2);
|
||||
ctx.lineTo(x2-head*Math.cos(angle+Math.PI/6),y2-head*Math.sin(angle+Math.PI/6));
|
||||
ctx.stroke();
|
||||
}
|
||||
if (!ctx) return;
|
||||
var head = 10;
|
||||
var dx = x2-x1, dy=y2-y1;
|
||||
var angle = Math.atan2(dy,dx);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1,y1);
|
||||
ctx.lineTo(x2, y2);
|
||||
ctx.lineTo(x2-head*Math.cos(angle-Math.PI/6),y2-head*Math.sin(angle-Math.PI/6));
|
||||
ctx.moveTo(x2, y2);
|
||||
ctx.lineTo(x2-head*Math.cos(angle+Math.PI/6),y2-head*Math.sin(angle+Math.PI/6));
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
////// 设置某个canvas的文字字体 //////
|
||||
@ -200,14 +205,17 @@ ui.prototype.drawImage = function (name, image, x, y, w, h, x1, y1, w1, h1) {
|
||||
}
|
||||
|
||||
// 只能接受2, 4, 8个参数
|
||||
if (core.isset(x) && core.isset(y) && core.isset(w) && core.isset(h) && core.isset(x1) && core.isset(y1) && core.isset(w1) && core.isset(h1)) {
|
||||
ctx.drawImage(image, x, y, w, h, x1, y1, w1, h1);
|
||||
}
|
||||
else if (core.isset(x) && core.isset(y) && core.isset(w) && core.isset(h)) {
|
||||
ctx.drawImage(image, x, y, w, h);
|
||||
}
|
||||
else if (core.isset(x) && core.isset(y)) {
|
||||
if (core.isset(x) && core.isset(y)) {
|
||||
if (core.isset(w) && core.isset(h)) {
|
||||
if (core.isset(x1) && core.isset(y1) && core.isset(w1) && core.isset(h1)) {
|
||||
ctx.drawImage(image, x, y, w, h, x1, y1, w1, h1);
|
||||
return;
|
||||
}
|
||||
ctx.drawImage(image, x, y, w, h);
|
||||
return;
|
||||
}
|
||||
ctx.drawImage(image, x, y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,13 +432,12 @@ ui.prototype.drawWindowSkin = function(background,canvas,x,y,w,h,direction,px,py
|
||||
// 仿RM窗口皮肤 ↓
|
||||
var dstImage = core.getContextByName(canvas);
|
||||
if (!dstImage) return;
|
||||
var dx = 0, dy = 0;
|
||||
// 绘制背景
|
||||
dstImage.drawImage(background, 0, 0, 128, 128, x+2, y+2, w-4, h-4);
|
||||
// 绘制边框
|
||||
// 上方
|
||||
dstImage.drawImage(background, 128, 0, 16, 16, x, y, 16, 16);
|
||||
for (dx = 0; dx < w - 64; dx += 32) {
|
||||
for (var dx = 0; dx < w - 64; dx += 32) {
|
||||
dstImage.drawImage(background, 144, 0, 32, 16,x+dx+16, y, 32, 16);
|
||||
dstImage.drawImage(background, 144,48, 32, 16,x+dx+16, y+h-16, 32, 16);
|
||||
}
|
||||
@ -438,7 +445,7 @@ ui.prototype.drawWindowSkin = function(background,canvas,x,y,w,h,direction,px,py
|
||||
dstImage.drawImage(background, 144,48,w-dx-32, 16,x+dx+16, y+h-16,w-dx-32, 16);
|
||||
dstImage.drawImage(background, 176, 0, 16, 16, x+w-16, y, 16, 16);
|
||||
// 左右
|
||||
for (dy = 0; dy < h - 64; dy += 32) {
|
||||
for (var dy = 0; dy < h - 64; dy += 32) {
|
||||
dstImage.drawImage(background, 128,16, 16, 32, x,y+dy+16, 16, 32);
|
||||
dstImage.drawImage(background, 176,16, 16, 32, x+w-16,y+dy+16, 16, 32);
|
||||
}
|
||||
@ -1478,7 +1485,7 @@ ui.prototype.drawReplay = function () {
|
||||
ui.prototype.drawGameInfo = function () {
|
||||
core.status.event.id = 'gameInfo';
|
||||
this.drawChoices(null, [
|
||||
"数据统计", "查看工程", "查看评论", "操作帮助", "关于本塔","下载离线版本", "返回主菜单"
|
||||
"数据统计", "查看工程", "游戏主页", "操作帮助", "关于本塔","下载离线版本", "返回主菜单"
|
||||
]);
|
||||
}
|
||||
|
||||
@ -2499,16 +2506,37 @@ ui.prototype.drawKeyBoard = function () {
|
||||
|
||||
core.clearLastEvent();
|
||||
|
||||
var left = 16, top = 48, right = 416 - 2 * left, bottom = 416 - 2 * top;
|
||||
core.fillRect('ui', left, top, right, bottom, core.material.groundPattern);
|
||||
core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2);
|
||||
var left = 16, top = 48, width = 416 - 2 * left, height = 416 - 2 * top;
|
||||
|
||||
var background = core.status.textAttribute.background;
|
||||
var isWindowSkin = false;
|
||||
if (typeof background == 'string') {
|
||||
background = core.material.images.images[background];
|
||||
if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true;
|
||||
else background = core.initStatus.textAttribute.background;
|
||||
}
|
||||
if (!isWindowSkin) background = core.arrayToRGBA(background);
|
||||
var borderColor = core.status.globalAttribute.borderColor;
|
||||
var titleColor = core.arrayToRGBA(core.status.textAttribute.title);
|
||||
var textColor = core.arrayToRGBA(core.status.textAttribute.text);
|
||||
|
||||
core.clearMap('ui');
|
||||
if (isWindowSkin) {
|
||||
core.setAlpha('ui', 0.85);
|
||||
this.drawWindowSkin(background,'ui',left,top,width,height);
|
||||
}
|
||||
else {
|
||||
core.fillRect('ui', left, top, width, height, background);
|
||||
core.strokeRect('ui', left - 1, top - 1, width + 1, height + 1, borderColor, 2);
|
||||
}
|
||||
core.setAlpha('ui', 1);
|
||||
|
||||
core.setTextAlign('ui', 'center');
|
||||
var globalFont = core.status.globalAttribute.font;
|
||||
core.fillText('ui', "虚拟键盘", 208, top+35, "#FFD700", "bold 22px "+globalFont);
|
||||
core.fillText('ui', "虚拟键盘", 208, top+35, titleColor, "bold 22px "+globalFont);
|
||||
|
||||
core.setFont('ui', '17px '+globalFont);
|
||||
core.setFillStyle('ui', '#FFFFFF');
|
||||
core.setFillStyle('ui', textColor);
|
||||
var offset = 128-9;
|
||||
|
||||
var lines = [
|
||||
@ -2519,7 +2547,7 @@ ui.prototype.drawKeyBoard = function () {
|
||||
["Z","X","C","V","B","N","M"],
|
||||
["-","=","[","]","\\",";","'",",",".","/","`"],
|
||||
["ES","TA","CA","SH","CT","AL","SP","BS","EN","DE"]
|
||||
]
|
||||
];
|
||||
|
||||
lines.forEach(function (line) {
|
||||
for (var i=0;i<line.length;i++) {
|
||||
@ -2528,9 +2556,12 @@ ui.prototype.drawKeyBoard = function () {
|
||||
offset+=32;
|
||||
});
|
||||
|
||||
core.setTextAlign('ui', 'center');
|
||||
|
||||
core.fillText("ui", "返回游戏", 416-80, offset-3, '#FFFFFF', 'bold 15px '+globalFont);
|
||||
|
||||
if (isWindowSkin)
|
||||
this.drawWindowSelector(background, 300, offset - 22, 72, 27);
|
||||
else
|
||||
core.strokeRect('ui', 300, offset - 22, 72, 27, "#FFD700", 2);
|
||||
}
|
||||
|
||||
////// 绘制状态栏 /////
|
||||
@ -2580,7 +2611,7 @@ ui.prototype.drawStatistics = function () {
|
||||
var current = core.clone(total);
|
||||
|
||||
core.floorIds.forEach(function (floorId) {
|
||||
var floor=core.status.maps[floorId];
|
||||
var floor=core.status.maps[floorId]||core.floors[floorId];
|
||||
var blocks=core.status.maps[floorId].blocks;
|
||||
// 隐藏层不给看
|
||||
if (floor.cannotViewMap && floorId!=core.status.floorId) return;
|
||||
@ -2605,14 +2636,12 @@ ui.prototype.drawStatistics = function () {
|
||||
else {
|
||||
var id = event.id;
|
||||
|
||||
var temp = core.clone(core.status.hero);
|
||||
|
||||
core.setFlag("__statistics__", true);
|
||||
|
||||
if (core.isset(total.count[id])) {
|
||||
var hp=0, atk=0, def=0, mdef=0;
|
||||
|
||||
if (cls[id]=='items' && id!='superPotion') {
|
||||
var temp = core.clone(core.status.hero);
|
||||
core.setFlag("__statistics__", true);
|
||||
var ratio = floor.item_ratio||1;
|
||||
if (core.isset(core.items.itemEffect[id])) {
|
||||
try {
|
||||
@ -2625,6 +2654,7 @@ ui.prototype.drawStatistics = function () {
|
||||
atk = core.status.hero.atk - temp.atk;
|
||||
def = core.status.hero.def - temp.def;
|
||||
mdef = core.status.hero.mdef - temp.mdef;
|
||||
core.status.hero = temp;
|
||||
}
|
||||
else {
|
||||
// 装备
|
||||
@ -2644,7 +2674,6 @@ ui.prototype.drawStatistics = function () {
|
||||
if (t!="") ext[id]=t;
|
||||
}
|
||||
|
||||
core.status.hero = core.clone(temp);
|
||||
total.count[id]++;
|
||||
total.add.hp+=hp;
|
||||
total.add.atk+=atk;
|
||||
@ -2776,30 +2805,39 @@ ui.prototype.drawPaint = function () {
|
||||
|
||||
////// 绘制帮助页面 //////
|
||||
ui.prototype.drawHelp = function () {
|
||||
core.drawText([
|
||||
"\t[键盘快捷键列表]"+
|
||||
"[CTRL] 跳过对话 [Z] 转向\n" +
|
||||
"[X] 怪物手册 [G] 楼层传送\n" +
|
||||
"[A] 读取自动存档 [S/D] 存读档页面\n" +
|
||||
"[K/V] 快捷商店 [ESC] 系统菜单\n" +
|
||||
"[T] 道具页面 [Q] 装备页面\n" +
|
||||
"[B] 数据统计 [H] 帮助页面\n" +
|
||||
"[R] 回放录像 [E] 显示光标\n" +
|
||||
"[SPACE] 轻按 [M] 绘图模式\n" +
|
||||
"[N] 返回标题页面 [P] 查看评论区\n" +
|
||||
"[O] 查看工程 [F7] 打开debug穿墙模式\n" +
|
||||
"[PgUp/PgDn] 浏览地图\n"+
|
||||
"[1~4] 快捷使用破炸飞和其他道具\n"+
|
||||
"[Alt+0~9] 快捷换装",
|
||||
"\t[鼠标操作]"+
|
||||
"点状态栏中图标: 进行对应的操作\n"+
|
||||
"点任意块: 寻路并移动\n"+
|
||||
"点任意块并拖动: 指定寻路路线\n"+
|
||||
"双击空地: 瞬间移动\n"+
|
||||
"单击勇士: 转向\n"+
|
||||
"双击勇士: 轻按(仅在轻按开关打开时有效)\n"+
|
||||
"长按任意位置:跳过剧情对话或打开虚拟键盘"
|
||||
]);
|
||||
core.clearLastEvent();
|
||||
if (core.material.images.keyboard) {
|
||||
core.status.event.id = 'help';
|
||||
core.lockControl();
|
||||
core.setAlpha('ui', 1);
|
||||
core.drawImage('ui', core.material.images.keyboard, 0, 0);
|
||||
}
|
||||
else {
|
||||
core.drawText([
|
||||
"\t[键盘快捷键列表]"+
|
||||
"[CTRL] 跳过对话 [Z] 转向\n" +
|
||||
"[X] 怪物手册 [G] 楼层传送\n" +
|
||||
"[A] 读取自动存档 [S/D] 存读档页面\n" +
|
||||
"[V] 快捷商店 [ESC] 系统菜单\n" +
|
||||
"[T] 道具页面 [Q] 装备页面\n" +
|
||||
"[B] 数据统计 [H] 帮助页面\n" +
|
||||
"[R] 回放录像 [E] 显示光标\n" +
|
||||
"[SPACE] 轻按 [M] 绘图模式\n" +
|
||||
"[N] 返回标题页面 [P] 游戏主页\n" +
|
||||
"[O] 查看工程 [F7] 打开debug穿墙模式\n" +
|
||||
"[PgUp/PgDn] 浏览地图\n"+
|
||||
"[1~4] 快捷使用破炸飞和其他道具\n"+
|
||||
"[Alt+0~9] 快捷换装",
|
||||
"\t[鼠标操作]"+
|
||||
"点状态栏中图标: 进行对应的操作\n"+
|
||||
"点任意块: 寻路并移动\n"+
|
||||
"点任意块并拖动: 指定寻路路线\n"+
|
||||
"双击空地: 瞬间移动\n"+
|
||||
"单击勇士: 转向\n"+
|
||||
"双击勇士: 轻按(仅在轻按开关打开时有效)\n"+
|
||||
"长按任意位置:跳过剧情对话或打开虚拟键盘"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
////// 动态canvas //////
|
||||
|
||||
@ -436,18 +436,17 @@ utils.prototype.decodeRoute = function (route) {
|
||||
index++;
|
||||
return str;
|
||||
}
|
||||
var mp = {
|
||||
"U": "up",
|
||||
"D": "down",
|
||||
"L": "left",
|
||||
"R": "right"
|
||||
}
|
||||
|
||||
while (index<route.length) {
|
||||
var c=route.charAt(index++);
|
||||
var nxt=(c=='I'|| c=='e' ||c=='F'||c=='S'||c=='Q'||c=='t')?getString():getNumber();
|
||||
|
||||
var mp = {
|
||||
"U": "up",
|
||||
"D": "down",
|
||||
"L": "left",
|
||||
"R": "right"
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case "U": case "D": case "L": case "R": for (var i=0;i<nxt;i++) ans.push(mp[c]); break;
|
||||
case "I": ans.push("item:"+nxt); break;
|
||||
@ -639,6 +638,7 @@ utils.prototype.readFileContent = function (content) {
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
alert(e);
|
||||
}
|
||||
alert("不是有效的JSON文件!");
|
||||
|
||||
|
||||
@ -27,7 +27,8 @@ main.floors.sample0=
|
||||
"firstArrive": [
|
||||
{
|
||||
"type": "setText",
|
||||
"background": "winskin.png"
|
||||
"background": "winskin.png",
|
||||
"time": 0
|
||||
},
|
||||
"\t[样板提示]首次到达某层可以触发 firstArrive 事件,该事件可类似于RMXP中的“自动执行脚本”。\n\n本事件支持一切的事件类型,常常用来触发对话,例如:",
|
||||
"\t[hero]\b[up,hero]我是谁?我从哪来?我又要到哪去?",
|
||||
|
||||
@ -703,7 +703,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
case 90: // Z:转向
|
||||
core.turnHero();
|
||||
break;
|
||||
case 75: case 86: // K/V:打开快捷商店列表
|
||||
case 86: // V:打开快捷商店列表
|
||||
core.openQuickShop(true);
|
||||
break;
|
||||
case 32: // SPACE:轻按
|
||||
@ -741,7 +741,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
case 79: // O:查看工程
|
||||
window.open(core.platform.isPC?"editor.html":"editor-mobile.html", "_blank");
|
||||
break;
|
||||
case 80: // P:查看评论
|
||||
case 80: // P:游戏主页
|
||||
window.open("/score.php?name="+core.firstData.name+"&num=10", "_blank");
|
||||
break;
|
||||
case 49: // 快捷键1: 破
|
||||
|
||||
BIN
project/images/keyboard.png
Normal file
BIN
project/images/keyboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
Loading…
Reference in New Issue
Block a user