HTML5游戏_基于DOM平台跳跃小游戏开发
玩家精灵碰撞
- 效果图
- 本章新内容
- filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
var 年龄数组 = [32, 33, 12, 40];
var 大于三十的年龄数组 = 年龄数组.filter
(
function(年龄)
{
return 年龄 > 30;
}
);
//大于三十的年龄数组 [32,33,40]
- **some()**方法用于检测数组中的元素是否满足指定条件,some()方法会依次执行数组的每个元素,并返回布尔值
var 年龄数组 = [32, 33, 12, 40];
var 是否有等于四十岁的年龄 = 年龄数组.some
(
funtion(年龄)
{
return 年龄 === 40;
}
);
//是否有等于四十岁的年龄 true
- 我们先来修改 生成地图数据.js 在生成地图数据函数里添加玩家和状态属性,然后再添加 玩家精灵碰撞 方法和 判断精灵碰撞 方法
生成地图数据.js
/**
*@描述: 生成地图数据 函数
*@传参: 地图 (地图数组的一项,如 地图数组[0] )
*@参数: 宽,高,元素数组,精灵数组,玩家,状态
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
function 生成地图数据(地图)
{
//定义属性 宽 为地图[]数组的长度
this.宽 = 地图[0].length;
//定义属性 高 为地图数组的长度
this.高 = 地图.length;
//定义属性 元素数组 用来存放游戏里每个元素对应地图数据中的元素类型
this.元素数组 = [];
//定义 精灵数组 用来存放游戏里对应地图数据中的精灵
this.精灵数组 = [];
//遍历地图数组,识别地图元素
for (var y = 0; y < this.高; y++)
{
//定义变量 行 来存放地图里一行的数据
const 行 = 地图[y];
//定义数组 元素行 来存放解析地图一行数据后的元素类型
let 元素行 = [];
//遍历一行地图数据
for (var x = 0; x < this.宽; x++)
{
//定义变量 元素 来存 行[] 里的数据
const 元素 = 行[x];
//定义变量 元素类型 来存解析后的元素类型
let 元素类型 = null;
//定义变量 精灵内容 来保存在精灵集合对象中找出元素对应的属性
const 精灵内容 = 精灵集合[元素];
//判断元素
if (精灵内容)
{
//如果是精灵集合中元素,添加到精灵数组
this.精灵数组.push(new 精灵内容(new 矢量(x, y), 元素));
}
else if (元素 === "x")
{
元素类型 = "墙体";
}
else if (元素 === "@")
{
元素类型 = "玩家";
}
else if (元素 === "!")
{
元素类型 = "熔岩";
}
//将元素类型添加到元素行
元素行.push(元素类型)
}
//将一行数据添加到元素数组
this.元素数组.push(元素行);
}
//filter() 方法会创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
this.玩家 = this.精灵数组.filter
(
function(精灵)
{
return 精灵.类型 === "玩家"
}
)[0];
//游戏状态,null表示没有结束,成功表示游戏胜利,失败表示游戏失败
this.状态 = null;
}
/**
*@描述: 生成地图数据 添加 动画 方法
*@传参: 每帧执行时间(每帧执行时间)
*@参数:
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
生成地图数据.prototype.动画 = function(每帧执行时间, 按键内容)
{
//定义变量 最大每帧执行时间=0.05
const 最大每帧执行时间 = 0.05;
//循环查看是否需要补帧动画
while (每帧执行时间 > 0)
{
//定义变量 当前帧执行时间 如果每帧执行时间大于最大每帧执行时间则取最大每帧执行时间0.05,即秒20帧
const 当前帧执行时间 = Math.min(每帧执行时间, 最大每帧执行时间);
//循环遍历 精灵数组
this.精灵数组.forEach(function(精灵)
{
//依次执行精灵.行为方法
精灵.行为(当前帧执行时间, this, 按键内容);
}, this);
//结合循环条件查看是否需要补帧动画
每帧执行时间 -= 当前帧执行时间;
}
};
/**
*@描述: 生成地图数据 添加 判断障碍物 方法
*@传参: 坐标 大小
*@参数:
*@返回值: 元素类型
*@创建人: 王天宇
*@创建时间:2021/03/01
*@修改人和其它信息:
**/
生成地图数据.prototype.判断障碍物 = function(坐标, 大小)
{
//定义区域大小
//x起始位置
const x起始位置 = Math.floor(坐标.x);
//x结束位置 坐标x+大小矢量的x
const x结束位置 = Math.ceil(坐标.x + 大小.x);
//y起始位置
const y起始位置 = Math.floor(坐标.y);
//y结束位置 坐标y+大小矢量的y
const y结束位置 = Math.ceil(坐标.y + 大小.y);
//判断区域是否在地图的左右上边界
if (x起始位置 < 0 || x结束位置 > this.宽 || y起始位置 < 0)
{
return "墙体";
}
//判断区域是否在下边界
if (y结束位置 > this.高)
{
return "熔岩";
}
//判断区域内是否有障碍物
for (let y = y起始位置; y < y结束位置; y++)
{
for (let x = x起始位置; x < x结束位置; x++)
{
const 元素类型 = this.元素数组[y][x];
//判断元素类型 是否有值
if (元素类型)
{
return 元素类型;
}
}
}
};
/**
*@描述: 生成地图数据 添加 玩家精灵碰撞 方法
*@传参: 碰撞精灵类型, 碰撞精灵
*@参数:
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/05
*@修改人和其它信息:
**/
生成地图数据.prototype.玩家精灵碰撞 = function(碰撞精灵类型, 碰撞精灵)
{
//判断碰撞精灵类型如果是熔岩同时状态为null
if (碰撞精灵类型 == "熔岩" && this.状态 == null)
{
//定义状态为失败
this.状态 = "失败";
}
//判断碰撞精灵类型是金币
else if (碰撞精灵类型 == "金币")
{
//将碰撞的金币精灵从精灵数组中删除
this.精灵数组 = this.精灵数组.filter(function(其他精灵)
{
return 其他精灵 != 碰撞精灵;
});
//判断精灵数组中是否还有金币精灵
if (!this.精灵数组.some(
function(碰撞精灵)
{
return 碰撞精灵.类型 == "金币";
}))
{
//没有金币精灵 设定状态为成功
this.状态 = "成功";
}
}
};
/**
*@描述: 生成地图数据 添加 判断精灵碰撞 方法
*@传参: 精灵
*@参数:
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/05
*@修改人和其它信息:
**/
生成地图数据.prototype.判断精灵碰撞 = function(精灵)
{
//依次判断精灵与其他精灵是否发生碰撞
for (var i = 0; i < this.精灵数组.length; i++)
{
const 其他精灵 = this.精灵数组[i];
//判断精灵坐标与大小是否与精灵有碰撞
if (其他精灵 != 精灵 &&
精灵.坐标.x + 精灵.大小.x > 其他精灵.坐标.x &&
精灵.坐标.x < 其他精灵.坐标.x + 其他精灵.大小.x &&
精灵.坐标.y + 精灵.大小.y > 其他精灵.坐标.y &&
精灵.坐标.y < 其他精灵.坐标.y + 其他精灵.大小.y)
{
return 其他精灵;
}
}
};
- 修改 精灵.js 补充 玩家精灵的 行为 方法,玩家精灵的 x/y方向移动 方法中关于精灵碰撞的部分
//定义全局对象 精灵集合
var 精灵集合 =
{
"@": 玩家精灵,
"o": 金币精灵,
"=": 熔岩精灵,
"v": 熔岩精灵,
"|": 熔岩精灵
};
//定义全局变量 玩家移动速度
var 玩家移动速度 = 10;
//定义全局变量 玩家跳跃速度
var 玩家跳跃速度 = 14;
//定义全局变量 重力
var 重力 = 30;
/**
*@描述: 玩家精灵 函数
*@传参: 坐标 (矢量)
*@参数: 坐标,大小,速度矢量,类型
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/04
*@修改人和其它信息:
**/
function 玩家精灵(坐标)
{
this.类型 = "玩家";
this.坐标 = 坐标;
this.大小 = new 矢量(0.5, 1);
this.速度矢量 = new 矢量(0, 0);
}
/**
*@描述: 玩家精灵 添加 行为 方法
*@传参: 每帧执行时间, 生成地图数据, 按键内容
*@参数:
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/04
*@修改人和其它信息:
**/
玩家精灵.prototype.行为 = function(每帧执行时间, 生成地图数据, 按键内容)
{
this.x方向移动(每帧执行时间, 生成地图数据, 按键内容);
this.y方向移动(每帧执行时间, 生成地图数据, 按键内容);
const 碰撞精灵 = 生成地图数据.判断精灵碰撞(this);
if (碰撞精灵)
{
document.getElementById("碰撞").innerHTML = "碰撞精灵:" + 碰撞精灵.类型;
生成地图数据.玩家精灵碰撞(碰撞精灵.类型, 碰撞精灵);
}
else
{
document.getElementById("碰撞").innerHTML = "碰撞精灵:";
}
};
/**
*@描述: 玩家精灵 添加 x方向移动 方法
*@传参: 每帧执行时间, 生成地图数据, 按键内容
*@参数: 新坐标,障碍物
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/04
*@修改人和其它信息:
**/
玩家精灵.prototype.x方向移动 = function(每帧执行时间, 生成地图数据, 按键内容)
{
//给 速度矢量.x 赋值0
this.速度矢量.x = 0;
//判断按键内容
if (按键内容.左)
{
this.速度矢量.x -= 玩家移动速度;
}
if (按键内容.右)
{
this.速度矢量.x += 玩家移动速度;
}
//定义定量 新坐标
const 新坐标 = this.坐标.偏移(new 矢量(this.速度矢量.x * 每帧执行时间, 0));
//定义定量 障碍物
const 障碍物 = 生成地图数据.判断障碍物(新坐标, this.大小);
//判断有没有障碍物
if(障碍物)
{
//有障碍物
生成地图数据.玩家精灵碰撞(障碍物);
}
else
{
this.坐标 = 新坐标;
}
};
/**
*@描述: 玩家精灵 添加 y方向移动 方法
*@传参: 每帧执行时间, 生成地图数据, 按键内容
*@参数: 新坐标,障碍物
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/04
*@修改人和其它信息:
**/
玩家精灵.prototype.y方向移动 = function(每帧执行时间, 生成地图数据, 按键内容)
{
//给 速度矢量.y 每帧执行时间 * 重力
this.速度矢量.y += 每帧执行时间 * 重力;
//定义定量 新坐标
const 新坐标 = this.坐标.偏移(new 矢量(0, this.速度矢量.y * 每帧执行时间));
//定义定量 障碍物
const 障碍物 = 生成地图数据.判断障碍物(新坐标, this.大小);
//判断有没有障碍物
if(障碍物)
{
生成地图数据.玩家精灵碰撞(障碍物);
//下方有障碍物
if (按键内容.上 && this.速度矢量.y > 0)
{
//如果按上键,给玩家速度矢量.y一个向上的速度
this.速度矢量.y = -玩家跳跃速度;
}
else
{
//定义速度矢量.y=0
this.速度矢量.y = 0;
}
}
else
{
//无障碍物
if (按键内容.下 && this.速度矢量.y > 0)
{
//如果按下键,给玩家速度矢量.y一个向下的速度
this.速度矢量.y += 每帧执行时间 * 重力 * 2;
}
this.坐标 = 新坐标;
}
};
/**
*@描述: 熔岩精灵 函数
*@传参: 坐标 (矢量)
*@参数: 初始坐标,坐标,大小,速度矢量,类型
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/01
*@修改人和其它信息:
**/
function 熔岩精灵(坐标, 元素)
{
//定义属性 类型
this.类型 = "熔岩";
//定义属性 初始坐标
this.坐标 = 坐标;
//定义大小
this.大小 = new 矢量(1, 1);
//根据元素来定义速度矢量属性 在x,y上的移动速度
if(元素 === "=")
{
//= 是横向移动熔岩,所以x有速度y没有
this.速度矢量 = new 矢量(2, 0);
}
else if(元素 === "|")
{
//| 是横向移动熔岩,所以y有速度x没有
this.速度矢量 = new 矢量(0, 2);
}
else if(元素 === "v")
{
//v 是掉落熔岩,所以y有速度x没有
this.速度矢量 = new 矢量(0, 3);
this.初始坐标 = 坐标;
}
}
/**
*@描述: 熔岩精灵 添加 行为 方法
*@传参: 每帧执行时间, 生成地图数据
*@参数:
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/03/01
*@修改人和其它信息:
**/
熔岩精灵.prototype.行为 = function(每帧执行时间, 生成地图数据)
{
//熔岩精灵偏移后的新坐标
const 新坐标 = this.坐标.偏移(this.速度矢量.矢积(每帧执行时间));
//判断熔岩精灵偏移后的新坐标是否有障碍物
if (!生成地图数据.判断障碍物(新坐标, this.大小))
{
//新坐标区域内没有障碍元素,熔岩可以移动
//将新坐 付给 坐标
this.坐标 = 新坐标;
}
//有障碍物 回到初始坐标
else if (this.初始坐标)
{
this.坐标 = this.初始坐标;
}
//有障碍物 反向运动
else
{
this.速度矢量 = this.速度矢量.矢积(-1);
}
};
/**
*@描述: 金币精灵 函数
*@传参: 坐标 (矢量)
*@参数: 初始坐标,大小,晃动值,类型
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
function 金币精灵(坐标)
{
//定义属性 类型
this.类型 = "金币";
//定义属性 初始坐标
this.初始坐标 = this.坐标 = 坐标;
//定义大小 因为游戏场景中每格大小为15*15
this.大小 = new 矢量(0.7, 0.7);
//定义属性 晃动值 初始的晃动系数
/*
PI是180°,PI*2=360° 随机数(0~1)*PI*2 就是在0°~360°中随机取一个角度
范围即0*3.1415*2 ~ 0.9999*3.1415*2
*/
this.晃动值 = Math.random() * Math.PI * 2;
}
/**
*@描述: 金币精灵 添加 行为 方法
*@传参: 每帧执行时间 (每帧执行时间)
*@参数: 晃动速度,晃动区域,晃动坐标y
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
金币精灵.prototype.行为 = function(每帧执行时间)
{
//定义定量 晃动速度
const 晃动速度 = 8;
//定义定量 晃动区域
const 晃动区域 = 0.07;
//晃动值自加 每帧执行时间*晃动速度=每帧移动距离
this.晃动值 += 每帧执行时间 * 晃动速度;
//定义定量 晃动坐标y
const 晃动坐标y = Math.sin(this.晃动值) * 晃动区域;
//设置坐标偏移后的值
this.坐标 = this.初始坐标.偏移(new 矢量(0, 晃动坐标y));
};
- 最后再html页面里面加一个h3标签来显示碰撞信息
html页面
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>html跳跃小游戏</title>
<!--CSS样式-->
<link rel="stylesheet" type="text/css" href="./css/css样式.css">
</head>
<body>
<h5 id="fps" style="color: #ffffff;">FPS=0</h5>
<h5 id="碰撞" style="color: #ffffff;">碰撞精灵:</h5>
<!--pre标签可定义预格式化的文本-->
<pre id="按键监听测试" style="color: #ffffff;"></pre>
<!--JS脚本-->
<script type="text/javascript" src="./js/精灵.js"></script>
<script type="text/javascript" src="./js/地图数组.js"></script>
<script type="text/javascript" src="./js/工具函数.js"></script>
<script type="text/javascript" src="./js/按键监听.js"></script>
<script type="text/javascript" src="./js/生成地图数据.js"></script>
<script type="text/javascript" src="./js/生成关卡.js"></script>
<script type="text/javascript" src="./js/运行帧动画.js"></script>
<script>
//初始化程序
function 初始化()
{
//开始第一个关卡
开始关卡(0);
}
function 开始关卡(n)
{
//生成地图数据
var 新地图数据 = new 生成地图数据(地图数组[n]);
//生成关卡
var 新关卡 = new 生成关卡(document.body, 新地图数据);
//运行帧动画
运行帧动画(function(每帧执行时间)
{
/*这个方法是游戏里每帧运行的所有内容,包括动画/判断碰撞/按键监听等*/
//播放关卡地图里精灵一帧动画动作
新地图数据.动画(每帧执行时间, 按键内容);
//重新绘制一帧关卡
新关卡.画精灵层();
//计算每秒帧数
document.getElementById("fps").innerHTML = "FPS=" + (1 / 每帧执行时间).toFixed(2);
//每帧显示按键信息,	代表tab制表符
document.getElementById("按键监听测试").innerHTML =
"按键左=" + (按键内容.左 === true) +
"	按键右=" + (按键内容.右 === true) +
"	按键上=" + (按键内容.上 === true) +
"	按键下=" + (按键内容.下 === true);
//执行每帧动作方法 返回false时结束运行帧动画, 返回其他则继续执行动画
return true;
});
}
初始化();
</script>
</body>
</html>
- 效果图