如何用 JavaScript 编写游戏
今天的浏览器允许您创建具有完整图形的游戏。以下是使用 JavaScript 和 HTML5 编写简单赛车游戏的方法。
浏览器现在为 JavaScript 开发人员提供了许多用于创建有趣站点的选项。 Flash曾经被用来做这个——它很流行,无数的游戏、播放器、花哨的界面等等都是在它上面创造出来的。但是,它们不再在任何现代浏览器中运行。
Flash技术重量级,漏洞百出,因此开始放弃。特别是因为有 HTML5 形式的替代方案。
Canvas 是可以使用 JS 命令在其上进行绘制的画布。它可用于创建动画背景、各种构造函数,最重要的是,游戏。
在本文中,您将学习如何使用 JavaScript 和 HTML5 创建浏览器游戏。但首先,我们建议您熟悉 JS 中的面向对象编程(只需了解类、方法和对象是什么)。这是创建游戏的最佳方式,因为它允许您使用实体而不是抽象数据。但是,有一个缺点:任何版本的 Internet Explorer 都不支持 OOP。
游戏页面布局
首先,您需要创建一个显示画布的页面。这需要很少的 HTML:
<!DOCTYPE html>
<html>
<head>
<title>JS游戏</title>
<link rel="stylesheet" href="style.css">
<meta charset="utf-8">
</head>
<body>
<div class="wrapper">
<canvas width="0" height="0" class="canvas" id="canvas">您的浏览器不支持 JavaScript è HTML5</canvas>
</div>
<script src="game.js"></script>
</body>
</html>
现在我们需要添加样式:
正文,html
{
宽度:100%;
高度:100%;
填充:0px;
边距:0px;
溢出:隐藏;
}
.wrapper
{
宽度:100%;
高度:100%;
}
。帆布
{
宽度:100%;
高度:100%;
背景:#000;
}
请注意,在 HTML 中,canvas 元素的宽度和高度为零,而 CSS 指定为 100%。在这方面,画布的行为就像一个图像。它具有实际分辨率和可见分辨率。
使用样式更改可见分辨率。但是,图片的尺寸将保持不变:它只会被拉伸或压缩。这就是为什么稍后将通过脚本指定实际宽度和高度的原因。
游戏脚本
首先,让我们为游戏添加一个脚本蓝图:
var canvas = document.getElementById("canvas"); // 从 DOM 中获取画布
var ctx = canvas.getContext("2d"); //获取上下文 - 通过它您可以使用画布
变量比例= 0.1; //机器秤
调整大小(); //页面加载时,设置画布大小
window.addEventListener("resize", Resize); //改变窗口大小会改变画布大小
window.addEventListener("keydown", function (e) { KeyDown(e); }); //接收来自键盘的击键
变量对象 = []; //游戏对象数组
var 道路 = []; //带背景的数组
var 播放器 = null; //玩家控制的对象 - 这里将是对象数组中对象的编号
函数开始()
{
计时器 = setInterval(更新,1000 / 60); //游戏状态每秒会更新60次——按照这个速度,正在发生的事情的更新会显得很流畅
}
函数停止()
{
清除间隔(定时器); //停止更新
}
function Update() //游戏更新
{
画();
}
function Draw() //处理图形
{
ctx.clearRect(0, 0, canvas.width, canvas.height); //从上一帧清除画布
}
功能 KeyDown(e)
{
开关(e.keyCode)
{
案例 37: //左
休息;
案例 39: //对
休息;
案例 38: //向上
休息;
案例 40: //向下
休息;
案例 27: //Esc
休息;
}
}
函数调整大小()
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
该脚本包含创建游戏所需的一切:数据(数组)、更新、绘制和控制功能。它只剩下用基本逻辑来补充它。也就是说,准确指定对象的行为方式以及它们在画布上的显示方式。
游戏逻辑
在 Update() 函数调用期间,游戏对象的状态将发生变化。之后,它们将使用 Draw() 函数在画布上绘制。所以我们实际上并没有在画布上移动对象,我们绘制它们一次,然后更改它们的坐标,擦除旧图像并使用新坐标显示对象。这一切发生得如此之快,以至于给人一种运动的错觉。
让我们看一个道路的例子。
此图像显示在画布上并逐渐向下移动。紧接着,又会显示出另一幅这样的画面,让人感觉像是一条没有尽头的路。
为此,让我们创建一个 Road 类:
班道
{
构造函数(图像,y)
{
这个.x = 0;
这个.y = y;
this.image = new Image();
this.image.src = 图像;
}
更新(路)
{
this.y += 速度; //刷新时图片下移
if(this.y > window.innerHeight) //如果图像越过了画布边缘,改变位置
{
this.y = road.y - this.image.height + 速度; //新位置用第二个背景表示
}
}
}
将 Road 类的两个对象添加到背景数组中:
var 道路 =
[
new Road("images/road.jpg", 0),
新路(“图片/路.jpg”,626)
]; //背景数组
您现在可以更改 更新() 功能,使图像的位置随每一帧而变化。
function Update() //游戏更新
{
道路[0].更新(道路[1]);
道路[1].更新(道路[0]);
画();
}
只需添加这些图像的输出:
function Draw() //处理图形
{
ctx.clearRect(0, 0, canvas.width, canvas.height); //从上一帧清除画布
for(var i = 0; i < 道路长度; i++)
{
ctx.drawImage
(
road[i].image, //渲染图像
0, //图像中的初始X位置
0, //图像中的初始Y轴位置
road[i].image.width, //图像宽度
road[i].image.height, //图像高度
road[i].x, //画布上的X轴位置
road[i].y, //画布上的Y轴位置
canvas.width, //图像在画布上的宽度
canvas.width //由于背景的宽度和高度相同,所以宽度指定为高度
);
}
}
现在你可以看到它在游戏中是如何工作的:
现在是添加玩家和 NPC 的时候了。为此,您需要编写一个 Car 类。它将有一个 Move() 方法,玩家可以使用该方法控制他的汽车。 NPC 的移动将通过 Update() 完成,它只是更改 Y 坐标。
类车
{
构造函数(图像,x,y)
{
这个.x = x;
这个.y = y;
this.image = new Image();
this.image.src = 图像;
}
更新()
{
this.y += 速度;
}
移动(v,d)
{
if(v == "x") //X轴移动
{
这个.x += d; //抵消
//
if(this.x + this.image.width * scale > canvas.width)
{
这个.x -= d;
}
如果(this.x < 0)
{
这个.x = 0;
}
}
else //Y轴移动
{
这个.y += d;
if(this.y + this.image.height * scale > canvas.height)
{
这个.y -= d;
}
如果(这个.y < 0)
{
这个.y = 0;
}
}
}
}
让我们创建第一个要检查的对象。
变量对象 =
[
新车("images/car.png", 15, 10)
]; //游戏对象数组
var 播放器 = 0; //玩家控制的物体数量
现在您需要向 Draw() 函数添加一个用于绘制汽车的命令。
for(var i = 0; i < objects.length; i++)
{
ctx.drawImage
(
objects[i].image, //渲染图像
0, //图像中的初始X位置
0, //图像中的初始Y轴位置
objects[i].image.width, //图像宽度
objects[i].image.height, //图像高度
objects[i].x, //画布上的X轴位置
objects[i].y, //画布上的Y轴位置
objects[i].image.width * scale, //画布上图像的宽度乘以比例
objects[i].image.height * scale //图像在画布上的高度乘以比例
);
}
在按下键盘时调用的 KeyDown() 函数中,您需要添加对 Move() 方法的调用。
功能 KeyDown(e)
{
开关(e.keyCode)
{
案例 37: //左
对象[玩家].Move("x", -speed);
休息;
案例 39: //对
objects[player].Move("x", speed);
休息;
案例 38: //向上
objects[player].Move("y", -speed);
休息;
案例 40: //向下
objects[player].Move("y", speed);
休息;
案例 27: //Esc
如果(计时器 == 空)
{
开始();
}
别的
{
停止();
}
休息;
}
}
现在您可以检查渲染和控制。
碰撞时什么都没有发生,但这将在以后修复。首先,您需要确保删除视图中丢失的对象。这是为了避免堵塞 RAM。
在 Car 类中,我们添加值为 false 的字段 dead,然后在 Update() 方法中对其进行更改:
如果(this.y > canvas.height + 50)
{
this.dead = true;
}
现在您需要更改游戏的更新功能,替换与对象关联的代码:
var hasDead = false;
for(var i = 0; i < objects.length; i++)
{
如果(我!=玩家)
{
对象[i].Update();
如果(对象[i].dead)
{
有死=真;
}
}
}
如果(已死亡)
{
对象.shift();
}
如果您不移除对象,当生成太多汽车时,游戏将开始降低计算机速度。
游戏对象碰撞
现在您可以开始实施碰撞。为此,为 Car 类编写一个方法 Collide(),它将检查汽车的坐标:
碰撞(汽车)
{
变量命中=假;
if(this.y < car.y + car.image.height * scale && this.y + this.image.height * scale > car.y) //如果物体水平在同一条线上
{
if(this.x + this.image.width * scale > car.x && this.x < car.x + car.image.width * scale) //如果物体垂直在同一条线上
{
命中=真;
}
}
回击;
}
现在我们需要在 Update() 函数中添加碰撞检查:
变量命中=假;
for(var i = 0; i < objects.length; i++)
{
如果(我!=玩家)
{
hit = objects[player].Collide(objects[i]);
如果(命中)
{
alert("你崩溃了!");
停止();
休息;
}
}
}
这是游戏中的内容
碰撞时可以添加任何逻辑:
• 打开动画;
• 添加效果;;
• 删除对象;
• 健康状况的改变,等等。
所有这些都由开发人员自行决定。
结论
这是一个非常简单的游戏,但足以了解 JS 如何处理图形以及一般如何创建游戏。您可以在 GitHub 存储库中找到图像和完整的游戏代码。
使用画布非常适合处理图形:它提供了强大的功能并且不会过多地加载浏览器。我们现在也有一个可用的 WebGL 库(示例和用法),它可以为您提供大量性能和 3D 工作(canvas 无法做到这一点)。
理解 WebGL 可能很困难——也许相反,许多人对尝试 Unity 引擎更感兴趣,它知道如何编译项目以在浏览器中运行它们。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
本文链接:https://www.qanswer.top/18380/02530608
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/webdev/288059.html