小时候我们玩过拼图游戏,是用自己的手去拼的。今天我们来研究研究用javascript来拼图。同样是拼图,但用js拼图要比用手拼图麻烦多了,因此以后我要把它优化成引擎。

一、前言

以上是一段导语,话不扯远,对《三国志曹操传》熟悉的玩家知道,《三国志曹操传》的地图是由小地图块拼成的,那要实现它就和导语说得一样:很麻烦。不过即使麻烦也是一门技术,因此在此分享给大家,希望大家喜欢。

前几章的位置:

用Javascript开发《三国志曹操传》-开源讲座(三)-人物对话中,仿打字机输出文字

http://blog.csdn.net/yorhomwang/article/details/8008759

用Javascript开发《三国志曹操传》-开源讲座(二)-让目标人物移动

http://blog.csdn.net/yorhomwang/article/details/8007871

用Javascript开发《三国志曹操传》-开源讲座(一)-让静态人物动起来

http://blog.csdn.net/yorhomwang/article/details/7984576

二、代码讲解

今天我要换换讲解方式,先不给代码,我们先来想想原理。现在,假如你有一幅图片,把它裁开成若干份,并打乱。现在如果让你用js把他们组织起来,如何做呢?先不说图的顺序,首先来看把它们弄在一起就很难了。这时我减少难度,给你几个选择:
A.用margin慢慢调        B.用数组把它们排列好        C.放弃

在这道题中,选A是很不明智的,选C就代表你也拿不定主意。看来选B是最好的。既然都告诉大家用数组,那就先上代码吧。免得消磨大家兴致。
js代码:

/**Prompt:*If you want to add hurdle, find string: "{{Add hurdle above." and "{{After add hurdle, add the hurdle to the vector above." please.*If you want to add or change type of grid, find string: "{{Add new grid above.".*If you want to change position of map, please find string: "{{Change map margin above.".*If the icon of crid is changed, you have to change the size of icon. Find "{{Change icon size above." to change size.*///Map of hurdle or military or resource.var vView = [];/*Remarks:*L: land *S: sea *R: river *W: swamp *A: lawn *B: bridge *H: house *h: hospital *w: warehouse *b: bourse *M: military academy *m: military factories*r: research Center *P: port *D: dock *s: Shipyard*/var mScene = {'L': ['./land.png', '陆地'], 'S': ['./sea.png', '河流'], 'T': ['./tree.png', '树木'], 'B': ['./bridge.png', '桥'], 'C': ['./beach.png', '沙滩']};//{{Add new grid above.var mCurrent = {Margin: {left: -1, top: -1, right: -1, bottom: -1}, Position: {X: -1, Y: -1}, Type: 'NONE'};var mTitle = {};var sHurdleONE = 'S,S,S,S,S,S,S,S,S,S,S'+ ';T,L,T,T,T,T,S,S,S,S,T'+ ';T,L,L,T,S,S,S,S,S,L,T'+ ';T,L,L,L,C,C,C,S,S,T,S'+ ';T,L,L,L,C,C,C,B,B,L,T'+ ';T,L,L,C,C,C,C,S,S,L,T'+ ';T,L,L,C,C,T,S,S,L,L,T';//{{Add hurdle above.var vHurdles = [sHurdleONE];//{{After add hurdle, add the hurdle to the vector above.function _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin){var mCoordMember = {left: nWidthBasic, top: nHeightBasic, right: nWidthBasic + nPicWidth, bottom: nHeightBasic + nPicHeight};var mPositionMember = {X: (mCoordMember.left - mMargin.x) / nPicWidth, Y: (mCoordMember.top - mMargin.y) / nPicHeight};var mItem = {Coord: mCoordMember, Position: mPositionMember, Type: cType};return mItem;}function _loadHurdle(sHurdle){var nBasic = 0;var nWidthBasic = nBasic;            //margin-left.var nHeightBasic = 0;                //margin-top.//{{Change map margin above.var nPicWidth = 45;        //Picture width is nBasic.var nPicHeight = 45;        //Picturn height is nHeightBasic.//{{Change icon size above.var nSub;var nRow;var nCol;var v = sHurdle.split(';');var vRec = [];for(nSub = 0; nSub < v.length; nSub++){var vCrid = v[nSub].split(',');vRec[vRec.length] = vCrid;}for(nRow = 0; nRow < vRec.length; nRow++){var vCol = vRec[nRow];for(nCol = 0; nCol < vCol.length; nCol++){var cType = vCol[nCol];var mMargin = {x: nBasic, y: nBasic};vView[vView.length] = _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin);nWidthBasic += nPicWidth;}nHeightBasic += nPicHeight;nWidthBasic = nBasic;}}//Show map with vector 'vView'.function _showMap(sID){var xDiv=document.getElementById(sID);var xGrid;var xImg;var nTop = 0;var nSub;var sIdPrefix = 'ID_IMG_NUM_';var sIdGrid = 'ID_A_NUM_';for(nSub = 0; nSub < vView.length; nSub++){var mGrid = vView[nSub];if(mGrid){var xMargin = mGrid.Coord;var cType = mGrid.Type;var xProper = mScene[cType];if(xProper){xGrid = document.createElement('a');xImg = document.createElement('img');xImg.style.position = 'absolute';xImg.style.marginLeft = xMargin.left;xImg.style.marginTop = xMargin.top;xImg.src = xProper[0];xImg.style.border = '0px solid #000000';xImg.id = sIdPrefix + nSub;xImg.style.width = 45;xImg.style.height = 45;xImg.style.display = 'block';xGrid.onclick = function(e){var xCurrentGrid = e.target;var sId = xCurrentGrid.id;var nIdAsSub = parseInt(sId.substring(sIdPrefix.length, sId.length));mCurrent = vView[nIdAsSub];if(!mCurrent){alert("Error 0004.");}};xGrid.title = xProper[1] + '(' + parseInt(mGrid.Position.X) + ', ' + parseInt(mGrid.Position.Y+2) + ')';xGrid.id = sIdGrid + nSub;xGrid.appendChild(xImg);xDiv.appendChild(xGrid);}else{alert("Error: 0003.");}}else{alert("Error: 0002.");}}}//Show map of hurdle.function _showHurdle(nHurdle){if(vHurdles[nHurdle - 1]){_loadHurdle(vHurdles[nHurdle - 1]);_showMap('ID_DIV_BATTLEFIELD');}else{alert("Error: 0001.");}}

看看,这点程序就用了195行,而且这还是一张地图,看来还很有点麻烦哦。没关系,慢慢解释。
首先还是把素材放在这里:

tree.png land.png sea.png bridge.png beach.png

素材不是来自《三国志曹操传》,因为没整理好《三国志曹操传》的地图素材,所以就随便找了些。不过也照样可以用。希望大家不要介意。
 
麻烦的代码最容易弄得乱七八糟,因此在此时要良好的区分开样式设置和拼图核心。
拼图核心在哪里呢???在这里:

var mScene = {'L': ['./land.png', '陆地'], 'S': ['./sea.png', '河流'], 'T': ['./tree.png', '树木'], 'B': ['./bridge.png', '桥'], 'C': ['./beach.png', '沙滩']};//{{Add new grid above.var mCurrent = {Margin: {left: -1, top: -1, right: -1, bottom: -1}, Position: {X: -1, Y: -1}, Type: 'NONE'};var mTitle = {};var sHurdleONE = 'S,S,S,S,S,S,S,S,S,S,S'+ ';T,L,T,T,T,T,S,S,S,S,T'+ ';T,L,L,T,S,S,S,S,S,L,T'+ ';T,L,L,L,C,C,C,S,S,T,S'+ ';T,L,L,L,C,C,C,B,B,L,T'+ ';T,L,L,C,C,C,C,S,S,L,T'+ ';T,L,L,C,C,T,S,S,L,L,T';//{{Add hurdle above.var vHurdles = [sHurdleONE];//{{After add hurdle, add the hurdle to the vector above.

首先我把S,T,B,C,L定义好,使S代表河流,T代表树木,B代表桥,C代表沙滩,L代表陆地。var mCurrent后面有用,暂不解释。然后是var mTitle,这个专门是用来显示title的,所以也不解释了。关键是在下:

var sHurdleONE = 'S,S,S,S,S,S,S,S,S,S,S'+ ';T,L,T,T,T,T,S,S,S,S,T'+ ';T,L,L,T,S,S,S,S,S,L,T'+ ';T,L,L,L,C,C,C,S,S,T,S'+ ';T,L,L,L,C,C,C,B,B,L,T'+ ';T,L,L,C,C,C,C,S,S,L,T'+ ';T,L,L,C,C,T,S,S,L,L,T';

这段代码就是把定义好的S,T,B,C,L连在一起的核心。后面只用定义S,T,B,C,L的宽度高度定义就能把它们连成一块。并且只要把它们在数组里的位置调一调就能改变样式。
接下来为了能切换地图,我们把第一张地图放进了数组:

var vHurdles = [sHurdleONE];
//{{After add hurdle, add the hurdle to the vector above.

如果以后加了地图,只用把地图所属的数组名加到vHurdles数组就可以了,调用是就可以直接写对应下标。
样式设置在下:

function _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin){var mCoordMember = {left: nWidthBasic, top: nHeightBasic, right: nWidthBasic + nPicWidth, bottom: nHeightBasic + nPicHeight};var mPositionMember = {X: (mCoordMember.left - mMargin.x) / nPicWidth, Y: (mCoordMember.top - mMargin.y) / nPicHeight};var mItem = {Coord: mCoordMember, Position: mPositionMember, Type: cType};return mItem;}function _loadHurdle(sHurdle){var nBasic = 0;var nWidthBasic = nBasic;            //margin-left.var nHeightBasic = 0;                //margin-top.//{{Change map margin above.var nPicWidth = 45;        //Picture width is nBasic.var nPicHeight = 45;        //Picturn height is nHeightBasic.//{{Change icon size above.var nSub;var nRow;var nCol;var v = sHurdle.split(';');var vRec = [];for(nSub = 0; nSub < v.length; nSub++){var vCrid = v[nSub].split(',');vRec[vRec.length] = vCrid;}for(nRow = 0; nRow < vRec.length; nRow++){var vCol = vRec[nRow];for(nCol = 0; nCol < vCol.length; nCol++){var cType = vCol[nCol];var mMargin = {x: nBasic, y: nBasic};vView[vView.length] = _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin);nWidthBasic += nPicWidth;}nHeightBasic += nPicHeight;nWidthBasic = nBasic;}}//Show map with vector 'vView'.function _showMap(sID){var xDiv=document.getElementById(sID);var xGrid;var xImg;var nTop = 0;var nSub;var sIdPrefix = 'ID_IMG_NUM_';var sIdGrid = 'ID_A_NUM_';for(nSub = 0; nSub < vView.length; nSub++){var mGrid = vView[nSub];if(mGrid){var xMargin = mGrid.Coord;var cType = mGrid.Type;var xProper = mScene[cType];if(xProper){xGrid = document.createElement('a');xImg = document.createElement('img');xImg.style.position = 'absolute';xImg.style.marginLeft = xMargin.left;xImg.style.marginTop = xMargin.top;xImg.src = xProper[0];xImg.style.border = '0px solid #000000';xImg.id = sIdPrefix + nSub;xImg.style.width = 45;xImg.style.height = 45;xImg.style.display = 'block';xGrid.onclick = function(e){var xCurrentGrid = e.target;var sId = xCurrentGrid.id;var nIdAsSub = parseInt(sId.substring(sIdPrefix.length, sId.length));mCurrent = vView[nIdAsSub];if(!mCurrent){alert("Error 0004.");}};xGrid.title = xProper[1] + '(' + parseInt(mGrid.Position.X) + ', ' + parseInt(mGrid.Position.Y+2) + ')';xGrid.id = sIdGrid + nSub;xGrid.appendChild(xImg);xDiv.appendChild(xGrid);}else{alert("Error: 0003.");}}else{alert("Error: 0002.");}}}

以上的代码很简单,自己可以看看,提示一下:当你在自己开发的过程中如果弹出一个Error: 0002, Error: 0003, Error: 0001什么之类的,就代表出了错,需要马上去检查。这是为了在麻烦的程序开发中有一点提醒而设计的。值得注意的是:这里的图片全是createElement弄出来的,所以请不要猜疑html代码里有什么蹊跷。
接着看:

function _showHurdle(nHurdle){if(vHurdles[nHurdle - 1]){_loadHurdle(vHurdles[nHurdle - 1]);_showMap('ID_DIV_BATTLEFIELD');}else{alert("Error: 0001.");}}

这是在你要弄出地图的调用函数,当你在html代码里写上:<body οnlοad="_showHurdle(nHurdle)">几可以把拼的图一下子画出来。nHurdle就是地图在数组vHurdles里的对应下标,最低是1,而不是0,也就是说要用第一张地图,那nHurdle就该赋值为1,调用是写为:<body οnlοad="_showHurdle(1)">。

源代码下载:http://files.cnblogs.com/ducle/map.rar 

三、演示效果

演示图在下:


由于是静态的,所以就不给demo了。这种方法虽然很麻烦,而且地图块多了就很慢,但是毕竟是种技术,如果大家有什么好的方法也可以来告诉我。
 
希望大家多支持。谢谢。

----------------------------------------------------------------

欢迎大家转载我的文章。

转载请注明:转自Yorhom's Game Box

欢迎继续关注我的博客

用Javascript开发《三国志曹操传》-开源讲座(四)-用地图块拼成大地图相关推荐

  1. html5游戏开发--动静结合(二)-用地图块拼成大地图 初探lufylegend

    一.前言 本次教程将向大家讲解如何用html5将小地图块拼成大地图,以及如何用现有的高级html5游戏开发库件lufylegend.js开发游戏. 首先让我们来了解了解如何用html5实现动画,毕竟& ...

  2. 用Javascript开发《三国志曹操传》-零部件开发(四)-用地图块拼成大地图

    小时候我们玩过拼图游戏,是用自己的手去拼的.今天我们来研究研究用javascript来拼图.同样是拼图,但用js拼图要比用手拼图麻烦多了,因此以后我要把它优化成引擎. 一.前言 以上是一段导语,话不扯 ...

  3. 用Javascript开发《三国志曹操传》-开源讲座(五)-可移动地图的实现

    前几章的位置: 用Javascript开发<三国志曹操传>-开源讲座(四)-用地图块拼成大地图 http://blog.csdn.net/yorhomwang/article/detail ...

  4. 用Javascript开发《三国志曹操传》-零部件开发(五)-可移动地图的实现

    前几章的位置: 用Javascript开发<三国志曹操传>-零部件开发(四)-用地图块拼成大地图 http://www.cnblogs.com/ducle/archive/2012/09/ ...

  5. 用Javascript开发《三国志曹操传》-开源讲座(三)-情景对话中,仿打字机输出文字

    前两讲我告诉了大家如何使人物移动,那么今天我们就来看看如何实现仿<三国志曹操传>人物情景对话.其他讲的具体链接我写在下方. 用Javascript开发-<三国志曹操传>-开源讲 ...

  6. 用Javascript开发《三国志曹操传》-开源讲座(三)-情景对话中,仿打字机输出文字...

    前两讲我告诉了大家如何使人物移动,那么今天我们就来看看如何实现仿<三国志曹操传>人物情景对话.其他讲的具体链接我写在下方. 用Javascript开发-<三国志曹操传>-开源讲 ...

  7. 用Javascript开发《三国志曹操传》-开源讲座(一)-让静态人物动起来

    首先来说,让一个游戏赋有可玩性必须要动静结合.(哈哈,大家以为我要讲作文了...但其实我今天要讲的是Javascript)静态的东西谁不会做呢?因为东西一生下来就是静态的(除非你是用的gif动画),所 ...

  8. 用Javascript开发《三国志曹操传》-开源讲座(二)-人物行走的实现

    上一讲我们谈到了如何让静态人物变为动态,今天我们来谈谈如何使人物移动,因为这一讲涉及上一讲内容所以我把上一讲的链接写在下方: http://blog.csdn.net/yorhomwang/artic ...

  9. 用Javascript开发《三国志曹操传》-零部件开发(三)-人物对话中,仿打字机输出文字...

    前两讲我告诉了大家如何使人物移动,那么今天我们就来看看如何实现仿<三国志曹操传>人物情景对话.具体的链接我写在下方. Javascript游戏开发-<三国志曹操传>-开源讲座( ...

最新文章

  1. Hibernate 连接池的三种配置方式
  2. Cannot find System Java Compiler. Ensure that you have installed a JDK (not just a JRE) and configur
  3. 通过OWA修改密码,提示您输入的密码不符合最低安全要求
  4. 本地编译Hadoop2.8.0源码总结和问题解决(转自:http://blog.csdn.net/young_kim1/article/details/50324345)
  5. 并查集(浓缩的精华模版!!!!)
  6. [CSA49G][XSY3315] Bunny on Number Line (DP)
  7. 弹层,iframe页面
  8. Mindomo Desktop for mac(思维导图软件)中文版
  9. qq 病毒 html,盗qq号软件里有病毒吗
  10. P3554 LUK-Triumphal arch 解题报告
  11. 山东计算机设计大赛,山东大学控制学院本科生获中国大学生计算机设计大赛国家级二等奖...
  12. 单纤光模块与双纤光模块的区别是什么?
  13. linux打开txt文件命令_「linux命令详解」lsof命令解析,教你一步打开所有文件
  14. Ethercat远程IO模块接线准则
  15. 记录人生第一个网站,以及相对路径图片无法显示的问题
  16. #计算机应用与技巧分享 #应用推荐 #录屏 Captura 免费开源的屏幕录制工具
  17. NSN 内部推荐 -- 不能从电子邮件地址认证身份和来源.
  18. ubuntu16怎么升级到ubuntu18
  19. matlab多条曲线绘制在一张表格——设置绘图曲线类型、plot设置名称、坐标轴范围和精度
  20. DONNET俱乐部的新拐点-加入“国际.NET协会”The International .NET Association (INETA)

热门文章

  1. 聊聊阻容降压原理 和 实际使用的电路
  2. 周杰伦粉丝赢了超话大战
  3. saltstack 的安装
  4. 2W 字详解设计模式
  5. 生活里的插曲——致《奔跑吧,兄弟》
  6. Android开发天气预报自我记录
  7. 详 mpls option a b c产生背景 及实验
  8. 建站3年仍旧失败 ! 个人站长失败仿佛是必然
  9. 新版海螺影视主题模板M3.1全解密版本多功能苹果CMSv10后台自适应主题开源全解密版
  10. 网站服务器怎么屏蔽ip段,iis屏蔽ip段,网站禁止ip访问