This commit is contained in:
oc 2019-04-04 01:50:50 +08:00
parent b91e40c037
commit 7fd843bf44
9 changed files with 625 additions and 124 deletions

View File

@ -215,7 +215,7 @@ core.events._changeFloor_beforeChange = function (info, callback) {
if (info.time == 0)
core.events._changeFloor_changing(info, callback);
else
core.show(core.dom.floorMsgGroup, info.time / 2, function () {
core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () {
core.events._changeFloor_changing(info, callback);
});
}, 25)
@ -724,6 +724,8 @@ name自定义名称可用户注销使用。
func具体执行录像的函数是一个函数体或者插件中的函数名。
func需要接受action参数代表录像回放时的当前操作行为。
如果func返回true则代表成功处理了此次操作返回false代表没有进行处理。
自己添加的录像项只能由数字、大小写、下划线线、冒号等符号组成,否则无法正常压缩和解压缩。
对于自定义内容比如中文文本或数组请使用JSON.stringify再core.encodeBase64处理。
请注意回放录像时的二次记录问题(即回放时录像会重新记录路线)。
@ -1842,6 +1844,495 @@ core.stopAnimate(id, doCallback)
### ui.js
ui.js负责一切UI界面的绘制。主要包括三个部分
- 设置某个画布的属性的相关API
- 具体的某个UI界面的绘制
- 动态创建画布相关的API
```js
// ------ 设置某个画布的属性的相关API ------//
这系列函数的name一般都是画布名可以是系统画布或动态创建的画布。
但也同时也允许直接传画布的context本身将返回自身。
core.getContextByName(name)
根据画布名找到一个画布的context支持系统画布和自定义画布。
如果不存在画布此函数返回null。
该参数也可以直接传画布的context自身则返回自己。
core.clearMap(name)
清空某个画布图层。
该函数的name也可以是'all',若为'all'则为清空所有系统画布。
core.fillText(name, text, x, y, style, font)
在某个画布上绘制一段文字。
text为要绘制的文本x,y为要绘制的坐标style可选为绘制的样式font可选为绘制的字体。下同
请注意textAlign和textBaseline将决定绘制的左右对齐和上下对齐方式。
具体可详见core.setTextAlign()和core.setTextBaseline()函数。
core.fillBoldText(name, text, x, y, style, font)
在某个画布上绘制一个描黑边的文字。
core.fillRect(name, x, y, width, height, style)
绘制一个矩形。style可选为绘制样式。如果设置将调用core.setFillStyle()。(下同)
core.strokeRect(name, x, y, width, height, style, lineWidth)
绘制一个矩形的边框。style可选为绘制样式如果设置将调用core.setStrokeStyle()。
lineWidth如果设置将调用core.setLineWidth()。(下同)
core.drawLine(name, x1, y1, x2, y2, style, lineWidth)
绘制一条线。
core.drawArrow(name, x1, y1, x2, y2, style, lineWidth)
绘制一个箭头。
core.setFont(name, font) / core.setLineWidth(name, lineWidth)
设置一个画布的字体/线宽。
core.setAlpha(name, font) / core.setOpacity(name, font)
设置一个画布的绘制不透明度和画布本身的不透明度。
两者区别如下:
- setAlpha是设置"接下来绘制的内容的不透明度",不会对已经绘制的内容产生影响。
> 比如setAlpha('ui', 0.5)则会在接下来的绘制中使用0.5的不透明度。
- setOpacity是设置"画布本身的不透明度",已经绘制的内容也会产生影响。
> 比如我已经在UI层绘制了一段文字再setOpacity则也会让已经绘制的文字变得透明。
尽量不要对系统画布使用setOpacity因为会对已经绘制的内容产生影响自定义创建的画布则不受此限制。
core.setFillStyle(name, style) / core.setStrokeStyle(name, style)
设置一个画布的填充样式/描边样式。
core.setTextAlign(name, align)
设置一个画布的文字横向对齐模式这里的align只能为'left', 'right'和'center'。
默认为'left'。
core.setTextBaseline(name, baseline)
设置一个画布的纵向对齐模式。有关textBaseline的说明可参见如下资料
http://www.runoob.com/tags/canvas-textbaseline.html
默认值是'alphabetic'。
请注意系统画布在绘制前都是没有设置过textBaseline的都是按照alphabetic进行坐标绘制。
因此如果你修改了系统画布的textBaseline来绘图记得再绘制完毕后修改回来。
core.calWidth(name, text, font)
计算一段文字在某个画布上的绘制宽度此函数其实是ctx.measureText()的包装。
font可选如果存在则会先设置该画布上的字体。
此函数不会对文字进行换行如需换行版本请使用core.splitLines()函数。
core.splitLines(name, text, maxWidth, font)
计算一段文字在某画布上换行分割的结果。
text为文字内容maxWidth为最大宽度可为null表示不自动换行。
font可选如果存在则会先设置该画布上的字体。
此函数将返回一个换行完毕的文本列表。
core.drawImage(name, image, x, y, w, h, x1, y1, w1, h1)
在一张画布上绘制一张图片此函数其实是ctx.drawImage()的包装。
可以查看下面的文档以了解各项参数的信息:
http://www.w3school.com.cn/html5/canvas_drawimage.asp
这里的image允许传一个图片画布。也允许传递图片名将从你导入的图片中获取图片内容。
// ------ 具体的某个UI界面的绘制 ------ //
core.closePanel()
结束一切事件和UI绘制关闭UI窗口返回游戏。
此函数将以此调用core.clearUI()core.unlockControl()并清空core.status.event里面的内容。
core.clearUI()
重置UI窗口。此函数将清掉所有的UI帧动画和光标清空UI画布并将alpha设为1。
core.drawTip(text, id)
在左上角以气泡的形式绘制一段提示。
text为文字内容仅支持${}的表达式计算,不支持换行和变色。
id可选为同时绘制的图标ID如果不为null则会同时绘制该图标仅对32x32的素材有效
core.drawText(content, callback)
绘制一段文字。contents为一个字符串或一个字符串数组callback为全部绘制完毕的回调。
支持所有的文字效果(如\n${}\r\\i等也支持\t和\b的语法。
如果当前在事件处理中或录像回放中则会自动转成core.insertAction处理。
不建议使用该函数如有绘制文字的需求请尽量使用core.insertAction()插入剧情文本事件。
core.drawWindowSelector(background, x, y, w, h)
绘制一个WindowSkin的闪烁光标。background可为winskin的图片名或图片本身。
x,y,w,h为绘制的左上角位置和宽高都是像素为单位。
core.drawWindowSkin(background, ctx, x, y, w, h, direction, px, py)
绘制一个WindowSkin。background可为winskin的图片名或图片本身。
ctx为画布名或画布本身x,y,w,h为左上角位置和宽高都是像素为单位。
direction, px, py可选如果设置则会绘制一个对话框箭头。
core.drawBackground(left, top, right, bottom, posInfo)
绘制一个背景图。此函数将使用你在【剧情文本设置】中设置的背景即用纯色或WindowSkin来绘制。
left, top, right, bottom为你要绘制的左上角和右下角的坐标。
posInfo如果不为null则是一个含position, px和py的对象表示一个对话框箭头的绘制。
core.drawTextContent(ctx, content, config)
根据配置在某个画布上绘制一段文字。此函数会被core.drawTextBox()所调用。
ctx为画布名或画布本身如果不设置则会忽略该函数。
content为要绘制的文字内容支持所有的文字效果如\n${}\r\\i等但不支持支持\t和\b的语法。
config为绘制的配置项目前可以包括如下几项
- left, top在该画布上绘制的左上角像素位置不设置默认为(0,0)。
> 该函数绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。
- maxWidth单行最大宽度超过此宽度将自动换行不设置不会自动换行。
- color默认颜色为#XXXXXX形式。如果不设置则使用剧情文本设置中的正文颜色。
- bold是否粗体。如果不设置默认为false。
- align文字对齐方式仅在maxWidth设置时有效默认为'left'。
- fontSize字体大小如果不设置则使用剧情文本设置中的正文字体大小。
- lineHeight绘制的行距值如果不设置则使用fontSize*1.3即1.3被行距)。
- time打字机效果。如果此项不为0则会用打字机效果逐个字进行绘制并设置core.status.event.interval定时器。
core.drawTextBox(content, showAll)
绘制一个对话框。content为一个字符串或一个字符串数组。
支持所有的文字效果(如\n${}\r\\i等也支持\t和\b的语法。
该函数将使用用户在剧情文本设置中的配置项进行绘制。
实际执行时会计算文本框宽度并绘制背景绘制标题和头像再调用core.drawTextContent()绘制正文内容。
showAll可选如果为true则不会使用打字机效果而全部显示主要用于打字机效果的点击显示全部。
core.drawScrollText(content, time, lineHeight, callback)
绘制一个滚动字幕。content为绘制内容time为总滚动时间默认为5000lineHeight为行距比例默认为1.4)。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i等但不支持\t和\b效果。
可以通过剧情文本设置中的align控制是否居中绘制offset控制其距离左边的偏移量。
core.textImage(content, lineHeight)
将文本图片化。content为绘制内容lineHeight为行距比例默认为1.4)。
可以通过剧情文本设置中的align控制是否居中绘制。
此函数将返回一个临时画布的canvas供转绘到其他画布上使用。
core.drawChoices(content, choices)
绘制一个选项框。
content可选为选项上方的提示文字支持所有的文字效果如\n${}\r\\i等也支持\t效果。
choices必选为要绘制的选项内容是一个列表。其中的每一项
- 可以是一个字符串,表示选项文字,将使用剧情文本设置中的正文颜色来绘制,仅支持${}表达式计算。
- 或者是一个包含text, color和icon的对象。
> text必选为要绘制的文字内容仅支持${}的表达式计算,
> color为要绘制的选项颜色可以是#XXXXXX的格式或RGBA数组。不设置则使用正文颜色。
> icon为要绘制的图标ID支持使用素材的ID或者系统图标。
core.drawConfirmBox(text, yesCallback, noCallback)
绘制一个确认框。text为确认文字支持\n换行但不支持自动换行和${}表达式计算。
yesCallback和noCallback分别为确定和取消的回调函数。
可以在调用此函数前设置core.status.event.selection来控制默认的选中项0确定1取消
此函数和core.myconfirm的区别主要在于
- 此函数会清掉UI层原有的绘制信息core.myconfirm不会清除。
- 此函数可以用键盘进行操作core.myconfirm必须用鼠标点击。
另外请注意:本函数和事件流的执行不兼容,选择也不会进录像。
如果需要在事件流中调用请使用提供选择项。
core.drawWaiting(text)
绘制一个等待界面,一般用于同步存档之类的操作。
调用此函数后需要再调用core.closePanel()才会恢复游戏。
core.drawPagination(page, totalPage, y)
绘制一个分页。y如果不设置则绘制在最后一行。
core.drawBook(index) / core.drawBookDetail(index)
绘制怪物手册,绘制怪物的详细信息。
core.drawFly(page) / core.drawCenterFly() / core.drawShop(shopId)
绘制楼传页面,中心对称飞行器,绘制商店
core.drawToolbox(index) / core.drawEquipbox(index) / core.drawKeyBoard()
绘制道具栏,绘制装备栏,绘制虚拟键盘。
core.drawMaps(index, x, y) / core.drawSLPanel(index, refresh)
绘制浏览地图,绘制存读档界面。
core.drawStatusBar()
自定义绘制状态栏仅在状态栏canvas化开启时有效实际被转发到了脚本编辑中。
core.drawStatistics()
绘制数据统计。将从脚本编辑中获得要统计的数据列表,再遍历所有地图进行统计。
core.drawAbout() / core.drawPaint() / core.drawHelp()
绘制关于界面,绘图模式,帮助界面。
// ------ 动态创建画布相关的API ------ //
core.ui.createCanvas(name, x, y, width, height, z)
动态创建一个自定义画布。name为要创建的画布名如果已存在则会直接取用当前存在的。
x,y为创建的画布相对窗口左上角的像素坐标width,height为创建的长宽。
z值为创建的纵向高度关系到画布之间的覆盖z值高的将覆盖z值低的系统画布的z值可在个性化中查看。
返回创建的画布的context也可以通过core.dymCanvas[name]或core.getContextByName获得。
core.ui.relocateCanvas(name, x, y)
重新定位一个自定义画布。x和y为画布的左上角坐标。
core.ui.resizeCanvas(name, width, height)
重新设置一个自定义画布的大小。width和height为新设置的宽高。此操作会清空画布。
core.ui.deleteCanvas(name)
删除一个自定义画布。
core.ui.deleteAllCanvas()
删除所有的自定义画布。
```
### utils.js
utils.js是一个工具函数库里面有各个样板中使用到的工具函数。
```js
core.replayText(text, need, times)
将一段文字中的${}表达式进行替换。need和time一般可以直接忽略。
core.calValue(value, prefix, need, time)
计算一个表达式的值支持status:xxx等的计算。
prefix为前缀switch:xxx的独立开关使用need和time一般可以直接忽略。
core.unshift(a, b) / core.push(a, b)
将b插入到列表a之前或之后。b可以是一个元素或者一个数组。
core.decompress(value)
解压缩一个字符串并进行JSON解析。value可能会被LZString或LZW算法进行压缩。
返回解压后的JSON格式内容如果无法解压则返回null。
core.setLocalStorage(key, value)
将一个键值对存入localStorage中会立刻返回结果。
此函数会自动给key加上它的name作为前缀以便于不同塔之间的区分。
value为要存储的内容存储前会被JSON转成字符串形式并LZW算法进行压缩。
如果value为null则实际会调用core.removeLocalStorage()函数清除该key。
localStorage为浏览器的默认存储和存档无关只有5M的空间大小。
此函数立刻返回true或false如果为false则代表存储失败一般指的是空间满了。
core.getLocalStorage(key, defaultValue)
从localStorage中获得一个键的值会立刻返回结果。
此函数会自动给key加上它的name作为前缀以便于不同塔之间的区分。
如果对应的键值不存在或为null则会返回defaultValue。
返回的结果会被调用core.decompress进行解压缩和JSON解析。
core.removeLocalStorage(key)
从localStorage中删除一个键的值会立刻返回。
此函数会自动给key加上它的name作为前缀以便于不同塔之间的区分。
core.setLocalForage(key, value, successCallback, errorCallback)
将一个键值对存入localForage中异步返回结果。
如果用户没有开启【新版存档】开关则仍然会使用core.setLocalStorage()。
localForage为一个开源库项目地址 https://github.com/localForage/localForage
一般存入的是indexedDB这是一个浏览器的自带数据库没有空间限制。
successCallback和errorCallback均可选表示该次存储成功或失败的回调
此函数为异步的,只能通过回调函数来获得存储的成功或失败信息。
core.getLocalForage(key, defaultValue, successCallback, errorCallback)
从localForage中获得一个键的值异步返回结果。
如果对应的键值不存在则会使用defaultValue。
如果获得成功则会将core.decompress后的结果传入successCallback回调函数执行。
errorCallback可选如果失败则会将错误信息传入errorCallback()。
此函数是异步的,只能通过回调函数来获得读取的结果或错误信息。
core.clone(data)
深拷贝一个对象。有关浅拷贝,深拷贝,基本类型和引用类型等相关知识可参见:
https://zhuanlan.zhihu.com/p/26282765
core.splitImage(image, width, height)
等比例切分一张图片。width和height为每张子图片的宽高。
请确保原始图片的宽度和高度都是是width和height的倍数。
此函数将返回一个一维数组,每一项都是一张切分好的图片,横向再纵向排列。
例如4x3的图片按1x1切分得到一个长度为12的数组按如下方式进行排列
0 1 2 3
4 5 6 7
8 9 10 11
可以将很多需要的图片拼在一张大图上然后在插件的_afterLoadResources中切分。
切分好的图片再存入core.material.images.images中这样可以少很多IO请求。
core.formatDate(date) / core.formatDate2(date) / core.formatTime(time)
格式化日期和时间。
core.setTwoDigits(x)
将x变成两位数。其实就是 parseInt(x) < 10 ? "0" + x : x
core.formatBigNumber(x, onMap)
大数据格式化。x为要格式化的内容如果不合法会返回???。
onMap标记是否在地图上调用如果为真则尝试格式化成六位否则五位。
core.arrayToRGB(color) / core.arrayToRGBA(color)
将一个颜色数组,例如[255,0,0,1]转成#FF0000或rgba(255,0,0,1)的形式。
core.encodeRoute(route)
录像压缩和解压缩。route为要压缩的路线数组。
此函数将尽可能对录像进行压缩。对于无法识别的项目(比如自己添加的),将不压缩而原样放入。
例如,["up","up","left","move:3:5","test:2333","getNext","item:bomb","down"]
将被压缩成"U2LM3:5(test:2333)GIbomb:D"。
自己添加的录像项只能由数字、大小写、下划线线、冒号等符号组成,否则无法正常压缩和解压缩。
对于自定义内容比如中文文本或数组请使用JSON.stringify再core.encodeBase64处理。
压缩的结果将再次进行LZString.compressToBase64()的压缩以进一步节省空间。
core.decodeRoute(route)
解压缩一个录像,返回解压完毕的路线数组。
core.isset(v)
判定v是不是null, undefined或NaN。
请尽量避免使用此函数,而是直接判定 v == null (请注意 null==undefined
core.subarray(a, b)
判定数组b是不是数组a的一个前缀子数组。
如果是则返回a中除去b后的剩余数组否则返回null。
core.inArray(array, element)
判定array是不是一个数组以及element是否在该数组中。
core.clamp(x, a, b)
将x限定在[a,b]区间内。
core.getCookie(name)
获得一个cookie值如果不存在该cookie则返回null。
core.setStatusBarInnerHTML(name, value, css)
设置一个状态栏的innerHTML。此函数会自动设置状态栏的文字放缩和斜体等效果。
name为状态栏的名称如atk, def等。需要是core.statusBar中的一个合法项。
value为要设置到的数值如果是数字则会先core.formatBigNumber()进行格式化。
css可选为增添的额外css内容比如可以设定颜色等。
core.strlen(str)
计算某个字符串的实际长度。每个字符的长度ASCII码视为1中文等视为2。
core.reverseDirection(direction)
翻转方向,即"up"转成"down", "left"转成"right"等。
core.encodeBase64(str) / core.decodeBase64(str)
将字符串进行base64加密或解密。
core.convertBase(str, fromBase, toBase)
任意进制转换。此函数可能执行的非常慢,慎用。
core.rand(num)
使用伪种子生成伪随机数。该随机函数能被录像支持。
num如果设置大于0则生成一个[0, num-1]之间的数否则生成一个0到1之间的浮点数。
此函数为伪随机算法SL大法无效。即多次SL后调用的该函数返回的值都是相同的。
core.rand2(num)
使用系统的随机数算法得到的随机数。该随机函数能被录像支持。
num如果设置大于0则生成一个[0, num-1]之间的数否则生成一个0到2147483647之间的整数。
此函数使用了系统的Math.random()函数支持SL大法。
但是,此函数会将生成的随机数值存入录像,因此如果调用次数太多则会导致录像文件过大。
对于需要大量生成随机数但又想使用真随机支持SL大法的例如随机生成地图等可以采用如下方式
var x = core.rand2(100); for (var i = 0; i < x; i++) core.rand()
即先生成一个真随机数根据该数来推进伪随机的种子这样就可以放心调用core.rand()啦。
core.readFile(success, error)
读取一个本地文件内容。success和error分别为读取成功或失败的回调函数。
iOS平台暂不支持读取文件操作。
core.readFileContent(content)
读取到的文件内容。此函数会被APP等调用来传递文件的具体内容。
core.download(filename, content)
生成一个文件并下载。filename为文件名content为具体的文件内容。
iOS平台暂不支持下载文件操作。
core.copy(data)
将一段内容拷贝到剪切板。
core.myconfirm(hint, yesCallback, noCallback)
弹窗绘制一段提示信息并让用户确认。hint为提示信息。
yesCallback和noCallback分别为确定和取消的回调函数。
此函数和core.drawConfirmBox的区别主要在于
- drawConfirmBox会清掉UI层原有的绘制信息此函数不会清除。
- drawConfirmBox可以用键盘进行操作此函数必须用鼠标点击。
另外请注意:本函数的选择也不会进录像,一般用于全局的提示。
如果需要在事件流中调用请使用显示确认框或显示选择项。
core.myprompt(hint, value, callback)
弹窗让用户输入一段内容。hint为提示信息value为框内的默认填写内容。
callback为用户点击确认或取消后的回调。
如果用户点击了确认则会把框内的内容可能是空串传递给callback否则把null传递给callback。
core.showWithAnimate(obj, speed, callback) / core.hideWithAnimate(obj, speed, callback)
动画淡入或淡出一个对象。
core.consoleOpened()
检测当前的控制台是否处于开启状态。仅在全塔属性中的检查控制台开关开启时有效。
此函数有可能会存在误伤行为,即没开过控制台仍认为开启过。
core.hashCode(obj)
计算一个对象的哈希值。
core.same(a, b)
判定a和b是否相同包括类型相同和值相同。
如果a和b都是数组则会递归依次比较数组中的值如果都是对象亦然。
core.utils.http(type, url, formData, success, error, mimeType, responseType)
发送一个异步HTTP请求。
type为'GET'或者'POST'url为目标地址formData如果是POST请求则为表单数据。
success为成功后的回调error为失败后的回调。
mimeType和responseType如果设置将会覆盖默认值。
lzw_encode(s) / lzw_decode(s)
LZW压缩算法来自https://gist.github.com/revolunet/843889
```

View File

@ -1904,11 +1904,11 @@ actions.prototype._clickSettings = function (x, y) {
core.ui.drawKeyBoard();
break;
case 2:
core.clearSelector();
core.clearUI();
core.ui.drawMaps();
break;
case 3:
core.clearSelector();
core.clearUI();
core.ui.drawPaint();
break;
case 4:
@ -2211,7 +2211,7 @@ actions.prototype._clickReplay_fromBeginning = function () {
actions.prototype._clickReplay_fromLoad = function () {
core.status.event.id = 'replayLoad';
core.status.event.selection = null;
core.ui.clearSelector();
core.clearUI();
var saveIndex = core.saves.saveIndex;
var page = parseInt((saveIndex - 1) / 5), offset = saveIndex - 5 * page;
core.ui.drawSLPanel(10 * page + offset);
@ -2450,7 +2450,7 @@ actions.prototype._onupPaint = function () {
core.status.event.data.x = null;
core.status.event.data.y = null;
// 保存
core.paint[core.status.floorId] = lzw_encode(core.utils.encodeCanvas(core.dymCanvas.paint).join(","));
core.paint[core.status.floorId] = lzw_encode(core.utils._encodeCanvas(core.dymCanvas.paint).join(","));
}
actions.prototype.setPaintMode = function (mode) {
@ -2498,7 +2498,7 @@ actions.prototype.loadPaint = function () {
core.clearMap('paint');
var value = core.paint[core.status.floorId];
if (value) value = lzw_decode(value).split(",");
core.utils.decodeCanvas(value, 32 * core.bigmap.width, 32 * core.bigmap.height);
core.utils._decodeCanvas(value, 32 * core.bigmap.width, 32 * core.bigmap.height);
core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0);
core.drawTip("读取绘图文件成功");

View File

@ -308,7 +308,7 @@ control.prototype.showStartAnimate = function (noAnimate, callback) {
this._showStartAnimate_resetDom();
if (core.flags.startUsingCanvas || noAnimate)
return this._showStartAnimate_finished(core.flags.startUsingCanvas, callback);
core.hide(core.dom.startTop, 20, function () {
core.hideWithAnimate(core.dom.startTop, 20, function () {
core.control._showStartAnimate_finished(false, callback);
});
}
@ -339,7 +339,7 @@ control.prototype._showStartAnimate_finished = function (start, callback) {
////// 隐藏游戏开始界面 //////
control.prototype.hideStartAnimate = function (callback) {
core.hide(core.dom.startPanel, 20, callback);
core.hideWithAnimate(core.dom.startPanel, 20, callback);
}
////// 游戏是否已经开始 //////

View File

@ -344,6 +344,8 @@ core.prototype._afterLoadResources = function (callback) {
// 初始化地图
core.initStatus.maps = core.maps._initMaps();
core.control._setRequestAnimationFrame();
if (core.plugin._afterLoadResources)
core.plugin._afterLoadResources();
core.showStartAnimate();
if (callback) callback();
}

View File

@ -438,7 +438,7 @@ events.prototype.getItem = function (id, num, x, y, callback) {
var text = '获得 ' + core.material.items[id].name;
if (num > 1) text += "x" + num;
if (itemCls === 'items') text += core.items.getItemEffectTip(id);
core.drawTip(text, core.material.icons.items[id]);
core.drawTip(text, id);
core.updateStatusBar();
this.afterGetItem(id, x, y, callback);
@ -559,7 +559,7 @@ events.prototype._changeFloor_beforeChange = function (info, callback) {
if (info.time == 0)
core.events._changeFloor_changing(info, callback);
else
core.show(core.dom.floorMsgGroup, info.time / 2, function () {
core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () {
core.events._changeFloor_changing(info, callback);
});
}, 25)
@ -571,7 +571,7 @@ events.prototype._changeFloor_changing = function (info, callback) {
if (info.time == 0)
this._changeFloor_afterChange(info, callback);
else
core.hide(core.dom.floorMsgGroup, info.time / 4, function () {
core.hideWithAnimate(core.dom.floorMsgGroup, info.time / 4, function () {
core.events._changeFloor_afterChange(info, callback);
});
}
@ -771,10 +771,7 @@ events.prototype.startEvents = function (list, x, y, callback) {
////// 执行当前自定义事件列表中的下一个事件 //////
events.prototype.doAction = function () {
// 清空boxAnimate和UI层
core.status.boxAnimateObjs = [];
clearInterval(core.status.event.interval);
core.status.event.interval = null;
core.clearSelector();
core.clearUI();
// 判定是否执行完毕
if (this._doAction_finishEvents()) return;
// 当前点坐标和前缀

View File

@ -365,8 +365,8 @@ items.prototype._realLoadEquip = function (type, loadId, unloadId, callback) {
core.status.hero.equipment[type] = loadId || null;
// --- 提示
if (loadId) core.drawTip("已装备上" + loadEquip.name, core.material.icons.items[loadId]);
else if (unloadId) core.drawTip("已卸下" + unloadEquip.name, core.material.icons.items[unloadId]);
if (loadId) core.drawTip("已装备上" + loadEquip.name, loadId);
else if (unloadId) core.drawTip("已卸下" + unloadEquip.name, unloadId);
if (callback) callback();
}

View File

@ -23,12 +23,13 @@ ui.prototype._init = function () {
////////////////// 地图设置
ui.prototype.getContextByName = function (canvas) {
if (typeof canvas == 'string') {
if (core.canvas[canvas])
canvas = core.canvas[canvas];
else if (core.dymCanvas[canvas])
canvas = core.dymCanvas[canvas];
ui.prototype.getContextByName = function (name) {
var canvas = name;
if (typeof name == 'string') {
if (core.canvas[name])
canvas = core.canvas[name];
else if (core.dymCanvas[name])
canvas = core.dymCanvas[name];
}
if (canvas && canvas.canvas) {
return canvas;
@ -190,6 +191,36 @@ ui.prototype.calWidth = function (name, text, font) {
return 0;
}
////// 字符串自动换行的分割 //////
ui.prototype.splitLines = function (name, text, maxWidth, font) {
var ctx = this.getContextByName(name);
if (!ctx) return;
if (font) core.setFont(name, font);
var contents = [];
var last = 0;
for (var i = 0; i < text.length; i++) {
if (text.charAt(i) == '\n') {
contents.push(text.substring(last, i));
last = i + 1;
}
else if (text.charAt(i) == '\\' && text.charAt(i + 1) == 'n') {
contents.push(text.substring(last, i));
last = i + 2;
}
else {
var toAdd = text.substring(last, i + 1);
var width = core.calWidth(name, toAdd);
if (maxWidth && width > maxWidth) {
contents.push(text.substring(last, i));
last = i;
}
}
}
contents.push(text.substring(last));
return contents;
}
////// 绘制一张图片 //////
ui.prototype.drawImage = function (name, image, x, y, w, h, x1, y1, w1, h1) {
var ctx = this.getContextByName(name);
@ -233,25 +264,23 @@ ui.prototype.clearUI = function () {
clearInterval(core.status.event.interval);
core.status.event.interval = null;
core.status.boxAnimateObjs = [];
core.clearSelector();
core.clearMap('ui');
core.setAlpha('ui', 1);
}
////// 清除光标 //////
ui.prototype.clearSelector = function () {
if (core.dymCanvas._selector) core.deleteCanvas("_selector");
core.clearMap('ui');
core.setAlpha('ui', 1);
}
////// 左上角绘制一段提示 //////
ui.prototype.drawTip = function (text, itemIcon) {
ui.prototype.drawTip = function (text, id) {
var textX, textY, width, height;
clearInterval(core.interval.tipAnimate);
core.setFont('data', "16px Arial");
core.setTextAlign('data', 'left');
if (!itemIcon) {
if (id != null) {
var info = core.getBlockInfo(id);
if (info == null || !info.image || info.height != 32) id = null;
else id = info;
}
if (!id) {
textX = 16;
textY = 18;
width = textX + core.calWidth('data', text) + 16;
@ -263,10 +292,10 @@ ui.prototype.drawTip = function (text, itemIcon) {
width = textX + core.calWidth('data', text) + 8;
height = 42;
}
this._drawTip_animate(text, itemIcon, textX, textY, width, height);
this._drawTip_animate(text, id, textX, textY, width, height);
}
ui.prototype._drawTip_animate = function (text, itemIcon, textX, textY, width, height) {
ui.prototype._drawTip_animate = function (text, info, textX, textY, width, height) {
var alpha = 0, hide = false;
core.interval.tipAnimate = window.setInterval(function () {
if (hide) alpha -= 0.1;
@ -274,8 +303,8 @@ ui.prototype._drawTip_animate = function (text, itemIcon, textX, textY, width, h
core.clearMap('data', 5, 5, core.ui.PIXEL, height);
core.setAlpha('data', alpha);
core.fillRect('data', 5, 5, width, height, '#000');
if (itemIcon)
core.drawImage('data', core.material.images.items, 0, itemIcon * 32, 32, 32, 10, 8, 32, 32);
if (info)
core.drawImage('data', info.image, info.posX * 32, info.posY * 32, 32, 32, 10, 8, 32, 32);
core.fillText('data', text, textX + 5, textY + 15, '#fff');
core.setAlpha('data', 1);
if (alpha > 0.6 || alpha < 0) {
@ -507,13 +536,13 @@ ui.prototype.drawBackground = function (left, top, right, bottom, posInfo) {
}
////// 计算有效文本框的宽度
ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width, font) {
ui.prototype._calTextBoxWidth = function (ctx, content, min_width, max_width, font) {
// 无限长度自动换行
var allLines = core.splitLines(ctx, content, null, font);
// 如果不存在手动换行,尽量调成半行形式
if (allLines.length == 1) {
var w = core.calWidth(ctx, allLines[0]);
var w = core.calWidth(ctx, allLines[0]) + 5;
if (w<min_width*2.3) return core.clamp(w / 1.4, min_width, max_width);
if (w<max_width*2.2) return core.clamp(w / 2.4, min_width, max_width);
return core.clamp(w / 3.4, min_width, max_width);
@ -521,7 +550,7 @@ ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width, fon
// 存在手动换行:以最长的为准
else {
return core.clamp(allLines.reduce(function (pre, curr) {
return Math.max(pre, core.calWidth(ctx, curr))
return Math.max(pre, core.calWidth(ctx, curr) + 5)
}, 0), min_width, max_width);
}
}
@ -794,7 +823,7 @@ ui.prototype._drawTextBox_getHorizontalPosition = function (content, titleInfo,
var min_width = 220 - paddingLeft, max_width = validWidth;
// 无行走图或头像则可以适当缩小min_width
if (titleInfo.image == null) min_width = 160;
validWidth = this.calTextBoxWidth('ui', realContent, min_width, max_width, this._buildFont());
validWidth = this._calTextBoxWidth('ui', realContent, min_width, max_width, this._buildFont());
width = validWidth + paddingLeft + paddingRight;
left = core.clamp(32 * posInfo.px + 16 - width / 2 - core.bigmap.offsetX, left, right - width);
right = left + width;
@ -1090,6 +1119,20 @@ ui.prototype._drawConfirmBox_getRect = function (contents) {
return { top: top, left: left, bottom: bottom, right: right, width: right - left, height: bottom - top };
}
////// 绘制等待界面 //////
ui.prototype.drawWaiting = function(text) {
core.lockControl();
core.status.event.id = 'waiting';
core.clearUI();
text = core.replaceText(text || "");
var text_length = core.calWidth('ui', text, this._buildFont(19, true));
var width = Math.max(text_length + 80, 220), left = this.HPIXEL - parseInt(width / 2), right = left + width;
var top = this.HPIXEL - 48, height = 96, bottom = top + height;
this.drawBackground(left, top, right, bottom);
core.setTextAlign('ui', 'center');
core.fillText('ui', text, this.HPIXEL, top + 56, core.arrayToRGBA(core.status.textAttribute.text));
}
////// 绘制系统设置界面 //////
ui.prototype.drawSwitchs = function() {
core.status.event.id = 'switchs';
@ -1128,20 +1171,6 @@ ui.prototype.drawQuickShop = function () {
this.drawChoices(null, choices);
}
////// 绘制等待界面 //////
ui.prototype.drawWaiting = function(text) {
core.lockControl();
core.status.event.id = 'waiting';
core.clearSelector();
text = core.replaceText(text || "");
var text_length = core.calWidth('ui', text, this._buildFont(19, true));
var width = Math.max(text_length + 80, 220), left = this.HPIXEL - parseInt(width / 2), right = left + width;
var top = this.HPIXEL - 48, height = 96, bottom = top + height;
this.drawBackground(left, top, right, bottom);
core.setTextAlign('ui', 'center');
core.fillText('ui', text, this.HPIXEL, top + 56, core.arrayToRGBA(core.status.textAttribute.text));
}
////// 绘制存档同步界面 //////
ui.prototype.drawSyncSave = function () {
core.status.event.id = 'syncSave';
@ -1190,22 +1219,22 @@ ui.prototype.drawGameInfo = function () {
}
////// 绘制分页 //////
ui.prototype.drawPagination = function (page, totalPage, top) {
ui.prototype.drawPagination = function (page, totalPage, y) {
// if (totalPage<page) totalPage=page;
if (totalPage <= 1) return;
if (top == null) top = this.LAST;
if (y == null) y = this.LAST;
core.setFillStyle('ui', '#DDDDDD');
var length = core.calWidth('ui', page + " / " + page, this._buildFont(15, true));
core.setTextAlign('ui', 'left');
core.fillText('ui', page + " / " + totalPage, parseInt((this.PIXEL - length) / 2), top*32+19);
core.fillText('ui', page + " / " + totalPage, parseInt((this.PIXEL - length) / 2), y*32+19);
core.setTextAlign('ui', 'center');
if (page > 1)
core.fillText('ui', '上一页', this.HPIXEL - 80, top*32+19);
core.fillText('ui', '上一页', this.HPIXEL - 80, y*32+19);
if (page < totalPage)
core.fillText('ui', '下一页', this.HPIXEL + 80, top*32+19);
core.fillText('ui', '下一页', this.HPIXEL + 80, y*32+19);
}
////// 绘制键盘光标 //////
@ -1633,7 +1662,7 @@ ui.prototype.drawMaps = function (index, x, y) {
var offsetX = 32 * (data.x - this.HSIZE), offsetY = 32 * (data.y - this.HSIZE);
var value = core.paint[data.floorId];
if (value) value = lzw_decode(value).split(",");
core.utils.decodeCanvas(value, 32 * data.mw, 32 * data.mh);
core.utils._decodeCanvas(value, 32 * data.mw, 32 * data.mh);
core.drawImage('ui', core.bigmap.tempCanvas.canvas, offsetX * 32, offsetY * 32,
this.PIXEL, this.PIXEL, 0, 0, this.PIXEL, this.PIXEL);
}
@ -2359,13 +2388,13 @@ ui.prototype._drawPaint_draw = function () {
core.status.event.id = 'paint';
core.status.event.data = {"x": null, "y": null, "erase": false};
core.clearSelector();
core.clearUI();
core.createCanvas('paint', -core.bigmap.offsetX, -core.bigmap.offsetY, 32*core.bigmap.width, 32*core.bigmap.height, 95);
// 将已有的内容绘制到route上
var value = core.paint[core.status.floorId];
if (core.isset(value)) value = lzw_decode(value).split(",");
core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
core.utils._decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0);
core.setLineWidth('paint', 3);
@ -2384,7 +2413,7 @@ ui.prototype._drawPaint_draw = function () {
////// 绘制帮助页面 //////
ui.prototype.drawHelp = function () {
core.clearSelector();
core.clearUI();
if (core.material.images.keyboard) {
core.status.event.id = 'help';
core.lockControl();

View File

@ -75,35 +75,6 @@ utils.prototype.calValue = function (value, prefix, need, times) {
return value;
}
////// 字符串自动换行的分割 //////
utils.prototype.splitLines = function (canvas, text, maxLength, font) {
if (font) core.setFont(canvas, font);
var contents = [];
var last = 0;
for (var i = 0; i < text.length; i++) {
if (text.charAt(i) == '\n') {
contents.push(text.substring(last, i));
last = i + 1;
}
else if (text.charAt(i) == '\\' && text.charAt(i + 1) == 'n') {
contents.push(text.substring(last, i));
last = i + 2;
}
else {
var toAdd = text.substring(last, i + 1);
var width = core.calWidth(canvas, toAdd);
if (maxLength && width > maxLength) {
contents.push(text.substring(last, i));
last = i;
}
}
}
contents.push(text.substring(last));
return contents;
}
////// 向某个数组前插入另一个数组或元素 //////
utils.prototype.unshift = function (a, b) {
if (!(a instanceof Array) || b == null) return;
@ -128,6 +99,28 @@ utils.prototype.push = function (a, b) {
return a;
}
utils.prototype.decompress = function (value) {
try {
var output = lzw_decode(value);
if (output) return JSON.parse(output);
}
catch (e) {
}
try {
var output = LZString.decompress(value);
if (output) return JSON.parse(output);
}
catch (e) {
}
try {
return JSON.parse(value);
}
catch (e) {
main.log(e);
}
return null;
}
////// 设置本地存储 //////
utils.prototype.setLocalStorage = function (key, value) {
try {
@ -163,28 +156,6 @@ utils.prototype.setLocalStorage = function (key, value) {
}
}
utils.prototype.decompress = function (value) {
try {
var output = lzw_decode(value);
if (output) return JSON.parse(output);
}
catch (e) {
}
try {
var output = LZString.decompress(value);
if (output) return JSON.parse(output);
}
catch (e) {
}
try {
return JSON.parse(value);
}
catch (e) {
main.log(e);
}
return null;
}
////// 获得本地存储 //////
utils.prototype.getLocalStorage = function (key, defaultValue) {
var res = this.decompress(localStorage.getItem(core.firstData.name + "_" + key));
@ -628,6 +599,7 @@ utils.prototype.getCookie = function (name) {
////// 设置statusBar的innerHTML会自动斜体和放缩也可以增加自定义css //////
utils.prototype.setStatusBarInnerHTML = function (name, value, css) {
if (!core.statusBar[name]) return;
if (typeof value == 'number') value = this.formatBigNumber(value);
// 判定是否斜体
var italic = /^[-a-zA-Z0-9`~!@#$%^&*()_=+\[{\]}\\|;:'",<.>\/?]*$/.test(value);
@ -931,7 +903,7 @@ utils.prototype.myprompt = function (hint, value, callback) {
}
////// 动画显示某对象 //////
utils.prototype.show = function (obj, speed, callback) {
utils.prototype.showWithAnimate = function (obj, speed, callback) {
obj.style.display = 'block';
if (!speed && main.mode != 'play') {
obj.style.opacity = 1;
@ -951,7 +923,7 @@ utils.prototype.show = function (obj, speed, callback) {
}
////// 动画使某对象消失 //////
utils.prototype.hide = function (obj, speed, callback) {
utils.prototype.hideWithAnimate = function (obj, speed, callback) {
if (!speed || main.mode != 'play') {
obj.style.display = 'none';
if (callback) callback();
@ -970,7 +942,7 @@ utils.prototype.hide = function (obj, speed, callback) {
}, speed);
}
utils.prototype.encodeCanvas = function (ctx) {
utils.prototype._encodeCanvas = function (ctx) {
var list = [];
var width = ctx.canvas.width, height = ctx.canvas.height;
ctx.mozImageSmoothingEnabled = false;
@ -997,7 +969,7 @@ utils.prototype.encodeCanvas = function (ctx) {
}
////// 解析arr数组并绘制到tempCanvas上 //////
utils.prototype.decodeCanvas = function (arr, width, height) {
utils.prototype._decodeCanvas = function (arr, width, height) {
// 清空tempCanvas
var tempCanvas = core.bigmap.tempCanvas;
tempCanvas.canvas.width = width;

View File

@ -1,18 +1,28 @@
var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
{
"init": function () {
// 在这里写的代码,在所有模块加载完毕后,游戏开始前会被执行
console.log("插件编写测试");
// 可以写一些其他的被直接执行的代码
// 可以写一些直接执行的代码
// 在这里写的代码将会在【资源加载前】被执行,此时图片等资源尚未被加载。
// 请勿在这里对包括bgm图片等资源进行操作。
this.test = function () {
console.log("插件函数执行测试");
console.log(this);
this._afterLoadResources = function () {
// 本函数将在所有资源加载完毕后,游戏开启前被执行
// 可以在这个函数里面对资源进行一些操作,比如切分图片等。
// 这是一个将assets.png拆分成若干个32x32像素的小图片并保存的样例。
// var arr = core.splitImage("assets.png", 32, 32);
// for (var i = 0; i < arr.length; i++) {
// core.material.images.images["asset"+i+".png", arr[i]);
// }
}
// 可以在任何地方如afterXXX或自定义脚本事件调用函数方法为 core.plugin.xxx();
// 可以在任何地方如afterXXX或自定义脚本事件调用函数方法为 core.plugin.xxx();
// 从V2.6开始插件中用this.XXX方式定义的函数也会被转发到core中详见文档-脚本-函数的转发。
},
"drawLight": function () {