-
游戏简介
《flappy bird》是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品,游戏于2013年5月24日上线,并在2014年2月突然暴红。2014年2月,《Flappy Bird》被开发者本人从苹果及谷歌应用商店撤下。2014年8月份正式回归APP STORE,正式加Flappy迷们期待已久的多人对战模式。游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管所组成的障碍。我通过用cocos游戏引擎实现该游戏的编写,这也是我第一次使用cocos游戏引擎,如果有的地方编辑不当,请见谅!
-
游戏基本框架截图
-
Game
-
Menu
-
GameOver
-
游戏主要场景简单介绍
-
Menu:控制游戏登录界面,点击按钮进入游戏,控制包括背景滚动和场景切换
-
Game:控制游戏的具体内容,控制包括背景滚动、钢管类及其控制类、小鸟的操作及其形态的变化、碰撞域设置和对本局得分的统计显示以及最高分的显示
-
GameOver:游戏结束界面,包括对当局游戏得分的统计以及对改游戏最高分的统计
-
Menu场景的详细介绍
-
bgN节点:控制背景滚动
-
game_name节点:游戏名称图片插入【tap节点同理:游戏背景装饰】
-
floorN节点:控制地板滚动
-
btnStart节点:开始按钮节点
-
-
Game场景的详细介绍
-
bgN节点:控制背景滚动
-
pipeMgr:钢管控制类节点
-
floorN:地板滚动节点
-
bird3节点:小鸟节点
-
touchN节点:抓取区域节点
-
pipe节点:钢管节点
-
botton_pipe节点:钢管下部分区域【碰撞域】
-
top_pipe节点:钢管上部分区域【碰撞域】
-
passN节点:小鸟通过碰撞域
-
floorCol节点:地板碰撞域
-
scoreL节点:当前得分
-
scoreMaxL节点:游戏最高分
-
-
GameOver场景的详细介绍
-
bgN节点:滚动背景节点
-
图片节点:三个
-
scoreL节点:当前游戏得分
-
scoreMaxL节点:该游戏最高分
-
rGame节点:重新开始新的一轮游戏
-
-
anims:小鸟形态
- drop:小鸟下降状态
- rise:小鸟上升状态
- drop:小鸟下降状态
-
游戏中的所有script:
-
Game:
-
cc.Class({ extends: cc.Component, properties: { touchN:cc.Node, //playerN:cc.Node labelMaxScore:cc.Label }, // LIFE-CYCLE CALLBACKS: onLoad () { /* //全局区域分数 window.score=0; //或者cc.score=0 cc.maxScore=0 */ cc.gameDt={}; cc.gameDt.score=0 cc.gameDt.maxScore=0; let maxScore=cc.sys.localStorage.getItem('maxScore'); if(!maxScore){ cc.sys.localStorage.setItem('maxScore',0); }else{ cc.gameDt.maxScore=maxScore; this.labelMaxScore.string='当前最高分:'+maxScore+'分'; } let manager=cc.director.getCollisionManager(); manager.enabled=true; /* manager.enabledDebugDraw=true; manager.enabledDrawBoundingBox=true;*/ // let playerJs=this.playerN.getComponent('Player'); // this.canMove=false; //this.playerJs=this.playerN.getComponent('Player');//通过节点名取组件 //this.node.on(cc.Node.EventType.TOUCH_START,this.onTouchStart, this); //this.node.on(cc.Node.EventType.TOUCH_MOVE,this.onTouchMove, this); //this.node.on(cc.Node.EventType.TOUCH_END,this.onTouchEnd, this); //1、参数1:事件类型 //2、参数2:回调函数 //3、参数3 this.playerN=cc.find('Canvas/bird3'); let testN = cc.find('Canvas/test'); this.touchN.on(cc.Node.EventType.TOUCH_START,function(event){ let playerJs=this.playerN.getComponent('Player'); //let playerJs=this.playerN.getComponent('bird'); //playerJs.speed=playerJs.riseSpeed; playerJs.rise(); // playerJs.changeState(1); //playerJs.changeState(STATE.STATE_RISE); },this); }, // onTouchStart(event){ // let worldPos=event.getLocation(); // let pos=this.playerN.parent.convertToNodeSpaceAR(worldPos); // let rect=this.playerN.getBoundingBox();//获取节点作用范围的包围盒 // if(rect.contains(pos)){ // //说明鼠标在玩家包围盒内 // this.canMove=true; // } // this.playerJs.rise(); // }, // onTouchMove(event){ // if(this.canMove){ // let worldPos=event.getLocation(); // let pos=this.playerN.parent.convertToNodeSpaceAR(worldPos);//将后者坐标相对前者坐标 // this.playerN.x=pos.x; // this.playerN.y=pos.y; // } // }, // onTouchEnd(event){ // this.canMove=false; // }, start () { }, // update (dt) {}, });
-
-
GameOver:
-
cc.Class({ extends: cc.Component, properties: { scoreL:cc.Label, scoreMaxL:cc.Label }, // LIFE-CYCLE CALLBACKS: // onLoad () {}, start () { let scoreSave=cc.sys.localStorage.getItem('scoreSave'); this.scoreL.string=scoreSave+'分'; let maxScore=cc.sys.localStorage.getItem('maxScore'); this.scoreMaxL.string=maxScore+'分'; }, onBtnRStart(){ cc.director.loadScene('Menu'); } // update (dt) {}, });
-
-
Menu:
-
cc.Class({ extends: cc.Component, properties: { // bird:{ // type:cc.Node, // default:null // }, // speed:0, // speed_x:0, // accel:0 }, // LIFE-CYCLE CALLBACKS: //当前脚本所挂载的节点被加载时引擎会调用该脚本的onLoad函数,一般用于初始化操作 onLoad () { console.log('Menu is load!'); }, start () { console.log('Menu is start!'); }, onBtnStart(){ console.log('开始按钮被点击了!'); cc.sys.localStorage.setItem('scoreSave',0); cc.director.loadScene('Game'); }, update (dt) { //console.log('Menu is update!'); //拿到bird节点 //this.bird.y--; //this.bird.y = this.bird.y + this.speed*dt; // this.speed += this.accel*dt; // this.bird.y += this.speed*dt; // this.bird.x=this.bird.x+this.speed_x*dt; }, // lateUpdate(dt){ // console.log('Menu is late update!'); // } });
-
-
Pipe:
-
cc.Class({ extends: cc.Component, properties: { topPipe:cc.Node, bottomPipe:cc.Node, minBottomY:0, maxBottomY:0, minSpace:300, maxSpace:0 }, onLoad () { //下方水管,y轴取-450-200的随机整数 this.bottomPipe.y=Math.floor(Math.random()* (this.maxBottomY-this.minBottomY)+this.minBottomY); //随机间隔200-300 let space=Math.floor(Math.random()* (this.maxSpace+this.minSpace)+this.minSpace); this.topPipe.y=this.bottomPipe.y+space; }, start () { }, // update (dt) {}, });
-
-
PipeMgr:
-
cc.Class({ extends: cc.Component, properties: { pipePrefab:cc.Prefab }, onLoad () { //定时器 this.schedule(回调函数,时间间隔) //设计一个随机数2-7 //let pipeWidth=Math.floor(Math.random()*5+2); //根据分数来获取间隔 //1-10分:6 //11-20分: 5 //20分-: 3 // if(scoreSave<5){ // pipeWidth=6; // }else if(scoreSave<10){ // pipeWidth=5; // }else{ // pipeWidth=3; // } // let pipeWidth=scoreSave let pipeWidth=Math.floor(Math.random()*5+2); cc.sys.localStorage.setItem('widthP',pipeWidth); let widthP=cc.sys.localStorage.getItem('widthP'); this.schedule(this.addPipe,widthP); }, start () { }, addPipe(){ //创建钢管 //根据预制体prefabs创建模板 let pipeN=cc.instantiate(this.pipePrefab); pipeN.x=cc.winSize.width+100;//获取屏幕宽度 从外面运动进来 //1、this.node.addChild(pipe); //2. pipeN.parent=this.node; //动作系统 //cc.moveTo(时间,目的点); let moveTo=cc.moveTo(8,cc.v2(-100,pipeN.y)); //let movBy=cc.moveBy(cc.v2(-(cc.winSize.width+200),0)); let removeSelf=cc.removeSelf(); //pipeN.runAction(moveTo); //pipeN.runAction(removeSelf); let seq=cc.sequence(moveTo,removeSelf);//串行序列动作 顺序进行 //moveBy移动了多少距离 //moveBy移动到什么位置 pipeN.runAction(seq); let pipeWidth=Math.floor(Math.random()*5+2); this.unschedule(this.addPipe); this.schedule(this.addPipe,pipeWidth); //cc.sys.localStorage.setItem('widthP',pipeWidth); }, update (dt) { //取到所有钢管 // let children=this.node.children; // for(let i=0;i<children.length;++i){ // children[i].x += (-200)*dt; // } // for(let i=0;i<children.length;++i){ // if(children[i].x<-100){ // children[i].destroy(); // } // } }, });
-
-
Player:
-
//枚举表示状态 let STATE=cc.Enum({ STATE_NONE:-1,//-1从0开始代表默认值 STATE_RISE:-1, STATE_DROP:-1 }) //默认第一个为0,后一个比第一个多1 cc.Class({ extends: cc.Component, properties: { accel:0, speed:0, riseSpeed:300, scoreL:cc.Label, scoreMaxL:cc.Label, // audioSource: { // type: cc.AudioSource, // default: null // }, // play: function () { // this.audioSource.play(); // }, // pause: function () { // this.audioSource.pause(); // }, }, // LIFE-CYCLE CALLBACKS: onLoad () { //this.state=0;//0代表初始状态 1代表上升 2代表下降 this.state=STATE.STATE_NONE; this.anim=this.node.getComponent(cc.Animation); }, start () { }, rise(){ //this.anim.play('rise'); this.speed=this.riseSpeed; this.changeState(STATE.STATE_RISE); }, update (dt) { //速度=当前速度+加速度*时间 this.speed+=this.accel*dt; this.node.y+=this.speed*dt; if(this.speed<=0){ //this.changeState(2); this.changeState(STATE.STATE_DROP); } }, //简答到状态机 changeState(state){ if(this.state===state){ return; } this.state=state; this.anim.stop();//停止播放动作 //if(this.state===1){ if(this.state===STATE.STATE_RISE){ this.anim.play('rise'); this.node.rotation=0; //this.speed=this.riseSpeed; }else if(this.state===STATE.STATE_DROP){ //头朝下 this.anim.play('drop'); } }, onCollisionEnter(other,self){ // console.log('下啊啊啊'); // other.node.destroy(); if(other.tag===1){ console.log('钢管碰到'); //other.destroy(); //调用游戏结束界面 cc.director.loadScene('GameOver'); }else if(other.tag===2){ console.log('地板碰到'); //调用游戏结束界面 cc.director.loadScene('GameOver'); }else if(other.tag===3){ console.log('通过'); //得分 cc.gameDt.score++; this.scoreL.string='当前得分:'+cc.gameDt.score+'分'; let scoreSave=cc.sys.localStorage.setItem('scoreSave',cc.gameDt.score); if(cc.gameDt.score>cc.gameDt.maxScore){ //cc.gameDt.loadScene.setItem('maxScore',cc.gameDt.maxScore); cc.gameDt.maxScore=cc.gameDt.score; this.scoreMaxL.string='当前最高分:'+cc.gameDt.maxScore+'分'; cc.sys.localStorage.setItem('maxScore',cc.gameDt.maxScore); } } } });
-
-
Scorell:
-
cc.Class({ extends: cc.Component, properties: { scrollN1:cc.Node, scrollN2:cc.Node, speed:0 }, start () { }, update (dt) { this.scrollN1.x+=this.speed*dt; this.scrollN2.x+=this.speed*dt; if(this.scrollN1.x<=-this.scrollN1.width){ this.scrollN1.x=this.scrollN2.x+this.scrollN2.width; } if(this.scrollN2.x<=-this.scrollN2.width){ this.scrollN2.x=this.scrollN1.x+this.scrollN1.width; } }, });
-
-
游戏链接:https://pan.baidu.com/s/15nWxE0ZYVVc3vQ4mcbFZKA 提取码:hidu