前端實戰:從零到一實現H5拼圖小遊戲

作者: 徐小夕 來源:趣談前端

前端實戰:從零到一實現H5拼圖小遊戲

我去年曾寫過一個用H5,Javascript,css3實現的拼拼樂小遊戲,技術棧採用自己封裝的類Jquery框架 Xuery ,其中涉及到了很多經典的 javascript 演算法和css3特性 ,對大家的程式設計能力會有很大的提高,文末我也會放上原始碼獲取方式,大家可以學習體驗一下。

前言

因為該應用屬於 H5 遊戲,為了讓專案更輕量,我沒有采用第三方 ui 庫,如果大家想採用基於 vue 的第三方移動端ui庫,我給大家推薦幾個我之前用過的比較靠譜的:

Mint 餓了麼推出的移動端ui庫

NutUI 一套京東風格的移動端元件庫

muse-ui 基於MaterialUI風格的移動端UI元件

cube-ui 滴滴團隊開發的移動端UI元件庫

vant 有贊團隊的電商風格的移動端元件庫

atom-design atom風格的移動端ui元件庫

mand-mobile 滴滴團隊研發的基於金融場景的移動端ui元件庫

以上推薦的都是社群比較完善,bug比較少的元件庫,大家可以感受一下。

回到我們的小遊戲開發,考驗更多的是大家對 javascript 和css3 的掌握程度,在學習完這篇文章之後相信大家對 javascript 和 css3 的程式設計能力都會有極大的提升,後面還會介紹如何使用 canvas 實現生成戰績海報圖的功能。

正文

我們先來看看遊戲的預覽介面:

前端實戰:從零到一實現H5拼圖小遊戲

前端實戰:從零到一實現H5拼圖小遊戲

前端實戰:從零到一實現H5拼圖小遊戲

前端實戰:從零到一實現H5拼圖小遊戲

本文的演算法實現方式涉及到洗牌演算法,動態生成n維座標,圖片切割等,接下來會介紹核心演算法的實現, 至於vue-cli的使用方法,筆者之前也寫過對應的文章,大家可以研究學習一下。vue-cli搭建專案方式如下:

// 安裝 yarn global add @vue/cli // 建立專案 vue create pinpinle // 進入專案並啟動 cd pinpinle && yarn start

關於vue-cli3配置實戰,可以移步 一張圖教你快速玩轉vue-cli3

H5遊戲核心功能介紹

目前筆者主要整理樂如下核心功能,接下來筆者會一一帶大家實現:

實現純javascript上傳預覽圖片

實現拼圖分割功能

實現洗牌演算法

實現生成戰績海報功能

1。 實現純javascript上傳預覽圖片

檔案上傳預覽主要採用FileReader API實現,原理就是將file物件傳給FileReader的readAsDataURL然後轉化為data:URL格式的字串(base64編碼)以表示所讀取檔案的內容。 具體程式碼如下:

// 2。檔案上傳解析 let file = $(‘#file’); file。on(‘change’, function(e){ var file = this。files[0]; var fileReader = new FileReader(); // 讀取完成觸發的事件 fileReader。on​load = function(e) { $(‘。file-wrap’)[0]。style。backgroundImage = ‘url(’ + fileReader。result + ‘)’; imgSrc = fileReader。result; } file && fileReader。readAsDataURL(file); })

2。 實現拼圖分割功能

一般我們處理這種拼圖遊戲都會有如下方案:

用canvas分割圖片

採用n張不同的切好的切片圖片(方法簡單,但是會造成多次請求)

動態背景分割

經過權衡,筆者想出了第三種方法,也是自認為比較優雅的方法,即動態背景分割,我們只需要使用1張圖片,然後利於css的方式切割圖片,有點經典的雪碧圖的感覺,如下:

前端實戰:從零到一實現H5拼圖小遊戲

本質就是我們設定九個div,每個div都使用同一張圖片,並且圖片大小等於遊戲畫布大小,但是我們透過backgroundPosition(背景定位)的方式來實現切割圖片。這樣做的另一個好處是方便我們實現洗牌邏輯。

3。 實現洗牌演算法

洗牌邏輯依託於隨機演算法,這裡我們結合座標系,實現一個隨機生成二維座標系的邏輯,然後透過改變每個切片的translate位置,配合過渡動畫,即可實現洗牌功能和洗牌動畫。

3.1 陣列亂序演算法

陣列亂序比較簡單,程式碼如下:

// 陣列亂序 function upsetArr(arr) { arr。sort(function(a,b){ return Math。random() > 0。5 ? -1 : 1 }) }

3.2 洗牌邏輯

洗牌邏輯基於陣列亂序,具體邏輯如下:

// 洗牌方法 function shuffle(els, arr) { upsetArr(arr); for(var i=0, len=els。length; i< len; i++) { var el = els[i]; el。setAttribute(‘index’, i); // 將打亂後的陣列索引快取到元素中 el。style。transform = ‘translate(’ + arr[i]。x + ‘vw,’ + arr[i]。y + ‘vh’+ ‘)’; } }

3.3 生成n緯矩陣座標

n維矩陣主要用來做洗牌和計算成功率的,具體實現如下:

// 生成n維矩陣座標 function generateMatrix(n, dx, dy) { var arr = [], index = 0; for(var i = 0; i< n; i++) { for(var j=0; j< n; j++) { arr。push({x: j*dx, y: i*dy, index: index}); index++; } } return arr }

3.4 置換演算法

置換演算法主要用來切換拼圖的,比如使用者想移動拼圖,可以用過置換來實現:

// 陣列置換 unction swap(arr, indexA, indexB) { let cache = arr[indexA]; arr[indexA] = arr[indexB]; arr[indexB] = cache;

4。 實現生成戰績海報功能

生成戰績海報筆者採用canvas來實現,對於canvas的api不熟悉的可以檢視MDN,講的比較詳細。這裡筆者簡單實現一個供大家參考:

function generateImg() { var canvas = document。createElement(“canvas”); if(canvas。getContext) { var winW = window。innerWidth, winH = window。innerHeight, ctx = canvas。getContext(‘2d’); canvas。width = winW; canvas。height = winH; // 繪製背景 // ctx。fillStyle = ‘#06c’; var linear = ctx。createLinearGradient(0, 0, 0, winH); linear。addColorStop(0, ‘#a1c4fd’); linear。addColorStop(1, ‘#c2e9fb’); ctx。fillStyle = linear; ctx。fillRect(0, 0, winW, winH); ctx。fill(); // 繪製頂部影象 var imgH = 0; img = new Image(); img。src = imgSrc; img。on​load = function(){ // 繪製的圖片寬為。7winW, 根據等比換算繪製的圖片高度為 。7winW*imgH/imgW imgH = 。6*winW*this。height/this。width; ctx。drawImage(img, 。2*winW, 。1*winH, 。6*winW, imgH); drawText(); drawTip(); drawCode(); } // 繪製文字 function drawText() { ctx。save(); ctx。fillStyle = ‘#fff’; ctx。font = 20 + ‘px Helvetica’; ctx。textBaseline = ‘hanging’; ctx。textAlign = ‘center’; ctx。fillText(‘我只用了’ + (180 -dealtime) + ‘s,’ + ‘快來挑戰!’, winW/2, 。15*winH + imgH); ctx。restore(); } // 繪製提示文字 function drawTip() { ctx。save(); ctx。fillStyle = ‘#000’; ctx。font = 14 + ‘px Helvetica’; ctx。textBaseline = ‘hanging’; ctx。textAlign = ‘center’; ctx。fillText(‘關注下方二維碼開始遊戲’, winW/2, 。25*winH + imgH); ctx。restore(); } // 繪製二維碼 function drawCode() { var imgCode = new Image(); imgCode。src = ‘/piecePlay/images/logo。png’; imgCode。on​load = function(){ ctx。drawImage(imgCode, 。35*winW, 。3*winH + imgH, 。3*winW, 。3*winW); // 生成預覽圖 var img = new Image(); img。alt="前端實戰:從零到一實現H5拼圖小遊戲" data-isLoading="0" src="/static/img/blank.gif" data-src= convertCanvasToImage(canvas, 1)。src; img。className = ‘previewImg’; img。on​load = function(){ $(‘。preview-page’)[0]。appendChild(this); startDx = startDx - 100; transformX(wrap, startDx + ‘vw’); } } } } else { alert(‘瀏覽器不支援canvas!’) } }

H5拼圖小遊戲筆者已在github開源, 感興趣的可以學習參考。以上的邏輯部分的程式碼可以直接整合到vue專案中即可,由於實現比較簡單,這裡筆者就不詳細介紹了。