」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 使用 JavaScript IV 建立俄羅斯方塊:canvas

使用 JavaScript IV 建立俄羅斯方塊:canvas

發佈於2024-08-01
瀏覽:322

介紹

在該系列的新部分中,我們將了解如何顯示棋盤和當前在螢幕上下降的棋子。為此,我們必須在瀏覽器中繪製它,我們必須執行的選項是 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]刪除
最新教學 更多>
  • 如何將 HTML 附加到容器元素而不出現 InnerHTML 陷阱?
    如何將 HTML 附加到容器元素而不出現 InnerHTML 陷阱?
    在沒有innerHTML的情況下將HTML附加到容器元素重新訪問當前的問題是如何將HTML附加到容器元素,同時避免限制以及使用innerHTML屬性的陷阱。正如OP正確指出的那樣,innerHTML由於其替換現有內容的行為,可能會破壞嵌入媒體等動態元素。 幸運的是,有一個替代方案可以克服這些問題:i...
    程式設計 發佈於2024-11-06
  • 持續測試:確保 DevOps 管道的質量
    持續測試:確保 DevOps 管道的質量
    持续测试是现代软件开发中的关键实践,尤其是在 DevOps 框架内。它涉及在整个软件交付管道中自动执行测试,以确保对代码库所做的每项更改都得到彻底验证。通过将测试集成到开发过程的每个阶段,持续测试旨在尽早发现和解决缺陷,从而显着降低生产故障的风险。 什么是持续测试? 持续测试是作为软件交付管道的一...
    程式設計 發佈於2024-11-06
  • 背景顏色改變視頻
    背景顏色改變視頻
    在 Instagram 上關注我們 在本影片教學中,我將指導您使用 HTML、CSS 和 JavaScript 建立令人驚嘆的 Instagram 卡片。這張卡片具有充滿活力的變色邊框、圓形個人資料圖片和「關注我們」按鈕,為您的線上形象增添了吸引力。該專案非常適合增強您的作品集或社交媒體頁面,展示了...
    程式設計 發佈於2024-11-06
  • 如何使用 PHP 清除瀏覽器快取?
    如何使用 PHP 清除瀏覽器快取?
    使用 PHP 清除瀏覽器快取瀏覽器快取將經常存取的檔案儲存在本地,從而縮短網站載入時間。但是,如果快取的檔案已過時,它也會幹擾測試和開發。本文說明如何使用 PHP 清除瀏覽器快取。 清除瀏覽器快取的PHP 碼以下PHP 代碼將標頭髮送到客戶端瀏覽器,指示其清除其快取:header("Cac...
    程式設計 發佈於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
  • JSON Diff:開發人員完整指南
    JSON Diff:開發人員完整指南
    JSON(JavaScript 对象表示法)是一种广泛使用的数据格式,用于在系统之间交换信息。当开发人员使用 API、数据库和配置时,确保 JSON 数据保持一致和准确至关重要。这就是 JSON diff 发挥作用的地方。 JSON diff 工具允许开发人员快速发现两个 JSON 结构之间的差异...
    程式設計 發佈於2024-11-06
  • 你應該知道的 JavaScript 技巧
    你應該知道的 JavaScript 技巧
    蔡喬佈撰寫 1. 控制台.log 為控制台日誌新增顏色 別再這樣了! ❌ 試試這個吧。 ✅ 但如果你有一個物件數組,嘗試這個會更好嗎? 如果您想測量程式碼中某些操作的運行速度,請嘗試此操作。 執行console.time和console.timeEnd來測量瀏覽器控制台中花費的時...
    程式設計 發佈於2024-11-06
  • 掌握使用 Python 抓取 Google Scholar 的藝術
    掌握使用 Python 抓取 Google Scholar 的藝術
    如果您正在深入进行学术研究或数据分析,您可能会发现自己需要来自 Google 学术搜索的数据。不幸的是,没有官方的 Google Scholar API Python 支持,这使得提取这些数据有点棘手。然而,凭借正确的工具和知识,您可以有效地抓取 Google Scholar。在这篇文章中,我们将探...
    程式設計 發佈於2024-11-06
  • 使用 Go、Clean Architecture 和 PostgreSQL 建立強大的電子商務平台
    使用 Go、Clean Architecture 和 PostgreSQL 建立強大的電子商務平台
    概述 我們的目標是開發一個全面的電子商務解決方案,可以處理從產品管理到訂單處理的所有事務。該平台將成為線上業務的堅實基礎,能夠擴展以滿足不斷增長的需求並適應不斷變化的市場需求。 我們的電子商務平台的主要功能包括: 使用者驗證與個人資料管理 包含類別和子類別的產品目錄 購物車功能 ...
    程式設計 發佈於2024-11-06
  • Redis 解釋:主要功能、用例和實踐項目
    Redis 解釋:主要功能、用例和實踐項目
    Introduction Redis is an open-source, in-memory data structure store used as a database, cache, and message broker. It’s known for its perfor...
    程式設計 發佈於2024-11-06
  • 如何在 macOS 上設定 MySQL 自動啟動:開發人員逐步指南
    如何在 macOS 上設定 MySQL 自動啟動:開發人員逐步指南
    作為開發人員,我們經常發現自己在本地電腦上使用 MySQL 資料庫。雖然每次系統啟動時手動啟動 MySQL 是可以管理的,但這可能是一項乏味的任務。在本指南中,我們將逐步介紹將 MySQL 設定為在 macOS 上自動啟動的流程,從而節省您的時間並簡化您的工作流程。 先決條件 在我...
    程式設計 發佈於2024-11-06
  • 掌握 TypeScript:了解擴充的力量
    掌握 TypeScript:了解擴充的力量
    TypeScript 中的 extends 关键字就像一把瑞士军刀。它用于多种上下文,包括继承、泛型和条件类型。了解如何有效地使用扩展可以生成更健壮、可重用和类型安全的代码。 使用扩展进行继承 extends 的主要用途之一是继承,允许您创建基于现有接口或类的新接口或类。 inter...
    程式設計 發佈於2024-11-06
  • 如何將具有群組計數的欄位新增至 Pandas 中的分組資料框?
    如何將具有群組計數的欄位新增至 Pandas 中的分組資料框?
    如何在Pandas中向分組資料框中添加列在資料分析中,經常需要將資料分組並進行計算每組。 Pandas 透過其 groupby 函數提供了一種便捷的方法來做到這一點。一個常見的任務是計算每個組中某一列的值,並將包含這些計數的列加入到資料幀中。 考慮資料幀df:df = pd.DataFrame({'...
    程式設計 發佈於2024-11-06

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3