今天的浏览器允许您创建具有完整图形的游戏。以下是使用 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