FlappyBird
本人没有按照老师的做法去做,大体差不多,
当然老师做的更精细,有些不会的还是参考老师的方法
参考部分
- 小鸟如何像真实物体一样的重力效果
- 点击如何使小鸟飞翔
省略部分
3. 小鸟多动画(飞机大战其实有做,单纯偷懒)
4. 小鸟死亡滚动(猜想是给一个边缘力使其旋转,或代码直接使其旋转)
5. 中间区域碰撞(我用的是计时的方法,老师用碰撞方法,碰撞不阻碍移动)
6. UI界面的省略(UI界面省略部分)
7. 奖牌的发放(只是多个判断就能实现,所以懒得做了)
增加部分
8. 音频控制
背景
我的背景部分包含了很多
目之所及全是背景
光是绑定在BG上的组件就有很多,还没有参数,参数都是在代码里自己改
废话不多说,上代码
import { _decorator, AudioClip, AudioSource, Component, director, instantiate, Label, Node, Prefab, randomRangeInt, Slider } from 'cc';
import { AudioMgr } from './AudioMgr';
import { ts_bird_att } from './ts_bird_att';
const { ccclass, property } = _decorator;
@ccclass('ts_bg')
export class ts_bg extends Component {
speed : number = 100 // 背景移动速度
kj : number = 160 // 逃跑初始空间
pi_rate : number = 2 // 障碍物生成时间间隔
pi_time : number = 0 // 临时存储时间
fen : number = -6
end : boolean = false // 游戏是否结束,控制背景移动
set_bol : boolean = false
@property(Node) ui : Node = null
@property(Node) bg_day_1 : Node = null
@property(Node) bg_day_2 : Node = null
@property(Node) land_1 : Node = null
@property(Node) land_2 : Node = null
@property(Prefab) pipe_up : Prefab = null // 理论上为了减小安装包大小材质要尽可能复用
@property(Prefab) pipe_dw : Prefab = null
bg_arr : Node[] = []
@property(AudioClip) aud_bg : AudioClip = null
@property(AudioClip) aud_end : AudioClip = null
@property(Label) fen_up : Label = null
@property(Label) fen_now : Label = null
@property(Node) ui_set : Node = null
@property(Slider) ui_aud : Slider = null
static inthis: ts_bg
static getinthis() : ts_bg{return this.inthis}
start() {
ts_bg.inthis = this
AudioMgr.inst.play(this.aud_bg , this.ui_aud.progress)
this.bg_arr.push(this.bg_day_1,this.bg_day_2,this.land_1,this.land_2)
}
update(deltaTime: number) {
this.on_bg_move(deltaTime)
}
on_bg_move(deltaTime: number){ // 背景移动函数
if (this.end == true){return}
let no : Node
for (no of this.bg_arr){this.bg_move(no , deltaTime)}
this.on_pipe_rate(deltaTime)
}
bg_move(no : Node , dt : number){ // 复用移动函数
let np = no.getPosition()
if (np.x <= -1280){np.x = 1280}
no.setPosition(np.x - dt * this.speed , np.y)
}
on_pipe_rate(dt : number){ // 障碍生成函数
this.pi_time += dt
if (this.pi_time < this.pi_rate){return}
const pi_up = instantiate(this.pipe_up)
this.node.addChild(pi_up)
let up_y = randomRangeInt(-500, -200)
let pos = this.node.getPosition()
pos.x = 640 // 在屏外生成,所以是固定的
pi_up.setPosition(pos.x , up_y)
this.bg_arr.push(pi_up)
const pi_dw = instantiate(this.pipe_dw)
this.node.addChild(pi_dw)
// 这里特别注意 pipe我的高度是600,对半就是300,上下2个所以是600
pi_dw.setPosition(pos.x , this.kj + up_y + 600)
this.bg_arr.push(pi_dw)
this.pi_time = 0
this.fen += 1
this.kj -= 1
}
on_del(no : Node){ // 删除数组成员函数
for (let index = 0; index < this.bg_arr.length; index++) {
if (no.uuid == this.bg_arr[index].uuid){
this.bg_arr.splice(index,1) // 删除数组里面的node
no.destroy() // 销毁此node
}
}
}
on_end(){ // 游戏结束函数
// 控制音频
AudioMgr.inst.stop()
AudioMgr.inst.playOneShot(this.aud_end)
// 控制触摸移动
const bird = ts_bird_att.getinthis()
bird.move = false
this.end = true
// 控制ui
this.ui.active = true
this.fen_now.string = `当前得分 ${this.fen < 0 ? 0 : this.fen}`
let fup = localStorage.getItem(`fen_up`)
this.fen_up.string = `历史最高 ` + fup
if (Number(fup) < this.fen){
console.log(`新纪录`)
localStorage.setItem(`fen_up`,this.fen.toString())
}
//this.scheduleOnce(function(){director.pause()},1)
}
on_reset(){ // 游戏重开函数
director.resume()
director.loadScene(`s1`)
}
on_set_aud(){
AudioMgr.inst.play(this.aud_bg , this.ui_aud.progress)
}
on_set(){
this.set_bol = !this.set_bol
this.ui_set.active = this.set_bol
this.set_bol ? director.pause() : director.resume()
}
}
刚体问题后面会讲
这里只讲一下,障碍物的生成
下障碍物高度 + 逃逸空间 + 上障碍物高度 = 可视高度
写到这里的时候想了一下,我这里有个BUG
我没有写限制小鸟的高度(下方会发生碰撞,游戏结束)
游戏一开始小鸟一直飞高就不会碰到障碍物,这是个bug(加了两行代码搞定)
其他
小鸟代码
import { _decorator, Collider2D, Component, Contact2DType, Input, input, math, Node, RigidBody, RigidBody2D } from 'cc';
import { ts_bg } from './ts_bg';
const { ccclass, property } = _decorator;
@ccclass('ts_bird_att')
export class ts_bird_att extends Component {
static inthis : ts_bird_att
static getinthis() : ts_bird_att {return this.inthis}
move : boolean = true
start() {
ts_bird_att.inthis = this
input.on(Input.EventType.TOUCH_START , this.on_ts , this) // 开启触摸监听
const col = this.getComponent(Collider2D)
if (col){col.on(Contact2DType.BEGIN_CONTACT , this.on_bc , this)}
else {console.log(`碰撞开启异常`)}
//const rig = this.getComponent(RigidBody2D)
}
on_ts(){ // 触摸函数
if (this.move == false) {return}
const pos = this.node.getPosition()
if (pos.y >= 300){return}
const rig = this.getComponent(RigidBody2D)
let fc = new math.Vec2(0 , 6) // Y坐标移动 点击向上的速度
rig.linearVelocity = fc // 给刚体施加一个力
}
on_bc(me : Collider2D , oth : Collider2D){ // 碰撞函数
console.log(`bird碰撞`,oth.name)
ts_bg.getinthis().on_end()
}
update(deltaTime: number) {
}
}
障碍物代码
import { _decorator, Component, Node } from 'cc';
import { ts_bg } from './ts_bg';
const { ccclass, property } = _decorator;
@ccclass('ts_pipe_att')
export class ts_pipe_att extends Component {
start() {
}
update(deltaTime: number) {
const pos = this.node.getPosition()
if (pos.x <= -640){ // 如果移动超出屏幕外则删除
ts_bg.getinthis().on_del(this.node)
}
}
}
场景结构
audio部分
之前写过_点击跳转
心得_刚体
这是个地板刚体属性(鼠标在左侧不动时会有中文提示,为cocos点赞)
作为一个地板肯定是静态的,意味着不受外力干扰
动态的话,碰撞起来也挺有趣的,可以试一下
重力为0的话它才会固定在某个位置上,
大于0的值会导致刚体有向下的重力
小于0不会导致向上漂浮
而小鸟的话则需要有重力,这样才会下坠
碰撞 sensor 是不能勾选的
audio部分
其实就是创建了一个滑动器
并把函数绑定上去就好了
再编写相应代码