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

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

 

一、前言

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

前几章的位置:

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

http://www.cnblogs.com/ducle/archive/2012/09/15/2686532.html

用Javascript开发《三国志曹操传》-零部件开发(二)-让目标人物移动

http://www.cnblogs.com/ducle/archive/2012/09/08/2677127.html

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

http://www.cnblogs.com/ducle/archive/2012/09/02/2667481.html

 

二、代码讲解

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

A.用margin慢慢调        B.用数组把它们排列好        C.放弃

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

js代码:

  1 /*
  2  *Prompt:
  3  *If you want to add hurdle, find string: "{{Add hurdle above." and "{{After add hurdle, add the hurdle to the vector above." please.
  4  *If you want to add or change type of grid, find string: "{{Add new grid above.".
  5  *If you want to change position of map, please find string: "{{Change map margin above.".
  6  *If the icon of crid is changed, you have to change the size of icon. Find "{{Change icon size above." to change size.
  7 */
  8 
  9 //Map of hurdle or military or resource.
 10 var vView = [];
 11 
 12 /*Remarks:
 13  *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
 14  *r: research Center *P: port *D: dock *s: Shipyard
 15 */
 16 var mScene = {
 17                 'L': ['./land.png', '陆地']
 18                 , 'S': ['./sea.png', '河流']
 19                 , 'T': ['./tree.png', '树木']
 20                 , 'B': ['./bridge.png', '桥']
 21                 , 'C': ['./beach.png', '沙滩']
 22             };
 23 //{{Add new grid above.
 24 
 25 var mCurrent = {
 26                     Margin: {
 27                         left: -1
 28                         , top: -1
 29                         , right: -1
 30                         , bottom: -1
 31                     }
 32                     , Position: {
 33                         X: -1
 34                         , Y: -1
 35                     }
 36                     , Type: 'NONE'
 37 
 38                 };
 39 var mTitle = {};
 40 
 41 var sHurdleONE = 
 42         'S,S,S,S,S,S,S,S,S,S,S'
 43         + ';T,L,T,T,T,T,S,S,S,S,T'
 44         + ';T,L,L,T,S,S,S,S,S,L,T'
 45         + ';T,L,L,L,C,C,C,S,S,T,S'
 46         + ';T,L,L,L,C,C,C,B,B,L,T'
 47         + ';T,L,L,C,C,C,C,S,S,L,T'
 48         + ';T,L,L,C,C,T,S,S,L,L,T'
 49         ;
 50 //{{Add hurdle above.
 51 
 52 var vHurdles = [sHurdleONE];
 53 //{{After add hurdle, add the hurdle to the vector above.
 54 
 55 function _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin)
 56 {
 57     var mCoordMember = {
 58                             left: nWidthBasic
 59                             , top: nHeightBasic
 60                             , right: nWidthBasic + nPicWidth
 61                             , bottom: nHeightBasic + nPicHeight
 62                         };
 63     var mPositionMember = {
 64                             X: (mCoordMember.left - mMargin.x) / nPicWidth
 65                             , Y: (mCoordMember.top - mMargin.y) / nPicHeight
 66                         };
 67     var mItem = {
 68                     Coord: mCoordMember
 69                     , Position: mPositionMember
 70                     , Type: cType
 71                 };
 72 
 73     return mItem;
 74 }
 75 
 76 function _loadHurdle(sHurdle)
 77 {
 78     var nBasic = 0;
 79     var nWidthBasic = nBasic;            //margin-left.
 80     var nHeightBasic = 0;                //margin-top.
 81     
 82     //{{Change map margin above.
 83 
 84     var nPicWidth = 45;        //Picture width is nBasic.
 85     var nPicHeight = 45;        //Picturn height is nHeightBasic.
 86     //{{Change icon size above.
 87     
 88     var nSub;
 89     var nRow;
 90     var nCol;
 91 
 92     var v = sHurdle.split(';');
 93     var vRec = [];
 94 
 95     for(nSub = 0; nSub < v.length; nSub++){
 96         var vCrid = v[nSub].split(',');
 97         vRec[vRec.length] = vCrid;
 98     }
 99 
100     for(nRow = 0; nRow < vRec.length; nRow++){
101         var vCol = vRec[nRow];
102 
103         for(nCol = 0; nCol < vCol.length; nCol++){
104             var cType = vCol[nCol];
105             var mMargin = {x: nBasic, y: nBasic};
106 
107             vView[vView.length] = _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin);
108 
109             nWidthBasic += nPicWidth;
110         }
111 
112         nHeightBasic += nPicHeight;
113         nWidthBasic = nBasic;
114     }
115 }
116 
117 
118 
119 //Show map with vector 'vView'.
120 function _showMap(sID)
121 {
122     var xDiv=document.getElementById(sID);
123 
124     var xGrid;
125     var xImg;
126 
127 
128     var nTop = 0;
129 
130     var nSub;
131     var sIdPrefix = 'ID_IMG_NUM_';
132     var sIdGrid = 'ID_A_NUM_';
133     for(nSub = 0; nSub < vView.length; nSub++){
134         var mGrid = vView[nSub];
135 
136         if(mGrid){
137             var xMargin = mGrid.Coord;
138             var cType = mGrid.Type;
139             var xProper = mScene[cType];
140             
141             if(xProper){
142                 xGrid = document.createElement('a');
143                 xImg = document.createElement('img');
144 
145                 xImg.style.position = 'absolute';
146                 xImg.style.marginLeft = xMargin.left;
147                 xImg.style.marginTop = xMargin.top;
148                 
149                 xImg.src = xProper[0];
150 
151                 xImg.style.border = '0px solid #000000';
152                 xImg.id = sIdPrefix + nSub;
153 
154                 xImg.style.width = 45;
155                 xImg.style.height = 45;
156     
157                 xImg.style.display = 'block';
158                 
159                 xGrid.onclick = function(e){
160                     var xCurrentGrid = e.target;
161                     var sId = xCurrentGrid.id;
162                     var nIdAsSub = parseInt(sId.substring(sIdPrefix.length, sId.length));
163 
164                     mCurrent = vView[nIdAsSub];
165                     if(!mCurrent){
166                         alert("Error 0004.");
167                     }
168                 };
169                 xGrid.title = xProper[1] + '(' + parseInt(mGrid.Position.X) + ', ' + parseInt(mGrid.Position.Y+2) + ')';
170                 xGrid.id = sIdGrid + nSub;
171 
172                 xGrid.appendChild(xImg);
173 
174                 xDiv.appendChild(xGrid);
175             }else{
176                 alert("Error: 0003.");
177             }
178         }else{
179             alert("Error: 0002.");
180         }
181     }
182 }
183 
184 //Show map of hurdle.
185 function _showHurdle(nHurdle)
186 {
187     if(vHurdles[nHurdle - 1]){
188         _loadHurdle(vHurdles[nHurdle - 1]);
189         _showMap('ID_DIV_BATTLEFIELD');
190     }else{
191         alert("Error: 0001.");
192     }
193 }
194     
195     

看看,这点程序就用了195行,而且这还是一张地图,看来还很有点麻烦哦。没关系,慢慢解释。

首先还是把素材放在这里,当然也可以去我的相册下载下来。

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

素材不是来自《三国志曹操传》,因为没整理好《三国志曹操传》的地图素材,所以就随便找了些。不过也照样可以用。希望大家不要介意。

 

麻烦的代码最容易弄得乱七八糟,因此在此时要良好的区分开样式设置和拼图核心。

拼图核心在哪里呢???在这里:

 1 var mScene = {
 2                 'L': ['./land.png', '陆地']
 3                 , 'S': ['./sea.png', '河流']
 4                 , 'T': ['./tree.png', '树木']
 5                 , 'B': ['./bridge.png', '桥']
 6                 , 'C': ['./beach.png', '沙滩']
 7             };
 8 //{{Add new grid above.
 9 
10 var mCurrent = {
11                     Margin: {
12                         left: -1
13                         , top: -1
14                         , right: -1
15                         , bottom: -1
16                     }
17                     , Position: {
18                         X: -1
19                         , Y: -1
20                     }
21                     , Type: 'NONE'
22 
23                 };
24 var mTitle = {};
25 
26 var sHurdleONE = 
27         'S,S,S,S,S,S,S,S,S,S,S'
28         + ';T,L,T,T,T,T,S,S,S,S,T'
29         + ';T,L,L,T,S,S,S,S,S,L,T'
30         + ';T,L,L,L,C,C,C,S,S,T,S'
31         + ';T,L,L,L,C,C,C,B,B,L,T'
32         + ';T,L,L,C,C,C,C,S,S,L,T'
33         + ';T,L,L,C,C,T,S,S,L,L,T'
34         ;
35 //{{Add hurdle above.
36 
37 var vHurdles = [sHurdleONE];
38 //{{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的,所以也不解释了。关键是在下:

1 var sHurdleONE = 
2         'S,S,S,S,S,S,S,S,S,S,S'
3         + ';T,L,T,T,T,T,S,S,S,S,T'
4         + ';T,L,L,T,S,S,S,S,S,L,T'
5         + ';T,L,L,L,C,C,C,S,S,T,S'
6         + ';T,L,L,L,C,C,C,B,B,L,T'
7         + ';T,L,L,C,C,C,C,S,S,L,T'
8         + ';T,L,L,C,C,T,S,S,L,L,T'
9         ;

这段代码就是把定义好的S,T,B,C,L连在一起的核心。后面只用定义S,T,B,C,L的宽度高度定义就能把它们连成一块。并且只要把它们在数组里的位置调一调就能改变样式。

接下来为了能切换地图,我们把第一张地图放进了数组:

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

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

样式设置在下:

  1 function _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin)
  2 {
  3     var mCoordMember = {
  4                             left: nWidthBasic
  5                             , top: nHeightBasic
  6                             , right: nWidthBasic + nPicWidth
  7                             , bottom: nHeightBasic + nPicHeight
  8                         };
  9     var mPositionMember = {
 10                             X: (mCoordMember.left - mMargin.x) / nPicWidth
 11                             , Y: (mCoordMember.top - mMargin.y) / nPicHeight
 12                         };
 13     var mItem = {
 14                     Coord: mCoordMember
 15                     , Position: mPositionMember
 16                     , Type: cType
 17                 };
 18 
 19     return mItem;
 20 }
 21 
 22 function _loadHurdle(sHurdle)
 23 {
 24     var nBasic = 0;
 25     var nWidthBasic = nBasic;            //margin-left.
 26     var nHeightBasic = 0;                //margin-top.
 27     
 28     //{{Change map margin above.
 29 
 30     var nPicWidth = 45;        //Picture width is nBasic.
 31     var nPicHeight = 45;        //Picturn height is nHeightBasic.
 32     //{{Change icon size above.
 33     
 34     var nSub;
 35     var nRow;
 36     var nCol;
 37 
 38     var v = sHurdle.split(';');
 39     var vRec = [];
 40 
 41     for(nSub = 0; nSub < v.length; nSub++){
 42         var vCrid = v[nSub].split(',');
 43         vRec[vRec.length] = vCrid;
 44     }
 45 
 46     for(nRow = 0; nRow < vRec.length; nRow++){
 47         var vCol = vRec[nRow];
 48 
 49         for(nCol = 0; nCol < vCol.length; nCol++){
 50             var cType = vCol[nCol];
 51             var mMargin = {x: nBasic, y: nBasic};
 52 
 53             vView[vView.length] = _createGrid(nWidthBasic, nHeightBasic, nPicWidth, nPicHeight, cType, mMargin);
 54 
 55             nWidthBasic += nPicWidth;
 56         }
 57 
 58         nHeightBasic += nPicHeight;
 59         nWidthBasic = nBasic;
 60     }
 61 }
 62 
 63 
 64 
 65 //Show map with vector 'vView'.
 66 function _showMap(sID)
 67 {
 68     var xDiv=document.getElementById(sID);
 69 
 70     var xGrid;
 71     var xImg;
 72 
 73 
 74     var nTop = 0;
 75 
 76     var nSub;
 77     var sIdPrefix = 'ID_IMG_NUM_';
 78     var sIdGrid = 'ID_A_NUM_';
 79     for(nSub = 0; nSub < vView.length; nSub++){
 80         var mGrid = vView[nSub];
 81 
 82         if(mGrid){
 83             var xMargin = mGrid.Coord;
 84             var cType = mGrid.Type;
 85             var xProper = mScene[cType];
 86             
 87             if(xProper){
 88                 xGrid = document.createElement('a');
 89                 xImg = document.createElement('img');
 90 
 91                 xImg.style.position = 'absolute';
 92                 xImg.style.marginLeft = xMargin.left;
 93                 xImg.style.marginTop = xMargin.top;
 94                 
 95                 xImg.src = xProper[0];
 96 
 97                 xImg.style.border = '0px solid #000000';
 98                 xImg.id = sIdPrefix + nSub;
 99 
100                 xImg.style.width = 45;
101                 xImg.style.height = 45;
102     
103                 xImg.style.display = 'block';
104                 
105                 xGrid.onclick = function(e){
106                     var xCurrentGrid = e.target;
107                     var sId = xCurrentGrid.id;
108                     var nIdAsSub = parseInt(sId.substring(sIdPrefix.length, sId.length));
109 
110                     mCurrent = vView[nIdAsSub];
111                     if(!mCurrent){
112                         alert("Error 0004.");
113                     }
114                 };
115                 xGrid.title = xProper[1] + '(' + parseInt(mGrid.Position.X) + ', ' + parseInt(mGrid.Position.Y+2) + ')';
116                 xGrid.id = sIdGrid + nSub;
117 
118                 xGrid.appendChild(xImg);
119 
120                 xDiv.appendChild(xGrid);
121             }else{
122                 alert("Error: 0003.");
123             }
124         }else{
125             alert("Error: 0002.");
126         }
127     }
128 }

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

接着看:

1 function _showHurdle(nHurdle)
2 {
3     if(vHurdles[nHurdle - 1]){
4         _loadHurdle(vHurdles[nHurdle - 1]);
5         _showMap('ID_DIV_BATTLEFIELD');
6     }else{
7         alert("Error: 0001.");
8     }
9 }

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

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

 

三、演示效果

演示图在下:

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

 

希望大家多支持。谢谢。

posted @ 2012-09-23 21:00  Yorhom Wang  阅读(2847)  评论(6编辑  收藏  举报
我的CSDN博客:http://blog.csdn.net/yorhomwang
我的cnblogs博客:http://www.cnblogs.com/ducle/
@2012 Yorhom Wang