摸鱼写游戏 之 《管道自由鸟》

前言

管道小鸟是一款比较经典的小游戏,基本操作就是用户点击屏幕让小鸟蹦跶,然后穿过一个一个下水管道,每穿过一个,则会增加指定分数,越往后速度越快。好玩是好玩,就是有点费手。
下面就开始游戏编写。

注: 游戏里数值都是固定的,比如鸟的大小,管道的距离,以及他们上下左右距离,是为了方便进行距离与距离之间的计算。比如计算鸟是否撞到顶部、撞到地板、撞到管道等。
又因为此游戏之前使用uniapp写的,uniapp用的是rpx,我也全部换成了px,导致部分一些数值计算的误差,喜欢的可在文章尾部取完整代码,自行调整。

摸鱼写游戏 之 《管道自由鸟》

一、基本布局

整体可以分为,背景、分数、开始游戏按钮、小鸟、管道、地板、地板彩带

<div class="bird-game">
	<div class="bird-box">
		<img src="img/bird-bg.png" class="bg" />
		<div class="bird-map">
			<!-- 分数 -->
			<div class="bird-number">{{ number }}</div>
			<!-- 开始游戏 -->
			<div class="bird-start" v-if="!isStart">开始游戏</div>
			<!-- 鸟 -->
			<div 
				class="bird hidden" 
				:class="{'bird-move': !isStart}" 
				:style="{'top': bird.top + 'px', 'left': bird.left + 'px'}"
			>
				<img src="img/bird.gif" mode="widthFix" />
			</div>
			<!-- 管道 -->
			<div class="bird-pipe" v-for="(item,index) in pipeList" :key="index" :style="{'right': item.pRight + 'px', 'width': pipe.width+'px'}">
				<div class="bird-pipe-top" :style="{'top': item.pTop +'px'}">
					<img src="img/pipe_t.png" width="100%" mode="widthFix" />
				</div>
				<div class="bird-pipe-bottom" :style="{'bottom': item.pBottom + 'px'}">
					<img src="img/pipe_b.png" width="100%" mode="widthFix" />
				</div>
			</div>
		</div>
	</div>
	<!-- 地板 -->
	<div class="bird-land">
		<div class="land-1"></div>
		<div class="land-2"></div>
		<div class="land-box land-move"></div>
		<div class="land-3"></div>
		<div class="land-4"></div>
	</div>
</div>

如何让管道从右向左移动,看起来鸟像往前飞的感觉。这里就用到强大的css
首先需要画一个彩带

.land-box {
	width: 100%;
	height: 20px;
	background: linear-gradient(-45deg, #9BE557 25%, #73BF2E 0%, #73BF2E 50%, #9BE557 0%, #9BE557 75%, #73BF2E 0%);
	background-size: 40px 40px;
	background-position: 250% 0;
}

然后加上animation即可

.land-move { 
	animation: ani_land 8.5s linear infinite; 
}
@keyframes ani_land {
	0% {background-position: 250% 0;}
	100% {background-position: 0 0;}
}

二、游戏实现

(1)需要的配置参数

isStart: false,						// 游戏是否开始
isEnd: false,						// 游戏是否结束
number: 0,							// 分数
map:{	width: 438, height: 600 },	// 地图
bird:{								// 小鸟
	width: 34,
	height: 24,
	left: 80,
	top: 300,
	speedStart: 1, 				// 初始速度
	speedPlus: 0.03, 			// 加速度
	speedMax: 4,				// 上限速度
	flyMaxHeight: 50,			// 每点一次飞行的最大高度
	flyStageHeight: 5,			// 飞行的阶梯增加高度
	flyRelaHeight: 0,			// 当前飞行的相对高度,也就是飞行的那个过程,高度是多少,因为有时没到达顶部,玩家又点一次
	flyDirect: null,			// up上升,down下落
},	
flyTimer: null,
pipe:{							// 管道
	width: 45,
	height: 364,
},
pipeVerticel: 100,				// 上下管道之间的垂直距离
pipeDistance: 200,				// 左右管道之间的水平距离
pipeList: [						// 存放管道数组,默认先产生一个
	{ pRight: -150, pTop: -200, pBottom: -200 }
], 	

(2)监听用户点击空格(用来开始游戏,起飞小鸟)

document.addEventListener('keydown', (e) => {
	if(e.keyCode == 32) {
		this.start()
	}
})

(3)游戏开始

start(){
	if(this.isEnd){
		console.log('游戏已结束');
		return;
	}
	if(this.flyTimer){
		clearInterval(this.flyTimer);
		this.flyTimer = null;
	}
	this.isStart = true;
	this.bird.flyDirect = 'up';
	this.flyTimer = setInterval(()=>{
		this.birdFly();
		this.pipeMove();
	}, 10)
},

(4)小鸟运动

当我们每次点击空格的时候,小鸟都会向上运动,升到指定最高处,然后自由落体。
我们每次点击空格,其实就是改变小鸟的方向

birdFly(){
	// 上升
	if(this.bird.flyDirect == 'up'){
		if(this.bird.flyRelaHeight <= this.bird.flyMaxHeight){
			this.bird.top -= this.bird.flyStageHeight;
			this.bird.flyRelaHeight += this.bird.flyStageHeight;
		}else{
			this.bird.flyDirect = 'down';
			this.bird.flyRelaHeight = 0;
			this.bird.speedStart = 1;
		}
	}
	// 到达顶部
	if(this.bird.top <= 0){
		this.bird.top = 0;
		this.die();
	}
	// 下降
	if(this.bird.flyDirect == 'down'){
		this.bird.top = this.bird.top + this.bird.speedStart * this.bird.speedStart;
		if(this.bird.speedStart < this.bird.speedMax){
			this.bird.speedStart += this.bird.speedPlus;
		}
	}
	// 到达底边
	if(this.bird.top >= this.map.height - this.bird.height){
		this.bird.top = this.map.height - this.bird.height;
		this.die();
	}
}

小鸟上升是个减速运动,越来越慢,直到速度为0。然后再根据加速度,越来越快的加速下落。
而我们如果点击过快,小鸟一直上升,就可能会碰到顶部。
如果松手,就会一直下落,撞地板,都会游戏结束。

(5)管道移动

为啥需要让管道移动呢,其实这个游戏看起来是小鸟一直往前飞,其实小鸟的左右距离是固定不动的,只能上下移动,而真正的移动,是管道加上地板动画,让游戏看起来是一直向前的。所以这里我们就开始生成管道,然后让管道由右向左移动。

摸鱼写游戏 之 《管道自由鸟》

鸟的宽高是固定的,每个管道的高度是固定的,管道与管道之间上下左右的距离也都是能拿到的。
所以做的过程中我们只要多注意鸟与周围管道直接的距离把控,即可

// 管道移动 添加删除管道
pipeMove(){
	// 如果数组中的最后一个到达右边的时候,增加一个
	if(this.pipeList[this.pipeList.length - 1].pRight >= 0){
		// 因为固定了上下管道距离,所以我们只要随机上下其中一个管道的距离值,再用整体高度-上下管道的距离 - 随机距离 = 另外一个管道的距离
		let pipeRandom = this.random(50, 300);
		let obj = {
			pRight: -(this.pipeList[this.pipeList.length - 1].pRight*1 + this.pipeDistance*1),
			pTop: -pipeRandom,
			pBottom: -(this.map.height*1 - pipeRandom*1 - this.pipeVerticel*1),
		};
		this.pipeList.push(obj);
	}
	// 如果第一个到达左边的时候,删除第一个
	if(this.pipeList[0].pRight >= this.map.width){
		this.pipeList.shift();
	}
	// 遍历管道移动
	for(let i = 0; i < this.pipeList.length; i++){
		let birdMouthRight = this.map.width - this.bird.width - this.bird.left;	// 鸟嘴到右边的距离
		// 判断是否碰撞管道 (注意:已经飞过的管道需要去除)
		// 当没有飞过当前的管道
		if(this.pipeList[i].pRight <= this.map.width - this.bird.left){
			// 有咩有撞到上管道
			if(
				(this.pipeList[i].pRight + this.pipe.width) >= birdMouthRight && 
				(this.pipe.height + this.pipeList[i].pTop) >= this.bird.top
			){
				this.die();
				return;
			}
			// 有咩有撞到下管道
			if(
				(this.pipeList[i].pRight + this.pipe.width) >= birdMouthRight && 
				(this.pipe.height + this.pipeList[i].pBottom) >= (this.map.height - this.bird.height - this.bird.top)
			){
				this.die();
				return;
			}
		}
		// 判断分数,也就是刚好飞过某一个管道
		console.log(this.pipeList[i].pRight);
		const pRight = Math.floor(this.pipeList[i].pRight);
		// 这个固定的数值不准确,
		// 需要进行固定管道的右侧移动距离,使所有每次飞过的管道的pRight值都相等即可
		if(pRight === 358){
			this.number++;
		}
		this.pipeList[i].pRight += 1.2;
	}
}

(6)游戏结束

die(){
	clearInterval(this.flyTimer)
	this.isEnd = true;
	console.log('你死了');
},

三、总结

游戏整体不算难,但是注意的细节还是比较多的,尤其是对数值的计算。其中小鸟的上升与下降,还是不丝滑,此地方可优化,让鸟缓慢上升与重力下降。还有鸟的运动抬头与俯冲,都可以根据上升下降来进行调整。总的来说,游戏还是比较有瑕疵的,因为每个地方都是以前自己慢慢琢磨出来的,自我感觉还是良好的。
游戏吗,就是不断的摸索和优化。
最后附上完整代码

大炮 – gitee – 管道小鸟

喜欢游戏的还可以看看我的其他游戏文章:

摸鱼写游戏 之《俄罗斯冰块》

摸鱼写游戏 之 《数字华容道》

摸鱼写游戏 之 《扫个锤子雷》

摸鱼写游戏 之 《疯狂斗兽棋》

摸鱼写游戏 之 《AI五子棋》

摸鱼写游戏 之 《丛林贪吃蛇》

原文链接:https://juejin.cn/post/7218163893915189306 作者:大炮前端事务所

(0)
上一篇 2023年4月5日 下午4:47
下一篇 2023年4月5日 下午4:58

相关推荐

发表回复

登录后才能评论