添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Laya实现flappybird

前言

本文是使用laya实现的flappy bird。

先来看下整个游戏过程:

本文从2个方面介绍,首先介绍下涉及到的Laya重点知识,然后再简单介绍下实现flappybird的要点。

Laya基础知识

游戏中的常用术语

刚接触游戏,时常一脸懵逼里面的各种词汇:预制体、刚体。当然物理好的童鞋例外。

下面我来介绍下几个常用术语:

  1. 首先认识碰撞器

什么是碰撞器?在游戏中比如 一架飞机发射了子弹,那么当这个子弹和敌人,相互碰撞的时候,那么这个敌人应该就被消灭了,这就是碰撞器,在游戏中很多时候都需要用到碰撞器,所以这是最开始就需要了解的。

  1. 刚体组件

刚体能让你的游戏对象被物理引擎所控制,它能通过受到 推力 扭力 来实现真实的物理表现效果。 所有游戏对象必须包含刚体组件来实现重力、通过脚本施加力、或者与其他对象进行交 互,这一切都通过NVIDIA的PhysX物理引擎来实现。

举个例子,飞机是在天上飞的,当我们给它添加一个刚体组件,那么它就有了重力,比如飞机只能够承受 1000kg的重量,但是它缺承受了2000kg的重量,那么它就会向下坠落,这就是刚体组件的作用。

  1. 预制体

为什么我们要去学习预制体,预制体在游戏中用到的地方也很多,比如飞机发射子弹,这个子弹我们把它做成一个预设,也就是当我们按下键盘的某一个键的时候它才会被创建在游戏中,这个对游戏的性能才有保障,如果我们一开始就把这些子弹加入到游戏中,那么这样电脑内存就会不断的增加, 所以只有当需要它的时候,才让它出现,这就是预制体它的含义

  1. Animation 动画

举个例子,在游戏中角色释放一个技能,那么这个技能就会播放一个特效,大家都玩过 gif图片,gif是动态的,动画也就是由很多张图片循环去播放,这样就做成了技能的效果,这就是Animation的作用。

  1. 状态机

状态机的作用是用来管理所有我们制作好的动画,举个例子,比如我们释放技能飞龙在天,这个时候就去播放一条龙在天上飞的这个动画,当我们释放其他技能时候,相对应的去播放动画特效,因为我们在做游戏的时候不仅仅只做一个特效, 每一个技能都需要制作一个特效,那么这些特效做好了,我们就需要用状态机去控制它在什么时候播放这个特效,这就是状态机的作用

2D物理系统

我们做的flappybird时就需要了解laya的2D物理系统,因为小鸟,大地都是受重力作用的刚体。

官网传送门: 2D物理系统

LayaAir引擎中集成的Box2D物理系统,首先要了解 刚体rigidbody 碰撞体collider ,当物体包含刚体的时候就可以收到物理引擎的影响,当物体包含碰撞体的时候物体可以发生碰撞,当物体含有碰撞体不含有刚体的时候可以被碰撞但不发生物理运动学动力影响。

  • 刚体rigidbody :刚体是指在运动中和受力作用后,形状和大小不变,而且内部各点的相对位置不变的物体。
  • 碰撞体collider :碰撞体是给物体加一个判定框,当碰撞框重叠的时候,两物体发生碰撞。
  • 关节joint : 关节可以对两个或多个物体进行一种约束。

刚体组件介绍

RigidBody 类继承自 Component ,刚体支持三种类型: static dynamic kinematic ,默认为 dynamic

  • static为静态类型 ,静止不动,不受重力影响,质量无限大,可以通过节点移动,旋转,缩放进行控制;在模拟环境下静态物体是不会移动的,就好像有无限大的质量。在Box2D的内部会将质量至反,存储为零。静态物体有零速度。静态物体不能和其它静态或运动学物体进行碰撞。
  • dynamic为动态类型,受重力影响 ;动态物体可以进行全模拟。它们可以被用户手动移动,但是通常情况下会根据受力进行移动。动态物体可以和任何物体发生碰撞。动态物体总是拥有有限的非零质量。如果你尝试设置动态物体的质量为零,它会自动设置一个1千克质量的物体。 比如我们flappyBird中的小鸟。
  • kinematic为运动类型,不受重力影响 ,可以通过施加速度或者力的方式使其运动。运动学物体在模拟环境中根据自身的速度进行移动。运动学物体自身不受力的作用。虽然用户可以手动移动它,但是通常情况下我们会设置它的速度来进行移动。运动学物体的行为就像是有无限大的质量,尽管如此,在Box2D内部还是会对运动学物体的质量至反设置为零。运动学物体不能和其它静态或运动学物体进行碰撞。 比如我们flappyBird中的地面和背景

LayaAir 脚本参数说明

flappyBird制作要点

流程介绍

1.Laya的下载,vscode下载 2.VS代码模板的创建 3.素材导入,制作天空草地背景 4.让天空和草地动起来,循环替换 5.放置鸟,鼠标点击施加力 鸟的animation动画制作 6.碰撞检测 7.柱子的动态随机生成 8.成绩增加与UI显示 9.游戏结束界面 10.排行榜 11.再来一局 12.开始游戏 13.音效添加 14.发布微信小游戏 15.接入微信云开发实现数据同步

项目目录介绍

代码目录:

工程目录:


背景和柱子的运动

游戏中所有物体的运动统一公用autoMove脚本文件。

利用 Laya 中的 Laya.RigidBody 刚体的线性运动 linearVelocity

// 仅设置横向速度
this.owner.getComponent(Laya.RigidBody).linearVelocity={x:speed,y:0}

碰撞检测

基础的游戏引擎都有碰撞检测,在laya中碰撞检测使用碰撞事件中的 onTriggerEnter 即可。

相互阻挡 需要有 RigidBody BoxCollider 组件。

// 碰撞检测
 onTriggerEnter(other){
  // 处理碰撞

动画制作

1.新建一个动画场景

2.在动画时间轴中进行创建动画,可以针对每帧进行制作、以及预览动画。


柱子随机生成&对象池的使用

1. 创建柱子预制体 :前面提到过预制体,在该动画中柱子就是我们所说的预制体。 首先编辑好节点后,在节点的属性右上角保存,就能够保存预制体。


2.定义好预制体,才能在UI组件界面显示

/** @prop {name:columnPre, tips:"柱子预制体", type:Prefab, default:null}*/
        this.columnPre=null;

3.间隔时间生成随机位置的柱子。采用对象池方便回收柱子。

Pool 是对象池类,用于对象的存储、重复使用。 合理使用对象池,可以有效减少对象创建的开销,避免频繁的垃圾回收,从而优化游戏流畅度。
getItemByCreateFun(sign: string, createFun: Function, caller?: any): any 根据传入的对象类型标识字符,获取对象池中此类型标识的一个对象实例。当对象池中无此类型标识的对象时,则使用传入的创建此类型对象的函数,新建一个对象返回。
// columnSpawn.js
// 生成柱子的方法
    spawn(){
        var bottomColumn=Laya.Pool.getItemByCreateFun("Column",this.creatFun,this);
        columnParent.addChild(bottomColumn)
        bottomColumn.rotation=0;
        columnArr.push(bottomColumn)
        bottomColumn.rotation=0;
        var bottomY=this.getRandom(400,800);
        bottomColumn.pos(672,bottomY);
        bottomColumn.getComponent(column).canAddScore=true;
        // 顶部柱子和底部柱子差值
        var cha=this.getRandom(245,348);
        var topY=bottomY-cha;
        var topColumn=Laya.Pool.getItemByCreateFun("Column",this.creatFun,this);
        columnParent.addChild(topColumn)
        topColumn.rotation=180;
        topColumn.pos(928,topY);
        // 移除顶部柱子的成绩增加
        topColumn.getComponent(column).canAddScore=false;
        columnArr.push(topColumn)
    creatFun(){
        var temp=this.columnPre.create();
        return temp;
    //获取min - max之间的随机值
    getRandom(min,max){
        var ranValue=0;
        if(max>min){
            ranValue=Math.random()*(max-min)
            ranValue+=min;
        }else{
            ranValue=Math.random()*(min-max)
            ranValue+=max;
        return ranValue;
    // column.js
    if(this.owner.x <= -216){
            this.owner.removeSelf() // 移除屏幕后,从舞台删除自己
            Laya.Pool.recover("Column",this.owner)

小鸟飞行

小鸟受重力作用,给小鸟一个向上的力,则会进行自由上抛运动。

mouseDown() {
  if(this.isStart == false) return;
  if(isGameOver) return;
                              this.owner.getComponent(Laya.RigidBody).linearVelocity = {x:0,y:this.force}
  this.owner.autoAnimation = 'Fly'
  this.owner.loop = false
// 每次飞行播放fly音乐
Laya.SoundManager.playSound("audio/fly.mp3",1)

计分

因为鸟的 x 位置不动,所以看柱子的 x 坐标小于小鸟位置 x 则可以视为加分。 如图所示,当柱子的 x<-11 即可加分


事件分发&监听

// 派发一个结束事件
  Laya.stage.event('GameOver')
  // 监听结束事件 
  Laya.stage.on("GameOver",this,function(){
  isGameover = true

添加音效

playSound : 播放音效。 音效可以同时播放多个。 playMusic : 播放背景音乐。 背景音乐同时只能播放一个 ,如果在播放背景音乐时再次调用本方法,会先停止之前的背景音乐,再播发当前的背景音乐。

Laya.SoundManager.playSound("audio/hit.mp3",1)

生成微信小程序&接入微信云开发

生成微信小程序: 点击发布,选择压缩,因为微信小程序有大小限制(4M)。发布成功后在 release 文件夹就有生成的微信小游戏 wxgame。


接入云开发:

1.申请云开发 2.创建云函数和数据库 3.注意每个云函数都需要本地安装,否则会调用失败(问题原因: 小程序云函数调用失败解决方案 )。

4.laya中使用需要先初始化云函数,然后再调用具体的云方法即可。

// 初始化云函数