JS游戏开发(四)用地图块拼成大地图

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

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

一、前言

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

二、代码讲解

今天我要换换讲解方式,先不给代码,我们先来想想原理。现在,假如你有一幅图片,把它裁开成若干份,并打乱。现在如果让你用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.");  
     }  
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.

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

首先还是把素材放在这里.

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

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

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

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. 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

首先我把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' 
         ; 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

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

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

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

如果以后加了地图,只用把地图所属的数组名加到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.");  
         }  
     }  
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.

以上的代码很简单,自己可以看看,提示一下:当你在自己开发的过程中如果弹出一个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.");  
     }  
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

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

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

三、演示效果

演示图在下:

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

原文链接:http://www.cnblogs.com/ducle/archive/2012/09/23/2699066.html

责任编辑:张伟 来源: Ducle的博客
相关推荐

2011-08-09 13:10:32

iPhone地图开发

2012-10-08 09:37:14

JSHTML5游戏开发

2022-04-11 17:28:41

戴尔

2021-07-06 12:06:40

React

2012-05-15 13:10:57

HTML5

2021-06-15 14:33:00

高德百度腾讯

2013-05-16 14:31:49

GoogleGoogle Maps

2012-07-13 14:36:07

Java

2021-03-18 08:11:18

PythonDash工具

2013-12-03 10:58:50

Cocos2D-X砖块地图

2012-09-18 13:13:17

2011-09-29 11:00:54

百度地图API

2012-11-27 10:07:24

eWeek诺基亚Here地图

2017-07-21 11:28:57

前端Threejs3D地图

2012-06-25 09:55:53

诺基亚地图Windows Pho

2021-01-07 06:14:31

数据地图可视化数据可视化

2011-09-16 10:37:42

地图API

2011-10-21 10:16:25

百度地图API

2013-05-31 10:33:51

2012-12-18 09:51:53

谷歌地图苹果地图
点赞
收藏

51CTO技术栈公众号