1. 程式人生 > >JS開發HTML5遊戲《神奇的六邊形》(一)

JS開發HTML5遊戲《神奇的六邊形》(一)

近期出現一款魔性的消除類HTML5遊戲《神奇的六邊形》,今天我們一起來看看如何通過開源免費的青瓷引擎(www.zuoyouxi.com)來實現這款遊戲。


(點選圖片可進入遊戲體驗)

因內容太多,為方便大家閱讀,所以分成四部分來講解。

本文為第一部分,主要包括:

1. 功能分析

2. 建立工程與場景

3. 玩家分數管理

4. 棋盤設計與實現

5. 屏幕布局

若要一次性檢視所有文件,也可點選這裡

功能分析

首先分析遊戲的功能點、演算法和資料,然後依此制訂程式碼組織結構。如下圖:


主要功能點

  1. 棋盤的資料結構與繪製
  2. 3個形狀的生成
  3. 形狀拖拽填入棋盤
  4. 行消除判定與死亡判定
  5. 各種表現,例如消除動畫、加分動畫等

程式碼結構

將遊戲邏輯(例如棋盤資料結構、死亡判定等)和介面邏輯分開,分別置於logic和ui介面。所有的UI介面交給UIManager指令碼統一維護管理。

二. 建立工程與場景

建立工程Tetris和空的主場景Main,設定如下:

本工程中,畫布背景(background)設定為透明

遊戲入口與遊戲初始化

在Scripts目錄下建立檔案:Tetris.js。程式碼如下:

/**
     * 遊戲入口
     */
    window.Tetris = qc.Tetris = {
        // 所有的操作指令集合
        operation: {}
    };

    // 遊戲邏輯初始化
    qc.initGame = function(game) {
        // 將遊戲例項記錄下來,便於訪問
        Tetris.game = game;

        // 幀率顯示為60幀(滿幀)
        game.time.frameRate = 60;
    };
設定此指令碼為入口指令碼:


此指令碼首先定義了名字空間,將全域性的資料都記錄在qc.Tetris。遊戲入口中,記錄了game的例項並將幀率限定為60幀(預設在手機下為30幀)

三. 玩家分數管理

  1. 建立指令碼:Scripts/logic/Score.js:

/**
  * 維護分數資訊
  */
 var Score = qc.Tetris.Score = function() {
     var self = this;
     self._current = 0;
     self._best = 0;

     // 將本地資料讀取出來
     var game = qc.Tetris.game;
     var current = game.storage.get('current'),
         best = game.storage.get('best');
     if (current) self._current = current;    
     if (best) self._best = best;
 };
 Score.prototype = {};
 Score.prototype.constructor = Score;

 Object.defineProperties(Score.prototype, {
     current: {
         get: function() { return this._current; },
         set: function(v) {
             this._current = v;
             if (this.best < v) this.best = v;
         }
     },

     best: {
         get: function() { return this._best; },
         set: function(v) {
             this._best = v;
             var storage = qc.Tetris.game.storage;
             storage.set('best', v);
             storage.save();
         }
     }
 });

Score類維護了兩個資料:current(當前玩家的分數)、best(玩家的歷史最高分)

2. 例項化Score類

開啟Tetris.js指令碼,在initGame方法中,加入程式碼:

qc.initGame = function(game) {
     // 將遊戲例項記錄下來,便於訪問
     Tetris.game = game;

     // 幀率顯示為60幀(滿幀)
     game.time.frameRate = 60;

     // 初始化分數資訊
     Tetris.score = new qc.Tetris.Score();
 };
四. 棋盤設計與實現

棋盤為一邊長為5的正六變形,為了方便計算,我們如下設定棋盤的座標系(下文稱為:格子邏輯座標):


原點在六邊形中心點,半徑為4。

  1. 修改Tetris.js檔案,增加棋盤的配置資訊:

window.Tetris = qc.Tetris = {
     // 棋盤的大小(半徑)
     SIZE: 4,

     // 棋盤中,每個格子的寬度和高度
     BLOCK_W: 61,
     BLOCK_H: 67,

     // 所有的操作指令集合
     operation: {}
 };

棋盤格子的大小 = 格子圖片的大小,後續匯入資源後可以看到其大小為61*67。

2. 在Scripts/logic下建立檔案Board.js,維護棋盤的資料,程式碼如下:

var Board = qc.Tetris.Board = function() {
     var self = this,
         size = qc.Tetris.SIZE,
         len = qc.Tetris.BLOCK_H;

     // 構建用來轉換格子座標的矩陣
     var m = self.m = new qc.Matrix();
     m.a = len;
     m.c = len / 2;
     m.d = len * (Math.sqrt(3) / 2);

     // 初始化棋盤資料
     self.data = {};
     for (var i = -size; i <= size; i++) {
         for (var j = -size; j <= size; j++) {
             // 這些格子落在六邊形外,忽略掉
             if (i * j > 0 && Math.abs(i + j) > size) continue;
             if (i * j < 0 && (Math.abs(i) > size || Math.abs(j) > size)) continue;

             // 計算格子的座標和對應螢幕上的偏移
             var pos = Tetris.makePos(i, j);
             var pt = self.toWorld(new qc.Point(i, j));
             self.data[pos] = {
                 value: 0,
                 x: pt.x,
                 y: pt.y
             };
         }
     }
 };
 Board.prototype = {};
 Board.prototype.constructor = Board;

 Object.defineProperties(Board.prototype, {
     /**
      * @property {boolean} die - 當前是否已經死亡了
      * @readonly
      */ 
     die: {
         get: function() {
             // TODO: 等待實現
         }
     }
 });

 /**
  * 清空棋盤
  */
 Board.prototype.clear = function() {
     for (var pos in this.data) {
         this.data[pos].value = 0;
     }
 };

 /**
  * 重新開始遊戲
  */
 Board.prototype.restart = function() {
     this.clear();
 };

 // 判定形狀可以放進來不
 // pos: 目標邏輯座標
 // list: 形狀的資訊
 Board.prototype.checkPutIn = function(pos, list) {
     // TODO: 等待實現
 };

 // 把某個形狀放進來
 Board.prototype.putIn = function(pos, list, value) {
     // TODO: 等待實現
 };

 // 根據格子的邏輯座標,算出所在的螢幕座標
 // distance: 兩個格子中心點之間的距離
 Board.prototype.toWorld = function(p, distance) {
     if (!distance)
         return this.m.apply(p);

     var m = new qc.Matrix();
     m.a = distance;
     m.c = distance * 0.5;
     m.d = distance * (Math.sqrt(3) * 0.5);
     return m.apply(p);
 };

 // 根據格子的螢幕座標,反算格子的邏輯座標
 Board.prototype.toLocal = function(p) {
     return this.m.applyInverse(p);
 };

3. 修改Tetris.js,在qc.initGame方法中,例項化本物件:
qc.initGame = function(game) {
     // 將遊戲例項記錄下來,便於訪問
     Tetris.game = game;

     // 幀率顯示為60幀(滿幀)
     game.time.frameRate = 60;

     // 初始化分數資訊
     Tetris.score = new qc.Tetris.Score();

     // 構建棋盤物件
     Tetris.board = new qc.Tetris.Board();
 };
同時,在本檔案中實現兩個函式:makePos和readPos:
// 構建座標
 window.Tetris.makePos = function(x, y) {
     return x + '_' + y;
 };

 // 獲取座標
 window.Tetris.readPos = function(pos) {
     var arr = pos.split('_');
     return new qc.Point(arr[0]*1, arr[1]*1);
 };

五. 屏幕布局

在美術設計時,以640*960解析度(iPhone4)進行設計,其他解析度的螢幕需要自適應。如下圖:


  • 整個介面分為標題欄(Top)、棋盤(Board)、3個形狀(Shape)
    • Top:高度在iPhone4上為130。這裡有兩個資訊:當前分數與歷史最高分數
    • Board:棋盤,其大小為600*580
    • Shape:3個形狀,大小為600*230,距離底部20
  • 自適應方案:
    • 以 640*960為基準,等比縮放,確保所有內容都能全部顯示
    • 當解析度比較瘦長時(即Height/Width > 960/640)時,Board和Shape保持和底部位置不變(方便單手操作)。Top高度自動增加
    • 當解析度比較寬時(即Height/Width < 960/640)時,Board和Shape保持居中,兩邊留白

匯入資源

  1. 新建資料夾:Assets/atlas/[email protected],將以下檔案拖入並打包圖集(圖片請在示例工程中檢視)
    blue.png、cyan.png、gray.png、green.png、lightyellow.png、red.png、shadow.png、white.png、yellow.png
    darkblue.png、darkcyan.png、darkgreen.png、darklightyellow.png、darkred.png、darkyellow.png等,具體請參考示例工程
    格子在沒有資料時,顯示gray.png。其他形狀的格子顏色,有6種(blue、cyan、green、lightyellow、yellow、red)

  2. 將以下檔案拖入資料夾Assets/raw(raw目錄下的資源都不會被打包,例如圖片直接原樣保留,適用於css樣式表指定資源)
    blue.png、cyan.png、gray.png、green.png、lightyellow.png、red.png、yellow.png等,具體請參考示例工程,各圖片的用途在後續中會說明。

介面佈局

      1. 建立UIRoot,並設定Reference Resolution(參考解析度)為 640*960,Manual Type為Expand


 簡單的理解:設定了以後,就可以認為螢幕的寬度>=640,高度>=960

2. 建立棋盤。棋盤大部分情況下是“靜態”的,只是在有新的形狀放入時才會變化。如果棋盤的每個格子作為UIImage進行貼圖,則每幀都需要重繪幾十個格子圖片,對渲染效率會有所影響。這裡我們適用DOM方案,裡面每個格子使用div進行繪製。因此建立一個DOM節點,設定其大小為:600*580,同時由於棋盤距離底部的位置固定,因此在佈局上:水平居中、垂直距離底部250,自身中心點在底部中心位置。如下圖:


3. 新增一個Node節點,掛載3個形狀。Node大小為 600*230,距離底部20。如下圖:


4. 建立DOM節點顯示歷史最高分(不常變化,因此不用UIText,使用Dom更高效)。本節點大小為200*60,距離螢幕右邊20,頂部20:

5. 建立DOM節點顯示當前分(不常變化,因此不用UIText,使用Dom更高效)。本節點大小為200*80,水平居中,頂部頂部29:


下一篇:JS開發HTML5遊戲《神奇的六邊形》(二)(TO BE CONTINUED)


相關推薦

JS開發HTML5遊戲神奇六邊形

近期出現一款魔性的消除類HTML5遊戲《神奇的六邊形》,今天我們一起來看看如何通過開源免費的青瓷引擎(www.zuoyouxi.com)來實現這款遊戲。 (點選圖片可進入遊戲體驗) 因內容太多,為方便大家閱讀,所以分成四部分來講解。 本文為第一部分,主要包括:

unity遊戲開發之ULua框架介紹

1.基礎介紹 ①ULua 整合開發環境叫做:SimpleFramework,SimpleFramework 分為NGUI 和UGUI兩個版本,區別是NGUI 版本的框架資源中含有NGUI 這個外掛。SimpleFramework 本身不是Unitypackage 格式,而是一個Unity3D的專

Unity遊戲開發教程:飛機大戰

Unity版本:Unity 2018.2.14f1 新建專案 File -> New project -> 輸入Project name -> Preate project 匯入飛

遊戲敏捷開發專案管理之我見

縱觀整個遊戲開發週期,大部分時間都是在趕趕趕,趕開發進度,趕Bug進度,趕釋出進度。搞得交投爛額,搞得最後大家筋疲力竭,最終商務、策劃、boss都覺得開發不給力。所以我們有必要,也有義務去採取一些措施來

使用cocos2d-js製作遊戲新手引導

    ​  想到新手引導的功能時可能很多人都會覺得頭痛,難以下手。特別是在遊戲本身功能或需求還不穩定的情況,更是難以應付,本人就是在這種情況下接受了一個艱鉅的任務。在痛定思痛之後,開始了引導功能開

H5遊戲開發之phaser學習筆記

1、Phaser.Game(width, height, renderer, parent, state, transparent, antialias, physicsConfig) width: 遊戲的寬度,也就是用來渲染遊戲的canvas的寬度,單位為px hei

Visual C++ 遊戲開發筆記 紋理對映技術

一、引言 江山如此多嬌,風景如畫。萬物都有其獨特的特點。真實世界中的物體,在計算機三維世界中如果單單用各種各樣的幾何體以及頂點座標,頂點顏色來模擬的話,往往缺乏生機,往往差強人意。 比如說我們要繪製出如下效果的一個貼了瓷磚的立方體: 綜合我們之前講過的知識,繪製一個立方體是小菜一

我的Unity遊戲開發筆記之特效基礎:粒子效果面板

如何在Unity中實現粒子效果? 首先,右鍵點選 Hierarchy欄,選擇effects->Particle System,這樣你就新建了一個粒子系統,如圖所示: 下面來介紹右側監視器(Inspector)內的內容: 首先是Transform,分別為Positio

jsp 快速開發報表 chart.js 餅圖示例 系列教材

畫餅圖,需要有兩個js,一個是chart.js一個是jquery.min.js,我這兩個都放在了webContent下了引入方法: <script type="text/javasc

【Visual C++】遊戲開發五十六 淺墨DirectX教程二十三 打造遊戲GUI介面

眾所周知,GUI是遊戲中不可缺少的元素,這篇文章中,我們首先了解了遊戲GUI介面的知識與相關概念,然後一起設計了一個封裝好GUI圖形介面的C++類。這個類有著非常強的擴充套件性,使用也是極其方便,很適合二次開發。 先看一張實現的效果圖吧: 其中的背景音樂,遊戲圖

【Visual C++】遊戲開發筆記之四——遊戲畫面繪圖基本圖形繪製

毛星雲,網路ID「淺墨」,90後,熱愛遊戲開發、遊戲引擎、計算機圖形、實時渲染等技術,就職於騰訊互娛。 微軟最有價值專家 著作《Windows遊戲程式設計之從零開始》、《OpenCV3程式設計入門》 碩士就讀於南京航空航天大學航天學院(2013級碩士研究生),已於2016年三月畢業。本科

U3D遊戲開發—程式設計師轉型篇背景介紹

第一篇部落格,如有什麼思維上或者講述的不夠合理,歡迎各種網路上的大神砸磚; 為什麼寫這篇部落格,可能跟本人性格有關係,“好為人師”,高中的時候,最喜歡給女朋友將地址知識了,把她講的不會了,我居然喜歡上了不擅長的地理;所以根據這個原理,所以才有了這個系列的部落格;      

70後遊戲輔助開發程式猿的人生路

         本人1976年生於一個國營廠礦企業,1998年畢業於國內二流大學計算機軟體專業,大學期間學的最好的是Pascal語言,因為教Pascal語言的老師是個女神,是全班男同學YY的物件。為

JS函數和對象

inf ack bsp 用法 .cn 求和 封裝 obj [0 在本文章中,將對JS中的函數和對象進行一些講解,不對之處還請之處 一.JS中的函數 1.1無參函數 其形式如下代碼所示 function box(){ alert("我是一個函數,只有被調用才會執行

前端之 —— node.js摸爬打滾之路

turn lan name resp function oba ack val 括號 安裝: window下的安裝,node.js直接上官網下載:https://nodejs.org/en/ 選擇LTS,也就是版本號比較低的穩定版,下載下來後運行下載的文件進行安裝; 通

Qt5.9.1結合REF開發基於chorm的瀏覽器

編譯 ++ mar 建立 eat generate sha 設計 source 下載cef3的源碼 cef簡介   嵌入式Chromium框架(簡稱CEF) 是一個由Marshall Greenblatt在2008建立的開源項目,它主要目的是開發一個基於Google Chr

Kotlin開發基礎從0開始

code ... 多說 lang 學習 function ria lis lac 為什麽學習kotlin kotlin在今年的Google IO 上正式被確認為Android的官方開發語言,想必原因大家也能猜到一二,一是Google與oracle關於Java相關的版權相關的

尋找bug並消滅系列——記錄在Android開發所遇到的bug

ont 屬性 XML android oid content 事件監聽器 監聽 設置 之前使用了Android Studio的插件直接為button綁定了監聽器,並實現onClick方法(我的onClick方法無論點擊哪一個都是要實現setcontentview這個方法設置

vue.js實戰學習——內置指令

name 初始 節點 刪除 html元素 data post 編譯 16px 註:此內容摘抄自:梁灝的《Vue.js實戰》 註:記得要引入vue.js才能運行哦,文章中貼出的代碼直接復制是不行的,html css js 都放在了一起,而且也沒有引用vue.js。 1.v

全棧開發之HTML快速入門

ack enter 提示 其他 red tle 顯示圖片 val password 一、HTML 是什麽? HTML 指的是超文本標記語言 (Hyper Text Markup Language) HTML 不是一種編程語言,而是一種標記語言 (markup lan