像素鸟,鸟儿飞飞飞

学习CocosCreator有段时间了,现在花了两天时间写了个像素鸟的小游戏,这个游戏之前又看到过,但是不知道怎么又下架了,之前还是蛮火的游戏,想起来后去网上看了看,原来是因为侵犯了 超级玛丽 的游戏元素,都是像素级小游戏,嗯,国外人的版权意识还是挺高的。好了,题外话就到这了,开始切入正题吧。

写这个游戏也不难,最主要的是思路,该怎么去写,我也在网上看到过 C++版 的,易语言的,Cocos2d的,都挺多的,都是大神啊

我这个是Creator版的,跟Cocos2d有点差别,但是差别又不大

好了,上代码(本来是想截图的,但是想想还是要对得起自己,还是手敲吧)

这个游戏我是用 ts 写的,外加CocosCreator



onLoad(){

  // 获取到小鸟,管道,背景,陆地的节点, 这些this的都是先在前面声明了的

  // 小鸟

  this.bird = cc.find(‘layout_wrap/node_bird‘, this.node)

  // 背景

  this.bg = cc.find(‘layout_wrap/layout_bg‘, this.node)

  // 管道

  this.pipe = cc.find(‘layout_wrap/layout_cont‘, this.node)

  // 陆地

  this.land = cc.find(‘layout_wrap/layout_land‘, this.node)

  // 初始化数据

  this.initData()

}

// 这里去初始化一下,一些声明的游戏数据

private initData(): void {

  this.time = 0 // 帧率(每帧调用,模拟小鸟扇动翅膀)

  this.speed = 0 // 速度

  this.distance = 150 // 管道距离

  this.rateSpeed = 1 // 移速

  this.upSpeed = 2 // 加速

  this.slowSpeed = 0.06 // 减速

  // 监听运行事件

  let wrap = cc.find(‘layout_wrap‘, this.node)

  wrap.on(cc.Node.EventType.TOUCH_START, this.runnIng.bind(this), this)

  // 开始界面

  this.layoutstar = cc.find(‘layout_wrap/layout_star‘, this.node)

  // 开始按钮

  this.starbtn = cc.find(‘layout_content/button_play‘, this.layoutstar)

  this.addClickEvent(this.starbtn, ‘onClickStar‘)

  // 暂停按钮

  let pausebtn = cc.find(‘node_score/button_pause‘, wrap)

  this.addClickEvent(pausebtn, ‘onClickPause‘)

  // 继续按钮

  let resumebtn = cc.find(‘layout_pause/button_resume‘, wrap)

  this.addClickEvent(resumebtn, ‘onClickResume‘)

  // 游戏结束,重新开始

  let again = cc.find(‘layout_over/node_content/button_play‘, wrap)

  this.addClickEvent(again, ‘onClickAgain‘)

  // Get Ready提示节点

  this.ready = cc.find(‘node_score/node_ready‘, wrap)

  // 游戏结束

  this.gameover = cc.find(‘layout_over‘, wrap)

  // 加载管道

  this.addPipe()

  // 碰撞系统

  let manager = cc.director.getCollisionManager()

  manager.enabled = true

}

//下面开始写功能

// 点击开始

protected onClickStar(): void {

  // 缩放界面

  let act = cc.callFunc(() => {

    this.layoutstar.active = false

    this.layoutstar.destroy()

  })

  // 这里用到动作系统的缩放和渐隐,算是一点点动画效果吧

  let seq = cc.sequence(cc.spawn(cc.scaleTo(0.3, 0), cc.fadeOut(0.3)), act)

  if (this.layoutstar) {

    this.layoutstar.runAction(seq)

  }

  // 这里是避免忘记吧结束界面没有隐藏掉,

  if (this.gameover) {

    this.gameover.active = false

  }

}

// 点击运行

private runnIng(): void {

  if (this.ready.active && !this.layoutstar.active) {

    // 隐藏Get Ready提示节点

    this.ready.active = false

    // 显示update, ison是作为update的开关

    this.ison = true

  }

  this.speed = 2.5 // 给小鸟一个向上的加速度

}

// 加载管道, 这里的管道是通过预制体来加载上去的

private addPipe(): void {

  this.LoadPrefabs(‘node_pipe‘, (n: cc.Node) => {

    if (!n) {

      return

    }

    for (let i = 0; i < 4; i++) {

    // 复制节点

    let copy = cc.instantiate(n)

    // 插入节点

    this.pipe.addChild(copy, i)

    // 调整管道位置

    copy.x = this.node.width / 2 + (this.distance + copy.width) * i

    // 480~720

    copy.y = (Math.random() * 0.5 + 1) * 480

    if (i > 0) {

      // 相邻管道之间的差距不超过120

      this.distanceY(i, i - 1)

    }

    }

  })

}

// 移动背景

private moveBg(bgs: cc.Node): void {

  bgs.x = bgs.x - 1

  // 当背景移动出屏幕后,将这个背景再加到两个背景的前面

  // 像素对齐,所以bg.x为一个确切数

  if (bgs.x < -614) {

    bgs.x = 1228

    // 调整节点顺序

    if (bgs == this.bg.children[0]) {

    this.bg.children[1].zIndex = 0

    this.bg.children[2].zIndex = 1

    this.bg.children[0].zIndex = 2

    } else if (bgs == this.bg.children[1]) {

    this.bg.children[2].zIndex = 0

    this.bg.children[0].zIndex = 1

    this.bg.children[1].zIndex = 2

    } else if (bgs == this.bg.children[2]) {

    this.bg.children[0].zIndex = 0

    this.bg.children[1].zIndex = 1

    this.bg.children[2].zIndex = 2

    }

  }

}

// 移动管道

private movePipe(pipes: cc.Node): void {

  pipes.x = pipes.x - 2

  // 当管道移动一个屏幕宽后,再将这个管道的位置改变到屏幕右侧

  if (pipes.x < -(pipes.width + this.node.width / 2)) {

    pipes.x = 515

    // 480~1000

    pipes.y = (Math.random() + 1) * 520 - 40

    // 相邻管道之间的差距不超过120

    if (pipes == this.pipe.children[0]) {

    this.distanceY(0, 3)

    } else if (pipes == this.pipe.children[1]) {

    this.distanceY(1, 0)

    } else if (pipes == this.pipe.children[2]) {

    this.distanceY(2, 1)

    } else if (pipes == this.pipe.children[3]) {

    this.distanceY(3, 2)

    }

  }

}

// 移动陆地

private moveLand(lands: cc.Node): void {

  lands.x = lands.x - 2 * this.rateSpeed

  // 当陆地移动一个屏幕宽后,再将这个陆地的位置改变到屏幕右侧

  if (lands.x < -(this.node.width)) {

    lands.x = this.node.width - 2 * this.rateSpeed

  }

}

// 相邻管道之间的Y方向差距

private distanceY(a: number, b: number): void {

  if (Math.abs(this.pipe.children[a].y - this.pipe.children[b].y) > 140) {

    this.pipe.children[a].y = this.pipe.children[b].y + ((Math.random() * 2 - 1) * 140)

    if (this.pipe.children[a].y > 1000) {

    this.pipe.children[a].y = this.pipe.children[b].y - (Math.random() * 140)

    } else if (this.pipe.children[a].y < 480) {

    this.pipe.children[a].y = this.pipe.children[b].y + (Math.random() * 140)

    }

  }

}

// 最主要的是这个思路,要形成流畅的效果,就要每帧都去调用它,

update(dt: number) {

  // 终止移动

  if (this.gameover.active) {

    this.ison = false

  }

  // 帧率切换节点的显示,模拟扇翅膀

  if (this.ison) {

    let timeTemp = this.time + dt

    this.time = timeTemp

    if (this.time > 0.5) {

      if (this.bird.children[0].active) {

      this.bird.children[0].active = false

      this.bird.children[1].active = true

    }

    else if (this.bird.children[1].active) {

      this.bird.children[1].active = false

      this.bird.children[2].active = true

    }

    else if (this.bird.children[2].active) {

      this.bird.children[2].active = false

      this.bird.children[3].active = true

    }

    else if (this.bird.children[3].active) {

      this.bird.children[3].active = false

      this.bird.children[0].active = true

    }

    // 别忘了要重置为零

    this.time = 0

  }

  // 给定小鸟的下降减速

  this.speed = this.speed - 0.06

  // 小鸟在y轴上的移动

  this.bird.y = this.bird.y + this.speed

  // 小鸟上飞改变方向, 通过改变旋转方向来实现小鸟的朝向

  this.bird.angle = this.speed * 10

  // 移动背景

  this.moveBg(this.bg.children[0])

  this.moveBg(this.bg.children[1])

  this.moveBg(this.bg.children[2])

  // 移动管道

  this.movePipe(this.pipe.children[0])

  this.movePipe(this.pipe.children[1])

  this.movePipe(this.pipe.children[2])

  this.movePipe(this.pipe.children[3])

  // 移动陆地

  this.moveLand(this.land.children[0])

  this.moveLand(this.land.children[1])

  }

}

// 这是挂载在主场景上的脚本,画面和功能做出来了,但是如果没有结束,那么相信这个游戏也不会太有趣



// 如何来结束游戏? 那就是当小鸟装上管道后,就结束游戏,如果没有,那就加分啦

// 这里用到的是碰撞去写的,当然也可以去用其他的方法去实现

// 这是挂载在小鸟的这个节点上的脚本

// 加载的时候会初始分数

onLoad() {

  // 分数

  this.gameMain.Score = 0

  // 分数节点

  this.topScore = cc.find(‘node_score/label_score‘, this.node.parent)

}

// 这里用到的碰撞,在小鸟,管道,和中间的空隙都会绑定碰撞的组件

// 当小鸟撞在管道上,游戏结束,

// 小鸟通过中间的空隙,加一分

onCollisionEnter(other, self) {

  if (other.tag == 2) {

    this.gameMain.Score++

  } else if (other.tag == 1) {

  this.gameOver()

  }

  // 显示分数

  this.topScore.getComponent(cc.Label).string = this.gameMain.Score.toString()

}

// 结束游戏

private gameOver(): void {

  // 显示结束游戏的界面

  let gameover = cc.find(‘layout_over‘, this.node.parent)

  gameover.active = true

  // 渐显

  gameover.runAction(cc.fadeTo(0.5, 255))

  // 分数

  let scorelabel = cc.find(‘node_content/sprite_panel/label_score‘, gameover).getComponent(cc.Label)

  scorelabel.string = this.gameMain.Score.toString()

  // 重置分数

  this.scheduleOnce(() => {

    this.gameMain.Score = 0

  }, 0.5)

}



好啦,一个简单的单机像素鸟就做好了,想要更详细的源码的小伙伴可以私聊我哦~~

下面放出效果图,唉,没有挂载服务器,无法直接上传到web平台,只能放出gif啦

原文地址:https://www.cnblogs.com/zhen-prz/p/11470545.html

时间: 2024-10-06 10:00:14

像素鸟,鸟儿飞飞飞的相关文章

使用Libgdx开发的FlappyBird(像素鸟、疯狂的小鸟)游戏源码

本帖最后由 宋志辉 于 2014-10-21 15:06 编辑 点击进入下载地址 Flappy Bird(飞扬的小鸟)由一位来自越南河内的独立游戏开发者阮哈东开发,是一款形式简易但难度极高的休闲游戏.简单但不粗糙的8比特像素画面.超级马里奥游戏中的水管.眼神有点呆滞的小鸟和几朵白云,白天夜晚两种模式便构成了游戏的一切.玩家需要不断控制点击屏幕的频率来调节小鸟的飞行高度和降落速度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟不小心擦碰到了管子的话,游戏便宣告结束. 本源码是参照Flappy Bird

android eclipse 下制作像素鸟

从资源文件加载bitmap至内存 birdBmp=BitmapFactory.decodeResource(this.getContext().getResources(), R.drawable.bird); 从Bitmap创建Bitmap 及matrix变化应用 Bitmap birdBmp2=Bitmap.createBitmap(birdBmp, 0,0,birdBmp.getWidth(), birdBmp.getHeight(), matrix, true); canvas setB

我不相信傻鸟的道理

最近无聊,就随处在贴吧里看了看,无意间看到一篇之前的高考零分作文,顿时对这个高考生肃然起敬,这是一个物理学霸,无疑的.可惜这篇作文放错了地方,要是发表在物理学术论坛上,妥妥的满分呀! 下面我就把大致的提纲说下: 阅读下面的材料,根据要求作文.     有一种鸟,它能够飞行几万公里,飞越太平洋,而它需要的只是一小截树枝. 在飞行中,它把树枝衔在嘴里,累了就把那截树枝扔到水面上,然后飞落到树枝上 休息一会儿,饿了就站在树枝上捕鱼,困了就站在树枝上睡觉.谁能想到,小鸟成 功地飞越了太平洋,靠的却仅是一

鸵鸟非鸟?

TQ: 有如下定义: Class 鸟{...:public virtual void Fly(){};...} Class 麻雀{...:public virtual void Fly(){...};...} Class 大雁{...:public virtual void Fly(){...};...} ...... 如果是鸵鸟不能飞,就在飞的方法里抛出异常...异常不能算是一种正常编程逻辑吧 XJ 异常并不是一种好的方法 FX·SL 异常是可以的--异常名就是NotImplException

宋人千首绝句【之一】

<千首宋人绝句>是清代严长明编辑的书籍.全书共十卷,分七言.五言.六言三部分,其中七言七卷.五言两卷.六言一卷,且按帝王.后妃.宫掖.宗室.降王.宋臣.闺媛等分类,收录有王安石.苏轼.黄庭坚.秦观.陆游.杨万里.范成大等著名诗人的六言绝句. 编著者简介:严长明(1731—1787),清诗文家.字冬友,一字道甫,号东有,江宁(今南京)人.长明幼即显露奇慧.年十一岁,李绂典试江南,十分惊奇于这个童子的聪慧,特嘱咐从方苞学.不久,进扬州马曰琯.马曰璐兄弟的学馆,尽读其“小玲珑山庄”藏书.乾隆二十七年

读论语集注(1)

"子曰:学而时习之,不亦说乎?有朋自远方来,不亦乐乎?人不知而不愠,不亦君子乎?"大家非常熟悉的三句话,也是论语第一篇学而篇的第一句话,朱熹在他的书里把学而篇称为入道之门,积德之基.而这开篇第一章更是讲出了学而篇的本意. 我最想说的是第一句,“学而时习之,不亦乐乎?” ”学之为言效也“,效在古文里边有模仿,效仿的意思,也就是说学的这个过程实际上是一个模仿,效仿的过程.那模仿什么呢?“人性皆善,而觉有先后,后觉者必效先觉之所为,乃可以明善而复其初也.”这句话我理解为每个人都有自己的长处和

【史上最全】微信朋友圈游戏源码下载

源码介绍:  所有源码都是html5开发,可以跨平台,无论谷歌安卓还是苹果ios都可以流畅运行,游戏可以根据自己的情况添加链接,可以分享到微信圈后跳转的你的游戏平台页.个别游戏可以设置指定次数提示添加微信账号回复指定内容获得答案.保证游戏可运行性,不像某些不良卖家价格很高买来的根本没几个能用或者很多凑数游戏. 一个简单的营利模式: 通过手机作为入口,分享某某游戏的得分到朋友圈,朋友圈内的病毒式传播速度超过你想象.然后你可以自己加入关注微信代码.百度移动广告代码.淘客代码.等等吧,可以发挥的空间非

无人机将迎来黄金时代

无人机其实不是个新鲜玩意儿,它早就有了,而且给社会做出了巨大的贡献.笔者小时候看<动物世界>时,就非常好奇,那种百鸟乱飞的画面是怎么拍出来的,难不成要摄影师趴到树上蹲点,等着鸟儿们一同起飞,当时,竟然还对摄影师产生了一种肃然起敬的感觉.现在知道了,这个可以利用无人机拍摄,想拍什么角度都行,而且除了无人机之外,摄影师还会放炮,惊起一滩鸥鹭,以创造更唯美的画面. 2016新年伊始,网上爆出了"无人机惊扰天鹅事件",大概内容就是,青海湖畔聚集了1829只大天鹅,个别摄影爱好者为了

泛型的应用

一.简介: 先看看泛型的概念--“通过参数化类型来实现在同一份代码上操作多种数据类型.利用“参数化类型”将类型抽象化,从而实现灵活的复用”. 很多初学者在刚开始接触泛型的时候会比较难理解 “泛型” 在这里先把 “泛型”当作一个形容词 这样比较方便理解 因为很多东西都可以是泛型的 比如-- “泛型的类” ,“泛型的方法”,“泛型的接口”,“泛型的委托” 等...很多时候我们使用泛型可以极大减少代码重复使程序更加清爽,也可以避免不必要的‘装箱’ ‘拆箱’过程. 为什么要有泛型? 在程序设计的过程中我