接物游戏demo:
接物元素设置了不同分值
指定时间内,接到元素则加分,接到炸弹则减分,计时结束,游戏停止
demo代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=750, user-scalable=no">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<meta name="apple-mobile-web-app-title" content="">
<title>接物demo</title>
<style>
@charset "utf-8";
*{ margin:0px; padding:0px; box-sizing:border-box; -webkit-tap-highlight-color:rgba(0,0,0,0); tap-highlight-color:rgba(0,0,0,0); cursor:pointer;}
html{ max-width:750px; margin:0 auto;}
body{ font-family:"PingFangSC-Regular","STHeitiSC-Light","微软雅黑","Microsoft YaHei","sans-serif"; font-size:28px; line-height:1.6; color:#333;
-webkit-user-select:none; user-select:none;
-webkit-touch-callout:none; touch-callout:none;
}
li{ list-style:none;}
i{ font-style:normal;}
[v-cloak]{ display: none;}
html, body{ height:100%; background-color: #fff; position:relative; overflow: hidden;}
.page{ width:100%; height:100%; position:absolute; left:0; top:0; overflow: hidden;}
.page.game{ background-color: skyblue; overflow-y: auto; -webkit-overflow-scrolling: touch;}
.game_body{}
.show_time{ width: 100%; padding: 20px; text-align: center; position: absolute; left: 0; top: 0;}
.show_time span{ margin: 0 10px;}
.show_time span i{ margin: 0 5px; color: palevioletred; font-size: 32px; font-weight: bold;}
#imgShowList{ width: 100%; height: 100vh; position: relative; overflow: hidden;}
.basket{ width: 100%; position: fixed; left: 0; top: 1100px;}
#gameBtn{ width: 200px; height: 80px; position: absolute; left: 0; top: 0;}
.game_start_btn{ padding: 0 15px; height: 60px; line-height: 60px; border-radius: 30px 0 0 30px; background-color: pink; position: absolute; right: 0; top: 60vh;}
</style>
</head>
<body>
<section id="app" v-cloak>
<div class="page game">
<div class="game_body">
<!-- 坠落图片展示区 -->
<div id="imgShowList">
<!-- <img v-if="item.imgY < gameBtnTop" v-for="item in gameImgList" :style="'width:' + item.imgW + 'px;left:' + item.imgX + 'px;'" :src="item.img" /> -->
<img-down v-on:set_score="addScore" :countdown_time="countdownTime" :game_btn_height="gameBtnHeight" :game_btn_width="gameBtnWidth" :game_btn_top="gameBtnTop" :game_btn_left="gameLeftNum" :down_img="item" v-for="item in gameImgList"></img-down>
</div>
<!-- 接物篮子 -->
<div class="basket">
<img id="gameBtn" src="btn.png" >
</div>
<div v-if="!inGame" @click="gameStart" class="game_start_btn">开始游戏</div>
<div class="show_time"><span>剩余<i>{{countdownTime}}</i>s</span> | <span>得分<i>{{currScore}}</i></span></div>
</div>
</div>
</section>
<template id="imgDownTemp">
<div v-if="showTemp" :style="'text-align: center;position:absolute;width:' + down_img.imgW + 'px;left:' + down_img.imgX + 'px;top:' + imgY + 'px'">
<p v-if="showScore" style="width: 100%;position: absolute;left: 0;bottom: -100%;">{{down_img.score > 0 ? '+' + down_img.score : down_img.score}}</p>
<img v-else :src="down_img.img" style="width: 100%;position: absolute;left: 0;bottom: -100%;" />
</div>
</template>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.7.14/vue.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/howler/2.2.4/howler.min.js"></script>
<script type="text/javascript">
var soundYes = new Howl({
src: ['game/yes.mp3']
});
var soundNo = new Howl({
src: ['game/no.mp3']
});
</script>
<script type="text/javascript">
Vue.component('img-down', {
data: function () {
return {
showTemp:true, // 坠落图片Y轴超过区域时不再显示
imgY:0, // 坠落图片Y轴
showScore:false, // 坠落图片被“接住”时,展示加分或减分分值
setpNum:1, // 坠落图片Y轴偏移量
timer:null,
timeStep:null, // 定时器执行时长(毫秒)
// 定时器执行时长(坠落速度快、中、慢)(毫秒)
timeStepData:{
timeFast:5,
timeslow:8,
timeslowest:10,
}
}
},
props:['countdown_time','game_btn_height','game_btn_width','game_btn_top','game_btn_left','down_img'],
template: '#imgDownTemp',
mounted() {
// 坠落图片Y轴偏移量根据随机数值设置,以此影响不同的坠落速度效果
if(Math.random()*10 > 5){
this.setpNum = 2;
}
// 计时到20秒、10秒时,坠落速度不同程度加快
if(this.countdown_time <= 10){
this.timeStep = this.timeStepData['timeFast'];
}else if(this.countdown_time <= 20){
this.timeStep = this.timeStepData['timeslow'];
}else{
if(this.setpNum == 1){
this.timeStep = this.timeStepData['timeslow'];
}else{
this.timeStep = this.timeStepData['timeslowest'];
}
}
this.timer = setInterval(this.imgShowDown,this.timeStep);
},
methods:{
imgShowDown(){
// 计时结束-游戏结束
if(this.countdown_time <= 0){
clearInterval(this.timer);
}
this.imgY+=this.setpNum;
// 坠落图片到达接物篮子Y轴位置
if(this.imgY > this.game_btn_top){
// clearInterval(this.timer);
// 接到了
if((this.down_img.imgX + this.down_img.imgW) > this.game_btn_left && this.down_img.imgX < (this.game_btn_width + this.game_btn_left)){
this.$emit('set_score',this.down_img.score);
this.showScore = true;
clearInterval(this.timer);
setTimeout(()=>{
this.showTemp = false;
},100)
if(this.down_img.score > 0){
soundYes.play();
}else{
soundNo.play();
}
}else{
// this.showTemp = false;
}
}
//
if(this.imgY > (this.game_btn_top + this.game_btn_height)){
clearInterval(this.timer);
this.showTemp = false;
}
}
}
})
document.oncontextmenu = function(e){
e.preventDefault();
}
var VM = new Vue({
el:"#app",
data:{
winW:0, // 页面宽度
gameBtn:'', // 接物篮子
gameBtnHeight:0, // 接物篮子高度
gameBtnWidth:0, // 接物篮子宽度
gameBtnWidthHalf:0, // 接物篮子宽度一半
gameBtnMaxLeft:0, // 接物篮子最大left值
gameBtnTop:0, // 接物篮子对顶部距离
gameLeftNum:0, // 接物篮子left值
inGame:false, // 是否游戏进行中
currScore:0, // 当前得分
countdownTiming:0,
countdownTimeDefault:30, // 初始化倒计时时间(秒)
countdownTime:0,
gameImgW:60, // 坠落图片宽
gameImgMaxLeft:0, // 坠落图片的最大left值
gameImgList:[], // 坠落图片-最终展示的列表数据
// 坠落图片-原始配置数据(图片及对应分值),游戏时从中随机取一个追加至gameImgList中
gameImgData:[
{
img:'game/1.png',
score:1,
},
{
img:'game/2.png',
score:2,
},
{
img:'game/3.png',
score:3,
},
{
img:'game/4.png',
score:4,
},
{
img:'game/5.png',
score:5,
},
{
img:'game/6.png',
score:-5,
},
{
img:'game/6.png',
score:-5,
},
],
},
created() {
},
mounted() {
this.initParameter();
},
watch: {
},
methods:{
// 游戏参数初始化数据
initParameter(){
this.winW = document.documentElement.offsetWidth || document.body.offsetWidth;
this.gameBtn = document.getElementById('gameBtn');
this.gameBtnHeight = this.gameBtn.offsetHeight;
this.gameBtnWidth = this.gameBtn.offsetWidth;
this.gameBtnWidthHalf = this.gameBtnWidth / 2;
this.gameBtnMaxLeft = this.winW - this.gameBtnWidthHalf * 2;
this.gameBtnTop = document.getElementsByClassName('basket')[0].offsetTop;
this.gameImgMaxLeft = this.winW - this.gameImgW;
this.gameBtn.style.left = (this.winW / 2 - this.gameBtnWidthHalf) + 'px';
},
// 拖动接物篮子
touchmove(e){
e.preventDefault();
this.gameLeftNum = e.touches[0].pageX - this.gameBtnWidthHalf;
this.gameLeftNum = this.gameLeftNum < 0 ? 0 : this.gameLeftNum > this.gameBtnMaxLeft ? this.gameBtnMaxLeft : Math.floor(this.gameLeftNum);
this.gameBtn.style.left = this.gameLeftNum + 'px';
// console.log(this.gameLeftNum , this.gameBtn.offsetLeft)
},
// 开始游戏,计时等设置
startGame(){
this.inGame = true;
this.currScore = 0;
this.currScoreData = [];
this.gameImgList = [];
this.gameBtn.addEventListener('touchmove',this.touchmove,false);
this.gameBtn.style.left = (this.winW / 2 - this.gameBtnWidthHalf) + 'px';
this.countdownTiming = 0;
this.countdownTime = this.countdownTimeDefault;
this.changeTime();
},
// 计时
// timing , rafId;
changeTime(k){
// console.log(k);
if(!this.timing && k){
this.timing = k
}
// 1秒执行60次
this.rafId = requestAnimationFrame(this.changeTime);
// 倒计时计算
this.countdownTiming++;
// 1秒(1000ms)执行一次
if(this.countdownTiming % 60 == 0){
this.countdownTime-= 1;
}
if(this.countdownTime <= 0){
this.gameEnd();
cancelAnimationFrame(this.rafId);
}
// 动态添加坠落图片(时间越短,添加的坠落图片越多)
if(this.countdownTiming % 40 == 0){
this.setImgToPage();
}
},
// 动态添加坠落图片
setImgToPage(){
let randomKey = Math.floor(Math.random() * this.gameImgData.length);
let imgX = Math.floor(Math.random() * this.gameImgMaxLeft);
this.gameImgList.push({imgX,imgY:0,imgW:this.gameImgW,...this.gameImgData[randomKey]})
},
// 加分减分统计
addScore(score){
this.currScore += score;
this.currScoreData.push(score);
},
///
// 开始游戏
gameStart(){
this.startGame();
},
// 计时结束-游戏结束
gameEnd(){
console.log(this.currScoreData);
this.inGame = false;
this.gameBtn.removeEventListener('touchmove',this.touchmove,false);
},
}
})
</script>
</body>
</html>