”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 JavaScript IV 创建俄罗斯方块:canvas

使用 JavaScript IV 创建俄罗斯方块:canvas

发布于2024-08-01
浏览:874

介绍

在该系列的新部分中,我们将了解如何显示棋盘和当前在屏幕上下降的棋子。为此,我们必须在浏览器中绘制它,我们必须执行的选项是 Canvas HTML 元素。

class Canvas {
    static SEPARATION = 2;
    #_painting = false;
    #_element = null;
    #_board = null;
    #_piece = null;

    constructor(element, board)
    {        
        element.width = 5   ( board.cols * Board.PIXEL_SIZE );
        element.height = 5   ( board.rows * Board.PIXEL_SIZE );

        this._board = board;
        this._element = element;
    }

    // más cosas...
}

这个类Canvas表示同名的HTML元素,在构造函数中作为参数传递。由于您要绘制棋盘,因此它也作为参数传递,以便访问要绘制的点。

它所做的第一件事是根据板本身通过其属性 colsrowsCanvas 的大小以适应板]。棋盘还通过 PIXEL_SIZE 告诉我们有多少像素组成了棋盘的每个棋子或每个单元的一个点。

重新绘制游戏

让我们少走弯路。我们必须画出木板和那一刻正在下降的棋子,对吗?好吧,让我们开始吧。


类画布 { // 更多的东西... 画() { if (this._painting) { 返回; } const ctx = this.element.getContext( "2d" ); const SEP = Canvas.SEPARATION; this._painting = true; this.clear(); this.paintBoard( ctx, SEP ); this.paintPiece( ctx, SEP ); this._painting = false; } 清除() { const ctx = this.element.getContext( "2d" ); ctx.clearRect( 0, 0, this.element.width, this.element.height ); } }
class Canvas {
    // más cosas...

    paint()
    {
        if ( this._painting ) {
            return;
        }

        const ctx = this.element.getContext( "2d" );
        const SEP = Canvas.SEPARATION;

        this._painting = true;
        this.clear();

        this.paintBoard( ctx, SEP );
        this.paintPiece( ctx, SEP );

        this._painting = false;
    }

    clear()
    {
        const ctx = this.element.getContext( "2d" );

        ctx.clearRect( 0, 0, this.element.width, this.element.height );
    }
}
首先,我们获取 2D 上下文,这将允许我们在画布上绘图。出于好奇,还有一个 3D 上下文,它基于 WebGL。

我们有一些守卫(

_painting),它们可以防止多个线程在给定时间同时(在不同点)执行该方法。如果该方法的执行时间长于重绘之间的时间,则可能会发生这种情况。虽然好吧,那样的话我们还会遇到很多其他问题......

下一步是删除先前重绘中屏幕上的内容(

)。我们使用 clear() 方法来执行此操作,该方法使用 clearRect() 删除画布上的图像。

然后我们画木板,然后画那一刻掉下来的那块。嗯,就这样了。麦芽酒,交付完成。

我说不。让我们看看棋盘和棋子是如何绘制的。首先是给木板上漆。 SEP 是我们在棋子和棋盘方块之间留下的间隔。这个框是我们在标题为

绘制框架的代码段中绘制的第一个东西。 它是一个简单的矩形,可以使用 StrokeRect() 绘制,它接受四个参数,其中包括左上角顶点的位置,然后是其宽度和高度。

画板

类画布 { // 更多的东西... 画板(ctx,SEP) { //画框 ctx.笔划宽度 = 1; ctx. StrokeStyle = this.board.color; ctx. 笔划矩形( 1, 1, this.element.width - 1, this.element.height -1 ); //画板 for(让 numRow = 0; numRow class Canvas { // más cosas... paint() { if ( this._painting ) { return; } const ctx = this.element.getContext( "2d" ); const SEP = Canvas.SEPARATION; this._painting = true; this.clear(); this.paintBoard( ctx, SEP ); this.paintPiece( ctx, SEP ); this._painting = false; } clear() { const ctx = this.element.getContext( "2d" ); ctx.clearRect( 0, 0, this.element.width, this.element.height ); } } 接下来是一个嵌套循环(行和列),因此我们将查看板上的哪些单元格有内容(整数 1,与整数 0),然后绘制一个边长为 PIXEL_SIZE 的小正方形。

因此,第一个循环循环遍历行,直到

Board.rows。然后我们使用 getRow() 方法获取完整的行,并用内循环遍历它,直到 Board.cols.

因此,给定行/列中的一个单元格

f/cBoard.getCell(f, c),以及考虑到 JavaScript 有一个 Boolean 构造函数,它接受除 0 之外的任何值的整数,表示 true,我们绘制一个边长为 PIXEL_SIZE 的正方形。因此,要知道在哪里绘制行 f,我们必须乘以 PIXEL_SIZE 并添加板框和第一个单元格之间的间距。由于它们是正方形,我们将以相同的方式找到列 c:SEP (c * PIXEL_SIZE).

画出这件作品

我们对这些作品做了类似的事情。通过拥有一个形状 (

shape)(它只不过是一个矩阵),我们将再次拥有两个循环,外部循环用于行,内部循环用于列。

类画布 { // 更多的东西... 油漆片(ctx,SEP) { const SHAPE = this.piece.shape; for(让 numRow = 0; numRow class Canvas { // más cosas... paint() { if ( this._painting ) { return; } const ctx = this.element.getContext( "2d" ); const SEP = Canvas.SEPARATION; this._painting = true; this.clear(); this.paintBoard( ctx, SEP ); this.paintPiece( ctx, SEP ); this._painting = false; } clear() { const ctx = this.element.getContext( "2d" ); ctx.clearRect( 0, 0, this.element.width, this.element.height ); } } 同样,如果我们找到 1,我们将绘制一个边长为 PIXEL_SIZE 的正方形。绘制构成该块的每个方块的位置由该块本身的行/列位置给出(

Piece.row/Piece. 卷心菜)。您必须将其乘以 PIXEL_SIZE 并添加与框的分隔。

El juego Insertrix en su estado actual

现在,我们将能够看到的非常......平淡。棋盘是空的,我们没有游戏循环,所以棋子甚至不会落下。我们将在下一部分中讨论该主题,以便我们可以开始看到与上图类似的内容。

版本声明 本文转载于:https://dev.to/baltasarq/creando-un-tetris-con-javascript-iv-canvas-1h7k?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • Python 字典如何保持代码干净、干燥
    Python 字典如何保持代码干净、干燥
    Python 字典和 DRY 原则:初学者快速指南 嘿! ?如果您正在深入研究 Python 编程,您可能偶然发现了字典,并且可能想知道“Python 中的字典到底是什么?它如何帮助我更智能地编写代码?”不用担心,让我们用一种超级简单的方式来分解它。 Python ...
    编程 发布于2024-11-06
  • 使用 Django、Twilio 和 Pinata 构建安全的匿名反馈系统
    使用 Django、Twilio 和 Pinata 构建安全的匿名反馈系统
    在本指南中,我将引导您使用 Django、用于短信通知的 Twilio、用于安全媒体上传的 Pinata 以及用于响应式样式的 TailwindCSS 构建安全匿名反馈系统。在本教程结束时,您将拥有一个功能齐全的反馈系统,用户可以在其中提交反馈、选择上传媒体以及接收短信通知 - 所有这些都考虑到安全...
    编程 发布于2024-11-06
  • 为什么 Tkinter Entry 的 get 函数不返回任何内容?
    为什么 Tkinter Entry 的 get 函数不返回任何内容?
    Tkinter Entry 的 get 函数没有产生任何结果:综合解释当尝试使用 get() 从 Tkinter Entry 小部件检索用户输入时函数时,您可能会遇到空返回值。这个看似令人困惑的问题源于 Tkinter 的异步特性和函数执行的顺序。在提供的代码片段中,您尝试在创建 Entry 后立即...
    编程 发布于2024-11-06
  • 使用 NodeJs 开始使用 RabbitMq
    使用 NodeJs 开始使用 RabbitMq
    RabbitMq简介 RabbitMq 是一个消息代理,允许在不同服务之间发送和接收消息。它是一个实现高级消息队列协议(AMQP)的消息代理。用 Erlang 编程语言编写。 安装 RabbitMq RabbitMq 可以使用各自的包管理器安装在不同的操作系统上。 RabbitMQ需...
    编程 发布于2024-11-06
  • 让网络更加互联
    让网络更加互联
    让网络更加互联 - Infometka 如何解决“隐形网站”问题 作为一名 Web 开发人员和 ???️??????️ 的创建者,我一直热衷于解决现实世界的问题。今天,我想分享我开发的一个解决方案,我相信它可以为无数网站所有者带来重大改变,并在某种程度上使互联网成为一个更加互联的地方。 ...
    编程 发布于2024-11-06
  • 使用 React 构建 Loop Studio
    使用 React 构建 Loop Studio
    介绍 Loop Studio 是一个沉浸式网站,旨在展示各种虚拟现实 (VR) 项目。使用 React,我们可以有效地管理和渲染不同的组件,以构建有凝聚力和交互式的用户体验。该项目采用简洁的设计,带有导航标题、详细的 VR 部分、创作画廊以及带有社交媒体链接的页脚。 ...
    编程 发布于2024-11-06
  • 如何解决用PHP在CURL中发送多维数组时出现“数组到字符串转换”错误?
    如何解决用PHP在CURL中发送多维数组时出现“数组到字符串转换”错误?
    通过 CURL 和 PHP 发送多维数组使用 CURL 发布包含多维数组的表单数据时,遇到“数组到字符串转换”错误是一个常见问题。当尝试使用包含数组的数组设置 CURLOPT_POSTFIELDS 时会发生这种情况。由于 Content-Type 标头必须是 multipart/form-data ...
    编程 发布于2024-11-06
  • 如何在 Selenium 中使用 \"span:contains(\'String\')\" 解决 InvalidSelectorException?
    如何在 Selenium 中使用 \"span:contains(\'String\')\" 解决 InvalidSelectorException?
    Selenium 中的 Invalid SelectorException with "span:contains('String')"在 Firefox 中使用 Python 中的 Selenium 时,尝试使用 CSS 选择器“span:contains(&#...
    编程 发布于2024-11-06
  • 如何将 HTML 附加到容器元素而不出现 InnerHTML 陷阱?
    如何将 HTML 附加到容器元素而不出现 InnerHTML 陷阱?
    在没有innerHTML的情况下将HTML附加到容器元素重新访问当前的问题是如何将HTML附加到容器元素,同时避免限制以及使用innerHTML属性的陷阱。正如OP正确指出的那样,innerHTML由于其替换现有内容的行为,可能会破坏嵌入媒体等动态元素。幸运的是,有一个替代方案可以克服这些问题:in...
    编程 发布于2024-11-06
  • 持续测试:确保 DevOps 管道的质量
    持续测试:确保 DevOps 管道的质量
    持续测试是现代软件开发中的关键实践,尤其是在 DevOps 框架内。它涉及在整个软件交付管道中自动执行测试,以确保对代码库所做的每项更改都得到彻底验证。通过将测试集成到开发过程的每个阶段,持续测试旨在尽早发现和解决缺陷,从而显着降低生产故障的风险。 什么是持续测试? 持续测试是作为软件交付管道的一...
    编程 发布于2024-11-06
  • 背景颜色改变视频
    背景颜色改变视频
    在 Instagram 上关注我们 在本视频教程中,我将指导您使用 HTML、CSS 和 JavaScript 构建令人惊叹的 Instagram 卡片。该卡片具有充满活力的变色边框、圆形个人资料图片和“关注我们”按钮,为您的在线形象增添了吸引力。该项目非常适合增强您的作品集或社交媒体页面,展示了简...
    编程 发布于2024-11-06
  • 如何使用 PHP 清除浏览器缓存?
    如何使用 PHP 清除浏览器缓存?
    使用 PHP 清除浏览器缓存浏览器缓存将经常访问的文件存储在本地,从而缩短网站加载时间。但是,如果缓存的文件已过时,它也会干扰测试和开发。本文介绍如何使用 PHP 清除浏览器缓存。清除浏览器缓存的 PHP 代码以下 PHP 代码将标头发送到客户端浏览器,指示其清除其缓存:header("C...
    编程 发布于2024-11-06
  • AWS Lambda 与 Go,初始样板
    AWS Lambda 与 Go,初始样板
    照片由 Lukáš Vaňátko 在 Unsplash 上拍摄 介绍 Go 由于其简单性一直是我最喜欢的语言之一。最近,我决定弄清楚如何使用用 Go 编写的 lambda 函数创建一个简单的样板无服务器项目。我对工具和开发人员体验很好奇。 目标 我想创建一个 RES...
    编程 发布于2024-11-06
  • 在 Laravel 中对底部为空值和非空值的行进行降序排序
    在 Laravel 中对底部为空值和非空值的行进行降序排序
    使用数据库时,经常会遇到某些字段可能为空或 NULL 的情况。经常出现的一个挑战是如何对记录进行排序,以便具有空字段的行出现在结果集的底部,而具有非空值的行以有意义的方式排序(例如,降序)。在这篇文章中,我将通过一个实际示例向您展示如何在 Laravel 中实现这一目标。 设想 假设...
    编程 发布于2024-11-06
  • 橄榄油的好处
    橄榄油的好处
    橄榄油的好处 橄榄油通常被誉为地中海饮食的基石,不仅可以为各种菜肴增添风味,而且还对健康有益。橄榄油从橄榄树的果实中提取,已经使用了几个世纪,现代研究不断发现它的许多优点。以下是将橄榄油纳入饮食的一些主要好处: 1. 心脏健康 橄榄油富含单不饱和脂肪,尤其是油酸,众...
    编程 发布于2024-11-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3