管道像素鸟

前言 

本次要制作的游戏 —— 管道小鸟,直接上代码。

 

1、游戏界面

 

<template>
	<!-- 管道小小鸟 -->
	<view class="bird-game" @click="start">
		<view class="bird-box u-rela">
			<u-image src="/static/image/bird/bird-bg.png" width="100%" height="100%" :fade="false"></u-image>
			<view class="bird-map">
				<!-- 分数 -->
				<view class="bird-number">{{number}}</view>
				<!-- 开始游戏 -->
				<view class="bird-start" v-if="!isStart">开始游戏</view>
				<!-- 鸟 -->
				<view class="bird hidden" :class="{'bird-move': !isStart}" :style="{'top':`${bird.top}rpx`, 'left':`${bird.left}rpx`, 'width': `${bird.width}rpx`, 'height': `${bird.height}rpx`}">
					<u-image src="/static/image/bird/bird.gif" mode="widthFix"></u-image>
				</view>
				<!-- 管道 -->
				<view class="bird-pipe" v-for="(item,index) in pipeList" :key="index" :style="{'right':`${item.pRight}rpx`, 'width': `${pipe.width}rpx`}">
					<view class="bird-pipe-top" :style="{'top': `${item.pTop}rpx`}">
						<u-image src="/static/image/bird/pipe_t.png" width="100%" mode="widthFix" :fade="false"></u-image>
					</view>
					<view class="bird-pipe-bottom" :style="{'bottom': `${item.pBottom}rpx`}">
						<u-image src="/static/image/bird/pipe_b.png" width="100%" mode="widthFix" :fade="false"></u-image>
					</view>
				</view>
			</view>
		</view>
		<!-- 地板 -->
		<view class="land">
			<view class="land-1"></view>
			<view class="land-2"></view>
			<view class="land-box" :class="{'land-move': !isEnd}"></view>
			<view class="land-3"></view>
			<view class="land-4"></view>
		</view>
	</view>
</template>

2、游戏样式

<style>
	page{background-color: #DED895;}
</style>
<style lang="scss" scoped>
.bird-game{width: 100%;height: calc(100vh - 88rpx)}
.bird-box{
	width: 100%;height: 64%;background-color: rgb(0,135,147);
	.bird-map{
		position: absolute;width: 100%;height: 100%;top: 0;right: 0;bottom: 0;left: 0;z-index: 2;overflow: hidden;
		.bird{position: absolute;transition: transform .4s;}
		.bird-number{position: absolute;font-size: 70rpx;color: #fff;font-weight: bold;left: 50%;transform: translateX(-50%);top: 60rpx;text-shadow: 8rpx 8rpx 4rpx rgba(0,0,0,1);z-index: 999;}
		.bird-start{position: absolute;font-size: 80rpx;color: rgb(47,227,43);font-weight: bold;left: 50%;transform: translateX(-50%);top: 300rpx;text-shadow: 4rpx 4rpx 4rpx rgba(255,255,255,1);}
		.bird-pipe{
			position: absolute;top: 0;bottom: 0;
			.bird-pipe-bottom,
			.bird-pipe-top{position: absolute;width: 100%;}
		}
	}
}
// 小鸟上下摆动
.bird-move{animation: ani_bird .75s infinite cubic-bezier(0.215, 0.61, 0.355, 1);}
@keyframes ani_bird{
	0%{transform: translateY(0);}
	50%{transform: translateY(-20rpx);}
	100%{transform: translateY(0);}
}
// 地面
.land{
	.land-box{
		width: 100%;height: 40rpx;background: linear-gradient(-45deg, #9BE557 25%, #73BF2E 0%, #73BF2E 50%, #9BE557 0%,#9BE557 75%, #73BF2E 0%,);background-size: 80rpx 80rpx;
		background-position: 250% 0;
	}
	.land-1{width: 100%; height: 4rpx;background-color: #523546;}
	.land-2{width: 100%; height: 4rpx;background-color: #DEF886;}
	.land-3{width: 100%; height: 4rpx;background-color: #558121;}
	.land-4{width: 100%; height: 4rpx;background-color: #E0B24E;}
}
.land-move{animation: ani_land 8.5s linear infinite;}
@keyframes ani_land{
	0%{background-position: 250% 0;}
	100%{background-position: 0 0;}
}
</style>

3、游戏逻辑

<script>
	export default {
		data() {
			return {
				isStart: false,			// 游戏是否开始
				isEnd: false,			// 游戏是否结束
				number: 0,				// 分数
				map:{					// 地图
					width: 0,
					height: 0,
				},
				bird:{					// 小鸟
					width: 70,
					height: 50,
					left: 160,
					top: 600,
					speedStart: 1, 		// 初始速度
					speedPlus: 0.2, 	// 加速度
					speedMax: 10,		// 上限速度
					flyMaxHeight: 100,	// 每点一次飞行的最大高度
					flyStageHeight: 10,	// 飞行的阶梯增加高度
					flyRelaHeight: 0,	// 当前飞行的相对高度,也就是飞行的那个过程,高度是多少,因为有时没到达顶部,玩家又点一次
					flyDirect: null,	// up上升,down下落
				},	
				flyTimer: null,
				pipe:{					// 管道
					width: 90,
					height: 728,
				},
				pipeVerticel: 200,		// 上下管道之间的垂直距离
				pipeDistance: 400,		// 左右管道之间的水平距离
				pipeList: [				// 存放管道数组
					{pRight: -300, pTop: -400, pBottom: -400}
				], 						
				
			};
		},
		onLoad() {
			setTimeout(()=>{
				this.getMapEle();
			},100);
		},
		onUnload() {
			clearInterval(this.flyTimer);
		},
		methods:{
			// 获取地图属性
			getMapEle(){
				this.$u.getRect('.bird-box').then(res => {
					this.map.width = Math.floor(res.width) * 2;
					this.map.height = Math.floor(res.height) * 2;
				})
			},
			// 点击屏幕 游戏开始
			start(){
				if(this.isEnd){
					uni.showToast({title: "游戏已结束",icon:'error'});
					return;
				}
				if(this.flyTimer){
					clearInterval(this.flyTimer);
					this.flyTimer = null;
				}
				this.isStart = true;
				this.bird.flyDirect = 'up';
				this.flyTimer = setInterval(()=>{
					this.birdFly();
					this.pipeMove();
				},20)
			},
			// 小鸟运动
			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();
				}
			},
			// 管道移动 添加删除管道
			pipeMove(){
				// 如果数组中的最后一个到达右边的时候,增加一个
				if(this.pipeList[this.pipeList.length - 1].pRight >= 0){
					// 因为固定了上下管道距离,所以我们只要随机上下其中一个管道的距离值,再用整体高度-上下管道的距离-随机距离 = 另外一个管道的距离
					let pipeRandom = this.$u.random(100, 600);
					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;
						}
					}
					// 判断分数,也就是刚好飞过某一个管道
					if(this.pipeList[i].pRight === 592){
						this.number++;
					}
					this.pipeList[i].pRight += 4;
				}
			},
			// 死亡
			die(){
				clearInterval(this.flyTimer)
				this.isEnd = true;
				uni.showModal({
					content: "你死了",
					showCancel: false,
					success: res=>{
						if (res.confirm) {
							this.reset();
						}
					}
				});
			},
			// 重新开始
			reset(){
				uni.redirectTo({
					url: '/pages/games/bird'
				})
			},
		}
	}
</script>

 

posted @ 2021-12-27 16:25  007的张大炮  阅读(189)  评论(0编辑  收藏  举报