亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

用HTML5開發(fā)一個(gè)小游戲

CompileYouth / 1808人閱讀

摘要:它是基于開始且隨時(shí)間變化的一個(gè)因子。最后調(diào)用函數(shù)并且將本次的時(shí)間保存下來。這個(gè)現(xiàn)象的出現(xiàn)主要是因?yàn)樵诤瘮?shù)中將和寫死了,所以一個(gè)最簡單的方法就是在中傳入?yún)?shù)然后在調(diào)用的時(shí)候傳入捕獲時(shí)位置的參數(shù)最后在開始游戲的時(shí)候?qū)⒎旁谧钪虚g即可大功告成

先上效果圖

開始之前的準(zhǔn)備

game.html

js/ 里面創(chuàng)建game.js

images/ 里面放三張圖片,一張背景圖片(background.png),一張英雄圖片(hero.png),一張怪物的圖片(monster.png)

game.html里面寫上以下幾行簡單的HTML代碼:


Simple Canvas Game

我們在game.html引入了game.js文件,沒錯(cuò),剩下的所有工作都是在操作game.js,為其添加游戲的js代碼。

創(chuàng)建畫布

在game.js 里面,我們首先需要為游戲的舞臺(tái)創(chuàng)建一張畫布(canvas):

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);

這里通過js來創(chuàng)建了一個(gè)元素并設(shè)置canvas的寬和高,最后將其添加到標(biāo)簽后。var ctx = canvas.getContext("2d");中的ctx變量是我們后面會(huì)用到的,具體的canvas用法查看這里的鏈接:

https://developer.mozilla.org/en/canvas_tutorial

準(zhǔn)備圖片

游戲需要加載我們之前存放在images文件夾下面的三張圖片:

// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true;
};
bgImage.src = "images/background.png";

// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
    heroReady = true;
};
heroImage.src = "images/hero.png";

// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
    monsterReady = true;
};
monsterImage.src = "images/monster.png";

以上三張圖片都是通過創(chuàng)建簡單的圖片對象來實(shí)現(xiàn)加載的,類似bgReady的三個(gè)變量用來標(biāo)識圖片是否已經(jīng)加載完成,如果如果在圖片加載未完成情況下進(jìn)行繪制是會(huì)報(bào)錯(cuò)的。如果你不太確定new Image()到底是個(gè)什么東西,你可以在bgImage.src = "images/background.png";之后使用console.log(bgImage);來查看,你看到的將是類似:



游戲?qū)ο?/b>

我們需要定義一些對象,以便我們在后面會(huì)用到:

var hero = {
    speed: 256 // movement in pixels per second
};
var monster = {};
var monstersCaught = 0;

既然是英雄抓獲怪物,我們得要有一個(gè)英雄怪物的對象。而英雄有一個(gè)speed屬性用來控制他每秒移動(dòng)多少像素。怪物游戲過程中不會(huì)移動(dòng),所以暫時(shí)不用設(shè)置屬性。monstersCaught則用來存儲(chǔ)怪物被捉住的次數(shù),初始值當(dāng)然為0了。

處理用戶的輸入

游戲是給人玩的,那么我們怎么知道用戶到底在這個(gè)過程中干了什么?按了鍵盤?點(diǎn)了鼠標(biāo)?這些都是用戶在玩游戲的時(shí)候的輸入,所以我們一旦捕獲到這些輸入,我們就可以根據(jù)游戲的邏輯對用戶的輸入進(jìn)行處理了:

// Handle keyboard controls
var keysDown = {};

addEventListener("keydown", function (e) {
    keysDown[e.keyCode] = true;
}, false);

addEventListener("keyup", function (e) {
    delete keysDown[e.keyCode];
}, false);

這里我們只是監(jiān)聽兩個(gè)用戶的輸入:

keydown

keyup

然后我們將用戶的輸入先保存起來,并沒有立即響應(yīng)。為此,我們用keysDown這個(gè)對象來保存用戶按下的鍵值(keyCode),如果按下的鍵值在這個(gè)對象里,那么我們就做相應(yīng)處理。

  

在前端開發(fā)中,一般是用戶觸發(fā)了點(diǎn)擊事件然后才去執(zhí)行動(dòng)畫或發(fā)起異步請求之類的

開始一輪游戲

游戲在結(jié)束的時(shí)候,我們需要開始新的一輪游戲,所以在game.js添加reset函數(shù)

// Reset the game when the player catches a monster
var reset = function () {
    hero.x = canvas.width / 2;
    hero.y = canvas.height / 2;


    // Throw the monster somewhere on the screen randomly
    monster.x = 32 + (Math.random() * (canvas.width - 64));
    monster.y = 32 + (Math.random() * (canvas.height - 64));

};

reset()函數(shù)用于開始新一輪和游戲,在這個(gè)方法里我們將英雄放回畫布中心同時(shí)將怪物放到一個(gè)隨機(jī)的地方。

更新對象

在游戲的過程中,不管是用戶在玩(有正確輸入的狀態(tài))還是游戲結(jié)束,我們都是需要及時(shí)更新游戲的對象:

var update = function (modifier) {
    if (38 in keysDown) { // Player holding up
        hero.y -= hero.speed * modifier;
    }
    if (40 in keysDown) { // Player holding down
        hero.y += hero.speed * modifier;
    }
    if (37 in keysDown) { // Player holding left
        hero.x -= hero.speed * modifier;
    }
    if (39 in keysDown) { // Player holding right
        hero.x += hero.speed * modifier;
    }

    // Are they touching?
    if (
        hero.x <= (monster.x + 32)
        && monster.x <= (hero.x + 32)
        && hero.y <= (monster.y + 32)
        && monster.y <= (hero.y + 32)
    ) {

        ++monstersCaught;
        reset();
    }


};

update函數(shù)負(fù)責(zé)更新游戲的各個(gè)對象,會(huì)被規(guī)律地重復(fù)調(diào)用。首先它負(fù)責(zé)檢查用戶當(dāng)前按住的是中方向鍵,然后將英雄往相應(yīng)方向移動(dòng)。

有點(diǎn)費(fèi)腦力的或許是這個(gè)傳入的modifier 變量。你可以后面將要實(shí)現(xiàn)的main 方法里看到它的來源,但這里還是有必要詳細(xì)解釋一下。它是基于1開始且隨時(shí)間變化的一個(gè)因子。例如1秒過去了,它的值就是1,英雄的速度將會(huì)乘以1,也就是每秒移動(dòng)256像素;如果半秒鐘則它的值為0.5,英雄的速度就乘以0.5也就是說這半秒內(nèi)英雄以正常速度一半的速度移動(dòng)。理論上說因?yàn)檫@個(gè)update函數(shù)被調(diào)用的非常快且頻繁,所以modifier的值會(huì)很小,但有了這一因子后,不管我們的代碼跑得快慢,都能夠保證英雄的移動(dòng)速度是恒定的。

這里需要說明一下下面的判斷怪物和英雄是什么根據(jù):

 if (
        hero.x <= (monster.x + 31)
        && monster.x <= (hero.x + 31)
        && hero.y <= (monster.y + 32)
        && monster.y <= (hero.y + 32)
    )

上面的31,32是由heromonster圖片的大小決定的,我們的hero圖片是32x32,monster圖片是30x32,所以根據(jù)坐標(biāo)的位于圖片中心的法制,就可以得到上面的判斷條件。

現(xiàn)在英雄的移動(dòng)已經(jīng)是基于用戶的輸入(按下,,,鍵)了,接下來該檢查移動(dòng)過程中所觸發(fā)的事件了,也就是英雄與怪物相遇。這就是本游戲的勝利點(diǎn),monstersCaught +1然后重新開始新一輪。

渲染物體

之前寫的代碼都是在準(zhǔn)備前期工作和處理一些游戲的狀態(tài)等,下面將進(jìn)入正題:我們需要將所有的東西畫出來

// Draw everything
var render = function () {
    if (bgReady) {
        ctx.drawImage(bgImage, 0, 0);
    }

    if (heroReady) {
        ctx.drawImage(heroImage, hero.x, hero.y);
    }

    if (monsterReady) {
        ctx.drawImage(monsterImage, monster.x, monster.y);
    }

    // Score
    ctx.fillStyle = "rgb(250, 250, 250)";
    ctx.font = "24px Helvetica";
    ctx.textAlign = "left";
    ctx.textBaseline = "top";
    ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
};

這里的ctx就是最前面我們創(chuàng)建的變量。然后利用canvasdrawImage()首先當(dāng)然是把背景圖畫出來。然后如法炮制將英雄和怪物也畫出來。這個(gè)過程中的順序是有講究的,因?yàn)楹螽嫷奈矬w會(huì)覆蓋之前的物體。

這之后我們改變了一下Canvas的繪圖上下文的樣式并調(diào)用fillText來繪制文字,也就是記分板那一部分。本游戲沒有其他復(fù)雜的動(dòng)畫效果和打斗場面,繪制部分大功告成

主循環(huán)函數(shù)

我們實(shí)現(xiàn)了將畫面畫出來以后,我們緊接著需要實(shí)現(xiàn)的就是游戲的循環(huán)結(jié)構(gòu),于是將它放在main函數(shù)里:

// The main game loop
var main = function () {
    var now = Date.now();

    var delta = now - then;
    //console.log(delta);
    update(delta / 1000);
    render();

    then = now;

    // Request to do this again ASAP
    requestAnimationFrame(main);
};

上面的主函數(shù)控制了整個(gè)游戲的流程。先是拿到當(dāng)前的時(shí)間用來計(jì)算時(shí)間差(距離上次主函數(shù)被調(diào)用時(shí)過了多少毫秒)。得到modifier后除以1000(也就是1秒中的毫秒數(shù))再傳入update函數(shù)。最后調(diào)用render 函數(shù)并且將本次的時(shí)間保存下來。

設(shè)置requestAnimationFrame()

在上面的main函數(shù)中,我們通過requestAnimationFrame()調(diào)用了main函數(shù),所以我們需要聲明:

var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;


這里這么多的||,不為別的,就是考慮到瀏覽器兼容問題而已。

最后啟動(dòng)游戲

萬事具備,只欠東風(fēng)。到此,所有的游戲代碼基本就寫完了,我們現(xiàn)在需要做的就是調(diào)用相應(yīng)的函數(shù)來啟動(dòng)游戲:


// Let"s play this game! var then = Date.now(); reset(); main();

到這里代碼就寫完了。先是設(shè)置一個(gè)初始的時(shí)間變量then用于首先運(yùn)行main函數(shù)使用。然后調(diào)用 reset 函數(shù)來開始新一輪游戲(如果你還記得的話,這個(gè)函數(shù)的作用是將英雄放到畫面中間同時(shí)將怪物放到隨機(jī)的地方以方便英雄去捉它)

用瀏覽器打開game.html,開始玩游戲吧!

進(jìn)一步思考

在玩游戲的過程中,你會(huì)發(fā)現(xiàn)每一次hero捕獲到monster,hero就回到了canvas畫布的正中間。那么現(xiàn)在需要做的就是,將hero在捕捉到monster的時(shí)候讓hero就停留在捕獲的位置,不再是回到canvas正中間。

這個(gè)現(xiàn)象的出現(xiàn)主要是因?yàn)樵?b>reset函數(shù)中將hero.xhero.y寫死了,所以一個(gè)最簡單的方法就是在reset中傳入?yún)?shù):

var reset = function (x,y) {
    hero.x = x;
    hero.y = x;
};

然后在update調(diào)用reset的時(shí)候傳入捕獲時(shí)位置的參數(shù):

var update = function (modifier) {

        //...other codes

        ++monstersCaught;
        reset(heor.x,hero.y);

};


最后在開始游戲的時(shí)候?qū)?b>hero放在canvas最中間即可:


var then = Date.now(); reset(canvas.width / 2,canvas.height / 2); main();

大功告成!

Hapyy Hacking

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/85822.html

相關(guān)文章

  • 推薦一些好HTML5 & JavaScript 游戲引擎開發(fā)

    摘要:推薦一些好用的游戲引擎開發(fā)庫引言如果你是一個(gè)游戲開發(fā)者,并且正在尋找一個(gè)可以與和無縫工作的游戲引擎。是另一個(gè)容易使用,適用于移動(dòng)設(shè)備和桌面的游戲引擎。是一個(gè)開源的用來創(chuàng)建使用高級技術(shù)和服務(wù)的游戲引擎。用于建立游戲和繪圖引擎。 推薦一些好用的 HTML5 & JavaScript 游戲引擎開發(fā)庫 0. 引言 如果你是一個(gè)游戲開發(fā)者,并且正在尋找一個(gè)可以與 JavaScript 和 HT...

    happen 評論0 收藏0
  • 推薦一些好HTML5 & JavaScript 游戲引擎開發(fā)

    摘要:推薦一些好用的游戲引擎開發(fā)庫引言如果你是一個(gè)游戲開發(fā)者,并且正在尋找一個(gè)可以與和無縫工作的游戲引擎。是另一個(gè)容易使用,適用于移動(dòng)設(shè)備和桌面的游戲引擎。是一個(gè)開源的用來創(chuàng)建使用高級技術(shù)和服務(wù)的游戲引擎。用于建立游戲和繪圖引擎。 推薦一些好用的 HTML5 & JavaScript 游戲引擎開發(fā)庫 0. 引言 如果你是一個(gè)游戲開發(fā)者,并且正在尋找一個(gè)可以與 JavaScript 和 HT...

    Zack 評論0 收藏0

發(fā)表評論

0條評論

CompileYouth

|高級講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<