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', 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, // 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, 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, 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, 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