Merge pull request #226 from ckcz123/v2.0

Add support for Tilesets
This commit is contained in:
Zhang Chen 2018-09-27 14:19:44 +08:00 committed by GitHub
commit 22ef52c2e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 451 additions and 107 deletions

View File

@ -16,22 +16,27 @@ data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"images": {
"_leaf": true,
"_type": "textarea",
"_data": "在此存放所有可能使用的图片 \n 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。 \n 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 \n 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 \n 依次向后添加"
"_data": "在此存放所有可能使用的图片tilesets除外 \n图片可以被作为背景图的一部分也可以直接用自定义事件进行显示。 \n 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 \n 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 \n 依次向后添加"
},
"tilesets": {
"_leaf": true,
"_type": "textarea",
"_data": "在此存放额外素材的图片名, \n可以自定导入任意张素材图片无需PS无需注册即可直接在游戏中使用 \n 形式如[\"1.png\", \"2.png\"] ,将需要的素材图片放在images目录下 \n 素材的宽高必须都是32的倍数且图片上的总图块数不超过1000即最多有1000个32*32的图块在该图片上"
},
"animates": {
"_leaf": true,
"_type": "textarea",
"_data": "在此存放所有可能使用的动画必须是animate格式在这里不写后缀名 \n 动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符 \n \"jianji\", \"thunder\" \n 根据需求自行添加"
"_data": "在此存放所有可能使用的动画必须是animate格式在这里不写后缀名 \n动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符 \n \"jianji\", \"thunder\" \n 根据需求自行添加"
},
"bgms": {
"_leaf": true,
"_type": "textarea",
"_data": "在此存放所有的bgm和文件名一致。第一项为默认播放项 \n 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好"
"_data": "在此存放所有的bgm和文件名一致。第一项为默认播放项 \n音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好"
},
"sounds": {
"_leaf": true,
"_type": "textarea",
"_data": "在此存放所有的SE和文件名一致 \n 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好"
"_data": "在此存放所有的SE和文件名一致 \n音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好"
},
"startBackground": {
"_leaf": true,
@ -440,7 +445,13 @@ data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "若此项为true则将状态栏中的楼层转换器按钮换为装备栏按钮"
"_data": "状态栏的装备按钮。若此项为true则将状态栏中的楼层转换器按钮换为装备栏按钮"
},
"equipPercentage": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "装备增加百分比属性。如果此项为true则装备属性全部按照百分比进行计算比如\"atk\": 20意味着攻击增加20%。\n如果多个装备百分比增加同一个属性的按加算处理。即一个10%一个20%总共是30%而不是32%"
},
/*
"enableDeleteItem": {

View File

@ -81,7 +81,8 @@ editor.prototype.init = function (callback) {
editor.prototype.idsInit = function (maps, icons) {
editor.ids = [0];
editor.indexs = [];
var MAX_NUM = 1000;
var MAX_NUM = Math.max.apply(null,Object.keys(maps_90f36752_8815_4be8_b32b_d7fad1d0542e));
editor.MAX_NUM=MAX_NUM;
var getInfoById = function (id) {
var block = maps.initBlock(0, 0, id);
if (hasOwnProp(block, 'event')) {
@ -89,7 +90,7 @@ editor.prototype.idsInit = function (maps, icons) {
}
}
var point = 0;
for (var i = 0; i < MAX_NUM; i++) {
for (var i = 0; i <= MAX_NUM; i++) {
var indexBlock = getInfoById(i);
editor.indexs[i] = [];
if (indexBlock) {
@ -106,6 +107,24 @@ editor.prototype.idsInit = function (maps, icons) {
}
}
editor.indexs[0] = [0];
var startOffset = core.icons.tilesetStartOffset;
for (var i in core.tilesets) {
var imgName = core.tilesets[i];
var img = core.material.images.tilesets[imgName];
var width = Math.floor(img.width/32), height = Math.floor(img.height/32);
if(img.width%32 || img.height%32){
alert(imgName+'的长或宽不是32的整数倍, 请修改后刷新页面')
}
for (var id=startOffset; id<startOffset+width*height;id++) {
var x = (id-startOffset)%width, y = parseInt((id-startOffset)/width);
var indexBlock = getInfoById(id);
editor.ids.push({'idnum': id, 'id': indexBlock.event.id, 'images': imgName, "x": x, "y": y, isTile: true});
point++;
editor.indexs[id]=[point];
}
startOffset += core.icons.tilesetStartOffset;
}
}
editor.prototype.mapInit = function () {
@ -319,6 +338,14 @@ editor.prototype.drawInitData = function (icons) {
sumWidth += images[img].width;
maxHeight = Math.max(maxHeight, images[img].height);
}
var tilesets = images.tilesets;
for (var ii in core.tilesets) {
var img = core.tilesets[ii];
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + tilesets[img].width) / 32, tilesets[img].height];
sumWidth += tilesets[img].width;
maxHeight = Math.max(maxHeight, tilesets[img].height);
}
var fullWidth = ~~(sumWidth * ratio);
var fullHeight = ~~(maxHeight * ratio);
@ -340,11 +367,17 @@ editor.prototype.drawInitData = function (icons) {
dc.drawImage(autotiles[im], nowx, nowy);
nowy += autotiles[im].height;
}
nowx += 3 * 32;
continue;
}
dc.drawImage(images[img], nowx, 0)
nowx += images[img].width;
}
for (var ii in core.tilesets) {
var img = core.tilesets[ii];
dc.drawImage(tilesets[img], nowx, 0)
nowx += tilesets[img].width;
}
//editor.drawMapBg();
//editor.mapInit();
}
@ -742,9 +775,9 @@ editor.prototype.listen = function () {
if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) {
var ysize = spriter.indexOf('48') === -1 ? 32 : 48;
loc.ysize = ysize;
pos.y = ~~(loc.y / loc.ysize);
pos.x = editor.widthsX[spriter][1];
pos.images = editor.widthsX[spriter][0];
pos.y = ~~(loc.y / loc.ysize);
if(core.tilesets.indexOf(pos.images)==-1)pos.x = editor.widthsX[spriter][1];
var autotiles = core.material.images['autotile'];
if (pos.images == 'autotile') {
var imNames = Object.keys(autotiles);
@ -773,13 +806,17 @@ editor.prototype.listen = function () {
} else {
if (hasOwnProp(autotiles, pos.images)) editor.info = {'images': pos.images, 'y': 0};
else if (pos.images == 'terrains') editor.info = {'images': pos.images, 'y': pos.y - 1};
else if (core.tilesets.indexOf(pos.images)!=-1) editor.info = {'images': pos.images, 'y': pos.y, 'x': pos.x-editor.widthsX[spriter][1]};
else editor.info = {'images': pos.images, 'y': pos.y};
for (var ii = 0; ii < editor.ids.length; ii++) {
if (( editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y )
if ((core.tilesets.indexOf(pos.images)!=-1 && editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y && editor.info.x == editor.ids[ii].x)
|| (hasOwnProp(autotiles, pos.images) && editor.info.images == editor.ids[ii].id
&& editor.info.y == editor.ids[ii].y)) {
&& editor.info.y == editor.ids[ii].y)
|| (core.tilesets.indexOf(pos.images)==-1 && editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y )
) {
editor.info = editor.ids[ii];
break;

View File

@ -320,10 +320,18 @@ editor_mode = function (editor) {
if (!core.isset(editor_mode.info.id)) {
// document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = '';
document.getElementById('enemyItemTable').style.display = 'none';
document.getElementById('tilesetsDiv').style.display = 'none';
document.getElementById('newIdIdnum').style.display = 'block';
return;
}
if (editor_mode.info.isTile) {
document.getElementById('enemyItemTable').style.display = 'none';
document.getElementById('tilesetsDiv').style.display = 'block';
document.getElementById('newIdIdnum').style.display = 'none';
return;
}
document.getElementById('newIdIdnum').style.display = 'none';
document.getElementById('tilesetsDiv').style.display = 'none';
document.getElementById('enemyItemTable').style.display = 'block';
var objs = [];

View File

@ -95,10 +95,7 @@ var editArea = new Vue({
var num = mapArray[y][x];
if (num == 0)
editor.map[y][x] = 0;
else if (num >= 1000) {
that.error = 3;
editor.map[y][x] = undefined;
} else if (typeof(editor.indexs[num][0]) == 'undefined') {
else if (typeof(editor.indexs[num][0]) == 'undefined') {
that.error = 2;
editor.map[y][x] = undefined;
} else editor.map[y][x] = editor.ids[[editor.indexs[num][0]]];

View File

@ -225,10 +225,15 @@ core.showBlock(x, y, floorId)
将某个点从禁用变成启用状态。
core.hideBlock(x, y, floorId)
将某个点从启用变成禁用状态,但不会对其进行删除。
此函数不会实际将该块从地图中进行删除,而是将该点设置为禁用,以供以后可能的启用事件。
core.removeBlock(x, y, floorId)
将某个点删除或从启用变成禁用状态。
如果该点不存在自定义事件(比如普通的怪物),则将直接从地图中删除。
否则将该点设置为禁用,以供以后可能的启用事件。
将从启用变成禁用状态,并尽可能将其从地图上删除
和hideBlock相比如果该点不存在自定义事件(比如门或普通的怪物),则将直接从地图中删除。
如果存在自定义事件,则简单的禁用它,以供以后可能的启用事件。
core.setBlock(number, x, y, floorId)

View File

@ -67,6 +67,26 @@ animate为该装备的攻击动画仅对type为0时有效。具体可参见[
{"type": 3, "atk": -20, "def": 50, "mdef": 50} // 装备类型是魔杖,效果是攻击-20防御和魔防各+50
```
### 装备按比例增加属性
从V2.4.2开始,装备可以选择按照比例来增加属性。
在全塔属性中有个`equipPercentage`开关如果将其打开则会所有值都按照比例计算。也就是类似Buff一样
例如,上面的例子就变成了:
``` js
{"type": 0, "atk": 10} // 装备类型是武器效果是攻击提升10%,使用默认的攻击动画
{"type": 0, "atk": 40, "animate": "sword"} // 装备类型为武器效果是攻击提升40%攻击动画是sword
{"type": 1, "def": 40} // 装备类型是防具效果是防御提升40%
{"type": 1, "def": 100, "mdef": 100} // 装备类型是防具效果是防御和魔防各提升100%
{"type": 3, "atk": -20, "def": 50, "mdef": 50} // 装备类型是魔杖效果是攻击下降20%防御和魔防各提升50%
```
所有取值全部向下取整。
值得注意的是多装备增加同一属性使用加法计算也就是比如武器增加30%攻击防具增加10%攻击最终合起来增加的是40%而不是43%的属性。
### 检测是否存在装备
可以使用`core.hasEquip(itemId)`来检测是否装上某个装备。

View File

@ -233,6 +233,34 @@ ID必须由数字字母下划线组成数字在1000以内且均不能和
因此在你修改了icons.js和maps.js两个文件也就是将素材添加到游戏后地图生成器的对应关系也将同步更新。
### 额外素材
从V2.4.2开始HTML5魔塔样板开始支持额外素材。
具体而言通过上面的“素材导入”的方式确实可以有效地添加素材到游戏。但是如果想增加大量自定义素材需要通过便捷PS工具将这些素材全部导入到`terrains.png`中,并且全部是单列,极度不友好。这也导致了野外风的制作相对变得很困难,增加了大量素材处理的工作量。
额外素材就是为了解决这个问题而被提出。
所谓`额外素材`即用户可以自定导入任意张素材图片无需PS无需注册即可直接在游戏中使用。这一点已经十分向RM靠拢了。
要使用额外素材,请将你需要的素材图片放在`images`目录下,并在`全塔属性`的`tilesets`中定义图片名。
**该素材的宽高必须都是32的倍数且图片上的总图块数不超过1000即最多有1000个32*32的图块在该图片上。**
```js
"tilesets": ["1.png", "2.png"] // 导入两个额外素材文件名分别是1.png和2.png
```
刷新后,系统会自动加载该素材并添加到素材区。
额外素材无需导入,无需注册。在`tilesets`中定义了图片后即可直接使用绘图无需再注册其数字和ID。其ID、索引和数字均为系统自动分配且不允许修改。
请注意额外素材的ID、索引和数字与该图片在tilesets数组中的index及该素材在图片上的位置都有关系。
!> **因此如果对`tilesets`数组随意删除或修改顺序,可能会导致所有额外素材全部发生变化!这点请务必注意!!!**
除此之外,额外素材在游戏中的使用和正式素材都是一致的,也能在前景或背景图层绘制。
## 自定义道具效果
本节中将继续介绍如何自己编辑一个道具的效果。

View File

@ -178,6 +178,16 @@
素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。
### 额外素材
从2.4.2开始H5魔塔样板支持额外素材你可以导入任意个类似RM中的tilesets文件且无需注册即可使用。
要使用额外素材,请在`全塔属性`中的`tilesets`项,添加额外素材的图片名称,刷新后即可在地图编辑器中使用。
额外素材不可注册其数字、ID和索引都是和该图块在图片上的位置相关不可编辑。
有关额外素材的更多说明参见[额外素材](personalization#额外素材)
## 控制台调试
HTML5的塔都是可以进行控制台调试的。

View File

@ -92,6 +92,9 @@
<h3 class="leftTabHeader">图块属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>
</h3>
<div class="leftTabContent">
<div id='tilesetsDiv'><!-- tilesets -->
<p>tilesets不允许编辑图块属性</p>
</div>
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum1000以内数字"/>

View File

@ -91,6 +91,9 @@
<h3 class="leftTabHeader">图块属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>
</h3>
<div class="leftTabContent">
<div id='tilesetsDiv'><!-- tilesets -->
<p>tilesets不允许编辑图块属性</p>
</div>
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum1000以内数字"/>

View File

@ -5,7 +5,7 @@
<meta http-equiv='X-UA-Compatible' content='IE=Edge, chrome=1'>
<meta name='author' content='ckcz123'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=yes'>
<title></title>
<title>HTML5魔塔</title>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<meta name="screen-orientation" content="portrait">
<meta name="full-screen" content="yes">

View File

@ -237,7 +237,6 @@ control.prototype.clearStatus = function() {
}
core.status = {};
core.clearStatusBar();
core.resize(main.dom.body.clientWidth, main.dom.body.clientHeight);
}
////// 重置游戏状态和初始数据 //////
@ -249,16 +248,8 @@ control.prototype.resetStatus = function(hero, hard, floorId, route, maps, value
totalTime=core.status.hero.statistics.totalTime;
}
// 停止各个Timeout和Interval
for (var i in core.timeout) {
clearTimeout(core.timeout[i]);
core.timeout[i] = null;
}
for (var i in core.interval) {
clearInterval(core.interval[i]);
core.interval[i] = null;
}
core.clearStatusBar();
// 清除游戏数据
core.clearStatus();
// 初始化status
core.status = core.clone(core.initStatus);

View File

@ -191,7 +191,6 @@ core.prototype.init = function (coreData, callback) {
document.title = core.firstData.title + " - HTML5魔塔";
document.getElementById("startLogo").innerHTML = core.firstData.title;
core.material.items = core.clone(core.items.getItems());
core.initStatus.maps = core.maps.initMaps(core.floorIds);
core.material.enemys = core.clone(core.enemys.getEnemys());
core.material.icons = core.icons.getIcons();
core.material.events = core.events.getEvents();
@ -299,6 +298,7 @@ core.prototype.init = function (coreData, callback) {
console.log(core.material);
// 设置勇士高度
core.material.icons.hero.height = core.material.images.hero.height/4;
core.initStatus.maps = core.maps.initMaps(core.floorIds);
core.setRequestAnimationFrame();
core.showStartAnimate();
@ -723,7 +723,12 @@ core.prototype.showBlock = function(x, y, floodId) {
core.maps.showBlock(x,y,floodId);
}
////// 将某个块从启用变成禁用状态 //////
////// 将某个块从启用变成禁用状态,但是并不删除它 //////
core.prototype.hideBlock = function(x, y, floorId) {
core.maps.hideBlock(x,y,floorId);
}
////// 将某个块从启用变成禁用状态,并删除该块 //////
core.prototype.removeBlock = function (x, y, floorId) {
core.maps.removeBlock(x,y,floorId);
}

View File

@ -129,7 +129,7 @@ enemys.prototype.getExtraDamage = function (enemy) {
enemys.prototype.nextCriticals = function (enemy, number) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var useTurn = !core.flags.useLoop; // 是否使用回合法计算临界值如果要用循环法则直接改为false。
var useTurn = !core.flags.useLoop;
number = number||1;
@ -161,6 +161,10 @@ enemys.prototype.nextCriticals = function (enemy, number) {
if (useTurn) { // 回合数计算法
for (var t = turn-1;t>=1;t--) {
var nextAtk = Math.ceil(mon_hp/t) + mon_def;
// 装备提升比例的计算临界
if (core.flags.equipPercentage) {
nextAtk = Math.ceil(nextAtk / core.getFlag('equip_atk_buff', 1));
}
if (nextAtk<=hero_atk) break;
if (nextAtk!=pre) {
var nextInfo = this.getDamageInfo(enemy, core.status.hero.hp, nextAtk, core.status.hero.def, core.status.hero.mdef);
@ -235,12 +239,19 @@ enemys.prototype.getCurrentEnemys = function (floorId) {
var enemy = core.material.enemys[enemyId];
var mon_hp = enemy.hp, mon_atk = enemy.atk, mon_def = enemy.def;
if (this.hasSpecial(enemy.special, 10)) {
mon_atk=core.status.hero.atk;
mon_def=core.status.hero.def;
var hero_atk = core.status.hero.atk, hero_def = core.status.hero.def, hero_mdef = core.status.hero.mdef;
if (core.flags.equipPercentage) {
hero_atk = Math.floor(core.getFlag('equip_atk_buff',1)*hero_atk);
hero_def = Math.floor(core.getFlag('equip_def_buff',1)*hero_def);
hero_mdef = Math.floor(core.getFlag('equip_mdef_buff',1)*hero_mdef);
}
if (this.hasSpecial(enemy.special, 3) && mon_def < core.status.hero.atk - 1)
mon_def = core.status.hero.atk - 1;
if (this.hasSpecial(enemy.special, 10)) {
mon_atk=hero_atk;
mon_def=hero_def;
}
if (this.hasSpecial(enemy.special, 3) && mon_def < hero_atk - 1)
mon_def = hero_atk - 1;
var specialText = core.enemys.getSpecialText(enemyId);
if (specialText.length>=3) specialText = "多属性...";

View File

@ -373,14 +373,14 @@ events.prototype.doAction = function() {
if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) {
core.animateBlock(data.loc,'show', data.time, function () {
data.loc.forEach(function (t) {
core.showBlock(t[0],t[1],data.floorId)
core.showBlock(t[0],t[1],data.floorId);
})
core.events.doAction();
});
}
else {
data.loc.forEach(function (t) {
core.showBlock(t[0],t[1],data.floorId)
core.showBlock(t[0],t[1],data.floorId);
})
this.doAction();
}
@ -391,15 +391,23 @@ events.prototype.doAction = function() {
if ((typeof data.loc[0] == 'number' || typeof data.loc[0] == 'string')
&& (typeof data.loc[1] == 'number' || typeof data.loc[1] == 'string'))
data.loc = [[core.calValue(data.loc[0]), core.calValue(data.loc[1])]];
data.loc.forEach(function (t) {
core.removeBlock(t[0],t[1],data.floorId);
})
if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) {
data.loc.forEach(function (t) {
core.hideBlock(t[0],t[1],data.floorId);
})
core.animateBlock(data.loc,'hide',data.time, function () {
data.loc.forEach(function (t) {
core.removeBlock(t[0],t[1],data.floorId)
})
core.events.doAction();
});
}
else this.doAction();
else {
data.loc.forEach(function (t) {
core.removeBlock(t[0],t[1],data.floorId)
})
this.doAction();
}
break;
case "setBlock": // 设置某图块
{

View File

@ -5,8 +5,38 @@ function icons() {
icons.prototype.init = function () {
this.icons = icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1;
//delete(icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1);
// tileset的起点
this.tilesetStartOffset = 10000;
}
icons.prototype.getIcons = function () {
return this.icons;
}
////// 根据图块数字或ID获得所在的tileset和坐标信息 //////
icons.prototype.getTilesetOffset = function (id) {
if (typeof id == 'string') {
// Tileset的ID必须是 X+数字 的形式
if (!/^X\d+$/.test(id)) return null;
id = parseInt(id.substring(1));
}
else if (typeof id != 'number') {
return null;
}
core.tilesets = core.tilesets || [];
var startOffset = this.tilesetStartOffset;
for (var i in core.tilesets) {
var imgName = core.tilesets[i];
var img = core.material.images.tilesets[imgName];
var width = Math.floor(img.width/32), height = Math.floor(img.height/32);
if (id>=startOffset && id<startOffset+width*height) {
var x = (id-startOffset)%width, y = parseInt((id-startOffset)/width);
return {"image": imgName, "x": x, "y": y};
}
startOffset += this.tilesetStartOffset;
}
return null;
}

View File

@ -175,10 +175,17 @@ items.prototype.loadEquip = function (equipId, callback) {
// 比较能力值
var result = core.compareEquipment(equipId,unloadEquipId);
core.status.hero.atk += result.atk;
core.status.hero.def += result.def;
core.status.hero.mdef += result.mdef;
if (core.flags.equipPercentage) {
core.setFlag('equip_atk_buff', core.getFlag('equip_atk_buff',1)+result.atk/100);
core.setFlag('equip_def_buff', core.getFlag('equip_def_buff',1)+result.def/100);
core.setFlag('equip_mdef_buff', core.getFlag('equip_mdef_buff',1)+result.mdef/100);
}
else {
core.status.hero.atk += result.atk;
core.status.hero.def += result.def;
core.status.hero.mdef += result.mdef;
}
// 更新装备状态
core.status.hero.equipment[loadEquipType] = equipId;
@ -214,9 +221,16 @@ items.prototype.unloadEquip = function (equipType, callback) {
var unloadEquip = core.material.items[unloadEquipId];
// 处理能力值改变
core.status.hero.atk -= unloadEquip.equip.atk || 0;
core.status.hero.def -= unloadEquip.equip.def || 0;
core.status.hero.mdef -= unloadEquip.equip.mdef || 0;
if (core.flags.equipPercentage) {
core.setFlag('equip_atk_buff', core.getFlag('equip_atk_buff',1)-(unloadEquip.equip.atk||0)/100);
core.setFlag('equip_def_buff', core.getFlag('equip_def_buff',1)-(unloadEquip.equip.def||0)/100);
core.setFlag('equip_mdef_buff', core.getFlag('equip_mdef_buff',1)-(unloadEquip.equip.mdef||0)/100);
}
else {
core.status.hero.atk -= unloadEquip.equip.atk || 0;
core.status.hero.def -= unloadEquip.equip.def || 0;
core.status.hero.mdef -= unloadEquip.equip.mdef || 0;
}
// 更新装备状态
core.status.hero.equipment[equipType] = null;

View File

@ -39,10 +39,28 @@ loader.prototype.load = function (callback) {
// 加载autotile
core.material.images.autotile = {};
core.loader.loadImages(Object.keys(core.material.icons.autotile), core.material.images.autotile, function () {
core.loader.loadAnimates();
core.loader.loadMusic();
if (core.isset(callback))
callback();
// 加载tilesets
core.material.images.tilesets = {};
if (!core.isset(core.tilesets)) core.tilesets = [];
core.loader.loadImages(core.clone(core.tilesets), core.material.images.tilesets, function () {
// 检查宽高是32倍数如果出错在控制台报错
for (var imgName in core.material.images.tilesets) {
var img = core.material.images.tilesets[imgName];
if (img.width%32!=0 || img.height%32!=0) {
console.warn("警告!"+imgName+"的宽或高不是32的倍数");
}
if (img.width * img.height > 32*32*1000) {
console.warn("警告!"+imgName+"上的图块素材个数大于1000");
}
}
core.loader.loadAnimates();
core.loader.loadMusic();
if (core.isset(callback))
callback();
})
})
})
})
@ -63,7 +81,7 @@ loader.prototype.loadIcons = function () {
}
loader.prototype.loadImages = function (names, toSave, callback) {
if (names.length==0) {
if (!core.isset(names) || names.length==0) {
if (core.isset(callback)) callback();
return;
}

View File

@ -60,6 +60,12 @@ maps.prototype.initBlock = function (x, y, id) {
if (disable!=null) tmp.disable = disable;
if (id in this.blocksInfo) tmp.event = JSON.parse(JSON.stringify(this.blocksInfo[id]));
else {
var tilesetOffset = core.icons.getTilesetOffset(id);
if (tilesetOffset != null) {
tmp.event = {"cls": "tileset", "id": "X"+id, "noPass": true};
}
}
return tmp;
}
@ -333,16 +339,30 @@ maps.prototype.canMoveDirectly = function (destX,destY) {
maps.prototype.drawBlock = function (block, animate, dx, dy) {
var cls = block.event.cls, height = block.event.height || 32;
var blockIcon = core.material.icons[cls][block.event.id];
var blockImage = core.material.images[cls];
animate=(animate||0)%(block.event.animate||1);
var image, x, y;
if (cls == 'tileset') {
var offset = core.icons.getTilesetOffset(block.event.id);
if (offset == null) return;
image = core.material.images.tilesets[offset.image];
x = offset.x;
y = offset.y;
height = 32;
}
else if (cls == 'autotile') return;
else {
image = core.material.images[cls];
x = (animate||0)%(block.event.animate||1);
y = core.material.icons[cls][block.event.id];
}
dx = dx || 0;
dy = dy || 0;
core.canvas.event.clearRect(block.x * 32 + dx, block.y * 32 + dy, 32, 32);
core.canvas.event.drawImage(blockImage, animate * 32, blockIcon * height + height-32, 32, 32, block.x * 32 + dx, block.y * 32 + dy, 32, 32);
core.canvas.event.drawImage(image, x * 32, y * height + height-32, 32, 32, block.x * 32 + dx, block.y * 32 + dy, 32, 32);
if (height>32) {
core.canvas.event2.clearRect(block.x * 32 + dx, block.y * 32 + 32 - height + dy, 32, height-32)
core.canvas.event2.drawImage(blockImage, animate * 32, blockIcon * height, 32, height-32, block.x * 32 + dx, block.y*32 + 32 - height + dy, 32, height-32);
core.canvas.event2.drawImage(image, x * 32, y * height, 32, height-32, block.x * 32 + dx, block.y*32 + 32 - height + dy, 32, height-32);
}
}
@ -379,6 +399,12 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
var id = block.event.id, cls = block.event.cls;
if (cls == 'autotile')
core.drawAutotile(canvas, arr, block, 32, 0, 0);
else if (cls == 'tileset') {
var offset = core.icons.getTilesetOffset(id);
if (offset!=null) {
canvas.drawImage(core.material.images.tilesets[offset.image], 32*offset.x, 32*offset.y, 32, 32, 32*block.x, 32*block.y, 32, 32);
}
}
else
canvas.drawImage(core.material.images[cls], 0, core.material.icons[cls][id] * 32, 32, 32, x * 32, y * 32, 32, 32);
}
@ -390,6 +416,7 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
////// 绘制某张地图 //////
maps.prototype.drawMap = function (mapName, callback) {
mapName = mapName || core.status.floorId;
core.clearMap('all');
core.removeGlobalAnimate(null, null, true);
var drawBg = function(){
@ -465,11 +492,9 @@ maps.prototype.drawMap = function (mapName, callback) {
if (block.event.cls == 'autotile') {
core.drawAutotile(core.canvas.event, mapArray, block, 32, 0, 0);
}
else {
if (block.event.id!='none') {
core.drawBlock(block);
core.addGlobalAnimate(block);
}
else if (block.event.id!='none') {
core.drawBlock(block);
core.addGlobalAnimate(block);
}
}
}
@ -675,13 +700,32 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) {
core.setAlpha('ui', 1.0);
block=block.block;
var blockIcon = core.material.icons[block.event.cls][block.event.id];
var blockImage = core.material.images[block.event.cls];
var height = block.event.height || 32;
var image, bx, by, height = block.event.height || 32;
if (block.event.cls == 'tileset') {
var offset = core.icons.getTilesetOffset(block.event.id);
if (offset==null) {
if (core.isset(callback)) callback();
return;
}
bx = offset.x;
by = offset.y;
image = core.material.images.tilesets[offset.image];
}
// 不支持autotile
else if (block.event.cls == 'autotile') {
if (core.isset(callback)) callback();
return;
}
else {
image = core.material.images[block.event.cls];
bx = 0;
by = core.material.icons[block.event.cls][block.event.id];
}
var opacityVal = 1;
core.setOpacity('route', opacityVal);
core.canvas.route.drawImage(blockImage, 0, blockIcon * height, 32, height, block.x * 32, block.y * 32 +32 - height, 32, height);
core.canvas.route.drawImage(image, bx * 32, by * height, 32, height, block.x * 32, block.y * 32 +32 - height, 32, height);
// 要运行的轨迹将steps展开
var moveSteps=[];
@ -721,6 +765,9 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) {
animateTime = 0;
if (animateCurrent>=animateValue) animateCurrent=0;
}
if (block.event.cls=='tileset') {
animateCurrent = bx;
}
// 已经移动完毕,消失
if (moveSteps.length==0) {
@ -728,7 +775,7 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) {
else opacityVal -= 0.06;
core.setOpacity('route', opacityVal);
core.clearMap('route', nowX, nowY-height+32, 32, height);
core.canvas.route.drawImage(blockImage, animateCurrent * 32, blockIcon * height, 32, height, nowX, nowY-height+32, 32, height);
core.canvas.route.drawImage(image, animateCurrent * 32, by * height, 32, height, nowX, nowY-height+32, 32, height);
if (opacityVal<=0) {
clearInterval(animate);
core.clearMap('route');
@ -749,7 +796,7 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) {
nowY+=scan[moveSteps[0]].y*2;
core.clearMap('route', nowX-32, nowY-32, 96, 96);
// 绘制
core.canvas.route.drawImage(blockImage, animateCurrent * 32, blockIcon * height, 32, height, nowX, nowY-height+32, 32, height);
core.canvas.route.drawImage(image, animateCurrent * 32, by * height, 32, height, nowX, nowY-height+32, 32, height);
if (step==16) {
// 该移动完毕,继续
step=0;
@ -778,13 +825,31 @@ maps.prototype.jumpBlock = function(sx,sy,ex,ey,time,keep,callback) {
core.setAlpha('ui', 1.0);
block=block.block;
var blockIcon = core.material.icons[block.event.cls][block.event.id];
var blockImage = core.material.images[block.event.cls];
var height = block.event.height || 32;
var image, bx, by, height = block.event.height || 32;
if (block.event.cls == 'tileset') {
var offset = core.icons.getTilesetOffset(block.event.id);
if (offset==null) {
if (core.isset(callback)) callback();
return;
}
bx = offset.x;
by = offset.y;
image = core.material.images.tilesets[offset.image];
}
// 不支持autotile
else if (block.event.cls == 'autotile') {
if (core.isset(callback)) callback();
return;
}
else {
image = core.material.images[block.event.cls];
bx = 0;
by = core.material.icons[block.event.cls][block.event.id];
}
var opacityVal = 1;
core.setOpacity('route', opacityVal);
core.canvas.route.drawImage(blockImage, 0, blockIcon * height, 32, height, block.x * 32, block.y * 32 +32 - height, 32, height);
core.canvas.route.drawImage(image, bx*32, by * height, 32, height, block.x * 32, block.y * 32 +32 - height, 32, height);
core.playSound('jump.mp3');
@ -823,18 +888,21 @@ maps.prototype.jumpBlock = function(sx,sy,ex,ey,time,keep,callback) {
animateTime = 0;
if (animateCurrent >= animateValue) animateCurrent = 0;
}
if (block.event.cls=='tileset') {
animateCurrent = bx;
}
if (jump_count>0) {
core.clearMap('route', drawX(), drawY()-height+32, 32, height);
updateJump();
core.canvas.route.drawImage(blockImage, animateCurrent * 32, blockIcon * height, 32, height, drawX(), drawY()-height+32, 32, height);
core.canvas.route.drawImage(image, animateCurrent * 32, by * height, 32, height, drawX(), drawY()-height+32, 32, height);
}
else {
if (keep) opacityVal=0;
else opacityVal -= 0.06;
core.setOpacity('route', opacityVal);
core.clearMap('route', drawX(), drawY()-height+32, 32, height);
core.canvas.route.drawImage(blockImage, animateCurrent * 32, blockIcon * height, 32, height, drawX(), drawY()-height+32, 32, height);
core.canvas.route.drawImage(image, animateCurrent * 32, by * height, 32, height, drawX(), drawY()-height+32, 32, height);
if (opacityVal<=0) {
clearInterval(animate);
core.clearMap('route');
@ -865,10 +933,29 @@ maps.prototype.animateBlock = function (loc,type,time,callback) {
var block = core.getBlock(t[0],t[1],null,true);
if (block==null) return;
block=block.block;
var image, bx, by, height = block.event.height || 32;
if (block.event.cls == 'tileset') {
var offset = core.icons.getTilesetOffset(block.event.id);
if (offset==null) {
if (core.isset(callback)) callback();
return;
}
bx = offset.x;
by = offset.y;
image = core.material.images.tilesets[offset.image];
}
// 不支持autotile
else if (block.event.cls == 'autotile') {
return;
}
else {
image = core.material.images[block.event.cls];
bx = 0;
by = core.material.icons[block.event.cls][block.event.id];
}
list.push({
'x': t[0], 'y': t[1], 'height': block.event.height||32,
'blockIcon': core.material.icons[block.event.cls][block.event.id],
'blockImage': core.material.images[block.event.cls]
'x': t[0], 'y': t[1], 'height': height,
'bx': bx, 'by': by, 'image': image
})
})
@ -880,7 +967,7 @@ maps.prototype.animateBlock = function (loc,type,time,callback) {
core.status.replay.animate=true;
var draw = function () {
list.forEach(function (t) {
core.canvas.route.drawImage(t.blockImage, 0, t.blockIcon*t.height, 32, t.height, t.x*32, t.y*32+32-t.height, 32, t.height);
core.canvas.route.drawImage(t.image, t.bx*32, t.by*t.height, 32, t.height, t.x*32, t.y*32+32-t.height, 32, t.height);
})
}
@ -923,6 +1010,27 @@ maps.prototype.showBlock = function(x, y, floodId) {
}
}
////// 只隐藏但不删除某块 //////
maps.prototype.hideBlock = function (x, y, floorId) {
floorId = floorId || core.status.floorId;
var block = core.getBlock(x,y,floorId,true);
if (block==null) return; // 不存在
// 删除动画,清除地图
if (floorId==core.status.floorId) {
core.removeGlobalAnimate(x, y);
core.canvas.event.clearRect(x * 32, y * 32, 32, 32);
var height = 32;
if (core.isset(block.block.event)) height=block.block.event.height||32;
if (height>32)
core.canvas.event2.clearRect(x * 32, y * 32 +32-height, 32, height-32);
}
block.disable = true;
core.updateStatusBar();
}
////// 将某个块从启用变成禁用状态 //////
maps.prototype.removeBlock = function (x, y, floorId) {
floorId = floorId || core.status.floorId;

View File

@ -865,6 +865,12 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
var monster = core.material.enemys[monsterId];
var mon_hp = monster.hp, mon_atk = monster.atk, mon_def = monster.def, mon_money=monster.money, mon_exp = monster.experience, mon_special=monster.special;
if (core.flags.equipPercentage) {
hero_atk = Math.floor(core.getFlag('equip_atk_buff',1)*hero_atk);
hero_def = Math.floor(core.getFlag('equip_def_buff',1)*hero_def);
hero_mdef = Math.floor(core.getFlag('equip_mdef_buff',1)*hero_mdef);
}
var initDamage = 0; // 战前伤害
// 吸血
@ -1849,10 +1855,15 @@ ui.prototype.drawEquipbox = function(index) {
if (!core.isset(compare[name]) || compare[name]==0) return;
var color = '#00FF00';
if (compare[name]<0) color = '#FF0000';
var content = title + ' ' + core.getStatus(name) + '->';
var nowValue = core.getStatus(name), newValue = nowValue + compare[name];
if (core.flags.equipPercentage) {
var nowBuff = core.getFlag('equip_'+name+"_buff",1), newBuff = nowBuff+compare[name]/100;
nowValue = Math.floor(nowBuff*core.getStatus(name));
newValue = Math.floor(newBuff*core.getStatus(name));
}
var content = title + ' ' + nowValue + '->';
core.fillText('ui', content, drawOffset, 89, '#CCCCCC', 'bold 14px Verdana');
drawOffset += core.canvas.ui.measureText(content).width;
var newValue = core.getStatus(name) + compare[name] + "";
core.fillText('ui', newValue, drawOffset, 89, color);
drawOffset += core.canvas.ui.measureText(newValue).width + 15;
})
@ -1918,20 +1929,32 @@ ui.prototype.drawSLPanel = function(index, refresh) {
if (!core.isset(core.status.event.ui))
core.status.event.ui = [];
core.clearMap('ui');
core.setAlpha('ui', 0.85);
core.fillRect('ui', 0, 0, 416, 416, '#000000');
core.setAlpha('ui', 1);
core.canvas.ui.textAlign = 'center';
var u=416/6, size=118;
var strokeColor = '#FFD700';
if (core.status.event.selection) strokeColor = '#FF6A6A';
var name=core.status.event.id=='save'?"存档":core.status.event.id=='load'?"读档":core.status.event.id=='replayLoad'?"回放":"";
var drawBg = function() {
core.clearMap('ui');
core.setAlpha('ui', 0.85);
core.fillRect('ui', 0, 0, 416, 416, '#000000');
core.setAlpha('ui', 1);
core.ui.drawPagination(page+1, max_page, 12);
core.canvas.ui.textAlign = 'center';
// 退出
core.fillText('ui', '返回游戏', 370, 403,'#DDDDDD', 'bold 15px Verdana');
if (core.status.event.selection)
core.setFillStyle('ui', '#FF6A6A');
if (core.status.event.id=='save')
core.fillText('ui', '删除模式', 48, 403);
else
core.fillText('ui', '输入编号', 48, 403);
}
var draw = function (data, i) {
var name=core.status.event.id=='save'?"存档":core.status.event.id=='load'?"读档":core.status.event.id=='replayLoad'?"回放":"";
core.status.event.ui[i] = data;
var id=5*page+i;
if (i<3) {
@ -1972,6 +1995,7 @@ ui.prototype.drawSLPanel = function(index, refresh) {
}
function drawAll() {
drawBg();
for (var i=0;i<6;i++)
draw(core.status.event.ui[i], i);
}
@ -1980,18 +2004,6 @@ ui.prototype.drawSLPanel = function(index, refresh) {
loadSave(0, drawAll);
}
else drawAll();
this.drawPagination(page+1, max_page, 12);
core.canvas.ui.textAlign = 'center';
// 退出
core.fillText('ui', '返回游戏', 370, 403,'#DDDDDD', 'bold 15px Verdana');
if (core.status.event.selection)
core.setFillStyle('ui', '#FF6A6A');
if (core.status.event.id=='save')
core.fillText('ui', '删除模式', 48, 403);
else
core.fillText('ui', '输入编号', 48, 403);
}
////// 绘制一个缩略图 //////
@ -2038,6 +2050,12 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
if (block.event.cls == 'autotile') {
core.drawAutotile(tempCanvas, mapArray, block, 32, 0, 0);
}
else if (block.event.cls == 'tileset') {
var offset = core.icons.getTilesetOffset(block.event.id);
if (offset!=null) {
tempCanvas.drawImage(core.material.images.tilesets[offset.image], 32*offset.x, 32*offset.y, 32, 32, 32*block.x, 32*block.y, 32, 32);
}
}
else {
if (block.event.id!='none') {
var blockIcon = core.material.icons[block.event.cls][block.event.id];

View File

@ -67,7 +67,7 @@ function main() {
'loader', 'control', 'utils', 'items', 'icons', 'maps', 'enemys', 'events', 'actions', 'data', 'ui', 'core'
];
this.pureData = [
"data","enemys","icons","maps","items","functions"
'data', 'enemys', 'icons', 'maps', 'items', 'functions'
];
this.materials = [
'animates', 'enemys', 'hero', 'items', 'npcs', 'terrains', 'enemy48', 'npc48'
@ -182,7 +182,7 @@ main.prototype.init = function (mode, callback) {
main.loaderFloors(function() {
var coreData = {};
["dom", "statusBar", "canvas", "images", "materials",
["dom", "statusBar", "canvas", "images", "tilesets", "materials",
"animates", "bgms", "sounds", "floorIds", "floors"].forEach(function (t) {
coreData[t] = main[t];
})

View File

@ -11,6 +11,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"images": [
"bg.jpg"
],
"tilesets": [],
"animates": [
"hand",
"sword",
@ -202,6 +203,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"bigKeyIsBox": false,
"equipment": false,
"equipboxButton": false,
"equipPercentage": false,
"enableAddPoint": false,
"enableNegativeDamage": false,
"hatredDecrease": true,

View File

@ -366,7 +366,17 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 怪物生命,怪物攻击、防御、特殊属性
var mon_hp = enemy.hp, mon_atk = enemy.atk, mon_def = enemy.def, mon_special = enemy.special;
// 勇士的负属性都按0计算
hero_hp=Math.max(0, hero_hp); hero_atk=Math.max(0, hero_atk); hero_def=Math.max(0, hero_def); hero_mdef=Math.max(0, hero_mdef);
hero_hp=Math.max(0, hero_hp);
hero_atk=Math.max(0, hero_atk);
hero_def=Math.max(0, hero_def);
hero_mdef=Math.max(0, hero_mdef);
// 装备按比例增加属性
if (core.flags.equipPercentage) {
hero_atk = Math.floor(core.getFlag('equip_atk_buff',1)*hero_atk);
hero_def = Math.floor(core.getFlag('equip_def_buff',1)*hero_def);
hero_mdef = Math.floor(core.getFlag('equip_mdef_buff',1)*hero_mdef);
}
// 如果是无敌属性,且勇士未持有十字架
if (this.hasSpecial(mon_special, 20) && !core.hasItem("cross"))
@ -495,6 +505,13 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.statusBar[item].innerHTML = core.formatBigNumber(core.getStatus(item));
});
// 装备按比例增加属性
if (core.flags.equipPercentage) {
core.statusBar.atk.innerHTML = core.formatBigNumber(Math.floor(core.getFlag('equip_atk_buff',1)*core.getStatus('atk')));
core.statusBar.def.innerHTML = core.formatBigNumber(Math.floor(core.getFlag('equip_def_buff',1)*core.getStatus('def')));
core.statusBar.mdef.innerHTML = core.formatBigNumber(Math.floor(core.getFlag('equip_mdef_buff',1)*core.getStatus('mdef')));
}
// 可以在这里添加自己额外的状态栏信息,比如想攻击显示 +0.5 可以这么写:
// if (core.hasFlag('halfAtk')) core.statusBar.atk.innerHTML += "+0.5";