Hilo是一個跨終端的互動游戲解決方案。
官網:http://hiloteam.github.io/index.html
馬上就要端午節了,公司要做一個接粽子的小游戲。網上找了一圈后決定用阿里團隊的Hilo庫進行開發。
游戲頁面
游戲代碼目錄
1.安裝hilo
npm install hilojs --save
2.index.vue
<template> <div class="hilo" ref="hilo"> <div class="gameInfo"> <div class="score">{{score}}</div> <div class="time">{{gameTime}}s</div> </div> <van-popup v-model="scorePopup" style="background: none;overflow: initial;"> <div class="scorePopup"> <div class="scorePopup-title">您本次游戲</div> <div class="scorePopup-score"> {{score}}分 </div> </div> </van-popup> </div> </template> <script> import Hilo from "hilojs"; import Game from "./js/game"; export default { name: '', data() { return { game: new Game(), scorePopup: false }; }, watch: { gameTime(val) { if (val == 0) { //游戲結束 setTimeout(() => { this.scorePopup = true; }, 1500); } } }, computed: { score() { return this.game.score }, gameTime() { return this.game.gameTime } }, methods: { }, mounted() { this.game.page = this.$refs.hilo; this.game.init(); }, } </script>
3.游戲圖片資源預加載 Asset.js
游戲界面創建前可先加載游戲內需要的圖片資源
使用Hilo的LoadQueue的隊列下載工具。
export default Hilo.Class.create({ Mixes: Hilo.EventMixin, queue: null, // 下載類 bg: null, // 背景 bigzZongzi: null, // 大粽子 zongzi: null, // 小粽子 fruit: null, // 香蕉 hand: null, // 手 beginBtn: null, // 開始按鈕 score0: null, // -1分 score1: null, // +1分 score2: null, // +2分 load() { let imgs = [{ id: 'bg', src: './images/bg.png' }, { id: 'bigzZongzi', src: './images/bigzZongzi.png' }, { id: 'zongzi', src: './images/zongzi.png' }, { id: 'fruit', src: './images/fruit.png' }, { id: 'hand', src: './images/hand.png' }, { id: 'beginBtn', src: './images/beginBtn.png' }, { id: 'score0', src: './images/score0.png' }, { id: 'score1', src: './images/score1.png' }, { id: 'score2', src: './images/score2.png' } ]; this.queue = new Hilo.LoadQueue(); this.queue.add(imgs); this.queue.on('complete', this.onComplete.bind(this)); this.queue.start(); }, onComplete() { //加載完成 this.bg = this.queue.get('bg').content; this.bigzZongzi = this.queue.get('bigzZongzi').content; this.zongzi = this.queue.get('zongzi').content; this.fruit = this.queue.get('fruit').content; this.hand = this.queue.get('hand').content; this.beginBtn = this.queue.get('beginBtn').content; this.score0 = this.queue.get('score0').content; this.score1 = this.queue.get('score1').content; this.score2 = this.queue.get('score2').content; //刪除下載隊列的complete事件監聽 this.queue.off('complete'); // complete暴露 this.fire('complete'); } })
4.游戲舞台對象 game.js
import Asset from './Asset' import Zongzi from './Zongzi' import Hand from './hand' export default class game { constructor(page) { this.page = page //設置的游戲時間 this.setGameTime = 30 this.gameTime = 0 this.gameStatus = "ready" /* play 游戲開始 ready 游戲結束 **/ // 下載隊列 this.asset = new Asset() // 畫布對象 this.stage = null // 畫布信息 this.width = innerWidth * 2 this.height = innerHeight * 2 < 1334 ? innerHeight * 2 : 1334 this.scale = 0.5 // 定時器對象 this.ticker = null //粽子對象 this.Zongzi = null //粽子下落速度 this.enemySpeed = 700 //粽子生成速度 this.createSpeed = 400 //接粽子的手 this.hand = null //開始按鈕 this.beginBtn = null //分數 this.score = 0 } init() { this.asset.on('complete', function () { this.asset.off('complete') this.initStage() }.bind(this)); this.asset.load() } initStage() { // 舞台 this.stage = new Hilo.Stage({ renderType:'canvas', width: this.width, height: this.height, scaleX: this.scale, scaleY: this.scale, container: this.page }); this.stage.enableDOMEvent([Hilo.event.POINTER_START, Hilo.event.POINTER_MOVE, Hilo.event.POINTER_END]); // 啟動定時器刷新頁面 參數為幀率 this.ticker = new Hilo.Ticker(60) // 舞台添加到定時隊列中 this.ticker.addTick(this.stage) // 添加動畫類到定時隊列 this.ticker.addTick(Hilo.Tween); //啟動ticker this.ticker.start(true); this.initBg(); this.initBeginBtn(); //this.initZongzi(); //this.initHand(); } initBg() { //初始化背景 let bgImg = this.asset.bg; new Hilo.Bitmap({ id: 'bg', image: bgImg, scaleX: this.width / bgImg.width, scaleY: this.height / bgImg.height }).addTo(this.stage); } initBeginBtn() { //初始化開始按鈕 this.beginBtn = new Hilo.Bitmap({ id: 'beginBtn', image: this.asset.beginBtn, //width: this.asset.beginBtn.width, //height: this.asset.beginBtn.height, x: (this.width - this.asset.beginBtn.width) / 2, y: this.height - this.asset.beginBtn.height - 200, rect: [0, 0, this.asset.beginBtn.width, this.asset.beginBtn.height] }).addTo(this.stage, 1); this.beginBtn.on(Hilo.event.POINTER_START, this.startGame.bind(this)) } startGame() { //開始游戲 this.initZongzi(); this.initHand() //this.beginBtn.removeFromParent() this.stage.removeChild(this.beginBtn) this.gameTime = this.setGameTime; this.score = 0; this.gameStatus = "play" this.calcTime() } calcTime() { //游戲時間 setTimeout(() => { if (this.gameTime > 0) { this.gameTime--; this.calcTime() } else { this.gameOver() } }, 1000); } gameOver() {//游戲結束 this.Zongzi.stopCreateEnemy() this.gameStatus = "ready" this.initBeginBtn() //this.hand.removeChild(this.hand.score) this.stage.removeChild(this.hand) } initZongzi() {//初始化粽子 this.Zongzi = new Zongzi({ id: 'Zongzi', height: this.height, width: this.width, enemySpeed: this.enemySpeed, createSpeed: this.createSpeed, pointerEnabled: false, // 不關閉事件綁定 無法操作舞台 zongziList: [this.asset.bigzZongzi, this.asset.zongzi, this.asset.fruit] }).addTo(this.stage, 2) //舞台更新 this.stage.onUpdate = this.onUpdate.bind(this); } initHand() {//初始化手 this.hand = new Hand({ id: 'hand', img: this.asset.hand, height: this.asset.hand.height, width: this.asset.hand.width, x: this.width / 2 - this.asset.hand.width / 2, y: this.height - this.asset.hand.height + 30 }).addTo(this.stage, 1); Hilo.util.copy(this.hand, Hilo.drag); this.hand.startDrag([-this.asset.hand.width / 4, this.height - this.asset.hand.height + 30, this.width - this.asset.hand.width / 2, 0]); } onUpdate() {//舞台更新 if (this.gameStatus == 'ready') { return } this.Zongzi.children.forEach(item => { if (this.hand.checkCollision(item)) { // 碰撞了 item.over(); this.score += item.score; switch (item.score) { case -1: this.hand.addScore(this.asset.score0) break; case 1: this.hand.addScore(this.asset.score1) break; case 2: this.hand.addScore(this.asset.score2) break; default: break; } } }) } }
5.粽子對象
Zongzi.js
import SmallZongzi from './SmallZongzi' let Enemy = Hilo.Class.create({ Extends: Hilo.Container, SmallZongziImg: null, timer: null, // 定時器 zongziList: [], enemySpeed: 0, createSpeed: 0, score: [2, 1, -1], tween: null, constructor: function (properties) { Enemy.superclass.constructor.call(this, properties); //this.onUpdate = this.onUpdate.bind(this); //this.createSmallZongzi() this.tween = Hilo.Tween; this.creatEnemy(); this.beginCreateEnemy(); }, random(lower, upper) { return Math.floor(Math.random() * (upper - lower + 1)) + lower; }, creatEnemy() { // 生成粽子 let number = this.random(0, 100); let index = null; if (number < 27) { //生成不同種類粽子概率 index = 0 } else if (number < 55) { index = 1 } else { index = 2 } let hold = new SmallZongzi({ image: this.zongziList[index], rect: [0, 0, this.zongziList[index].width, this.zongziList[index].height] }).addTo(this); hold.x = this.random(100, (this.width - 100)); hold.y = -300 * Math.random(); hold.score = this.score[index] this.tween.to(hold, { y: this.height + 200 }, { duration: 1400 / this.enemySpeed * 1000, loop: false, onComplete: () => { hold.removeFromParent() } }); }, beginCreateEnemy() {//開始生成 this.timer = setInterval(() => { this.creatEnemy(); }, this.createSpeed); }, stopCreateEnemy() {//停止生成並全部移除 clearInterval(this.timer) this.removeAllChildren() }, checkCollision(enemy) {//碰撞檢測 for (var i = 0, len = this.children.length; i < len; i++) { if (enemy.hitTestObject(this.children[i], true)) { return true; } } return false; } }) export default Enemy SmallZongzi.js let SmallZongzi = Hilo.Class.create({ Extends: Hilo.Bitmap, constructor: function (properties) { SmallZongzi.superclass.constructor.call(this, properties); this.onUpdate = this.onUpdate.bind(this); }, over(){ this.removeFromParent(); }, onUpdate() { if (this.parent.height < this.y) { this.removeFromParent(); return } } })
export default SmallZongzi
6.手對象 hand.js
let hand = Hilo.Class.create({ Extends: Hilo.Container, // 圖 img: null, //碗 bowl: null, //分數 score: null, constructor(properties) { hand.superclass.constructor.call(this, properties) this.initHand() this.initBowl() }, initHand() { //初始化背景 new Hilo.Bitmap({ id: 'hand', image: this.img, rect: [0, 0, this.img.width, this.img.height] }).addTo(this); }, initBowl() { //初始化碗 this.bowl = new Hilo.Bitmap({ id: 'bowl', //background: 'rgba(255,255,255,0.4)', rect: [0, 0, this.img.width / 3, 10], x: this.img.width / 3, y: 50 }).addTo(this); }, addScore(image) { //加分 this.score = new Hilo.Bitmap({ id: 'score', image: image, rect: [0, 0, image.width, image.height], x: (this.img.width - image.width) / 2, y: -image.height }).addTo(this); Hilo.Tween.to(this.score, { x: (this.img.width - image.width / 2) / 2, y: -2 * image.height, alpha: 0, width: image.width / 2, height: image.height / 2 }, { duration: 600, //delay: 100, ease: Hilo.Ease.Quad.EaseIn, onComplete: () => { } }); }, // 碰撞檢測 checkCollision(enemy) { if (enemy.hitTestObject(this.bowl, true)) { return true; } return false; } }) export default hand
轉自:https://blog.csdn.net/qq_37359757/article/details/106765753