如何在网页设计地图 类似于lol的网页游戏游戏地图区域

网页嵌入百度地图和使用百度地图api自定义地图的详细步骤
作者:佚名
字体:[ ] 来源:互联网 时间:05-05 15:48:29
这篇文章主要介绍了网页嵌入百度地图和使用百度地图api自定义地图的详细步骤,需要的朋友可以参考下
在网页中插入百度地图
如果想在自己的网页上面加入百度地图的话,可以用百度地图的api.具体使用方法如下:
第一步:进入百度创建地图的网站,搜索出自己要展示的位置,如下图所示。
第二步:设置地图,大家可以对网站显示地图的宽高进行设置,其余选项不动。
第三步:添加标注。点击第一个图标后,在右侧找到自己的位置,单击鼠标左键可定位。标记图标处可更换图标形状,名称和备注填入位置相关信息。
第四步:获取代码。将代码贴到你的网页里就OK了。代码如下:
代码如下:&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "&a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&/a&"&&html xmlns="&a href="http://www.w3.org/1999/xhtml"&http://www.w3.org/1999/xhtml&/a&"&&head&&meta http-equiv="Content-Type" content="text/ charset=gb2312" /&&meta name="keywords" content="百度地图,百度地图API,百度地图自定义工具,百度地图所见即所得工具" /&&meta name="description" content="百度地图API自定义地图,帮助用户在可视化操作下生成百度地图" /&&title&百度地图API自定义地图&/title&&!--引用百度地图API--&&style type="text/css"&
html,body{margin:0;padding:0;}
.iw_poi_title {color:#CC5522;font-size:14font-weight:overflow:padding-right:13white-space:nowrap}
.iw_poi_content {font:12px arial,sans-overflow:padding-top:4white-space:-moz-pre-word-wrap:break-word}&/style&&script type="text/javascript" src="&a href="http://api./api?key=&v=1.1&services=true"&&/script"&http://api./api?key=&v=1.1&services=true"&&/script&/a&&&/head&&/p&
&!--百度地图容器--&
&div style="width:697height:550border:#ccc solid 1" id="dituContent"&&/div&&/body&&script type="text/javascript"&
//创建和初始化地图函数:
function initMap(){
createMap();//创建地图
setMapEvent();//设置地图事件
addMapControl();//向地图添加控件
//创建地图函数:
function createMap(){
var map = new BMap.Map("dituContent");//在百度地图容器中创建一个地图
var point = new BMap.Point(113..822879);//定义一个中心点坐标
map.centerAndZoom(point,17);//设定地图的中心点和坐标并将地图显示在地图容器中
window.map =//将map变量存储在全局
//地图事件设置函数:
function setMapEvent(){
map.enableDragging();//启用地图拖拽事件,默认启用(可不写)
map.enableScrollWheelZoom();//启用地图滚轮放大缩小
map.enableDoubleClickZoom();//启用鼠标双击放大,默认启用(可不写)
map.enableKeyboard();//启用键盘上下左右键移动地图
//地图控件添加函数:
function addMapControl(){
//向地图中添加缩放控件
var ctrl_nav = new BMap.NavigationControl({anchor:BMAP_ANCHOR_TOP_LEFT,type:BMAP_NAVIGATION_CONTROL_LARGE});
map.addControl(ctrl_nav);
//向地图中添加缩略图控件
var ctrl_ove = new BMap.OverviewMapControl({anchor:BMAP_ANCHOR_BOTTOM_RIGHT,isOpen:1});
map.addControl(ctrl_ove);
//向地图中添加比例尺控件
var ctrl_sca = new BMap.ScaleControl({anchor:BMAP_ANCHOR_BOTTOM_LEFT});
map.addControl(ctrl_sca);
initMap();//创建和初始化地图&/script&&/html&
大家感兴趣的内容
12345678910
最近更新的内容> 运用Dreamweaver制作地图(热点图像区域)链接的方法运用Dreamweaver制作地图(热点图像区域)链接的方法我们浏览网页时,经常看到一些图片上会出现特别的超链接,即在一张图片上有多个局部区域和不同的网页链接,比如地图链接。
这就是映射图像(Image Map),它是指一幅根据链接对象不同而被人为划分为若干指向不同链接的区域或&热点&(Hotspots)的相应图像区域,当点击设置好的&热点&时,会弹出链接的相应页面。
Dreamweaver制作映射图像&&热点图像区域
现在就利用Dreamweaver CS5的图像热点功能制作一个地图链接的实例。
1. 在 Dreamweaver CS5 中新建一个HTML文件取名为 map.html,选择“插入”菜单,“图像”选项,如下图所示:
在页面中插入中国地图图像。
2. 绘制热点区域。单击页面上的中国地图,选择底部“属性”栏中的“矩形热点工具”在地图上绘制热点区域,如下图所示:
3. 当绘制完矩形热点区域后,或者重新选择绘制好的矩形热点区域后,图像属性面板将变成热点属性面板。在“链接”框中选择热点区域所要链接的目标网页,在“目标”框中选择“_blank”,使链接的网页在新窗口中打开,在“替换”框中填入相关的提示说明。如下图所示:
提示:在这里将“目标”设置为“_blank”表示在新的浏览器窗口中打开被链接的文档,并保持当前窗口可用。“目标”框中其他各选项的含义是:
1)“_parent”代表在链接所在的父框架集中打开链接文档;
2)“_self”代表在当前框架中打开链接文档,替换该框架中的内容;
3)“_top”代表在当前文档的最外层框架集中打开链接文档,替换所有框架中的内容。
4. 绘制其他热点区域。使用属性面板中的另外两个热点工具“圆形热点工具”和“多边形热点工具”同样可以在地图上绘制热点并设置相关的热点属性,其使用方法和“矩形热点工具”相同。
现在在地图上继续绘制其他热点区域并设置链接,最终效果下图所示:
提示:使用“多边形热点工具”时,先选择工具,在要绘制的区域点击鼠标左键,这时会弹出一个对话框,不用管它,直接点“确定”,然后继续单击鼠标左键,此时会看到在点击的区域,每多点击一次,绘制的图形就会变换一次,按此方法就可以绘制出你想要的多边形了。
5. 保存页面文件并按 F12 键进行预览。至此,本实例操作完毕。
源代码如下:
&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=gb2312" /&
&title&运用Dreamweaver制作地图(热点图像区域)链接的方法示例-&/title&
&p&&img src="append/.jpg" width="387" height="329" border="0" usemap="#Map" /&&/p&
&map name="Map" id="Map"&
&area shape="rect" coords="57,75,128,133" href="append/xinjiang.html" target="_blank" alt="新疆介绍" /&
&area shape="circle" coords="159,170,32" href="append/qinghai.html" target="_blank" alt="青海介绍" /&
&area shape="poly" coords="162,238,159,261,161,274,176,286,199,282,206,276,202,255,185,255,177,243,169,233,163,231,162" href="append/yunnan.html" target="_blank" alt="云南介绍" /&
&p&注:选择制作的热点区域:新疆、青海、云南,点击查看效果!&/p&
精华推荐&&&&&&&&&&&&Copyright&
All Rights Reserved&>&&>&&>&正文
《我的世界》地图制作及用法图文详解 我的世界地图怎么用
12:07:50 来源:互联网 作者:未知 编辑:墨池 
  《我的世界》地图是用来记录与查看地形的物品,可显示玩家探索过的世界,今天小编带来《我的世界》地图制作及用法图文详解,还不会制作使用地图的玩家,赶紧来看一下吧。
  每一张地图总共有128×128像素。每一个像素代表的实际大小由地图的缩放尺度决定。如果没有经过任何缩放操作,最初始的地图的每一个像素代表1格。你可以在工作台中将地图与纸合成以将其比例缩小一个尺度。
  我的世界在水平空间中几乎可说是无限的,所以一张地图根本不能够容纳整个世界。玩家可制作多张地图,且可以对齐到网格。详见多张地图。
  比例缩小:
  地图缩放等级由初始的1级可以逐渐用该合成方法增大到5级。
地图复制:
  得到的地图与原始地图完全相同,甚至当手持其中一张探索新区域时,另一张也会跟着更新。
  用此方法复制地图时,单次合成最多可以复制8张空地图。
  以后也许会让地图支持更多颜色与自定义材质包。
地图用法及性质
  右键拿出新作的地图,等待地图刷新完毕,就可以看清楚四周的地形了。地图中的圆点就是玩家自己的位置。
  地图传递了三个信息:
  地图类型。地图可以记录主世界、下界或末路之地。三种地图都必须在其对应的维度中激活。若查看的地图不对应所在的维度,则地图的内容会如常显示,但没有了方位指针,四处移动也不会更新地图。
  中心点。即空地图变成地图时所在的位置。
  一张地图的中心坐标是固定的,也就是说地图不像多数游戏的“卫星地图”那样,地图是动态的,中心就是玩家方位。另外,如果玩家走出了这张地图的显示范围之外,外部的地形不会显示在地图之上,此时就有必要做一张新的地图。
  当玩家在探索中时,新地形只有在玩家手中拿着地图时才会被记录。地图只会记录当时的地形,也就是说已记录的地形在修改过后,地图不会自动更新,只有在玩家拿着地图重新走过这个地区才能更新地图的显示内容。拿着地图时前方视线不会被遮挡,因为地图处于视野之下,玩家只有向下看才能看到完整的地图。
  想记录新区域的话就必须合成新地图。玩家走到新地图的理想中心点时,玩家就可以手持手中的空地图并右键点击了。此地会成为该地图永远的中心点,再也不能改变。
  地图只会在拿在手上时才会记录地形,尽管地形已经被另外一张地图记录也是如此。一张没有被拿出的地图是空白的,尽管其它地图已经记录了这张地图的区域。
  在正式版 1.0.0 到12w34a之间的版本里,玩家若要合成一张新地图,就不能使用Shift键:使用Shift键拿起的地图永远是 map_0 的副本,即在这个世界中合成的第一张地图。相同标记(map_0)的地图之间的地形记录会自动同步。在创造模式,map_0 会自动创建,中心点在重生点,而且在物品栏中直接取出的地图都是map_0。
  但其它地图仍然可以通过合成得到。合成的第一张地图是map_1,第二张是map_2,等等。且合成的地图无法重复得到,建议用箱子装起来。
  主条目: 地图物品格式
  地图上的每一个像素代表世界上一个特定的可视区域,且代表的X和Z轴坐标也是8的倍数。总体上地图上像素颜色由对应区域中出现最多的不透明方块的颜色决定,就如在空中俯视所见。但是也有例外。例如,沙石、金块、巨型红色蘑菇、羊毛和地狱岩在地图上的颜色为灰色。在区域内的少数方块不会对像素的颜色起任何影响,因此在缩放程度较大的地图中很多细节都看不到。
  海洋下15格以内的海底会略显淡蓝色,你可以通过此特征大致的估算海拔。
  地图的显示面积为128像素×128像素,故其覆盖面积从128×128到格不等(8×8到128×128个区块),数量与其缩放程度有关。缩放等级为4的地图与1.3.2正式版以及之前版本中的地图比例尺相同。
  在多人游戏中,地图有重要的社交意义,因为一个玩家可以把自己的地图给另外一个玩家,此时其他玩家可以看到别的人探索过的区域。地图是可以复制的,所以几个玩家可以共同探索一张地图。在相同的地图中其他玩家的方位也是可以知道的。
  地图一般作为玩家迷路时的指导。在单人游戏中地图可以指引去找剩余的矿藏,在多人游戏中,玩家可以查看其他玩家的地图。在不同维度中合成的地图不会标明玩家的方位,也不会出现内容的更新。
  在PvP服务器中地图也有很大作用,能够标出你敌人的位置。
  在下界中,由于有天花板,地图只会显示出红色和灰色。此时地图的唯一用处便是告知当前位置相对于地图制作地点的方位。此外方向指针会快速的旋转,并不能指明玩家的朝向。这时要记住,地图“上北下南”,再运用东南定律(此处,地狱岩中有“L”型图案指向东北方)便可确定方向。若地图在传送门旁边制作,则地图的中央就是传送门。地图也可以标明已探索的区域作为参考。
  在末路之地中合成的地图也只会显示出红色和灰色,尽管末路之地没有可见的天花板。但地图上的方向指针是正常工作的。
  地图也可以显示出海拔高度。海拔越高,地图上的图像越明亮。
  若玩家在第二人称或第三人称视角中拿着地图,只会显示出地图在物品栏中的图像,而不会出现实际的记录内容。
  如果你用第一人称视角拿着地图坐上船或矿车,然后切换到第三人称视角,最后回到第一人称视角,你会发现左手会摆放错误。在船或矿车上打开物品栏的时候也有可能导致这种情况的发生。
  在程序设计上地图不能记录虚空。虽然实际上极为罕见地能够记录,但更多情况下会导致游戏自动保存并崩溃。
  在有些服务器上地图可能不能正常使用,具体表现为记录的范围很窄,且只有零星的几个像素。
  当拿着地图破坏一个方块时,地图会被清空,地图的编号会增加1(如map_0 会变成 map_1)。(正式版 1.0.0 后不再出现。)
  在世界加载时,若玩家转向左边,地图上玩家的方向指针会偏离一个像素(约22.5°);若转向右边则表现正常。这也“追踪”了玩家在各个方向上的偏转角度。
  多人模式中的某些地图在探索地形时会一切正常,但当玩家重新登录时地图上会出现垂直的线。大多数情况下把地图交给别人看一会就会恢复正常。
  在多人模式中,合成一个新的地图有可能会清空放在物品栏中的旧地图。
  所有颜色的羊毛在地图上都显示为亮灰色。
  当在海拔230米处合成并查看地图的时候,游戏会自动保存并崩溃。(有记录的出现有一次)
  在正式版 1.2 中,合成的多个地图都只会是 map_0 的副本。
你知道吗:
  在PvP服务器中,合成和使用地图要谨慎,因为别人有可能通过地图发现你和你秘密基地的位置。注意:最好在重生点或远离自己基地的地方合成地图,以免暴露出机密的方位。
  地图只会显示地面上的地貌,即使你在探索山洞里。当你在建造通向地面的隧道时,地图是个很好的工具,用来判断上方是否危险(水、岩浆,沙等)
  只有地图和拉开的弓是 Minecraft 中需要双手来拿的物品。
  当玩家走出地图的边缘时,玩家的位置会短暂的跳跃到地图上的另外一边。
  当被放入玩家的物品栏中后,地图的名字总是被叫做map-x(除非地图的伤害值被正确修改),x是地图的编号,第一张地图就是map-0。
  当玩家拿着地图时,按F5切换到第三人称视角,并不会看到玩家低头在看地图,而仅仅是玩家物品栏中的地图图标。
  地图尽管是用纸做的,但是还是可以在雨中和水下使用。
  地图是minecraft中最细致的物品,它有比大型壁画多几倍的像素。
  Notch说过地图记录玩家自定义数据的特性会使得撰写书成为可能。甚至告示牌或者画都能使用自定义的材质。
  每个世界最多可以有65536张各不相同的地图。
  如果地图数量超过限制,游戏将会显示"Can\'t craft map: too many maps"(无法合成地图:地图数目过多)信息。
  使用"/give"指令得到的地图只会是map_0。若map_0从来未被合成过,则地图中央是原始的出生点。
  当前地图只能显示地表地形。但是 Notch 表示山洞地图是个很有趣的主意。
  Notch说他会试着让地图能挂在墙上。但是这个功能至今还未出现在游戏中(1.4的每周快照中物品展示框已能实现,尽管1x1的空间使得阅读地图有些吃力)。
  不同地图的数据分别保存在不同的文件中(.dat文件,如map_x.dat ,x是地图的编号,详见地图物品格式)。因此玩家可以管理他们的地图,如果玩家不小心制作了2张中心点相同的地图,他可以删除那个多余的地图来减少剩余地图编号的使用量。
  在多人模式中地图可以记录虚空。
  地图的中心点指的是在合成时玩家所站的位置,不是地图首次使用的地方,也不是工作台的位置。
  在查看地图时,手臂的材质会旋转,显示出背部的材质,因为玩家使用手心托住地图的。
其他制作教程:
  地图种子代码大全:
  修改地图名称颜色及字体教程:
更多相关内容请关注:
游戏制作:Mojang AB
游戏发行:Mojang AB、网易
游戏平台:PC/Xbox360/XboxOne/PS3/PS4/WiiU/PS Vita
上市时间:
游戏特色:
--游民指数
又是一个有生之年系列!由“我的三体制作组”利用游戏《我的世界》制作的动画《我的三体》终于更新到了第二季第二集。
《我的世界》高自由度的玩法使得玩家中涌现出各种大神,打造出一个又一个令人叹为观止的世界。不过大部分作品都是还原某个游戏或影视作品中已经存在的场景,而今天要介绍的这位玩家则是打造了一个纯原创的震撼王国。
在《我的世界》10月4日的更新内容中,就将带领我们进入中国的神话领域,感受“方块版”的仙侠元素。
玩家Alan Becker将这个世界带到了游戏中来,在《我的世界》中重塑了属于宫崎骏的动画天堂,近日Alan的新作品《我的世界》版《龙猫》正式完工,放出了宣传片。
喜欢《守望先锋》的玩家一定对好莱坞这张地图不陌生。这张地图的机制是先占领要点后运载目标,出场率很高。今天要给大家带来国外团队Team GBF用《我的世界》打造的这张地图。整个地图一砖一瓦都是玩家团队一点点打造出来的,甚至对内部也进行了还原,非常精细。
近日,国外大神公布了一段用《我的世界》游戏画面制作的视频,里面没有复杂的场景,只是沿一条轨道快速向前行进,而整个世界的画面都是扭曲旋转的。
国人团队@NLT_工作室出品了新的《我的世界》中世纪作品——《忒伊亚》,其规模的宏大用震撼来形容都不够。
今天,微软宣布《我的世界》Windows 10版本正式推出支持Oculus Rift的版本。
国内《我的世界》创造达人@青知Vision 则别出心裁,利用新的手法打造出了我的世界版《盗墓笔记》的动态海报场景。
一位ID名为MrSquishyYT的玩家在Reddit发帖,展示了自己费尽心血的成果:他总算能《我的世界》游戏中玩《口袋妖怪:火红》了。
虎牙直播第二届YSL《我的世界》建筑直播大赛正赛打响,脱颖而出的A、B两组首轮亮相,用完美表现为正赛拉开帷幕,一起来欣赏他们的作品吧!
《我的世界》玩家总是能带来不一样的惊喜,这次我们要介绍的是一位被日媒gamespark报道了的《我的世界》版“时代广场”。
近日有国外玩家以《纪念碑谷》为灵感,在《我的世界》中重现了游戏的城堡。
这次要介绍的是以《旺达与巨像》为灵感建造的两只巨像,作者Divici曾经打造过《我的世界》版的《霍比特人》。
我们之前曾经报道过有关VR版本《我的世界》的新闻,如今游戏发布了截图,来体会一下像素游戏保持原汁原味的风格。
《我的世界》作为游戏界的膝盖收割机,近日用一张截图再次让很多国内外玩家跪服,无论是在reddit还是微博推特上,都被疯狂转发。
一位《我的世界》外国画伯在游戏里花了六个小时制作了一副超现实主义画像,将它放到了一辆车上展示,起名为“Carry The Impossible”,画的内容是一座燃烧中的教堂,或许还带着点信仰意味?
今天要介绍的这位《我的世界》大神lukep323也是其中的一员,他在《我的世界》中打造了一座芝加哥城,用1:4的比例还原了整座城市的建筑。
一位玩家在《我的世界》里建造了一座城堡,他将《超级马里奥64》中的城堡用小方块搬到了《我的世界》中来,让我们来看看别人的世界是怎样打造奇迹的?
《我的世界》能玩《口袋妖怪》了!请注意,本次可不是一款《口袋妖怪》Mod,而是真的在“玩”《口袋妖怪》。
单机游戏下载
综合热点资讯
游民星空联运游戏前言上文我们进行了初步的高层设计,现在我们将实现图片预加载和显示地图的功能需求。从本文开始我采用TDD开发,大家可以看到在实现的过程中我们会修改设计,修改设计后又会修改对应的实现代码,这是一个不断迭代的过程。在有测试套件的保护下,我们可以放心地重构。本文目的掌握地图绘制的技术。本文主要内容开发策略预加载图片显示地图重构继续实现显示地图本文最终领域模型高层划分演示本文参考资料回顾上文与显示地图相关的领域模型&&开发策略使用我的控件YPreLoadImg来实现图片预加载,结合progressBar插件,能够显示出加载进度条。只建一个ShowMap类,用这个类来进行实验,找到显示地图的方法,然后在重构的时候再分离出Main类和MapData数据类。原因因为我对canvas很不熟悉,需要先集中精力熟悉canvas的使用,而不是把精力放在架构设计上。因为我是采用TDD开发,因此可以安全地进行重构。可以在实现&显示地图&功能后,再在重构时提炼出Main和MapData类。开发策略也是迭代修正的开发策略只是就当前的知识指定的大概计划,会随着开发的进行而进行细化和修正。如现在的开发策略并没有考虑到在重构时会增加Game类。预加载图片预加载的目的将图片下载到本地内存中。为什么要预加载必须等到图片完全加载后才能使用canvas对图片进行操作。如果试图在图片未完全加载之前就将其呈现到canvas上,那么canvas将不会显示任何图片。如果不使用预加载,则在使用图片之前需要先下载图片到本地。即使有浏览器优化,第一次使用图片时也需要先下载图片,这样在第一次使用图片时,会有卡的感觉。因此,在游戏开始之前,先要进行游戏初始化,预加载游戏所需的图片。如何进行预加载基本示例:var img = new Image();
//创建一个图片对象img.src = "test.png"; //下载该路径的图片 img.onload = function () { //图片下载完毕时异步调用callback函数。
callback(img); };预加载网上教程js图片预加载js 实现图片预加载浏览器重图片的预加载问题onload事件显示进度条YPreLoadImg控件结合进度条插件progressbar,可以显示出进度条。新增ShowMap类并实现预加载图片新增ShowMap类,使用TDD开发并实现预加载图片,需要先写测试用例。这里先简单介绍下测试驱动开发的步骤:写一个测试用例,验证行为运行测试,检查测试用例本身是否有错误(测试是否按自己所期望的方式失败)。写实现代码,使得测试通过重构代码运行测试,使得测试通过测试代码下面是关于预加载的测试代码(这里只是展示最后结果,实际开发中并不是一口气就先把测试代码写完然后就直接写实现代码了,而是每次先写验证一个行为的测试代码,然后再写相应的实现代码,然后再写验证下一个行为的测试代码,这样迭代开发):describe("showMap.js", function () {
describe("init", function () {
beforeEach(function () {
//不执行onload
spyOn(showMap, "onload").andCallFake(function () {
afterEach(function () {
it("传入的参数为数组,数组元素包含id和url属性", function () {
var urls = [];
var temp = [];
var i = 0, len = 0;
spyOn(window.YYC.Control, "PreLoadImg");
{ id: "ground", url: "ground.png" },
{ id: "wall", url: "wall.png" }
for (i = 0, len = temp. i & i++) {
urls.push({ id: temp[i].id, url: "../../../../Content/Bomber/Image/Map/" + temp[i].url });
showMap.init();
expect(YYC.Control.PreLoadImg).toHaveBeenCalled();
expect(YYC.Control.PreLoadImg.calls[0].args[0]).toBeArray();
expect(YYC.Control.PreLoadImg.calls[0].args[0][0].id).toBeDefined();
expect(YYC.Control.PreLoadImg.calls[0].args[0][0].url).toBeDefined();
describe("onload", function () {
function insertDom() {
dom = $("&div id='progressBar'&&/div&");
$("body").append(dom);
function removeDom() {
dom.remove();
beforeEach(function () {
insertDom();
afterEach(function () {
removeDom();
it("加载完毕后,隐藏加载进度条", function () {
expect($("#progressBar").css("display")).toEqual("block");
showMap.onload();
expect($("#progressBar").css("display")).toEqual("none");
});});实现代码var showMap = (function () {
var _getImg = function () {
var urls = [];
var temp = [];
var i = 0, len = 0;
temp = [{ id: "ground", url: "ground.png" }, { id: "wall", url: "wall.png" }];
for (i = 0, len = temp. i & i++) {
urls.push({ id: temp[i].id, url: "../../../../Content/Bomber/Image/Map/" + temp[i].url });
init: function () {
this.imgLoader = new YYC.Control.PreLoadImg(_getImg(), function (currentLoad, imgCount) {
$("#progressBar_img_show").progressBar(parseInt(currentLoad * 100 / imgCount, 10));
//调用进度条插件
}, YYC.Tool.func.bind(this, this.onload));
onload: function(){
$("#progressBar").css("display", "none");
alert("complete!");
window.showMap = showM}());
补充说明YYC.Tool.func.bind是我的一个工具类方法,作用是将onload中的this指向showMap。预加载完成后,调用onload,隐藏进度条,弹出对话框,提示&complete&。领域模型 运行在页面上调用init方法
$(function () {
showMap.init();
});显示效果&加载图片中加载完成重构识别出config类,放到辅助操作层  为什么要增加config?showMap中预加载图片的url是相对于当前页面的(//这个在html页面结构中需要测试!),所以在不同的页面预加载图片时(如在测试页面和实际页面),url的前缀可能不一样。因此我希望url的前缀是可以配置的,这样当在不同的页面调用showMap时,只需要改动配置文件就好了。  领域模型&  具体内容所以我增加Config全局配置类,在Config中配置url的前缀。该类属于辅助操作层。Configvar bomberConfig = {
url_pre: {
//showMap.js
SHOWMAP: "../../../../Content/Bomber/"
}};&&ShowMapvar _getImg = function () {...
for (i = 0, len = temp. i & i++) {
urls.push({ id: temp[i].id, url: bomberConfig.url_pre.SHOWMAP + temp[i].url });
}};显示地图开发策略现在我就要开始着手显示游戏地图了。考虑到我没有canvas的使用经验,因此我先进行试验,熟悉canvas中与显示地图相关的api;然后对代码和领域模型进行重构,提炼出新的显示地图的模型;最后再具体实现&显示地图&的功能。因为要使用canvas显示图片,先要对该图片进行预加载。因此先在showMap.onload中进行试验。注意:对onload的测试为异步测试(要等待图片加载完成后才能使用canvas显示图片)。用drawImage显示空地图片因为canvas中使用drawImage来绘制图片,因此需要先掌握该API的用法。测试代码it("绘制一张空地图片", function () {
spyOn(showMap, "getContext").andCallFake(function (canvas) {
showMap.context = canvas.getContext("2d");
spyOn(showMap.context, "drawImage");
showMap.init();
//延迟100ms测试
testTool.asynRun(function () {
expect(showMap.context.drawImage).toHaveBeenCalledWith(showMap.imgLoader.get("ground"), 0, 0);
});实现代码var showMap = (function () {
var _createCanvas = function () {
// 创建canvas,并初始化 (我们也可以直接以标签形式写在页面中,然后通过id等方式取得canvas)
var canvas = document.createElement("canvas");
//设置宽度、高度
canvas.width = 600;
canvas.height = 400;
document.body.appendChild(canvas);
var _getImg = function () {
var urls = [];
var temp = [];
var i = 0, len = 0;
temp = [{ id: "ground", url: "ground.png" }, { id: "wall", url: "wall.png" }];
for (i = 0, len = temp. i & i++) {
urls.push({ id: temp[i].id, url: bomberConfig.url_pre.SHOWMAP + "image/map/" + temp[i].url });
context: null,
imgLoader: null,
init: function () {
var self =
var canvas = _createCanvas();
//为了方便测试,将&取得2d绘图上下文&封装到方法中
this.getContext(canvas);
this.imgLoader = new YYC.Control.PreLoadImg(_getImg(), function (currentLoad, imgCount) {
$("#progressBar_img_show").progressBar(parseInt(currentLoad * 100 / imgCount, 10));
//调用进度条插件
}, YYC.Tool.func.bind(this, this.onload));
onload: function(){
$("#progressBar").css("display", "none");
this.context.drawImage(this.imgLoader.get("ground"), 0, 0);
getContext: function (canvas) {
this.context = canvas.getContext("2d");
window.showMap = showM}());补充说明这里canvas是动态创建的,但是这样创建canvas会有&html5 canvas 坐标成比例而不是固定值!(如drawImage中的dx、dy,clearRect中的x、y)&的问题!在后面的开发中,我们会碰到这个问题,到时候我再详细说明。运行效果&用createPattern显示空地图片区域在游戏开发中,可能需要绘制一片相同图片的区域,该区域由一张图片在x、y方向重复绘制而成,需要用到createPattern、fillStyle、fillRect。因此先进行实验。测试代码describe("画出地图", function () {
function spyOnContext(func) {
spyOn(showMap, "getContext").andCallFake(function (canvas) {
showMap.context = canvas.getContext("2d");
it("获得pattern", function () {
spyOnContext(function () {
spyOn(showMap.context, "createPattern");
showMap.init();
//延迟100ms测试
testTool.asynRun(function () {
expect(showMap.context.createPattern).toHaveBeenCalledWith(showMap.imgLoader.get("ground"), "repeat");
expect(showMap._pattern).not.toBeNull();
it("缓存pattern", function () {
spyOnContext(function () {
spyOn(showMap.context, "createPattern");
showMap.init();
expect(showMap.context.createPattern.calls.length).toEqual(1);
//*延迟100ms后,执行&showMap.init();&。
//*然后再延迟100ms后,如果showMap.context.createPattern没有被调用,就验证pattern被缓存了&
testTool.asynRun(function () {
showMap.init();
testTool.asynRun(function () {
expect(showMap.context.createPattern.calls.length).toEqual(1);
it("画出200*200的空地图片区域,ie、ff显示正常", function () {
spyOnContext(function () {
spyOn(showMap.context, "fillRect");
showMap.init();
testTool.asynRun(function () {
expect(showMap.context.fillStyle).toEqual(showMap._pattern);
expect(showMap.context.fillRect).toHaveBeenCalledWith(0, 0, 200, 200);
});});实现代码onload: function(){
$("#progressBar").css("display", "none");
if (!this._pattern) {
this._pattern = this.context.createPattern(showMap.imgLoader.get("ground"), "repeat");
this.context.fillStyle = this._
this.context.fillRect(0, 0, 200, 200);},运行效果重构现在需要停一下,对已有的代码进行梳理。创建bitmap类,并进行对应重构我发现,在showMap的onload方法中,多次使用到了图片对象:showMap.imgLoader.get("ground"),这个对象是预加载图片后的Image对象。考虑到在游戏中需要对图片进行操作,那为什么不能提出&图片类&的概念,将与图片本身相关的内容都放到该类中呢?因此,我提炼出Bitmap类,该类有以下职责:包含图片的信息(如图片对象image、width、height等)包含图片的基本操作(如剪切、缩放等)进一步思考绘制图片的draw方法应不应该放到Bitmap类中呢?考虑到Bitmap类是图片的包装类,包含与图片本身密切相关的属性和方法。而绘制图片方法的职责是读取图片的属性,使用canvas的api进行操作。Bitmap类不需要知道自己是如何被调用的,因此绘制图片的职责应该放到调用Bitmap的类,即放到ShowMap类中。为什么不创建图片的精灵类?因为图片不是独立的个体,它属于数据的概念,是精灵的一个属性,在概念上它并不是精灵。&Bitmap应该具体有哪些成员?属性:应该包含预加载后的图片对象、宽度和高度、图片的坐标。方法:目前来看,不需要对图片进行操作,因此不需要如剪切等方法。领域模型测试代码describe("Bitmap.js", function () {
var bitmap =
beforeEach(function () {
afterEach(function () {
describe("构造函数Init", function () {
function insertDom() {
dom = $("&img id='test_img'&");
$("body").append(dom);
function removeDom() {
dom.remove();
beforeEach(function () {
insertDom();
afterEach(function () {
removeDom();
it("获得预加载后的图片对象、宽度、高度、图片的坐标", function () {
bitmap = new Bitmap($("#test_img")[0], 2, 3, 4, 5);
expect(bitmap.img).not.toBeNull();
expect(bitmap.width).toEqual(2);
expect(bitmap.height).toEqual(3);
expect(bitmap.x).toEqual(4);
expect(bitmap.y).toEqual(5);
});});实际代码(function () {
var Bitmap = YYC.Class({
Init: function (img, width, height, x, y) {
var judge = YYC.Tool.
this.img =
this.width =
this.height =
Private: {
img: null,
height: 0,
window.Bitmap = B}());重构BitmapBitmap构造函数的参数太多了,因此使用一个对象直接量来包装参数:(function () {
var Bitmap = YYC.Class({
Init: function (data) {
this.img = data.
this.width = data.
this.height = data.
this.x = data.x;
this.y = data.y;
Private: {
img: null,
height: 0,
window.Bitmap = B}());运行测试,测试失败。修改测试代码,使测试通过:
it("获得预加载后的图片对象、宽度、高度、图片的坐标", function () {
bitmap = new Bitmap({
img: $("#test_img")[0],
height: 3,
expect(bitmap.img).not.toBeNull();
expect(bitmap.width).toEqual(2);
expect(bitmap.height).toEqual(3);
expect(bitmap.x).toEqual(4);
expect(bitmap.y).toEqual(5);
});创建BitmapFactory类因为在ShowMap类中需要创建Bitmap实例,因此需要增加Bitmap的工厂BitmapFactory类。理由如下:Bitmap构造函数有3个参数,比较复杂,需要将创建实例这个过程封装起来。因此需要工厂类来负责和管理创建过程。领域模型&测试代码describe("bitmapFactory.js", function () {
describe("createBitmap", function () {
function insertDom() {
dom = $("&img id='test_img'&");
$("body").append(dom);
function removeDom() {
dom.remove();
beforeEach(function () {
insertDom();
afterEach(function () {
removeDom();
it("方法存在", function () {
expect(bitmapFactory.createBitmap).toBeDefined();
it("如果参数为1个(HTMLImg对象),则bitmap的width、height为HTMLImg的width、height", function () {
var bitmap = null,
width = 0,
height = 0;
bitmap = bitmapFactory.createBitmap($("#test_img")[0]),
width = $("#test_img").width(),
height = $("#test_img").height();
expect(bitmap.width).toEqual(width);
expect(bitmap.height).toEqual(height);
it("如果参数为3个(HTMLImg对象、width、height),则bitmap的width、height为传入的width、height", function () {
var bitmap =
bitmap = bitmapFactory.createBitmap($("#test_img")[0], 100, 200),
expect(bitmap.width).toEqual(100);
expect(bitmap.height).toEqual(200);
});});实际代码(function () {
var bitmapFactory = {
createBitmap: function (img, width, height) {
if (arguments.length == 1) {
return new Bitmap(img, img.width, img.height);
else if (arguments.length == 3) {
return new Bitmap(img, width, height);
window.bitmapFactory = bitmapF}());showMap.onload对应改变onload: function(){
$("#progressBar").css("display", "none");
if (!this._pattern) {
this._pattern = this.context.createPattern(bitmapFactory.createBitmap(showMap.imgLoader.get("ground")).img, "repeat");
this.context.fillStyle = this._
this.context.fillRect(0, 0, 200, 200);},重构测试现在让我们来回头看下drawImage和createPattern的测试,在测试中都需要异步测试。每增加一个测试用例就需要延迟测试,这样增加了很多重复代码,为什么不能把延迟测试分离出去,从而在测试中把精力放到我们的主要任务-即如何测试行为上呢?因此,我把init方法放到测试页面SpecRunner上调用,然后在测试页面上对整个测试进行延迟,这样就能保证整个测试都是在图片预加载成功后进行的了。测试页面相关代码:&body&&script type="text/javascript"&(function () {
//图片预加载
main.init()
//清除&main.init()&创建的多余html元素
function clear() {
$("body").children().not("script").remove();
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function (spec) {
return htmlReporter.specFilter(spec);
var currentWindowOnload = window.
//延迟300ms执行测试(等待预加载完后执行)
setTimeout(function () {
if (currentWindowOnload) {
currentWindowOnload();
execJasmine();
function execJasmine() {
jasmineEnv.execute();
}})();&/script&&/body&现在测试用例中就不再需要&testTool.asynRun&进行异步测试了。重构ShowMap现在,让我们再来看看showMap类,发现该类做了三件事:游戏初始化:图片预加载游戏逻辑显示地图增加Main类根据单一职责原则,一个类只应该有一个职责,只有一个原因引起变化。再结合之前给出的领域模型,Main类是游戏入口,负责控制游戏的主循环,调用相关的操作。因此,将showMap中负责游戏初始化的init方法移到Main中。增加Game类showMap中还包含了游戏逻辑,如在onload中隐藏进度条,然后显示地图。根据以往游戏开发经验,知道游戏逻辑会越来越复杂,因此可以将游戏逻辑提取出来形成新类Game,这样ShowMap只负责调用canvas的API显示地图了。重构后的领域模型相关代码Mainvar main = (function () {
var _getImg = function () {
var urls = [];
var temp = [];
var i = 0, len = 0;
temp = [{ id: "ground", url: "ground.png" }, { id: "wall", url: "wall.png" }];
for (i = 0, len = temp. i & i++) {
urls.push({ id: temp[i].id, url: bomberConfig.url_pre.SHOWMAP + "image/map/" + temp[i].url });
imgLoader: null,
init: function () {
var game = new Game();
this.imgLoader = new YYC.Control.PreLoadImg(_getImg(), function (currentLoad, imgCount) {
$("#progressBar_img_show").progressBar(parseInt(currentLoad * 100 / imgCount, 10));
//调用进度条插件
}, YYC.Tool.func.bind(game, game.onload));
window.main =}());Game(function () {
var Game = YYC.Frame.MyClass({
Init: function () {
this.showMap = new ShowMap();
Private: {
showMap: null,
onload: function () {
$("#progressBar").css("display", "none");
this.showMap.drawMap();
window.Game = G}());&重构showMap改成类的形式将ShowMap改成类的形式。提出Layer结合领域模型分析和第2篇博文中分层渲染的概念,我增加Layer类,将图片类Bitmap装入Layer,然后使用Layer来统一绘制图片。Layer包含canvas属性,canvas由Game创建并通过Layer的构造函数将其注入到Layer中。Layer有一个draw方法,负责调用canvas的API来绘制图片。重构Layer  提出Collection考虑到Layer是集合类,因此可以将集合这个概念提出,形成新的Collection类,把集合的相关操作和集合的容器_childs放到Collection中,让Layer继承Collection。从而Layer就具有了集合类的功能。  进一步思考为什么这里选择继承的方式复用,而不是选择组合的方式复用呢?  通过继承来复用比起组合来说更方便和优雅,可以减少代码量。  从概念上来说,Collection和Layer都是属于集合类,应该属于一个类族。Collection是从Layer中提炼出来的,它是集合类的共性,因此Collection作为父类,Layer作为子类。  在可预见的未来中,Layer的变化在于逻辑的变化,而属于集合类的变化几乎没有,因此未来Layer的改动不会涉及Collection的改动。综上所述,这里采用继承的方式复用。  领域模型继续实现显示地图重构到这里就告一段落,现在继续实现&显示地图&。增加mapData根据领域模型,增加MapData类,它是一个二维数组,用来保存地图数据。MapData(function () {
var ground = 1,
var mapData = [
[ground, wall, ground, ground],
[ground, wall, ground, ground],
[ground, wall, ground, ground],
[ground, wall, ground, ground]
window.mapData = mapD}());增加MapDataOperateShowMap不应该直接操作MapData,因为:MapData在后续的迭代中可能会变化,因此需要封装这个变化,使得MapData变化时不会影响到ShowMap根据分层的结果,应该由数据操作层的类来操作MapData因此增加数据操作层的MapDataOperate,它负责获得mapData。领域模型相关代码MapDataOperate(function () {
var mapDataOperate = {
getMapData: function () {
return YYC.Tool.array.clone(mapData);
window.mapDataOperate = mapDataO}());显示地图的实现实现drawMap在ShowMap中,通过调用MapDataOperate的getMapData方法,就可以获得地图数据,然后再根据数据向Layer中加入对应的Bitmap类即可。相关代码ShowMap_getMapImg: function (i, j, mapData) {
switch (mapData[i][j]) {
img = main.imgLoader.get("ground");
img = main.imgLoader.get("wall");
}}...drawMap: function () {
var i = 0,
height = 34,
bitmap = null,
mapData = mapDataOperate.getMapData(),
this._createLayer();
for (i = 0; i & i++) {
//y为纵向height,x为横向width
for (j = 0; j & j++) {
img = this._getMapImg(i, j, mapData);
bitmap = bitmapFactory.createBitmap({ img: img, width: width, height: height, x: x, y: y });
this.layer.appendChild(bitmap);
this.layer.draw();}重构重构MapData将MapData的ground与wall设为枚举值,增加可读性。将枚举值放到Config类中。相关代码Config
GROUND: 1,
var ground = bomberConfig.map.type.GROUND,
wall = bomberConfig.map.type.WALL;重构drawMap  config增加bomberConfig.map配置目前地图大小是在drawMap写死了:大小为4*4,单元格宽度和高度为34px。考虑到地图大小可能在后期的开发中不断变化,因此将其放到Config中进行统一配置。相关代码Config
//方格宽度
WIDTH: 34,
//方格高度
HEIGHT: 34,
GROUND: 1,
},ShowMap_getMapImg: function (i, j, mapData) {
var img = null,
type = bomberConfig.map.
switch (mapData[i][j]) {
case type.GROUND:
img = window.imgLoader.get("ground");
case type.WALL:
img = window.imgLoader.get("wall");
}}...drawMap: function () {
var i = 0,
map = bomberConfig.map,
bitmap = null,
mapData = mapDataOperate.getMapData(),
this._createLayer();
for (i = 0; i & map.ROW; i++) {
//y为纵向height,x为横向width
y = i * map.HEIGHT;
for (j = 0; j & map.COL; j++) {
x = j * map.WIDTH;
img = this._getMapImg(i, j, mapData);
bitmap = bitmapFactory.createBitmap({ img: img, width: map.WIDTH, height: map.HEIGHT, x: x, y: y });
this.layer.appendChild(bitmap);
this.layer.draw();}本文最终领域模型&高层划分重构层增加数据操作层本文增加了MapDataOperate类,对应增加数据操作层。该层负责对数据进行操作。分析  Bitmap放到哪?我们来看下Bitmap的职责:包含图片的信息(如图片对象image、width、height等)包含图片的基本操作(如剪切、缩放等)从中得出Bitmap应该放到数据操作层。层、包、领域模型演示演示地址本文参考资料js图片预加载js 实现图片预加载浏览器重图片的预加载问题onload事件欢迎浏览上一篇博文:炸弹人游戏开发系列(2):初步设计欢迎浏览下一篇博文:炸弹人游戏开发系列(4):炸弹人显示与移动
、 、 、 、 、}

我要回帖

更多关于 类似于lol的网页游戏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信