H5 Flappy Bird 游戲制作 (2)

前言

上期,我們介紹了 canvas, GameManager 模塊,這期我們實現(xiàn)一下上次拆分的 canvasBackground 模塊爸邢。

canvas

由于畫布在全局是單一的科乎,所以在實現(xiàn) canvas 模塊時密强,我們采用單例模式宴杀。

新建 src/FlappyBird/canvas.js

// 定義 Canvas 類
class Canvas {
    constructor() {
        // 使用選擇器選擇 canvas DOM 節(jié)點
        const canvas = document.querySelector('canvas');
        // 根據(jù)設(shè)備分辨率設(shè)置寬高
        canvas.height = window.innerHeight * window.devicePixelRatio;
        canvas.width = window.innerWidth * window.devicePixelRatio;
        this.canvas = canvas;
    }

    // 提供獲取 context 的方法
    getCtx() {
        return this.canvas.getContext('2d');
    }

    // 提供清空屏幕展示內(nèi)容的方法
    clear() {
        const ctx = this.getCtx();
        ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }

    // 提供獲取 canvas 實際寬高的方法
    getSize() {
        return { width: this.canvas.width, height: this.canvas.height };
    }
}

// 實例化 Canvas 類
const canvas = new Canvas();

// 暴露單例
export default canvas;
// 將 ctx 暴露出去,為了方便使用
export const ctx = canvas.getCtx();

為了讓 canvas 占滿整個屏幕拾因,我們需要設(shè)置一些 css 樣式旺罢。在 src/FlappyBird/index.pcss 中添加:

/* 讓 html 占滿整個頁面的高度,默認 html 占了頁面的全寬绢记,因此不需要額外設(shè)置 */
html {
    height: 100%;
}
/* 去掉 body 上默認的 margin扁达,讓 body 的高度也占滿整個頁面 */
body {
    margin: 0;
    height: 100%;
}
/* 讓 canvas 元素變成塊級,占滿整個頁面 */
canvas {
    display: block;
    width: 100%;
    height: 100%;
}

Movable

在上次提到的模塊拆分時蠢熄,我們設(shè)想了 StickManager跪解,Inputcanvas签孔,Bird叉讥,Background 這幾個模塊。其中 StickManager饥追,Bird图仓,Background 三個模塊都需要移動,因此我們提取了公用的移動類 Movable但绕,這三個模塊繼承后可以共享移動的屬性和方法救崔。

// 定義基礎(chǔ)類
export default class Movable {

    constructor() {
        // 構(gòu)造函數(shù)中保存這個元素的橫向坐標(biāo)和縱向坐標(biāo) x 和 y,和橫向移動速度和縱向移動速度 vx 和 vy捏顺。
        // 這里都設(shè)置成 `0`六孵,也就是默認不移動
        this.x = 0;
        this.y = 0;
        this.vx = 0;
        this.vy = 0;
    }

    move() {
        const diff = 10;
        this.x += this.vx * diff / 1000;
        this.y += this.vy * diff / 1000;
        return { diff };
    }

}

其中橫向坐標(biāo)和縱向坐標(biāo)都是 canvas 坐標(biāo)系下的坐標(biāo),也就是從左到右 x 增加幅骄,從上到下 y 增加劫窒。

移動函數(shù)會在每次被調(diào)用的時候得到一個時間差。一種做法是時間差是真實時間的函數(shù)昌执,也就需要每次移動時需要記錄下當(dāng)前的時間烛亦,然后和上次的時間相減诈泼,得到的差值做一次比例運算:const diff = (currentTime - prevTime) * ratio;。第二種做法是固定差值煤禽,也就是認為每次 move 函數(shù)被調(diào)用和上次被調(diào)用之間的時間差固定:const diff = fixedValue铐达。這里我們簡單地采用第二種方式,并且讓 fixedValue 等于 10檬果。

拿到時間差后瓮孙,計算下一個位置的坐標(biāo),并且更新到自身的屬性上选脊,這樣在具體實例調(diào)用 paint 函數(shù)繪制圖像的時候杭抠,直接讀取坐標(biāo)畫到 canvas 上。這里的物體運動有兩種方式恳啥,勻速運動和加速度運動偏灿。運動的微分公式是 (delta s) = v * (delta t)。在加速度運動情況下钝的,只要每次修改速度就可以了 (delta v) = a * (delta t)翁垂。因此這里只要把位置的變化累加到原先的位置上 x += vx * diff。這里的速度的單位是像素每秒硝桩,diff 的單位是毫秒沿猜,所以需要除以 1000。最后把 diff 值返回出去碗脊,以便在外部計算速度差啼肩。

Background

有了 Movable 后,就可以實現(xiàn)背景了衙伶。

// 引入 canvas 和 ctx
import canvas, { ctx } from './canvas';
// 背景圖
import image from './background.png';
// 引入 `Movable
import Movable from './Movable';
// 聲明 `Background` 類繼承 `Movable` 類
export default class Background extends Movable {

    constructor() {
        // 調(diào)用父類的構(gòu)造函數(shù)
        super();
        // 加載背景圖資源
        this.image = new Image();
        this.image.src = image;
        const { width, height } = canvas.getSize();
        // 背景圖的寬高是按照整個屏幕的寬高設(shè)計的
        this.width = width;
        this.height = height;
        // 覆蓋掉默認的橫向移動速度祈坠,這里的背景圖需要向左移動,所以 `vx` 是負值
        this.vx = -100;
    }

    move() {
        // 調(diào)用父類的移動函數(shù)
        super.move();
        if (this.x < -this.width) {
            this.x += this.width;
        }
    }

    paint() {
        ctx.drawImage(this.image, this.x, 0, this.width, this.height);
        ctx.drawImage(this.image, this.x + this.width, 0, this.width, this.height);
    }
}

畫背景圖時痕支,我們用兩個圖片首位相連的方式颁虐。當(dāng)一張背景圖移出了屏幕,就讓它變成下一個背景圖:x = width卧须。

src/FlappyBird/GameManager.js 中引入 Background另绩,看下效果:

import canvas from './canvas';
import Background from './Background';

export default class GameManager {

    constructor() {
        // 初始化背景
        this.background = new Background();
    }

    paint() {
        // 每次重繪整個畫布。先清空畫布的所有東西花嘶,再移動背景笋籽,最后畫背景
        canvas.clear();
        this.background.move();
        this.background.paint();
    }

    loop() {
        this.paint();
        requestAnimationFrame(() => {
            this.loop();
        });
    }

    start() {
        this.loop();
    }

}

最后在 src/FlappyBird/index.js 中,調(diào)用 GameManager 初始化一個游戲:

// 基礎(chǔ)樣式
import './index.pcss';
import GameManager from './GameManager';

let gm = new GameManager();

// 開始游戲
gm.start();

可以看到背景一直向左移動椭员。

TBC

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末车海,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侍芝,老刑警劉巖研铆,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異州叠,居然都是意外死亡棵红,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門咧栗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逆甜,“玉大人,你說我怎么就攤上這事致板〗簧罚” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵斟或,是天一觀的道長素征。 經(jīng)常有香客問我,道長萝挤,這世上最難降的妖魔是什么稚茅? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮平斩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咽块。我一直安慰自己绘面,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布侈沪。 她就那樣靜靜地躺著揭璃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亭罪。 梳的紋絲不亂的頭發(fā)上瘦馍,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音应役,去河邊找鬼情组。 笑死,一個胖子當(dāng)著我的面吹牛箩祥,可吹牛的內(nèi)容都是我干的院崇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼袍祖,長吁一口氣:“原來是場噩夢啊……” “哼底瓣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蕉陋,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤捐凭,失蹤者是張志新(化名)和其女友劉穎拨扶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茁肠,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡患民,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了官套。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酒奶。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖奶赔,靈堂內(nèi)的尸體忽然破棺而出惋嚎,到底是詐尸還是另有隱情,我是刑警寧澤站刑,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布另伍,位于F島的核電站,受9級特大地震影響绞旅,放射性物質(zhì)發(fā)生泄漏摆尝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一因悲、第九天 我趴在偏房一處隱蔽的房頂上張望堕汞。 院中可真熱鬧,春花似錦晃琳、人聲如沸讯检。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽人灼。三九已至,卻和暖如春顾翼,著一層夾襖步出監(jiān)牢的瞬間投放,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工适贸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留灸芳,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓取逾,卻偏偏與公主長得像耗绿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子砾隅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程误阻,因...
    小菜c閱讀 6,358評論 0 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器究反,智...
    卡卡羅2017閱讀 134,600評論 18 139
  • 在前面一篇文章中精耐,我們分析了Android應(yīng)用程序窗口的繪圖表面的創(chuàng)建過程狼速。Android應(yīng)用程序窗口的繪圖表面在...
    一個不掉頭發(fā)的開發(fā)閱讀 4,549評論 0 14
  • 文/攬衣 【一】 浩浩蕩蕩的軍隊開赴戰(zhàn)場,領(lǐng)軍的那個少年卦停,器宇軒昂雄姿英發(fā)向胡。他是邶國最年輕的大將軍,鳶王邶鳶惊完。另外...
    攬衣閱讀 250評論 1 1
  • 姓名:陳增義 六項精進276,感謝1組成員 公司:上海市金山區(qū)錦湖日麗塑料有限公司 【日精進打卡第50天僵芹,總365...
    小哥i1114閱讀 162評論 0 0