用Vue实现打地鼠!!!
一、目标实现效果:
-
要求:
-
难度选择,不同难度地鼠不一样大
-
点中地鼠后,随机位置,地鼠位置不能超出游戏界面。
-
游戏重新开始的按钮
-
计时器功能,时间停止,弹窗得分情况。
-
二、分析实现
Vue讲求数据为王,我们只需要更改数据,dom操作Vue内部会帮助我们实现!
分析题目,我们可以把效果分为地鼠移动,难度选择,点击加分,重新开始,倒计时五个部分来实现
-
地鼠移动
-
想要一个东西动态起来,实际上就是在一定时间内不断更改它的位置
-
更改位置:position(数据)
-
时间:定时器
-
//数据position new Vue({ el: '#app', data() { return { //数据position // 位置初始值 position: { top: '0px', left: '0px' }, timerId:null } }, //页面加载函数 created() { // 速度和难度绑定,可以不用初始值 this.autoChange(); }, // 函数区 methods: { // 定时器更改位置(清除与再生) autoChange() { // 清除定时器 clearInterval(this.timerId); this.timerId = setInterval() }, // 改变位置(封装成一个函数,功能更加明显,可以复用) changePos() { // 随机生成位置,范围应该在0~(父级-自身) // 宽高必须固定 const x = Math.random() * (1200 - size); const y = Math.random() * (600 - size); this.position = { top: y + 'px', left: x + 'px' } } } })
-
-
难度选择
-
为了可以动态的增添难度选项,可以采用v-for的模式
-
难度与地鼠的大小绑定(即不同的难度,地鼠的配置不同),可以把地鼠配置数据单独封装起来,可以不断添加想要的效果(例如不同的速度)
-
地鼠难度与大小要设置初始值
new Vue({ el: '#app', data() { return { // 难度 curLevel: 'easy', // 位置初始值 position: { top: '0px', left: '0px' }, // 大小初始值 mouseSize: { width: '80px', height: '80px' }, options: [ { label: "简单", value: 'easy' }, { label: "中等", value: 'middle' }, { label: "困难", value: 'hard' } ], // 把每个难度存起来(游戏配置) levelOpts: { easy: { size: 80, speed: 2 * 1000 }, middle: { size: 60, speed: 1.5 * 1000 }, hard: { size: 40, speed: 1 * 1000 } }, timerId:null } }, created() { // 速度和难度绑定,可以不用初始值 this.autoChange(this.levelOpts[this.curLevel].speed); }, // 函数区 methods: { // 定时器更改位置(清除与再生) autoChange(speed) { // 清除定时器 clearInterval(this.timerId); this.timerId = setInterval(this.changePos, speed) }, // 改变位置(封装成一个函数,功能更加明显,可以复用) changePos() { const { size } = this.levelOpts[this.curLevel]; // 随机生成位置,范围应该在0~(父级-自身) // 宽高必须固定 const x = Math.random() * (1200 - size); const y = Math.random() * (600 - size); this.position = { top: y + 'px', left: x + 'px' } }, // 难度选择 levelChange(e) { // e.target.value拿到选中值 this.curLevel = e.target.value; // 解构赋值 const { size, speed } = this.levelOpts[this.curLevel]; this.mouseSize = { width: size + 'px', height: size + 'px' } //难度选择完后,要重启定时器 this.autoChange(speed); } } })
<select @change="levelChange"> <option v-for="option in options" :key="option.value" :value="option.value"> {{option.label}} </option> </select>
-
-
点击加分
给地鼠设置点击事件
hit() { this.score++; // 点击后,马上更换位置!! this.changePos(); },
-
重新开始
全部恢复初始设置
// 重新开始 replay() { // 重置数据 this.curLevel = 'easy'; // 解构赋值 const { size, speed } = this.levelOpts[this.curLevel]; this.mouseSize = { width: size + 'px', height: size + 'px' } this.autoChange(speed); this.countDown(); },
-
倒计时
// 倒计时 countDown() { this.score = 0; this.show = false; this.time = 6; clearInterval(this.timerCount); this.timerCount = setInterval(() => { if (this.time == 0) { clearInterval(this.timerCount); this.show = true; } else { this.time--; } }, 1000) }
三、完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./utils/vue.js"></script>
<style>
.container {
width: 100%;
}
.container .content {
width: 1200px;
border: 1px solid black;
margin: auto;
}
.container .content .game-panel {
width: 100%;
display: flex;
justify-content: space-between;
background-color: rgb(199, 197, 197);
padding: 10px 20px;
box-sizing: border-box;
}
.container .content .game-panel .right {
display: flex;
gap: 10px;
}
.container .content .game-panel .left {
display: flex;
gap: 10px;
}
.container .content .main {
background-color: aqua;
width: 100%;
height: 600px;
position: relative;
}
.container .content .main .mouse {
background-color: red;
position: absolute;
top: 0;
left: 0;
width: 80px;
height: 80px;
}
.container .alert {
width: 200px;
height: 100px;
position: fixed;
top: 200px;
left: 50%;
transform: translate(-50%);
text-align: center;
line-height: 100px;
background-color: hwb(0 78% 21%);
border: 1px solid hwb(0 78% 21%);
box-shadow: 0px 0px 15px hwb(0 78% 21%);
}
</style>
</head>
<body>
<div class="container" id="app">
<div class="content">
<div class="game-panel">
<div class="left">
<span>难度:</span>
<select @change="levelChange">
<option v-for="option in options" :key="option.value" :value="option.value">
{{option.label}}
</option>
</select>
<span>倒计时:{{time}}</span>
</div>
<div class="right">
<button @click="replay">重新开始</button>
<span>分数: {{score}}</span>
</div>
</div>
<div class="main">
<div class="mouse" :style="[position,mouseSize]" @click="hit"></div>
</div>
</div>
<div class="alert" v-show="show==true">
<div>你的得分为:{{score}}分</div>
</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data() {
return {
// 分数
score: 0,
// 难度
curLevel: 'easy',
// 倒计时
time: 6,
// 位置初始值
position: {
top: '0px',
left: '0px'
},
// 大小初始值
mouseSize: {
width: '80px',
height: '80px'
},
options: [
{ label: "简单", value: 'easy' },
{ label: "中等", value: 'middle' },
{ label: "困难", value: 'hard' }
],
// 把每个难度存起来(游戏配置)
levelOpts: {
easy: {
size: 80,
speed: 2 * 1000
},
middle: {
size: 60,
speed: 1.5 * 1000
},
hard: {
size: 40,
speed: 1 * 1000
}
},
timerId: null,
timerCount: null,
// 弹窗显示
show: false
}
},
created() {
// 速度和难度绑定,可以不用初始值
this.autoChange(this.levelOpts[this.curLevel].speed);
this.countDown();
},
// 函数区
methods: {
// 定时器更改位置(清除与再生)
autoChange(speed) {
// 清除定时器
clearInterval(this.timerId);
this.timerId = setInterval(this.changePos, speed)
},
// 改变位置(封装成一个函数,功能更加明显,可以复用)
changePos() {
const { size } = this.levelOpts[this.curLevel];
// 随机生成位置,范围应该在0~(父级-自身)
// 宽高必须固定
const x = Math.random() * (1200 - size);
const y = Math.random() * (600 - size);
this.position = {
top: y + 'px',
left: x + 'px'
}
},
hit() {
this.score++;
// 点击后,马上更换位置
this.changePos();
},
// 难度选择
levelChange(e) {
// e.target.value拿到选中值
this.curLevel = e.target.value;
// 解构赋值
const { size, speed } = this.levelOpts[this.curLevel];
this.mouseSize = {
width: size + 'px',
height: size + 'px'
}
this.autoChange(speed);
this.countDown();
},
// 重新开始
replay() {
// 重置数据
this.curLevel = 'easy';
// 解构赋值
const { size, speed } = this.levelOpts[this.curLevel];
this.mouseSize = {
width: size + 'px',
height: size + 'px'
}
this.autoChange(speed);
this.countDown();
},
// 倒计时
countDown() {
this.score = 0;
this.show = false;
this.time = 6;
clearInterval(this.timerCount);
this.timerCount = setInterval(() => {
if (this.time == 0) {
clearInterval(this.timerCount);
this.show = true;
} else {
this.time--;
}
}, 1000)
}
}
})
</script>
</html>
四、结尾
以上为简易版打地鼠游戏,通过拆分步骤,分别实现。大家有任何其他想法,欢迎讨论!!