天天看點

七爪源碼:如何用 JavaScript 編寫遊戲

七爪源碼:如何用 JavaScript 編寫遊戲

浏覽器現在為 JavaScript 開發人員提供了許多用于建立有趣站點的選項。 Flash曾經被用來做這個 - 它很流行,無數的遊戲、播放器、花哨的界面等等都是在它上面創造出來的。但是,它們不再在任何現代浏覽器中運作。

Flash技術重量級,漏洞百出,是以開始放棄。特别是因為有 HTML5 形式的替代方案。

Canvas 是可以使用 JS 指令在其上進行繪制的畫布。它可用于建立動畫背景、各種構造函數,最重要的是,遊戲。

在本文中,您将學習如何使用 JavaScript 和 HTML5 建立浏覽器遊戲。但首先,我們建議您熟悉 JS 中的面向對象程式設計(隻需了解什麼是類、方法和對象)。這是建立遊戲的最佳方式,因為它允許您使用實體而不是抽象資料。但是,有一個缺點:任何版本的 Internet Explorer 都不支援 OOP。

遊戲頁面布局

首先,您需要建立一個顯示畫布的頁面。這需要很少的 HTML:

<!DOCTYPE html>
<html>
    <head>
        <title>JS Game</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">Your browser does not support JavaScript и HTML5 </canvas>
        </div>
        <script src="game.js"></script>
    </body>
</html>           

現在我們需要添加樣式:

body, html
{
    width: 100%;
    height: 100%;
    padding: 0px;
    margin: 0px;
    overflow: hidden;
}
 
.wrapper
{
    width: 100%;
    height: 100%;
}
 
.canvas
{
    width: 100%;
    height: 100%;
    background: #000;
}           

請注意,在 HTML 中,canvas 元素的寬度和高度為零,而 CSS 指定為 100%。 在這方面,畫布的行為就像一個圖像。 它具有實際分辨率和可見分辨率。

使用樣式更改可見分辨率。 但是,圖檔的尺寸将保持不變:它隻會被拉伸或壓縮。 這就是為什麼稍後将通過腳本指定實際寬度和高度的原因。

遊戲腳本

首先,讓我們為遊戲添加一個腳本藍圖:

var canvas = document.getElementById("canvas"); //Retrieving a canvas from the DOM
var ctx = canvas.getContext("2d"); //Obtaining a context - through it you can work with the canvas
 
var scale = 0.1; //Machine scale
 
Resize(); //When the page loads, the canvas size is set
 
window.addEventListener("resize", Resize); //Changing the size of the window will change the size of the canvas
 
window.addEventListener("keydown", function (e) { KeyDown(e); }); //Receiving keystrokes from the keyboard
 
var objects = []; //An array of game objects
var roads = []; //An array with backgrounds
 
var player = null; //The object controlled by the player - here will be the number of the object in the objects array
 
function Start()
{
    timer = setInterval(Update, 1000 / 60); //The game state will update 60 times per second - at this rate, the update of what is happening will seem very smooth
}
 
function Stop()
{
    clearInterval(timer); //Stopping the update
}
 
function Update() //Game update
{
    Draw();
}
 
function Draw() //Working with graphics
{
    ctx.clearRect(0, 0, canvas.width, canvas.height); //Clearing the canvas from the previous frame
}
 
function KeyDown(e)
{
    switch(e.keyCode)
    {
        case 37: //Left
            break;
 
        case 39: //Right
            break;
 
        case 38: //Up
            break;
 
        case 40: //Down
            break;
 
        case 27: //Esc
            break;
    }
}
 
function Resize()
{
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}           

該腳本包含建立遊戲所需的一切:資料(數組)、更新、繪制和控制功能。 它隻剩下用基本邏輯來補充它。 也就是說,準确指定對象的行為方式以及它們在畫布上的顯示方式。

遊戲邏輯

在 Update() 函數調用期間,遊戲對象的狀态将發生變化。 之後,它們将使用 Draw() 函數在畫布上繪制。 是以我們實際上并沒有在畫布上移動對象,我們繪制它們一次,然後更改它們的坐标,擦除舊圖像并使用新坐标顯示對象。 這一切發生得如此之快,以至于給人一種運動的錯覺。

讓我們看一個道路的例子。

七爪源碼:如何用 JavaScript 編寫遊戲

此圖像顯示在畫布上并逐漸向下移動。 緊接着,又會顯示出另一幅這樣的畫面,讓人感覺像是一條沒有盡頭的路。

為此,讓我們建立一個 Road 類:

class Road
{
    constructor(image, y)
    {
        this.x = 0;
        this.y = y;
 
        this.image = new Image();
        
        this.image.src = image;
    }
 
    Update(road) 
    {
        this.y += speed; //The image shifts down when you refresh
 
        if(this.y > window.innerHeight) //If the image has gone over the edge of the canvas, change the position
        {
            this.y = road.y - this.image.height + speed; //The new position is indicated with the second background
        }
    }
}           

将 Road 類的兩個對象添加到背景數組中:

var roads = 
[
    new Road("images/road.jpg", 0),
    new Road("images/road.jpg", 626)
]; //background array           

您現在可以更改 Update() 函數,以便圖像的位置随每一幀而變化。

function Update() //Game Update
{
    roads[0].Update(roads[1]);
    roads[1].Update(roads[0]);
 
    Draw();
}           

隻需添加這些圖像的輸出:

function Draw() //Working with graphics
{
    ctx.clearRect(0, 0, canvas.width, canvas.height); //Clearing the canvas from the previous frame
 
    for(var i = 0; i < roads.length; i++)
    {
        ctx.drawImage
        (
            roads[i].image, //Render image
            0, //Initial X position in the image
            0, //Initial Y-axis position in the image
            roads[i].image.width, //Image width
            roads[i].image.height, //Image height
            roads[i].x, //X-axis position on the canvas
            roads[i].y, //Y-axis position on the canvas
            canvas.width, //The width of the image on the canvas
            canvas.width //Since the width and height of the background are the same, the width is specified as the height
        );
    }
}           

現在你可以看到它在遊戲中是如何工作的:

七爪源碼:如何用 JavaScript 編寫遊戲

現在是添加玩家和 NPC 的時候了。 為此,您需要編寫一個 Car 類。 它将有一個 Move() 方法,玩家可以使用該方法控制他的汽車。 NPC 的移動将通過 Update() 完成,它隻是更改 Y 坐标。

class Car
{
    constructor(image, x, y)
    {
        this.x = x;
        this.y = y;
 
        this.image = new Image();
 
        this.image.src = image;
    }
 
    Update()
    {
        this.y += speed;
    }
 
    Move(v, d) 
    {
        if(v == "x") //X-axis movement
        {
            this.x += d; //Offset
 
            //
            if(this.x + this.image.width * scale > canvas.width)
            {
                this.x -= d; 
            }
    
            if(this.x < 0)
            {
                this.x = 0;
            }
        }
        else //Y-axis movement
        {
            this.y += d;
 
            if(this.y + this.image.height * scale > canvas.height)
            {
                this.y -= d;
            }
 
            if(this.y < 0)
            {
                this.y = 0;
            }
        }
        
    }
}           

讓我們建立第一個要檢查的對象。

var objects = 
[
    new Car("images/car.png", 15, 10)
]; //An array of game objects
var player = 0; //the number of the object controlled by the player           

現在您需要向 Draw() 函數添加一個用于繪制汽車的指令。

for(var i = 0; i < objects.length; i++)
{
    ctx.drawImage
    (
        objects[i].image, //Render image
        0, //Initial X position in the image
        0, //Initial Y-axis position in the image
        objects[i].image.width, //Image width
        objects[i].image.height, //Image height
        objects[i].x, //X-axis position on the canvas
        objects[i].y, //Y-axis position on the canvas
        objects[i].image.width * scale, //The width of the image on the canvas multiplied by the scale
        objects[i].image.height * scale //The height of the image on the canvas multiplied by the scale
    );
}           

在按下鍵盤時調用的 KeyDown() 函數中,您需要添加對 Move() 方法的調用。

function KeyDown(e)
{
    switch(e.keyCode)
    {
        case 37: //Left
            objects[player].Move("x", -speed);
            break;

        case 39: //Right
            objects[player].Move("x", speed);
            break;
 
        case 38: //Up
            objects[player].Move("y", -speed);
            break;
 
        case 40: //Down
            objects[player].Move("y", speed);
            break;
 
        case 27: //Esc
            if(timer == null)
            {
                Start();
            }
            else
            {
                Stop();
            }
            break;
    }
}           

現在您可以檢查渲染和控制。

七爪源碼:如何用 JavaScript 編寫遊戲

碰撞時什麼都沒有發生,但這将在以後修複。 首先,您需要確定删除視圖中丢失的對象。 這是為了避免堵塞 RAM。

在 Car 類中,我們添加值為 false 的字段 dead,然後在 Update() 方法中對其進行更改:

if(this.y > canvas.height + 50)
{
    this.dead = true;
}           

現在您需要更改遊戲的更新功能,替換與對象關聯的代碼:

var hasDead = false;
 
for(var i = 0; i < objects.length; i++)
{
    if(i != player)
    {
        objects[i].Update();
 
        if(objects[i].dead)
        {
            hasDead = true;
        }
    }
}
 
if(hasDead)
{
    objects.shift();
}           

如果您不移除物體,當生成太多汽車時,遊戲将開始降低計算機速度。

遊戲物體碰撞

現在您可以開始實施碰撞。 為此,請為 Car 類編寫一個方法 Collide(),它将檢查汽車的坐标:

Collide(car)
{
    var hit = false;
 
    if(this.y < car.y + car.image.height * scale && this.y + this.image.height * scale > car.y) //If the objects are on the same line horizontally
    {
        if(this.x + this.image.width * scale > car.x && this.x < car.x + car.image.width * scale) //If the objects are on the same line vertically
        {
            hit = true;
        }
    }
 
    return hit;
}           

現在我們需要在 Update() 函數中添加碰撞檢查:

var hit = false;
 
for(var i = 0; i < objects.length; i++)
{
    if(i != player)
    {
        hit = objects[player].Collide(objects[i]);
 
        if(hit)
        {
            alert("You crashed!");
            Stop();
            break;
        }
    }
}           

這是遊戲中的内容

七爪源碼:如何用 JavaScript 編寫遊戲

碰撞時可以添加任何邏輯:

• 打開動畫;

• 添加效果;;

• 删除對象;

• 健康狀況的改變,等等。

所有這些都由開發人員自行決定。

結論

這是一個非常簡單的遊戲,但足以了解 JS 如何處理圖形以及一般如何建立遊戲。 您可以在 GitHub 存儲庫中找到圖像和完整的遊戲代碼。

使用畫布非常适合處理圖形:它提供了很棒的功能并且不會過多地加載浏覽器。 我們現在也有一個可用的 WebGL 庫(示例和用法),它可以為您提供大量的性能和 3D 工作(canvas 無法做到這一點)。

了解 WebGL 可能很困難——也許相反,許多人對嘗試 Unity 引擎更感興趣,它知道如何編譯項目以在浏覽器中運作它們。

關注七爪網,擷取更多APP/小程式/網站源碼資源!

繼續閱讀