HTML5游戏_基于DOM平台跳跃小游戏开发
移动的熔岩精灵
- 视频讲解
HTML5游戏
-
效果图
-
本章新知识
-
Math.floor() 函数返回小于或等于一个给定数字的最大整数.
Math.floor( 45.95);
// 45
Math.floor( 45.05);
// 45
Math.floor( 4 );
// 4
Math.floor(-45.05);
// -46
Math.floor(-45.95);
// -46
- Math.ceil() 函数返回大于或等于一个给定数字的最小整数.
Math.ceil(0.60);
//1
Math.ceil(0.40);
//1
Math.ceil(5);
//5
Math.ceil(5.1);
//6
(Math.ceil(-5.1);
//-5
Math.ceil(-5.9);
//-5
- 障碍物 游戏中可以阻挡精灵的都为障碍物,在游戏中表现为场景边界,墙体,静止熔岩
- 矢积 物理中称矢积,是一种在向量空间中向量的二元乘法运算.我们在工具函数.js里定义一个矢积函数用来设置游戏里所有精灵的矢积.
在 工具函数.js 中添加代码
/**
*@描述: 生成html标签 函数
*@传参: 名称(html标签类型) 类名称(html标签类名)
*@参数:
*@返回值: 标签(html标签)
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
function 生成html标签(名称, 类名称)
{
//定义变量 标签 保存创建的html标签
var 标签 = document.createElement(名称);
//类名称不为空
if (类名称)
{
//修改html标签的class属性
标签.className = 类名称;
}
//返回标签
return 标签;
}
/**
*@描述: 矢量 函数 在二维及以上维度既有大小又有方向的量为矢量
*@传参: x(x方向) y(y方向)
*@参数: x(x方向) y(y方向)
*@返回值: 无
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
function 矢量(x, y)
{
//定义属性 x方向
this.x = x;
//定义属性 y方向
this.y = y;
}
/**
*@描述: 矢量 添加 偏移 方法
*@传参: 偏移矢量(偏移矢量)
*@参数:
*@返回值: 位移后矢量
*@创建人: 王天宇
*@创建时间:2021/02/24
*@修改人和其它信息:
**/
矢量.prototype.偏移 = function(偏移矢量)
{
//返回偏移后的矢量
return new 矢量(this.x + 偏移矢量.x, this.y + 偏移矢量.y);
};
/**
*@描述: 矢量 添加 矢积 方法
*@传参: 矢量乘数(矢量乘数)
*@参数:
*@返回值: 矢积
*@创建人: 王天宇
*@创建时间:2021/03/01
*@修改人和其它信息:
**/
矢量.prototype.矢积 = function(矢量乘数)
{
return new 矢量(this.x * 矢量乘数, this.y * 矢量乘数);
};
- 在游戏中熔岩精灵分为三种,左右移动熔岩,上下移动熔岩,掉落熔岩
- 左右和上下移动熔岩碰到障碍物时会反向继续移动
- 掉落熔岩碰到障碍物时会重新掉落
- 首先我们在 精灵.js 里的 精灵集合 中去添加熔岩属性,然后跟定义金币精灵一样给添加熔岩精灵和熔岩精灵的行为方法
修改 精灵.js
//定义全局对象 精灵集合
var 精灵集合 =
{
"o": 金币精灵,
"=": 熔岩精灵,
"v": 熔岩精灵,
"|": 熔岩精灵
};
/**
*@描述: 熔岩精灵 函数
*@传参: 坐标 (矢量), 元素
*@参数: 初始坐标,坐标,缩放,速度矢量,类型
*@返回值: 无
*@创建人: 王天宇
*@创建时间: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));
};
- 接着我们在 生成地图数据.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(元素行);
}
}
/**
*@描述: 生成地图数据 添加 动画 方法
*@传参: 每帧执行时间(每帧执行时间)
*@参数:
*@返回值: 无
*@创建人: 王天宇
*@创建时间: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 元素类型;
}
}
}
};
运行html,我们可以看到三种熔岩分别按照自己的方式进行移动
效果图
B站讲解视频:https://www.bilibili.com/video/BV1nf4y167Zo/