JavaScript绘制游戏地图并且操控人物移动
作者:青花锁
JavaScript开发小游戏,目标是使用JavaScript绘制简单的二维地图,采用二维数组存储地图信息,使用表格绘制地图,每个td单元格存储数据。使用JavaScript keyPress键盘事件监听WASD键,按键触发时人物做出相应操作。人物下一步碰撞到障碍物,终止人物运动。
一、列计划
1.1、目标
做一个2D二维地图绘制、人物移动、障碍检测相关的单页面游戏
1.2、步骤
准备素材(图片):草坪、人物(熊猫)、障碍(石头)
初始化布局(表格),边距设置为0,无边框,设置背景图(草坪)平铺拉满
标记草坪、熊猫、石头的代码
初始化二维地图数据,初始化障碍物围墙,初始化人物位置
计算公共变量二维地图的行、列
合并二维地图数据、人物位置数据,渲染到页面
设置全局键盘事件(在Body上添加),监听wasd按键事件:w(上) s(下) a(左) d(右)
在事件里增加任务移动逻辑、增加边界逻辑
在事件里增加障碍检测逻辑
二、使用步骤
2.1、准备素材(图片):草坪、人物(熊猫)、障碍(石头)
2.2、初始化布局(表格),边距设置为0,无边框,设置背景图(草坪)平铺拉满
设置table的ID:map1001
代表是编号1001的地图
<style> table { border-collapse: collapse; padding: 0 ; background: url("../img/item/grass.png"); width:100%; height:100% ; background-position: center; background-size:cover; background-repeat: no-repeat; } td { width: 100px; height: 100px; } tr { display: block; margin: -5px; } </style> <body onload="init()" onkeypress="keypress(event)"> <table id="map1001"> </table> </body>
2.3、标记草坪、熊猫、石头的代码
<script> var empty = 0; //空地或草坪 var stone = 1; //石头的标记是1 var panda = 9; //熊猫的标记是9 </script>
2.4、初始化二维地图数据,初始化障碍物围墙,初始化人物位置
<script> /** * 加载地图数据 * 0 空地/草坪 * 1 石头 * 9 熊猫 * @type {number[]} */ var mapData = [ [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1] , [ 1 , 0 , 1 , 0 , 0 , 0 , 0 , 1] , [ 1 , 0 , 0 , 1 , 0 , 1 , 0 , 1] , [ 1 , 0 , 0 , 0 , 0 , 1 , 0 , 1] , [ 1 , 0 , 1 , 0 , 1 , 1 , 0 , 1] , [ 1 , 0 , 1 , 0 , 0 , 0 , 0 , 1] , [ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1] ] var initPoint = [1,4]; //初始化熊猫的位置是 1,4 </script>
2.5、计算公共变量二维地图的行、列
<script> var row = mapData.length; //地图的行 var column = mapData[0].length; //地图的列 </script>
2.6、合并二维地图数据、人物位置数据,渲染到页面
<script> /** * 合并二维地图数据、人物位置数据,渲染到页面 */ function init() { //二维数组里,去初始化熊猫的位置 mapData[initPoint[0]][initPoint[1]] = panda loadData(mapData); } /** * 渲染地图 * @param mapData */ function loadData(mapData) { // 获取地图对象 var map = document.getElementById("map1001"); //渲染一行八列的数据 var mapHTML = ""; for (var i = 0; i < row; i++) { mapHTML += "<tr>"; for (var j = 0; j < column; j++) { if( mapData[i][j] == 0 ){ mapHTML += "<td></td>"; } else if( mapData[i][j] == 1 ){ mapHTML += '<td><img src="../img/item/stone.png" style="height: 90px; height: 90px; border-radius: 50%;" ></td>'; } else if( mapData[i][j] == 9 ){ mapHTML += '<td><img src="../img/item/panda1.png" style="height: 90px; height: 90px; border-radius: 50%;" ></td>'; } } mapHTML += "</tr>"; } map.innerHTML = mapHTML; } </script> <body onload="init()" >
2.7、设置全局键盘事件(在Body上添加),监听wasd按键事件:w(上) s(下) a(左) d(右)、在事件里增加任务移动逻辑/增加边界逻辑、在事件里增加障碍检测逻辑
<script> /** * 监听wasd按键事件:w(上) s(下) a(左) d(右) * @param e */ var keypress = function keypress(e){ var keynum = window.event ? e.keyCode : e.which; if( 119 == keynum ) { var point = initPoint; if( point[0] < row - 1 ) { var xPoint = initPoint[1]; var yPoint = initPoint[0] - 1; if( checkStone(yPoint,xPoint) ){ console.log("碰撞到石头了,停止动作") return } console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint ) initPoint = [yPoint,xPoint] operatePanda(point); console.log("向上") } else { console.log("超出地图范围了,停止动作") } } else if( 97 == keynum ) { var point = initPoint; if( point[1] > 0 ) { var xPoint = initPoint[1] -1; var yPoint = initPoint[0]; if( checkStone(yPoint,xPoint) ){ console.log("碰撞到石头了,停止动作") return } console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint ) initPoint = [yPoint,xPoint] operatePanda(point); console.log("向左") } else { console.log("超出地图范围了,停止动作") } } else if( 115 == keynum ) { var point = initPoint; if( point[0] < row - 1 ) { var xPoint = initPoint[1]; var yPoint = initPoint[0] + 1; if( checkStone(yPoint,xPoint) ){ console.log("碰撞到石头了,停止动作") return } console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint ) initPoint = [yPoint,xPoint] operatePanda(point); console.log("向下") } else { console.log("超出地图范围了,停止动作") } } else if( 100 == keynum ) { var point = initPoint; if( point[1] < column -1 ) { var xPoint = initPoint[1] + 1; var yPoint = initPoint[0]; if( checkStone(yPoint,xPoint) ){ console.log("碰撞到石头了,停止动作") return } console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint ) initPoint = [yPoint,xPoint] operatePanda(point); console.log("向右") } else { console.log("超出地图范围了,停止动作") } } } /** * 障碍检测(可加多个障碍条件) * @param yPoint * @param xPoint * @returns {boolean} */ function checkStone(yPoint , xPoint ) { return mapData[yPoint][xPoint] == stone; } </script> <body onload="init()" onkeypress="keypress(event)">
3、部分效果
尝试走到右上角的位置,初始化位置:1,4,目标值:1,1
尝试走直线,从左走到目标,中途碰到石头障碍就走不动了,此时上下左都有石头障碍,都走不动,只能向右走
向右走1格
向下走2格
向左走2格
向上走一格
向左走一格
向上走一格
抵达目标
总结
以上就是今天要讲的内容,本文仅仅简单介绍了2D二维地图绘制、人物移动、障碍检测,可以根据此开发出自动寻径避障、多障碍物绘制、NPC自动出现并移动、人物动画动作、多地图切换、装备仓库、装备效果等。例如:推箱子、走迷宫、副本游戏、熊猫吃竹子等。