第一章 2D二维地图绘制、人物移动、障碍检测
第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示)
第三章 绘制冰宫宝藏地图、人物鼠标点击移动、障碍检测
第四章 绘制Q版地图、键盘上下左右地图场景切换
第五章 Q版地图上让英雄、地图都动起来
本章内容在第一章【2D二维地图绘制、人物移动、障碍检测】、第四章【绘制Q版地图、键盘上下左右地图场景切换】的基础上进行了升级,因此带大家回顾下这两章的内容
在第四章基础上继续添加任务
1、准备【物料层】,设置为地图图片高、宽, 计算物料层2D网格的行、列
2、设置物料层可视区域的行、列;
3、调整地图和英雄的步骤跨度一致;
4、在键盘上下左右事件里,增加英雄动作的逻辑,融合英雄、地图的移动逻辑,增加边界检测
5、看看最终效果
<div style="width: 95%; height: 95%; position: absolute; background-color: red; overflow: hidden; " id="parentDiv">
<div style="z-index: 1; height: 2480px; width: 3280px" id="mapDiv" >
<table class="main bg" id="map1001">table>
div>
div>
<style>
table.main {
border-collapse: collapse;
}
table.main td {
/*border: 0.5px red solid;*/ //调试地图时可开启
width: 79px;
height: 79px;
}
style>
<script>
// 英雄对象
var hero = {
currentPoint : [4, 6], //初始化英雄的位置是 4,6
}
script>
导入物料js
<script src="../js/item.js">script>
item.js
// 物品
var item = {};
item.initItem = function (){
item.empty = 0; //空地或草坪
item.stone = 1; //石头的标记是1
item.factory = 2; //工厂
item.girl = 3; //女子
item.girl_01 = 4; //女孩
item.kt = 5; //空投大礼包
item.lz = 6; //路障
item.pz = 7; //喷子
item.zz = 8; //沼泽
item.hero = 9; //英雄的标记是9
item.heroHasPath = 10; //自动寻径的英雄标记是10
item.wdss = 11; //僵尸的标记是11
item.lzAndempty = 12; //空白的路障
item.datas = []; // 物品的图片集合
var itemPrefixPath = "../img/item/";
item.datas[0] = ""; // 可行走的路径
item.datas[1] = itemPrefixPath + "stone.png";
item.datas[2] = itemPrefixPath + "gc.png";
item.datas[3] = itemPrefixPath + "girl.png";
item.datas[4] = itemPrefixPath + "girl.bmp";
item.datas[5] = itemPrefixPath + "kt.png";
item.datas[6] = itemPrefixPath + "lz.png";
item.datas[7] = itemPrefixPath + "pz.png";
item.datas[8] = itemPrefixPath + "zz.png";
item.datas[9] = itemPrefixPath + "/spine/hero002.gif";
item.datas[10] = itemPrefixPath + "/spine/tank.gif";
item.datas[11] = itemPrefixPath + "wdss.gif";
item.datas[12] = ""; //看不见的路障
}
根据地图绘制可行走路径,
/**
* 加载地图数据
* 0 可走的路径
* 12 看不见的路障
* @type {number[]}
*/
var mapData = [
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12 ],
[12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12 ],
[12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12 ],
[12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12 ],
[12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 0, 0, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 12, 0, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 12, 0, 0, 0, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 0, 12, 0, 0, 0, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 0, 0, 0, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 12, 12, 0, 12, 12, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 0, 12, 12, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 0, 12, 0, 0, 0, 0, 12, 0, 0, 0, 0, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 12, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
[12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ]
]
1、加载物料到地图对象里
2、设置可视区域的行、列
3、增加英雄与上下边框的距离计算方法
4、增加英雄与左右边框的距离计算方法
// 地图对象
var mapObj = {
data: mapData, //地图上的物品数据
// 设定地图最大的高度
maxRow: 8,
// 地图的行
row: function (){
return mapObj.data.length > this.maxRow ? this.maxRow : mapObj.data.length
},
// 设定地图最大的列
maxCol: 12,
//地图的列
col: function (){
return mapObj.data[0].length > this.maxCol ? this.maxCol : mapObj.data[0].length;
},
// 英雄与上下边框的距离
heroMarginTop: function () {
return Math.floor( this.row() / 2)
},
// 英雄与左右边框的距离
heroMarginLeft: function () {
return Math.floor( this.col() / 2)
},
}
var stepDistance = 80; // td的高、宽也设置成80或79px
1、在body标签上增加键盘事件
2、在文档准备好之后开始执行初始化方法
3、定义游戏窗口层、游戏地图层,并渲染页面
4、定义 键盘上下左右事件
5、在第四章基础上,上下左右事件里增加英雄动作的逻辑,融合英雄、地图的移动逻辑
6、增加双重地图检测,保持英雄在地图的中心位置(地图、英雄一起移动)
7、增加英雄边界检测(英雄在边界内时,只移动人物,不移动地图)
8、简单的碰撞检测,下一步到达的目标只有是空地的情况,英雄才能移动
<body onkeydown="keydown(event)">
</body>
//文档准备好之后开始执行
window.onload = function () {
init();
}
/**
* 定义游戏窗口层、游戏地图层,并渲染页面
*/
function init() {
// 定义游戏窗口层
parentDivEle = document.getElementById("parentDiv");
// 定义游戏地图层
mapDivEle = document.getElementById('mapDiv');
// 获取 1001地图 Dom元素
mapDiv = document.getElementById("map1001");
parentDivEle.style.width = (mapObj.col() + 1) * stepDistance + "px";
parentDivEle.style.height = (mapObj.row() + 1) * stepDistance + "px";
item.initItem();
//二维数组里,去初始化熊猫的位置
mapObj.data[hero.currentPoint[0]][hero.currentPoint[1]] = item.hero;
loadData();
}
/**
* 人物移动方法
* @param point
*/
function operateHero(point) {
mapObj.data[hero.currentPoint[0]][hero.currentPoint[1]] = item.hero
mapObj.data[point[0]][point[1]] = item.empty
loadData();
}
/**
* 渲染地图
* @param mapData
*/
function loadData() {
// 加载地图
mapDivEle.style.background= 'url("../img/item/bg/os.jpg")';
//渲染一行 row 列的数据
var mapHTML = "";
for (var i = 0; i < mapObj.data.length; i++) {
mapHTML += "";
for (var j = 0; j < mapObj.data[0].length ;j++) {
if (mapObj.data[i][j] == item.empty) { //只有点击路,才能自动寻径
mapHTML += " + i + "," + j + ")'> ";
} else if( mapObj.data[i][j] == item.lzAndempty ) {
mapHTML += " ";
} else {
mapHTML += '
+ item.datas[mapObj.data[i][j]] +'" style="width: 100%; height: 100%; border-radius: 0%;" > ';
}
}
mapHTML += " ";
}
// 渲染大地图
mapDiv.innerHTML = mapHTML;
}
/**
* 定义 键盘上下左右事件
* 并判断边界
* @param e
*/
var keydown = function (e) {
if (e.keyCode == 37) {
console.log("向左")
if( Number(mapDivEle.style.marginLeft.replaceAll("px", "")) - stepDistance < 0 ) {
var point = hero.currentPoint;
var xPoint = hero.currentPoint[1] -1;
var yPoint = hero.currentPoint[0];
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到障碍了,停止动作")
return
}
console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
if( xPoint <= (mapObj.data[0].length - mapObj.heroMarginLeft()) && Number(mapDivEle.style.marginLeft.replaceAll("px", "")) ) {
mapDivEle.style.marginLeft = Number(mapDivEle.style.marginLeft.replaceAll("px", "")) + stepDistance + "px";
}
hero.currentPoint = [yPoint, xPoint]
operateHero(point);
} else {
console.log("超出边界")
}
} else if (e.keyCode == 38) {
console.log("向上")
if( Number(mapDivEle.style.marginTop.replaceAll("px", "") ) - stepDistance < 0 ) {
var point = hero.currentPoint;
var xPoint = hero.currentPoint[1];
var yPoint = hero.currentPoint[0] - 1;
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到障碍了,停止动作")
return
}
console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
if( yPoint <= (mapObj.data.length - mapObj.heroMarginTop()) && Number(mapDivEle.style.marginTop.replaceAll("px", "")) < 0 ) {
mapDivEle.style.marginTop = Number(mapDivEle.style.marginTop.replaceAll("px", "")) + stepDistance + "px";
}
hero.currentPoint = [yPoint, xPoint]
operateHero(point);
} else {
console.log("超出边界")
}
} else if (e.keyCode == 39) {
console.log("向右")
if ( (parentDivEle.clientWidth) - mapDivEle.clientWidth <= Number(mapDivEle.style.marginLeft.replaceAll("px", ""))) {
var point = hero.currentPoint;
var xPoint = hero.currentPoint[1] + 1;
var yPoint = hero.currentPoint[0];
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到障碍了,停止动作")
return
}
// 超出边界,只移动英雄, 不移动地图
if ( xPoint > mapObj.heroMarginLeft() && (parentDivEle.clientWidth) - mapDivEle.clientWidth + stepDistance <= Number(mapDivEle.style.marginLeft.replaceAll("px", ""))) {
mapDivEle.style.marginLeft = Number(mapDivEle.style.marginLeft.replaceAll("px", "")) - stepDistance + "px";
}
console.log( "移动后的x轴距离:" + xPoint * stepDistance);
console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
hero.currentPoint = [yPoint, xPoint]
operateHero(point);
} else {
console.log("超出边界")
}
} else if (e.keyCode == 40) {
console.log("向下")
if( (parentDivEle.clientHeight) - mapDivEle.clientHeight <= Number(mapDivEle.style.marginTop.replaceAll("px", "")) ) {
var point = hero.currentPoint;
var xPoint = hero.currentPoint[1];
var yPoint = hero.currentPoint[0] + 1;
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到障碍了,停止动作")
return
}
console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
// 超出边界,只移动英雄, 不移动地图
if( yPoint > mapObj.heroMarginTop() && (parentDivEle.clientHeight) - mapDivEle.clientHeight + stepDistance <= Number(mapDivEle.style.marginTop.replaceAll("px", "")) ) {
mapDivEle.style.marginTop = Number(mapDivEle.style.marginTop.replaceAll("px", "")) - stepDistance + "px";
}
hero.currentPoint = [yPoint, xPoint]
operateHero(point);
} else {
console.log("超出边界")
}
}
loadData();
}
/**
* 障碍检测(可加多个障碍条件)
* @param yPoint
* @param xPoint
* @returns {boolean}
*/
function checkStone(yPoint, xPoint) {
return mapObj.data[yPoint][xPoint] != item.empty;
}
以上就是今天要讲的内容,本文简单介绍Q版地图的绘制,地图/英雄的移动、边界检测,喜欢的同学可以参考第二张把自动寻径加上。
原生JavaScript知识点就到这里结束了,以后前端知识点主要以Vue为主。