最近花了两周的时间研究了如何用JS开发一个类似梦幻西游,英雄联盟这种操作模式的Web游戏,通过鼠标右键点击行走,并且地图可以跟随人物的移动而不断的移动。

看一下效果:

demo1:

http://www.njhhsj.com/Game/Jianye/

操作:右键点击移动

 

demo2:

http://www.njhhsj.com/Game/mxd/

操作,A键左移,D键右移,空格键攻击。


这个demo的开发花了我挺长时间的,也参考了许多论坛上游戏爱好者的思维方式。
下面我将总结一下我开发过程中是如何实现的,防止以后自己忘了,哈哈~,主要是几个我花了很长时间思考的部分。
主要展示三个部分:
在总结前先给出一张我的思考图,如图把一张地图划分成九个区域,分别标上字母,灰色地区为窗口区域。



A、B、C、D分别为窗口的左上、左下、右下、右上的四分之一区域,并且在A、B、C、D区域中可以自由移动,人物初始化时在A区中。

以X轴方向移动为例:


1.从A进入D1区域(两条竖着的红线之间的区域)并且继续往右移动时,先到达窗口的二分之一位置也就是红线所在位置,停止人物的移动,切换成地图往左移动,当地图往左一直移动到右边界时,人物进入D区域切换成自由移动,地图到达最右边停止移动。
2.当往左移动时,从D进入D1区域,方法一样,而当人物在D1区域左右移动时中,只需要往反方向移动地图即可,之后再判断是否进入左右边界即可。

人物在Y轴上移动原理是一样的。

变量展示:
var last_X = 500 // 当前人物图片X轴坐标 ,last_Y = 300 // 当前人物图片Y轴坐标 ,Des_x = 547 //
需要人物图片X轴坐标 ,Des_y = 395 // 需要人物图片Y轴坐标 ,Cur_x = 547 // 人物脚底需要移动到的X坐标 ,Cur_y =
395 // 人物脚底需要移动到的坐标 ,Orz_x = 547 // 当前人物脚底X坐标 ,Orz_y = 395 // 当前人物脚底Y坐标 ,n = 0
,img_url ,m_role_mx = 0 // X轴速度分量 ,m_role_my = 0 // Y轴速度分量 ,angle ,mapx_shift =
0 // 地图X轴移动量 ,mapy_shift = 0 // 地图Y轴移动量 ,PI = 3.141592653 ,SPEED = 6 ,dtn =
null ,inlx = 0 // 人物X轴移动量 ,inly = 0 // 人物Y轴移动量 ,angle_D;
人物移动

当点击地图时获取人物的X,Y轴的偏移量inlx,inly,然后分别进行人物X,Y轴的区域判断,分别进行加操作,偏移量为0结束移动,
// 角色移动 MoveRole : function(){ var _this = gameMonitor; // 人物X轴状态 if(inlx >
0){ // A区域 if(Orz_x < w/2 && Orz_x > 0 && gameMonitor.mapX == 0 &&
gameMonitor.mapY == 0){ inlx -= Math.abs(m_role_mx); last_X += m_role_mx; Orz_x
+= m_role_mx; if(Orz_x > w/2){ Orz_x = w/2; } // B区域 }else if(Orz_x < w/2 &&
Orz_x > 0 && gameMonitor.mapX == 0 && gameMonitor.mapY == -(_this.bgHeight-h)){
inlx -= Math.abs(m_role_mx); last_X += m_role_mx; Orz_x += m_role_mx; // C区域
}else if(Orz_x > w/2 && Orz_x < w && gameMonitor.mapY == -(_this.bgHeight-h) &&
gameMonitor.mapX == -(_this.bgWidth-w)){ inlx -= Math.abs(m_role_mx); last_X +=
m_role_mx; Orz_x += m_role_mx; // D区域 }else if(Orz_x > w/2 && Orz_x < w &&
gameMonitor.mapY == 0 && gameMonitor.mapX == -(_this.bgWidth-w)){ inlx -=
Math.abs(m_role_mx); last_X += m_role_mx; Orz_x += m_role_mx; // A1区域 }else
if(Orz_x < w/2 && Orz_x > 0 && gameMonitor.mapX == 0 && gameMonitor.mapY < 0 &&
gameMonitor.mapY > -(_this.bgHeight-h)){ inlx -= Math.abs(m_role_mx); last_X +=
m_role_mx; Orz_x += m_role_mx; if(Orz_x > w/2){ Orz_x = w/2; } // C1区域 }else
if(Orz_x > w/2 && Orz_x < w && gameMonitor.mapX == -(_this.bgWidth-w) &&
gameMonitor.mapY < 0 && gameMonitor.mapY > -(_this.bgHeight-h)){ inlx -=
Math.abs(m_role_mx); last_X += m_role_mx; Orz_x += m_role_mx; // E区域地图移动 }else{
// 人物X轴超出窗口一半区域 Orz_x = w/2; mapx_shift = inlx; inlx = 0; } }else{ inlx = 0; }
// 人物Y轴状态 if(inly > 0){ // A区域 if(0 < Orz_y && Orz_y < h/2 && gameMonitor.mapX
== 0 && gameMonitor.mapY == 0){ inly -= Math.abs(m_role_my); last_Y +=
m_role_my; Orz_y += m_role_my; if(Orz_y > h/2){ Orz_y = h/2; } // B区域 }else
if(h/2 < Orz_y && Orz_y < h && gameMonitor.mapX == 0 && gameMonitor.mapY ==
-(_this.bgHeight-h)){ inly -= Math.abs(m_role_my); last_Y += m_role_my; Orz_y
+= m_role_my; // C区域 }else if(Orz_y > h/2 && Orz_y < h && gameMonitor.mapY ==
-(_this.bgHeight-h) && gameMonitor.mapX == -(_this.bgWidth-w)){ inly -=
Math.abs(m_role_my); last_Y += m_role_my; Orz_y += m_role_my; // D区域 }else
if(Orz_y > 0 && Orz_y < h/2 && gameMonitor.mapY == 0 && gameMonitor.mapX ==
-(_this.bgWidth-w)){ inly -= Math.abs(m_role_my); last_Y += m_role_my; Orz_y +=
m_role_my; if(Orz_y > h/2){ Orz_y = h/2; } // D1区域 }else if(0 < Orz_y && Orz_y
< h/2 && gameMonitor.mapY == 0 && gameMonitor.mapX < 0 && gameMonitor.mapX >
-(_this.bgWidth-w)){ inly -= Math.abs(m_role_my); last_Y += m_role_my; Orz_y +=
m_role_my; if(Orz_y > h/2){ Orz_y = h/2; } // B1区域 }else if(Orz_y > h/2 &&
Orz_y < h && gameMonitor.mapY == -(_this.bgHeight-h) && gameMonitor.mapX < 0 &&
gameMonitor.mapX > -(_this.bgWidth-w)){ // console.log("B1区域"+Orz_y) inly -=
Math.abs(m_role_my); last_Y += m_role_my; Orz_y += m_role_my; // E区域地图移动 }else{
Orz_y = h/2; mapy_shift = inly; inly = 0; } }else{ inly = 0; }
_this.MoveRoleImage(); // 人物八方位移动图切换 // 绘制角色
_this.hero.paint(img_url,last_X,last_Y); },
 

地图移动:


地图的移动X,Y轴是从(0,0)到(-(地图宽度-窗口宽度),-(地图高度-地图高度))这个范围。
当地图接收到偏移量mapx_shift,mapy_shift之后,开始移动,知道偏移量为0结束移动。
// 地图移动 MoveImage : function(ctx){ var _this = gameMonitor; //地图X轴需要移动
if(mapx_shift > 0){ mapx_shift -= Math.abs(m_role_mx); gameMonitor.mapX -=
m_role_mx; if(gameMonitor.mapX > 0){ gameMonitor.mapX = 0; }
if(gameMonitor.mapX < (-(_this.bgWidth-w))){ gameMonitor.mapX =
(-(_this.bgWidth-w)); } if(gameMonitor.mapX == 0){ // 到达左边界
_this.IsLeftBorder(); } if(gameMonitor.mapX == (-(_this.bgWidth-w))){ // 到达右边界
_this.IsRightBorder(); } }else{ mapx_shift = 0; } //地图Y轴需要移动 if(mapy_shift >
0){ mapy_shift -= Math.abs(m_role_my); gameMonitor.mapY -= m_role_my;
if(gameMonitor.mapY > 0){ gameMonitor.mapY = 0; } if(gameMonitor.mapY <
(-(_this.bgHeight-h))){ gameMonitor.mapY = (-(_this.bgHeight-h)); }
if(gameMonitor.mapY == 0){ // 到达上边界 _this.IsTopBorder(); } if(gameMonitor.mapY
== (-(_this.bgHeight-h))){ // 到达下边界 _this.IsBottomBorder(); } }else{ mapy_shift
= 0; } // 绘制背景 ctx.drawImage(img, gameMonitor.mapX, gameMonitor.mapY); },
 

边界处理


当进行跨区域操作时将人物偏移量inlx,inly赋值给地图的偏移量mapx_shift,mapy_shift让地图继续接替运动。
当人物进入到自由移动区域时,同样将地图偏移量mapx_shift,mapy_shift返给人物偏移量inlx,inly,接替运动。
// 是否在左边界 IsLeftBorder : function(){ var _this = gameMonitor;
console.log("=====进入左边界====") Orz_x = w/2 - 1; inlx = mapx_shift; if(mapy_shift
> 0){ inly = mapy_shift; } mapx_shift = 0; mapy_shift = 0; }, // 是否在右边界
IsRightBorder : function(){ var _this = gameMonitor;
console.log("====进入右边界====") Orz_x = w/2 + 1; inlx = mapx_shift; if(mapy_shift
> 0){ inly = mapy_shift; } mapx_shift = 0; mapy_shift = 0; }, // 是否在上边界
IsTopBorder : function(){ var _this = gameMonitor; console.log("====进入上边界====")
Orz_y = h/2 - 1; if(mapx_shift > 0){ inlx = mapx_shift; } inly = mapy_shift;
mapx_shift = 0; mapy_shift = 0; }, // 是否在下边界 IsBottomBorder : function(){ var
_this = gameMonitor; console.log("====进入下边界====") Orz_y = h/2 + 1;
if(mapx_shift > 0){ inlx = mapx_shift; } inly = mapy_shift; mapx_shift = 0;
mapy_shift = 0; },
最后再分享一个参考链接,这篇文章我也看了三四遍,由于语言不同,理解起来也不同。

https://blog.csdn.net/crocodile__/article/details/18039107
<https://blog.csdn.net/crocodile__/article/details/18039107>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信