TouchSnow的专栏

方向cocos2d-java,cocos2d-js ,cocos2d-x

flappy bird游戏源代码揭秘和下载

背景:

  最近火爆全球的游戏flappy bird让笔者叹为观止,于是花了一天的时间山寨了一个一模一样的游戏,现在把游戏的思路和源码分享出来,代码是基于javascript语言,cocos2d-x游戏引擎,cocos2d-x editor手游开发工具完成的,请读者轻砸;

  ps:运行demo必须配置好cocos2d-x editor,暂不支持其他工具。还有demo是跨平台的,可移植运行android,ios,html5移动系统等;


Android Apk下载:(演示效果)

 暂时只移植打包到android系统,可下载运行看看效果;

腾讯微云:http://share.weiyun.com/cac18d8c58d40bf2401b3fdeeb6bcb2f


代码下载:

代码集中营免费下载:  http://blog.makeapp.co/?p=306&preview=true

csdn下载:http://download.csdn.net/detail/touchsnow/6912707

百度云盘:http://pan.baidu.com/s/1pJnWDb9

金山快盘 :http://www.kuaipan.cn/file/id_25348935635745384.htm?source=1


代码如何移植到各平台:

 Android:http://blog.csdn.net/touchsnow/article/details/19176091

 html5:       http://blog.makeapp.co/?p=245


效果图:








cocos2d-x跨平台游戏引擎

cocos2d-x是全球知名的游戏引擎 ,引擎在全球范围内拥有众多开发者,涵盖国内外各知名游戏开发商。目前Cocos2d-x引擎已经实现横跨ios、Android、Bada、MeeGo、BlackBerry、Marmalade、Windows、Linux等平台。编写一次,到处运行,分为两个版本 cocos2d-c++和cocos2d-html5 本文使用了后者;
cocos2d-x 官网:http://cocos2d-x.org/
cocos2d-x 资料下载  http://cocos2d-x.org/download


cocos2d-x editor开发工具:

   cocos2dx editor,它是开发跨平台的手机游戏工具,运行window/mac系统上,javascript脚本语言,基于cocos2d-x跨平台游戏引擎, 集合代码编辑,场景设计,动画制作,字体设计,还有粒子,物理系统,地图等等的,而且调试方便,和实时模拟;

cocos2dx editor 下载,介绍和教程:http://blog.csdn.net/touchsnow/article/details/19070665

cocos2dx editor官方博客:http://blog.makeapp.co/;(请持续关注版本更新)


思路和源码:


  1 场景设计MainLayer.ccbx,如下图;主要分三层,开始场景、主场景、游戏结束场景,通过显示隐藏控制三个场景的切换。

 

   MainLayer.ccbx代码

<?xml version="1.0" encoding="UTF-8"?>

<Document
        jsControlled="true"
        jsController="MainLayer"
        resolution="default"
        >

    <Resolutions>
        <Resolution centeredOrigin="false" ext="iphone" height="1280" width="720" name="default" scale="1"/>
        <Resolution centeredOrigin="false" ext="iphone" height="720" width="1280" name="default1" scale="1"/>
    </Resolutions>

    <Animations>
        <Animation autoPlay="true"
                   id="0"
                   name="Default Timeline"
                   length="10"
                   chainedId="0"
                   offset="0.0"
                   position="0.0"
                   resolution="30"
                   scale="128">
            <CallbackChannel>
            </CallbackChannel>
            <SoundChannel>
            </SoundChannel>
        </Animation>

    </Animations>
    <Layer
            positionX="0" positionY="0.0"
            sizeType="Percent"
            width="100" height="100"
            anchorPointX="0.5" anchorPointY="0.5" ignoreAnchorPoint="true"
            scaleX="1" scaleY="1"
            >

      <Sprite positionType="LeftBottom" width="720.0" height="1280.0" positionX="0" positionY="0" anchorPointX="0"
                                         anchorPointY="0" src="Resources/bg.png" name="" var="" target="None" scaleX="1" scaleY="1" visible="true"/>
      <LayerColor positionType="LeftBottom" width="720" height="1280" positionX="0" positionY="0" anchorPointX="0"
                  anchorPointY="0" color="#fff2e8ff" visible="false"/>
      <Menu positionType="LeftBottom" width="40" height="40" positionX="356.0" positionY="237.0" anchorPointX="0.5"
              anchorPointY="0.5" scaleX="2.4" scaleY="1.725">
      </Menu>
      <Sprite positionType="LeftBottom" width="840.0" height="281.0" positionX="0" positionY="0" anchorPointX="0"
                                         anchorPointY="0" src="Resources/ground.png" var="ground" target="Doc"/>
      <Node positionType="LeftBottom" width="40" height="40" positionX="800" positionY="250" anchorPointX="0"
            anchorPointY="0" var="hoseNode" target="Doc">
        <Sprite positionType="LeftBottom" width="86.0" height="60.0" positionX="-500" positionY="400" anchorPointX="0.5"
                                         anchorPointY="0.5" src="Resources/flappy_packer.plist/bird3.png" var="test" target="Doc" visible="false"/>
        <Sprite positionType="LeftBottom" width="86.0" height="60.0" positionX="-550" positionY="500" anchorPointX="0.5"
                anchorPointY="0.5" src="Resources/flappy_packer.plist/bird1.png" var="bird" target="Doc" scaleX="1" scaleY="1" rotation="0" visible="true"/>
      </Node>
      <Node positionType="LeftBottom" width="40" height="40" positionX="303.0" positionY="500" anchorPointX="0.5"
            anchorPointY="0.5" var="readyNode" target="Doc" visible="true">
        <Sprite positionType="LeftBottom" width="508.0" height="158.0" positionX="95.0" positionY="584.0" anchorPointX="0.5"
                                         anchorPointY="0.5" src="Resources/flappy_packer.plist/getready.png"/>
        <Sprite positionType="LeftBottom" width="286.0" height="246.0" positionX="73.0" positionY="236.0" anchorPointX="0.5"
                                         anchorPointY="0.5" src="Resources/flappy_packer.plist/click.png"/>
      </Node>
      <Node positionType="LeftBottom" width="40" height="40" positionX="300" positionY="500" anchorPointX="0.5"
            anchorPointY="0.5" var="overNode" target="Doc" visible="true">
        <Sprite positionType="LeftBottom" width="590.0" height="298.0" positionX="72.0" positionY="219.0" anchorPointX="0.5"
                                         anchorPointY="0.5" src="Resources/flappy_packer.plist/base.png">
          <Sprite positionType="LeftBottom" width="508.0" height="158.0" positionX="286.0" positionY="458.0" anchorPointX="0.5"
                                         anchorPointY="0.5" src="Resources/flappy_packer.plist/gameover.png"/>
        </Sprite>
        <Menu positionType="LeftBottom" width="40" height="40" positionX="0" positionY="0" anchorPointX="0.5"
              anchorPointY="0.5">
          <MenuItem positionType="LeftBottom" width="290" height="176" positionX="-65.0" positionY="-92.0" anchorPointX="0.5"
                    anchorPointY="0.5" normalImage="Resources/flappy_packer.plist/start.png" target="Doc" onClick="onStartClicked"/>
          <MenuItem positionType="LeftBottom" width="290" height="176" positionX="230.0" positionY="-92.0" anchorPointX="0.5"
                    anchorPointY="0.5" target="Doc" normalImage="Resources/flappy_packer.plist/grade.png" onClick="onGradeClicked"/>
        </Menu>
      </Node>
    </Layer>


</Document>

 

2 代码编写MainLayer.js

   首先,小鸟在向前飞,其实是底部的路和水管在向左移动,相对的你就感觉小鸟在向右飞了;路循环移动代码:

MainLayer.prototype.groundRun = function ()
{
    var action1 = cc.MoveTo.create(0.5, cc.p(-120, 0));
    var action2 = cc.MoveTo.create(0, cc.p(0, 0));
    var action = cc.Sequence.create(action1, action2);
    this.ground.runAction(cc.RepeatForever.create(action));
}

   初始化高低不同的水管,每一关卡都由上下两水管和空隙组成。总长度相同,空隙也一定,随机取下面水管的长度,就形成错落有致的水管关卡;

MainLayer.prototype.newHose = function (num)
{
    var hoseHeight = 830;
    var acrossHeight = 300;
    var downHeight = 100 + getRandom(400);
    var upHeight = 1100 - downHeight - acrossHeight;

    var hoseX = 400 * num;

    var HoseName = FP_MAIN_TEXTURE.HOSE;
    var ccSpriteDown = cc.Sprite.createWithSpriteFrameName(HoseName[0]);
    ccSpriteDown.setZOrder(1);
    ccSpriteDown.setAnchorPoint(cc.p(0, 0));
    ccSpriteDown.setPosition(cc.p(hoseX, 0));
    ccSpriteDown.setScaleY(downHeight / hoseHeight);

    var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(HoseName[1]);
    ccSpriteUp.setZOrder(1);
    ccSpriteUp.setAnchorPoint(cc.p(0, 0));
    ccSpriteUp.setPosition(cc.p(hoseX, downHeight + acrossHeight));
    ccSpriteUp.setScaleY(upHeight / hoseHeight);

    this.hoseNode.addChild(ccSpriteDown);
    this.hoseNode.addChild(ccSpriteUp);
    this.hoseSpriteList.push(ccSpriteDown);
    this.hoseSpriteList.push(ccSpriteUp);
    return null;
}

  一开始进入游戏让底部路不断移动,初始化水管,显示准备游戏场景;

MainLayer.prototype.onEnter = function ()
{
    cc.AnimationCache.getInstance().addAnimations("Resources/flappy_frame.plist");
    this.groundRun();
    this.ground.setZOrder(10);
    this.birdReadyAction();
    this.bird.setZOrder(20);
    this.readyNode.setVisible(true);
    this.overNode.setVisible(false);

    for (var i = 0; i < 30; i++) {
        this.newHose(i);
    }
}

 点击屏幕,小鸟向上飞60dp,然后更快的速度下落(移动动画),同时闪动翅膀(帧动画);

MainLayer.prototype.birdRiseAction = function ()
{
    var riseHeight = 60;
    var birdX = this.bird.getPositionX();
    var birdY = this.bird.getPositionY();
    var time = birdY / 600;

    var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
    var flyAction = cc.Repeat.create(actionFrame, 90000);
    var riseAction1 = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight));
    var riseAction2 = cc.RotateTo.create(0, -30);
    var riseAction = cc.Spawn.create(riseAction1, riseAction2);
    var fallAction1 = cc.MoveTo.create(time, cc.p(birdX, 50));
    var fallAction2 = cc.Sequence.create(cc.DelayTime.create(time / 6), cc.RotateTo.create(0, 30));
    var fallAction = cc.Spawn.create(fallAction1, fallAction2);

    this.bird.stopAllActions();
    this.bird.runAction(cc.Spawn.create(
            cc.Sequence.create(riseAction, cc.DelayTime.create(0.1), fallAction),
            flyAction)
    );
}

 检测碰撞,如果小鸟碰到地面和水管,发生碰撞,这里碰撞直接用cocos2d-x 里面的图片和图片交叉函数 cc.rectIntersectsRect;

MainLayer.prototype.checkCollision = function ()
{
    if (this.bird.getPositionY() < 60) {
        cc.log("floor");
        this.birdFallAction();
        return;
    }
    for (var i = 0; i < this.hoseSpriteList.length; i++) {
        var hose = this.hoseSpriteList[i];
        if (!this.isInScreen(hose)) {
            // continue;
        }

        if (cc.rectIntersectsRect(hose.getBoundingBox(), this.bird.getBoundingBox())) {
            cc.log("hose positionX==" + hose.getBoundingBox().x);
            cc.log("this.bird positionX==" + this.bird.getBoundingBox().x);
            cc.log("i==" + i);
            cc.log("birdFallAction");
            this.birdFallAction();
            return;
        }
    }
}

碰撞后,小鸟先下落,游戏结束场景显示;

MainLayer.prototype.birdFallAction = function ()
{
    this.gameMode = OVER;
    this.bird.stopAllActions();
    this.ground.stopAllActions();
    var birdX = this.bird.getPositionX();
    var birdY = this.bird.getPositionY();
    var time = birdY / 2000;
    this.bird.runAction(cc.Sequence.create(
            cc.DelayTime.create(0.1),
            cc.Spawn.create(cc.RotateTo.create(time, 90), cc.MoveTo.create(time, cc.p(birdX, 50))))
    );
    this.overNode.setVisible(true);
}

游戏的难度主要在于多个水管的移动,小鸟触摸动画,检测碰撞,我把Mainlayer.js所有代码贴出来;

FP_MAIN_TEXTURE = {
    FRAME_ANIMS: "beanstalk/Resources/bs_main_anims.plist",
    HOSE: ["holdback1.png", "holdback2.png"]
}

READY = 1;
START = 2;
OVER = 3;

var MainLayer = function ()
{
    cc.log("MainLayer");
    this.bird = this.bird || {};
    this.ground = this.ground || {};
    this.hoseNode = this.hoseNode || {};
    this.readyNode = this.readyNode || {};
    this.overNode = this.overNode || {};

    this.passTime = 0;
    this.hoseSpriteList = [];
    this.isStart = false;

    this.gameMode = READY;
};

MainLayer.prototype.onDidLoadFromCCB = function ()
{
    if (sys.platform == 'browser') {
        this.onEnter();
    }
    else {
        this.rootNode.onEnter = function ()
        {
            this.controller.onEnter();
        };
    }

    this.rootNode.schedule(function (dt)
    {
        this.controller.onUpdate(dt);
    });

    this.rootNode.onExit = function ()
    {
        this.controller.onExit();
    };

    this.rootNode.onTouchesBegan = function (touches, event)
    {
        this.controller.onTouchesBegan(touches, event);
        return true;
    };

    this.rootNode.onTouchesMoved = function (touches, event)
    {
        this.controller.onTouchesMoved(touches, event);
        return true;
    };
    this.rootNode.onTouchesEnded = function (touches, event)
    {
        this.controller.onTouchesEnded(touches, event);
        return true;
    };
    this.rootNode.setTouchEnabled(true);
};

MainLayer.prototype.onEnter = function ()
{
    cc.AnimationCache.getInstance().addAnimations("Resources/flappy_frame.plist");
    this.groundRun();
    this.ground.setZOrder(10);
    this.birdReadyAction();
    this.bird.setZOrder(20);
    this.readyNode.setVisible(true);
    this.overNode.setVisible(false);

    for (var i = 0; i < 30; i++) {
        this.newHose(i);
    }
}

MainLayer.prototype.newHose = function (num)
{
    var hoseHeight = 830;
    var acrossHeight = 300;
    var downHeight = 100 + getRandom(400);
    var upHeight = 1100 - downHeight - acrossHeight;

    var hoseX = 400 * num;

    var HoseName = FP_MAIN_TEXTURE.HOSE;
    var ccSpriteDown = cc.Sprite.createWithSpriteFrameName(HoseName[0]);
    ccSpriteDown.setZOrder(1);
    ccSpriteDown.setAnchorPoint(cc.p(0, 0));
    ccSpriteDown.setPosition(cc.p(hoseX, 0));
    ccSpriteDown.setScaleY(downHeight / hoseHeight);

    var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(HoseName[1]);
    ccSpriteUp.setZOrder(1);
    ccSpriteUp.setAnchorPoint(cc.p(0, 0));
    ccSpriteUp.setPosition(cc.p(hoseX, downHeight + acrossHeight));
    ccSpriteUp.setScaleY(upHeight / hoseHeight);

    this.hoseNode.addChild(ccSpriteDown);
    this.hoseNode.addChild(ccSpriteUp);
    this.hoseSpriteList.push(ccSpriteDown);
    this.hoseSpriteList.push(ccSpriteUp);
    return null;
}

MainLayer.prototype.groundRun = function ()
{
    var action1 = cc.MoveTo.create(0.5, cc.p(-120, 0));
    var action2 = cc.MoveTo.create(0, cc.p(0, 0));
    var action = cc.Sequence.create(action1, action2);
    this.ground.runAction(cc.RepeatForever.create(action));
}

MainLayer.prototype.birdReadyAction = function ()
{
    var birdX = this.bird.getPositionX();
    var birdY = this.bird.getPositionY();
    var time = birdY / 2000;
    var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
    var flyAction = cc.Repeat.create(actionFrame, 90000);
    this.bird.runAction(cc.Sequence.create(
            flyAction)
    );
}

MainLayer.prototype.birdFallAction = function ()
{
    this.gameMode = OVER;
    this.bird.stopAllActions();
    this.ground.stopAllActions();
    var birdX = this.bird.getPositionX();
    var birdY = this.bird.getPositionY();
    var time = birdY / 2000;
    this.bird.runAction(cc.Sequence.create(
            cc.DelayTime.create(0.1),
            cc.Spawn.create(cc.RotateTo.create(time, 90), cc.MoveTo.create(time, cc.p(birdX, 50))))
    );
    this.overNode.setVisible(true);
}

MainLayer.prototype.birdRiseAction = function ()
{
    var riseHeight = 60;
    var birdX = this.bird.getPositionX();
    var birdY = this.bird.getPositionY();
    var time = birdY / 600;

    var actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("fly"));
    var flyAction = cc.Repeat.create(actionFrame, 90000);
    var riseAction1 = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight));
    var riseAction2 = cc.RotateTo.create(0, -30);
    var riseAction = cc.Spawn.create(riseAction1, riseAction2);
    var fallAction1 = cc.MoveTo.create(time, cc.p(birdX, 50));
    var fallAction2 = cc.Sequence.create(cc.DelayTime.create(time / 6), cc.RotateTo.create(0, 30));
    var fallAction = cc.Spawn.create(fallAction1, fallAction2);

    this.bird.stopAllActions();
    this.bird.runAction(cc.Spawn.create(
            cc.Sequence.create(riseAction, cc.DelayTime.create(0.1), fallAction),
            flyAction)
    );
}

MainLayer.prototype.onUpdate = function (dt)
{
    if (this.gameMode != START) {
        return;
    }
    this.passTime += dt;

    this.hoseNode.setPositionX(800 - 200 * this.passTime);
    this.bird.setPositionX(-500 + 200 * this.passTime);
    this.checkCollision();
}

MainLayer.prototype.checkCollision = function ()
{
    if (this.bird.getPositionY() < 60) {
        cc.log("floor");
        this.birdFallAction();
        return;
    }
    for (var i = 0; i < this.hoseSpriteList.length; i++) {
        var hose = this.hoseSpriteList[i];
        if (!this.isInScreen(hose)) {
            // continue;
        }

        if (cc.rectIntersectsRect(hose.getBoundingBox(), this.bird.getBoundingBox())) {
            cc.log("hose positionX==" + hose.getBoundingBox().x);
            cc.log("this.bird positionX==" + this.bird.getBoundingBox().x);
            cc.log("i==" + i);
            cc.log("birdFallAction");
            this.birdFallAction();
            return;
        }
    }
}

MainLayer.prototype.isInScreen = function (sprite)
{
    return (sprite.getPositionX() > 0 && sprite.getPositionX() < 720);
}

MainLayer.prototype.onExitClicked = function ()
{
}

MainLayer.prototype.onStartClicked = function ()
{
    cc.Director.getInstance().resume();
    cc.BuilderReader.runScene("", "MainLayer");
}

MainLayer.prototype.onExit = function ()
{
    cc.log("onExit");
}

MainLayer.prototype.onTouchesBegan = function (touches, event)
{
    var loc = touches[0].getLocation();
}

MainLayer.prototype.onTouchesMoved = function (touches, event)
{
}

MainLayer.prototype.onTouchesEnded = function (touches, event)
{
    if (this.gameMode == OVER) {
        return;
    }

    if (this.gameMode == READY) {
        this.gameMode = START;
        this.readyNode.setVisible(false);
    }

    var loc = touches[0].getLocation();
    this.birdRiseAction();

}

function isInRect(ccRect, ccTouchBeganPos)
{
    if (ccTouchBeganPos.x > ccRect.x && ccTouchBeganPos.x < (ccRect.x + ccRect.width)) {
        if (ccTouchBeganPos.y > ccRect.y && ccTouchBeganPos.y < (ccRect.y + ccRect.height)) {
            return true;
        }
    }
    return false;
}

function getRandom(maxSize)
{
    return Math.floor(Math.random() * maxSize) % maxSize;
}

再次提示代码下载地址:

csdn下载:http://download.csdn.net/detail/touchsnow/6912707

百度云盘:http://pan.baidu.com/s/1pJnWDb9

金山快盘 :http://www.kuaipan.cn/file/id_25348935635745384.htm?source=1


flappy博文系列:

flappy bird游戏源代码揭秘和下载

flappy bird游戏源代码揭秘和下载后续---移植到android真机上

flappy bird游戏源代码揭秘和下载后续---移植到html5网页浏览器

flappy bird游戏源代码揭秘和下载后续---日进5万美元的秘诀AdMob广告 

flappy bird游戏源代码揭秘和下载后续---移植到苹果ios上 (未写


笔者语:

想了解更多请进入官方博客,最新博客和代码在官方博客首发;请持续关注,还有更多cocos2dx editor游戏源码即将放出;

联系笔者:zuowen@makeapp.co(邮箱)qq群:232361142


后言:

为了鼓励更多手游爱好者加入cocos2d-x editor阵营,也为了读者坚定对该工具的信心,笔者基于以上的flappy bird代码和新的图片资源,往google play和中国应用市场发布了一个相似的游戏----腾飞的小鸟(fly bird)。该游戏还加入了广告模块,可以获得些许的广告费。也希望读者通过cocos2d-x editor可以在市场上发布更多的好游戏;

google play地址:https://play.google.com/store/apps/details?id=com.makeapp.game.flybird (小秘密:如果应用.apk后缀改为.rar,你会获得意想不到的东西

豌豆荚市场地址:http://www.wandoujia.com/apps/com.makeapp.game.flybird

机锋市场地址:    http://apk.gfan.com/Product/App741996.html

html5在线演示:http://www.makeapp.co/flybird/ (微软ie浏览器存在兼容性问题,请选择其他浏览器;公司内网,小卡,见谅)


阅读更多
个人分类: 实战项目--FlappyBird
想对作者说点什么? 我来说一句

Flappy Bird 游戏完整源码

2017年11月07日 1011KB 下载

flappy bird源代码

2014年02月26日 16.07MB 下载

FlappyBird源码及素材

2014年05月16日 1.19MB 下载

android高仿flappy bird源码

2014年04月11日 2.39MB 下载

FlappyBird源代码

2015年04月06日 1.3MB 下载

FlyBird游戏java源代码完整版

2015年07月26日 38.32MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭