这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~接下来的几篇都是uni-app的小实战,有助于我们更好的去学习uni-app~ 这是一个系列文章,有兴趣的小伙伴点个赞,点个收藏,关注一下吧~
主页: oliver尹的主页
格言: 跌倒了爬起来就好~
准备篇:https://oliver.blog.csdn.net/article/details/127185461
启动页实现:https://oliver.blog.csdn.net/article/details/127217681
敌机模型实现:https://oliver.blog.csdn.net/article/details/127332264
requestAnimationFrame详解:https://oliver.blog.csdn.net/article/details/127377916

《uni-app》一个非canvas的飞机对战小游戏实现-我方飞机实现

  • 一. 前言
  • 二. 阅读对象与难度
  • 三. 项目地址以及最终效果
  • 四. 我方飞机模型的实现
    • 4.1 分析分析
    • 4.2 我方飞机的样式
    • 4.3 我方飞机生成的实现
    • 4.4 我方飞机坐标的实现
    • 4.5 我方飞机的操控与位移
      • 4.5.1 初始化操作事件
      • 4.5.2 位移函数
  • 五. 阶段性展示
  • 六. 小结

一. 前言

上一篇中主要分享的是 位移这个功能的实现,简单的说就是通过 requestAnimationFrame 这个window对象上提供的原生能力,将坐标改变这个过程与屏幕帧率吻合实现了动画化,这种动画化的效果不管是从性能上,还是从动画的流畅度上都远好于 setTimeoutsetInterval,当然也包括本文中提到的我方飞机,其实现过程也是依靠 requestAnimationFrame 实现的位移;
本文主要分享的内容为我方飞机的实现,耐心看完,或许你会所有收获~

二. 阅读对象与难度

本文难度属于:中级本文中主要实现的我方飞机模型相关的操作,包括我方飞机坐标 位置初始化爆炸动画飞机位移等等,通过文本你可以大致了解到一下内容

  • Vue中的基础知识,包括v-for等常规用法;
  • 我方飞机的操控;
  • requestAnimationFrame 等等

具体内容可以参考以下的思维导图:

三. 项目地址以及最终效果

文本代码已上传CSDN上的gitCode,有兴趣的小伙伴可以直接clone,项目地址:https://gitcode.net/zy21131437/planegameuni
如果有小伙伴愿意点个星,那就非常感谢了~最终效果图如下:

四. 我方飞机模型的实现

4.1 分析分析

根据上面的效果图,我们先分析一下要实现的功能:

  1. 首先要实现的就是我方飞机的样式,当然也包括我方飞机被摧毁时的动画;
  2. 我方飞机初始化时候的坐标;
  3. 由于我们这个阶段是仅仅在web网页上进行控制的,因此,在操控上实现的是传统网页游戏那种WASD来控制我方飞机的上下左右移动;

大致上这三个功能在本文这个阶段是最主要的,再来估计一下如果要实现这几个功能可能要用到什么实现逻辑
第一个,我方飞机样式
飞机样式,这一块其实包含两部分:

  • 第一部分,我方飞机,其实就是DOM元素,加上背景图,这一点应该是毋庸置疑的;
  • 第二部分,爆炸动画,当敌机撞到我们控制的飞机时,我方飞机会被摧毁,被摧毁时会有一个爆炸的效果动画,既然是动画那肯定是老传统了,通过 CSS3animation 实现;

第二个,出生坐标
既然是坐标,那坐标肯定是有x和y的,从效果上看,我方飞机处于的位置在于屏幕的下方且处于中间位置;
第三个,位移
重头戏来了,通过之前我们知道移动是靠的 requestAnimationFrame 实现的,那操控呢,就是就是键盘事件,当按下指定的按键后,触发对应的控制位移的方法,这样就实现了对应方向的位移;

4.2 我方飞机的样式

先来看看我放飞机的样式,它的的素材图如下:

可能看到这会有一点点疑惑,不对啊,怎么是这种图片,我们其实可以这么理解,先看一个示意图

正常情况下,默认显示最左边的我方飞机素材图,也就是 正常状态下的飞机,当这个飞机模型接收到被摧毁的信号时,触发爆炸动画,此时的我方飞机模型只需要通过 animation 将右侧隐藏的图片分步显示出来,形成一个动画,具体完整代码如下:

<template><view class="plane" :class="getClass"></view>
</template><script>
export default {props: {data: {type: Object,default: () => {return {};}},},computed: {getClass() {const classStyle = [`plane`];const explosion = {};explosion[`plane_animate`] = this.isExplosion;classStyle.push(explosion);return classStyle;}},
};
</script>
<style scoped lang="scss">
.plane {position: fixed;width: 98px;height: 122px;z-index: 3;background: url(@/static/images/plane.png) no-repeat left top;
}.plane_animate {animation: plane_animate 0.5s steps(5) both infinite;-webkit-animation: plane_animate 0.5s steps(5) both infinite;
}/* 飞机-爆炸效果 */
@keyframes plane_animate {0% {background-position: 0 0;}100% {background-position: -490px 0;}
}@-webkit-keyframes plane_animate {0% {background-position: 0 0;}100% {background-position: -490px 0;}
}
</style>

完整代码差不多就是如上,我们分布看一下,首先是template

<template><view :class="getClass"></view>
</template>

template部分非常简洁,通过一个名为getClass的计算属性获取完整的类名数组,我们细看一下这个计算属性

getClass() {const classStyle = [`plane`];const explosion = {};explosion[`plane_animate`] = this.isExplosion;classStyle.push(explosion);return classStyle;
}

通这个属性中可以看到,最终返回出去的是一个数组,数组一共有两项,第一项是一个字符串,第二项是一个对象,举个例子吧,假设this.data.type的值是1,那么这个计算属性最终返回的结果是这个

["plane",{"plane_animate":this.data.isExplosion}]

我们放到css中去看一下,这个两个对应的样式

.plane {position: fixed;width: 98px;height: 122px;z-index: 3;background: url(@/static/images/plane.png) no-repeat left top;
}

标准DOM样式,宽,高,背景图等等,很明显这一个用于设定DOM基本属性的,另外一个

.plane_animate {animation: plane_animate 0.5s steps(5) both infinite;-webkit-animation: plane_animate 0.5s steps(5) both infinite;
}/* 飞机-爆炸效果 */
@keyframes plane_animate {0% {background-position: 0 0;}100% {background-position: -490px 0;}
}@-webkit-keyframes plane_animate {0% {background-position: 0 0;}100% {background-position: -490px 0;}
}

这是一个动画,关于animation的用法具体可以参考之前的博文,启动页的那一篇,里面有详细的用法解释,简单的说,就是当 this.data.isExplosion 的值为true的时候,plane_animate这个类名将会被添加到这个DOM上,当类名被添加的同时会立即执行名为plane_animate的动画,该动画会在0.5秒内分成5步显示完,动画改变的背景图的坐标,将x轴从0变到了-490px,实现了动画效果;
具体效果图如下:

4.3 我方飞机生成的实现

飞机的创建流畅和之前敌机的创建流程其实差不多,大致的流程是,我方的文件是一个单独的.vue文件,里面有我方飞机模型的所有参数功能,当参数创建成功后存入飞机数组,通过v-for将飞机数组遍历,其它的类似于是否爆炸等参数的则是通过props传入的飞机组件

因此,在父级,我们可以这么写

 <!-- 我方飞机 --><template v-if="isStart"><Plane v-for="plane in planeData" :data="plane" :params="config" :key="plane.id" @addBullet="addBullet" /></template><script>
import Plane from '../view/plane/plane.vue';
export default {data() {return {planeData: [],};},components: { Plane },methods: {initPlane() {const data = {width: 98,height: 122,x: (this.config.winWdith - 98) / 2,y: this.config.winHeight - 122,id: `plane` + new Date().getTime(),isExplosion: true};this.planeData.push(data);}}
};
</script>

子组件,也就是我方飞机组件则是如下,通过props将父组件中的飞机配置参数传入子组件

<script>
export default {props: {data: {type: Object,default: () => {return {};}},},
};
</script>

4.4 我方飞机坐标的实现

从效果图中我们其实可以看到,我方飞机y轴上飞机的生成位置处于屏幕的下半方,在x轴上处于

因此,实际上我们只需要固定X轴和Y轴的值即可~,先看X轴的代码

(this.config.winWdith - 98) / 2

在x轴上显示获取屏幕的宽度,减掉飞机的宽度再除以2,这就是飞机模型离左边距的距离,Y轴就更简单了

this.config.winHeight - 122

直接屏幕高度减掉一个固定值即可,接着就将参数传递到子组件接收

<template><view class="plane" :class="getClass" :style="{ left: data.x + 'px', top: data.y + 'px' }"></view>
</template>

在子组件中直接 设置left属性 以及 top属性 来控制我方飞机的的初始坐标方位;

4.5 我方飞机的操控与位移

我方飞机的操控是按键盘的WASD来控制飞机的前后左右移动,因此我们先看一下实现思路:

简单的说就是 飞机模型被加载的时候给当前页面添加一个监听事件,监听整个键盘的按键,当WASD这几个按键被按下的时候 打开对应的开关,因此循环执行飞机位移动画时得到位移方向确认,因此飞机即可向对应方向位移

4.5.1 初始化操作事件

操作事件的初始化,初始化一共分为两种,一种是按键按下时触发控制器为开一种是按键松开时触发控制器为关,先是控制器为开的操作

document.addEventListener('keydown', e => {switch (e.keyCode) {//up键case 38:this.keyTop = true;break;//down键case 40:this.keyBottom = true;break;//left键case 37:this.keyLeft = true;break;//right键case 39:this.keyRight = true;break;default:console.log('无效案件,请使用上、下、左、右控制');}
});

接着是 控制器关 的代码,如下:

document.addEventListener('keyup', e => {switch (e.keyCode) {//up键case 38:this.keyTop = false;break;//down键case 40:this.keyBottom = false;break;//left键case 37:this.keyLeft = false;break;//right键case 39:this.keyRight = false;break;}});

通过绑定 keydownkeyup 开控制开关的开启与关闭;

4.5.2 位移函数

先上代码

move() {if (this.keyTop && this.data.y > 0) {this.data.y -= 5;}if (this.keyBottom && this.data.y + 122 < this.params.winHeight) {this.data.y += 5;}if (this.keyLeft && this.data.x > 0) {this.data.x -= 5;}if (this.keyRight && this.data.x + 98 < this.params.winWdith) {this.data.x += 5;}
},
initMove() {this.moveTimer = () => {this.move();requestAnimationFrame(this.moveTimer);};this.moveTimer();
},

整个位移有两段,分别 实现位移动画 以及 位移动画的具体实现,一段一段看

initMove() {this.moveTimer = () => {this.move();requestAnimationFrame(this.moveTimer);};this.moveTimer();
},

这一段很明显,在敌机模型中也被用到了,作用就是通过 requestAnimationFrame 实现了飞机位移动画,位移的具体实现则是通过move()这个函数实现的

move() {if (this.keyTop && this.data.y > 0) {this.data.y -= 5;}if (this.keyBottom && this.data.y + 122 < this.params.winHeight) {this.data.y += 5;}if (this.keyLeft && this.data.x > 0) {this.data.x -= 5;}if (this.keyRight && this.data.x + 98 < this.params.winWdith) {this.data.x += 5;}
}

这里有4个判断,用于判断当前哪个开关是处于开关,当对应的开关处于打开的状态时,那么飞机将在对应方向上实现位移:

  • 第一个if,按键是W时执行,飞机在Y轴上的位移轨迹,每次在Y轴上减少5个像素,当然坐标不能小于0,小于0的话就到屏幕外了;
  • 第二个if,按键是S时执行,飞机在Y轴上的位移轨迹,每次在Y轴上增加5个像素,坐标加飞机本身高度不能大于屏幕高度,大于的话就到屏幕外了;
  • 第三个if,按键是A时执行,飞机在X轴上的位移轨迹,每次在X轴上减少5个像素,X轴上的坐标也不能小于0,小于的话就到屏幕外了;
  • 第四个if,按键是D时执行,飞机在X轴上的位移轨迹,每次在X轴上增加5个像素,坐标加飞机本身宽度不能大于屏幕宽度,大于的话就到屏幕外了;

这就是每次执行 requestAnimationFrame 的内部动画逻辑;

五. 阶段性展示

到这一章节,我们已经实现的效果图如下:

六. 小结

本文主要概述了我方飞机的实现,主要包含:

  • 飞机样式:其实就是设定好DOM,加入背景图,预设好爆炸的CSS动画;
  • 飞机生成:创建我方飞机配置参数,加入缓存数组,通过v-for指令循环生成飞机;
  • 飞机坐标:我方飞机的坐标位于屏幕的下方,是固定的;
  • 飞机操作位移:位移通过 requestAnimationFrame 实现,并在加载我方飞机时 添加按键监听,监听WASD这几个按键,当这几个按键被按下时,触发对应的位移效果;

但看飞机模型的代码量,也不算复杂,耐心看看还可以明白的,接下来就是碰撞检测了,这一块稍微涉及到了一些计算,当然,问题不大~
都已经看到这里了,点个赞吧,点个关注吧,谢谢

《uni-app》一个非canvas的飞机对战小游戏实现-我方飞机实现相关推荐

  1. 《uni-app》一个非canvas的飞机对战小游戏实现-碰撞检测的实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  2. 《uni-app》一个非canvas的飞机对战小游戏实现-敌机模型实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  3. 《uni-app》一个非canvas的飞机对战小游戏实现(一)准备

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  4. 《uni-app》一个非canvas的飞机对战小游戏-启动页

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  5. 怎么开发联机小游戏_Q飞机游戏:空战吃鸡大乱斗游戏!好玩的联机Q飞机对战小游戏...

    20000+游戏爱好者已加入我们! 带你发现好游戏! <Q飞机>游戏小程序好玩吗? <Q飞机>小游戏怎么玩? 只有你想不到, 没有我找不到的好游戏! 「良心好游戏推荐」 搜罗了 ...

  6. 《uni-app》一个非canvas的飞机对战小游戏实现-requestAnimationFrame详解

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言-博主看到后会去代替大家踩坑的-接下来的几篇都是uni-app的小实战,有助于我们更好的去学 ...

  7. 基于LabVIEW的飞机大作战小游戏(可做毕设)

    一.前言 Python是目前相当流行的一门编程语言,网上有人用Python做了一个<飞机大作战>的小游戏,并且出了一份视频教程,很有意思."基于Python的飞机大作战小游戏&q ...

  8. c语言小程序飞机大战,飞机大战微信小游戏:经典像素飞机大战小程序,点开即玩...

    50000+游戏爱好者已加入我们! 每天推荐好玩游戏! 关注我们,沐沐带你发现好游戏! <经典像素飞机大战>游戏小程序好玩吗? <经典像素飞机大战>小游戏怎么玩? 怎么进入&l ...

  9. HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形

    HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形 游戏介绍 完整代码 代码目录 游戏运行 HTML5 canvas 绘制图形 canvas 介绍 绘制函数 加载图片 生物行走动画绘制 ...

最新文章

  1. php创建类用什么关键字,PHP面向对象开发之类的常用关键字
  2. python文件指针_在使用python写入文件之前,如何将文件指针放在上面一行?
  3. java监控rabbitMq服务状态,SpringCloud-Turbine【RabbitMQ服务监控】
  4. 滑动轨迹 曲线 python_python – 计算轨迹(路径)中的转折点/枢轴点
  5. UFT开发实例:QTP调用OutLook自动发送邮件
  6. autopep8_Autopep8的使用
  7. Ajax内部交流文档(转)
  8. Linux之last命令
  9. 解决Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web modules
  10. 从零基础入门Tensorflow2.0 ----四、14. tf.io.decode_csv的使用
  11. linux操作系统日志查看,linux 如何查看系统日志
  12. 判别分析分为r型和q型吗_r型聚类分析
  13. TF卡格式化8G格式化时候变成128KB的解决办法
  14. 开发小程序插件如何实现盈利?
  15. laravel 常用文档
  16. python椭圆拟合_基于直接最小二乘的椭圆拟合(Direct Least Squares Fitting of Ellipses)...
  17. ARM实验板移植Linux操作系统,LCD显示汉字(名字)
  18. windows 文件夹属性全部都为只读。怎么解决?
  19. 新程序猿如何度过试用期
  20. Y05 - 017、猜小埋年龄游戏

热门文章

  1. Android support和Androidx库不能共存问题
  2. 南洋理工 55 懒省事的小明
  3. 前端岗位编写代码注意规范
  4. iOS swift3 尾随递归
  5. SGX,为数据处理构建硬件级 “安全隔离区” | 至强秘笈
  6. 金蝶云星空采购订单套打模板明细表里相同编码取最小交货日期
  7. c语言 putchar 转义字符,putchar - [ C语言中文开发手册 ] - 在线原生手册 - php中文网...
  8. 路由器和静态路由的配置
  9. 南京城-夫子庙古秦淮
  10. 数字集成电路设计(一、Verilog HDL数字集成电路设计方法概述)