最近做了一个比较不错的点击获取金币小游戏,这里分享给大家
主要实现方式是通过hilojs实现的
以下为官方文档的地址
官方文档
第一步:安装插件
npm i hilojs或者yarn add hilojs
第二步:创建一个Asset.js文件
import Hilo from "hilojs";
export default Hilo.Class.create({//素材加载类
Mixes: Hilo.EventMixin,
queue: null, // 下载类
gold10: null, // 金币
gold20: null, // 金币
gold50: null, // 金币
blindBox: null, // 盲盒
fireElement: null, // 金币
soil: null, // 红包
person: null, // 车
score0: null, // -1分
score1: null, // +1分
score2: null, // +2分
load() {
let imgs = [
{
id: 'gold10',//金币
src: 'https://sunndybody.gitee.io/monthover/10.png',
},
{
id: 'gold20',//金币
src: 'https://sunndybody.gitee.io/monthover/20.png',
},
{
id: 'gold50',//金币
src: 'https://sunndybody.gitee.io/monthover/50.png',
},
{
id: 'blindBox',//金币
src: 'https://sunndybody.gitee.io/monthover/hezi_120.png',
},
];
this.queue = new Hilo.LoadQueue();
this.queue.add(imgs);
this.queue.on('complete', this.onComplete.bind(this));
this.queue.on('error', (e) => {
console.log('加载出错', e)
})
this.queue.start();
},
onComplete() {
console.log('加载完成。。。。。')
this.gold10 = this.queue.get('gold10').content;//金币
this.gold20 = this.queue.get('gold20').content;//金币
this.gold50 = this.queue.get('gold50').content;//金币
this.blindBox = this.queue.get('blindBox').content;//盲盒
//删除下载队列的complete事件监听
this.queue.off('complete');
// complete暴露
this.fire('complete');
}
})
第三步:创建一个game.js文件
import Hilo from "hilojs";
import Asset from './Asset'//定义金币红包车参数
import goldContainer from './goldContainer'//随机生成金币红包臭蛋
const setTime = 14//游戏时长单位(s)
let startTime = 0
export default class game {//游戏主模块
constructor(page) {
this.page = page
//设置的游戏时间
this.setGameTime = setTime//设置时间
this.gameTime = 15
this.gameStatus = "start"//游戏状态
// 下载队列
this.asset = new Asset()
// 画布对象
this.stage = null
// 画布信息
this.width = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) * 2
// this.height = innerHeight * 2 < 1334 ? innerHeight * 2 : 1334
this.height = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) * 2
this.scale = 0.5
// 定时器对象
this.ticker = null
//生成金币盲盒
this.Gold = null
//金币生成速度
this.createSpeed = 300
//分数
this.score = 0
//定义一个碰撞的数组
this.crashList = []
//定时器
this.timerAll = null
//倒计时
this.countDown = 0
//盲盒
this.blindBoxNum = 0
}
init() {
this.asset.on('complete', function () {
this.asset.off('complete')
this.initStage()
}.bind(this));
this.asset.load()
}
initStage() {
// console.log(this.width,this.height)
// 舞台
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, 'click', 'mousedown', 'ontouchstart']);
// 启动定时器刷新页面 参数为帧率
this.ticker = new Hilo.Ticker(60)
// 舞台添加到定时队列中
this.ticker.addTick(this.stage)
// 添加动画类到定时队列
this.ticker.addTick(Hilo.Tween);
//启动ticker
this.ticker.start(true);
this.startGame();
}
startGame() { //开始游戏
startTime = new Date().getTime()
this.initGolds();
this.gameTime = this.setGameTime;
this.score = 0;
this.blindBoxNum = 0;
this.crashList = [];
this.gameStatus = "start"
this.calcTime()
}
calcTime() { //游戏时间
this.timerAll = setTimeout(() => {
if (this.gameTime > 0) {
this.gameTime--;
this.calcTime()
} else {
setTimeout(() => {
this.gameOver()
}, 500);
}
}, 1000);
}
clearCalcTime() {
this.Gold.score = [10, 20, 50, 0]
clearTimeout(this.timerAll);
}
gameOver() {//游戏结束调用
if (this.Gold && this.Gold.stopCreateEnemy()) {
this.Gold.stopCreateEnemy()
}
this.gameStatus = "end"
}
initGolds() {//初始化金币红包
this.Gold = new goldContainer({
id: 'background',
height: this.height,
width: this.width,
createSpeed: this.createSpeed,
pointerEnabled: true, // 不关闭事件绑定 无法操作舞台
goldList: [this.asset.gold10, this.asset.gold20, this.asset.gold50, this.asset.blindBox],
startTime
}).addTo(this.stage, 2)
this.Gold.on('click', (e) => {
this.checkedGlod(e)
})
//舞台更新
// this.stage.onUpdate = this.onUpdate.bind(this);
}
checkedGlod(e) {
// console.log(e.eventTarget.type, e.eventTarget)
if (e.eventTarget.type) {
if (e.eventTarget.type == "blindBox") {
this.blindBoxNum = 1
}
this.score += e.eventTarget.score
e.eventTarget.remove()
}
}
// onUpdate() {//舞台更新
// }
}
第四步:创建一个goldBitmap.js文件
import Hilo from "hilojs";
let goldBitmap = Hilo.Class.create({
Extends: Hilo.Bitmap,
tweenChild: null,
constructor: function (properties) {
goldBitmap.superclass.constructor.call(this, properties);
this.tweenChild = Hilo.Tween;
this.onUpdate = this.onUpdate.bind(this);
this.remove = this.remove.bind(this);
},
over() {
this.removeFromParent();
},
checkedAnimation(bol) {
if (bol) {
//Tween.to创建一个缓动动画,让当前可视对象从当前属性(scaleX: .2,scaleY: .2)变换到目标属性(scaleX: 1.4, scaleY: 1.4)
this.tweenChild.to(this,
{ scaleX: 6, scaleY: 6 },
{
duration: 600, //完成这个变换的时长
})
}
},
remove() {
// console.log(this)
this.removeFromParent();
},
onUpdatefn() { },
onUpdate() {
if (this.parent.height < this.y) {
this.removeFromParent();
return
}
}
})
export default goldBitmap
第五步:创建一个goldContainer.js文件
import Hilo from "hilojs";
import goldBitmap from './goldBitmap'
let goldContainer = Hilo.Class.create({
Extends: Hilo.Container,
goldBitmapImg: null,
timer: null, // 定时器
goldList: [],
createSpeed: 0,
score: [10, 20, 50, 0],//分数
ids: ['gold10', 'gold20', 'gold50', 'blindBox'],
gold10Num: [],
gold20Num: [],
gold50Num: [],
tween: null,
startTime: null,
differenceTime: 0,
constructor: function (properties) {
goldContainer.superclass.constructor.call(this, properties);
this.startTime = properties.startTime
this.tween = Hilo.Tween;
this.creatEnemy();
this.beginCreateEnemy();
},
random(lower, upper) {
return Math.floor(Math.random() * (upper - lower + 1)) + lower;
},
creatEnemy() {//最大分数700
// 金币雨持续时间15s,掉落61个,10金币50个,20金币10个,彩蛋1个
let now = new Date().getTime()
let differenceLine = parseInt((now - this.startTime) / this.createSpeed)
let difference = parseInt((now - this.startTime) / 1000)
this.differenceTime = difference
let str = differenceLine + ''
let s = Number(str.substring(str.length - 1))
// console.log(differenceLine, '-', s)
if (differenceLine < 50) {
this.createGold(0, 290)
}
if (differenceLine == 26) {
this.createGold(3, 300)
}
if (s == 4 || s == 8) {
this.createGold(1, 170)
}
},
createGold(index, enemySpeed) {
let hold = undefined
if (this.goldList[index].width && this.goldList[index].height) {//判断报错宽高
hold = new goldBitmap({
image: this.goldList[index],
rect: [0, 0, this.goldList[index].width, this.goldList[index].height],
width: this.goldList[index].width / 2,
height: this.goldList[index].height / 2,
scaleX: 3,//倍数
scaleY: 3,//倍数
}).addTo(this);
hold.type = this.ids[index]
}
//随机掉落
// hold.y = 600 * Math.random();
hold.y = 0;
hold.x = this.random(0, (this.width - this.goldList[index].width));
// console.log('x',hold.x)
hold.score = this.score[index]
this.tween.to(hold, {//运动速度
x: this.random(0, (this.width - this.goldList[index].width - 50)),
y: this.height
}, {
duration: 1400 / enemySpeed * 1000,
loop: false,
onComplete: () => {
hold.removeFromParent()
}
});
},
beginCreateEnemy() {//开始生成
this.timer = setInterval(() => {
this.creatEnemy();
}, this.createSpeed);
},
stopCreateEnemy() {//停止生成并全部移除
if (this.timer) {
clearInterval(this.timer)
this.removeAllChildren()
}
},
checkCollision(enemy) {//碰撞检测
console.log('enemy', 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 goldContainer
到现在所有的js文件已经创建实现完成了
我这个是在vue中实现的代码如下:
index.vue
<template>
<div class="fix">
<div class="start" v-if="isSow">
<start @open="startFn" />
</div>
<div class="hilo" v-else>
<div class="time">
剩余时间:{{ game.gameStatus == "end" ? 0 : gameTime }}s
</div>
<div ref="hilo" class="canvas"></div>
</div>
<Popup v-model="show" :close-on-click-overlay="false">
<div class="result">
<div class="res">
<div class="top">
<div class="jiangli">
<img src="@/assets/images/gold/huodejiangli.png" alt="" />
</div>
</div>
<div class="top1">
<img src="@/assets/images/gold/gonxihuode.png" alt="" />
</div>
<div class="jinbi">
<img src="@/assets/images/gold/jinbi.png" alt="" />
<span>+{{ score || 0 }}</span>
</div>
<div class="saizhi">
<img src="@/assets/images/gold/saizi12.png" alt="" />
<span>+{{ blindBoxNum || 0 }}次</span>
</div>
<div class="bottom">
<Button @click="backHome" type="default" class="back"
><img src="@/assets/images/gold/allow_kxj.png" alt=""
/></Button>
</div>
</div>
</div>
</Popup>
</div>
</template>
<script>
import Game from "./js/game";
import start from "./start";
import { Popup, Button, Toast } from "vant";
export default {
name: "game",
mixins: [],
components: { start, Popup, Button },
data() {
return {
game: new Game(),
isSow: true, //显示开始开始游戏页面
show: false,
};
},
created() {},
computed: {
score() {
//金币分数
return this.game.score;
},
blindBoxNum() {
//盲盒数
return this.game.blindBoxNum;
},
gameTime() {
//游戏时间
return this.game.gameTime;
},
},
watch: {
"game.gameStatus": {
handler(newName) {
if (newName == "end") {
// this.show = true;
this.queryGold({ score: this.score, blindBoxNum: this.blindBoxNum });
}
},
immediate: true,
},
},
mounted() {},
beforeDestroy() {
this.game.gameOver();
},
destroyed() {},
methods: {
queryGold(parems) {
console.log(parems);
this.show = true;
},
startFn() {
this.isSow = false;
let that = this;
this.$nextTick(() => {
that.game.page = this.$refs.hilo;
that.game.init();
});
},
backHome() {
this.show=false
},
},
};
</script>
<style lang="less" scoped>
.fix {
width: 100%;
height: 100vh;
background-color: #0a080b; //1a1511
background-image: url("../../assets/images/gold/gold-background.png");
background-repeat: no-repeat;
background-size: 100% auto;
background-position: bottom center;
.van-button {
border: none;
background: none;
height: auto;
}
.start {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 100;
}
.hilo {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
position: relative;
.canvas {
canvas {
width: 100% !important;
height: 99vh !important;
}
}
.time {
position: absolute;
top: 50px;
width: 100%;
text-align: center;
color: #fdf100;
font-size: 35px;
font-weight: 600;
}
}
.van-popup {
background: none;
width: 90%;
.result {
display: flex;
flex-direction: column;
align-items: center;
.res {
background: #ffff;
width: 100%;
border: 4px solid #d98f2d;
border-radius: 16px;
overflow: hidden;
.top {
display: flex;
align-items: center;
justify-content: center;
.jiangli {
width: 70%;
background-image: url("../../assets/images/gold/background54.png");
background-repeat: no-repeat;
background-size: 100% 100%;
text-align: center;
padding: 7px 0;
img {
width: 50%;
height: auto;
}
}
}
.top1 {
text-align: center;
margin-top: 30px;
img {
width: 30%;
}
}
.jinbi,
.saizhi {
display: flex;
justify-content: center;
align-items: center;
margin-top: 30px;
img {
width: 80px;
height: 80px;
}
span {
font-size: 60px;
font-weight: 600;
color: #d98f2d;
margin-left: 20px;
text-shadow: 0 0 5px black, 0 0 10px black;
}
}
.bottom {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: #fdf100;
padding: 30px 0;
margin-top: 30px;
.back {
text-align: center;
width: 50%;
margin-top: 20px;
img {
width: 100%;
height: auto;
}
}
}
}
}
}
}
</style>
start.vue
<template>
<div class="start">
<div class="content">
<div class="center">
<div class="zi">
<div class="quan">
<img src="@/assets/images/gold/3.png" alt="" v-if="ready == 3" />
<img
src="@/assets/images/gold/2.png"
alt=""
v-else-if="ready == 2"
/>
<img
src="@/assets/images/gold/1.png"
alt=""
v-else-if="ready == 1"
class="zi_1"
/>
<img src="@/assets/images/gold/3.png" alt="" v-else />
</div>
</div>
</div>
<div class="bottom">
<Button
@click="open"
type="default"
class="kaishi"
:disabled="disabled"
>
<img src="@/assets/images/gold/lijikaiqi.png" alt=""
/></Button>
</div>
</div>
</div>
</template>
<script>
// console.log('start',end,endTime)
import { Button, Toast } from "vant";
export default {
name: "start",
components: {
Button,
},
data() {
return {
show: false,
ready: 0,
disabled: false,
};
},
computed: {},
async mounted() {},
created() {
this.ready = 0;
this.disabled = false;
},
methods: {
open() {
this.disabled = true;
this.ready = 3;
let timer = setInterval(() => {
if (this.ready == 1) {
clearInterval(timer);
this.$emit("open");
} else {
this.ready--;
}
}, 1000);
},
closePopup() {
this.show = false;
},
},
};
</script>
<style lang="less" scoped>
.start {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.van-button {
border: none;
background: none;
height: auto;
}
.content {
width: 90%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 90px 0;
.center {
display: flex;
justify-content: center;
padding-top: 80px;
position: relative;
.zi {
position: absolute;
top: 0;
left: 0;
color: #ffff;
width: 100%;
text-align: center;
.quan {
display: inline-block;
width: 260px;
height: 260px;
border: 10px solid #d98f2d;
border-radius: 50%;
position: relative;
box-shadow: -5px 5px 10px -4px #d98f2d, 5px 5px 10px -4px #d98f2d;
img {
width: 130px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
}
img.zi_1 {
width: 70px;
}
}
}
}
.bottom {
display: flex;
flex-direction: column;
align-items: center;
.kaishi,
.back {
text-align: center;
width: 80%;
img {
width: 100%;
height: auto;
}
}
.back {
margin-top: 20px;
}
}
}
}
</style>
这样就算完成了
可查看点击获取金币demo、大富翁demo,源码可查看gitee