[超简单]怎么用Cocos2d-x v3.0做一个贪吃蛇,包括跨平台_DZ老师[图文码]傻瓜教程

其实这个教程写好很久了,也许因为(这个号是新号==true),发帖一直有问题,又因为((!草稿箱可以用)==true),最后决定先发出来,慢慢编辑…事情就是这样,喵!
------------------------篇幅有点长--------------------------不要着急---------------------------------------慢慢来--------------------------------------------------------

首先自我介绍一下,我是人人敬爱的DZ老师,撒花!撒花! 有问题的男同学可以给我留言。女同学加QQ460418221!然后这个教程一直发不上来,考虑了半天 我先发C,S,D,N 我会告诉你我把它当草稿箱了么。。 ,不想等我慢慢发上来的可以直接访问 http://blog.csdn.net/ycd_harry/article/details/23455787
-----------------------------------------------------------------------------要开始了啊------------------------------------------------------------------------------------------------------------

环境:
cocos2d-x-3.0rc1
Xcode5
OS X 10.9.2


*1.*创建一个新的项目!具体方法见:http://www.cocos2d-x.org/docs/manual/framework/native/getting-started/v3.0/how-to-start-a-new-game/en
(E文不好的朋友请自带翻译妹子或翻译软件)

项目就叫个snake!真是霸气。顺带一提cocos console真是赞!

机器叫了一会 给我了个文件夹叫snake。居然有194.5m!


,我和我的晚饭都觉得项目”自由“了,好饿阿 中饭没次



*2.*双击snake/pro.ios_mac/snake.xcodeproj 打开项目,按照国际惯例 我们先编译以下看看这货能不能跑!

跑的异常欢快!!
然后我们找到class 和resources 这两个文件夹很重要。


*3.*接下来 先准备好素材把!打开ps画一个 妥妥的

,就是这个像饭团一样的东西,要的自己拿吧 一块钱一个。
把这个饭团导入resources,直接拖!就是那个bo.png,这个贪吃蛇要用到的素材就这个饭团。


*4.*选个场景,就用这个项目自带的场景, 一个场景足够了,把除了那个按钮之外的node都注释掉吧,没用了。删了也没事。关闭按钮留着,好看又好用。


*5.*首先 我们先把控制实现,无非是上下左右3.0与以前的触摸机制不一样了,采用设置监听器的方式,让我想起了j2se里图形化界面的监听方式。
控制的实现思想:用两个一次函数 把屏幕分为4个三角型,上下左右分别一块,用来控制蛇的移动方向。看代码就明白!

auto listener1 = EventListenerTouchOneByOne::create();//创建一个监听
    listener1->setSwallowTouches(true);//设置是否想下传递触摸
    listener1->onTouchBegan = ](Touch* touch, Event* event){
        auto target = static_cast<Sprite*>(event->getCurrentTarget());//获取的当前触摸的目标
 
        Point p = target->convertToNodeSpace(touch->getLocation());
        Size s = target->getContentSize();
        Rect rect = Rect(0, 0, s.width, s.height);
        auto winsize = Director::getInstance()->getVisibleSize();
 
 
        if (rect.containsPoint(p))//判断触摸点是否在目标的范围内
        {
            if(winsize.height/winsize.width * p.x+p.y>winsize.height)
            {
                if(winsize.height/winsize.width * p.x<p.y)
                {
                    log("up");
                }else
                {
                    log("left");
                }
            }else
            {
                if(winsize.height/winsize.width * p.x<p.y)
                {
                    log("right");
                }
                else
                {
                    log("down");
                }
            }
 
            return true;
        }else
            return false;  
    };
 
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);

这样就完成了控制!方向键都省了。

顺带一提 在3.0里面声明变量可以不用说明类型 用auto代替,当然你也可以声明类型。


*6.*好了接下来我们把蛇实现了,蛇是一节节的,要一个vector来存储每一节,每节都用我们的上面的饭团图片来表示。贪吃蛇吃的苹果 也用这个图片来表示,为了区别 我们用setColor上点颜色。蛇上绿色吧,苹果是红色。然后我们在init里面创建蛇头和苹果。

this->apple = Sprite::create("bo.png");    apple->setAnchorPoint(Point(0,0));    apple->setPosition(Point(22*20,12*20));    apple->setColor(Color3B(255,0,0));    this->addChild(this->apple);      auto head = Sprite::create("bo.png");    head->setAnchorPoint(Point(0,0));    head->setPosition(Point(2*20,12*20));    head->setColor(Color3B(0,255,0));    this->snake.pushBack(head);    this->addChild(this->snake.at(0));

*7.*用一个schedule来控制蛇持续移动

void HelloWorld::up_date(float dt){
    move(this->direction, this->snake.size()-1);
}


this->direction = 2;
    this->speed = 100;
    schedule(schedule_selector(HelloWorld::up_date), 60/this->speed);

整型direction控制方向 1:上,2:右,3:下,4:左

整型speed 控制蛇的速度。
move方法来控制每一节身体的移动,具体见源码吧 比较多 不帖出来了。


*8.*关联控制器和direction ,刚才写好的控制现在可以用了,改变方向并调用一次move,为了操作的手感好一点 我在这里写了一个函数用来重置了控制移动的schedule,如果要改变速度的话也要调用这个函数,不过这边我们还不考虑变速。
很好!现在我们小蛇已经可以动了 ,不过只有一节。。。


*9.*接下来我们让我们的蛇可以吃苹果,写了一个函数testEat用来检测有没有吃到苹果!

void HelloWorld::testEat(){    auto head_size = this->snake.at(0)->getContentSize();    auto head_point = this->snake.at(0)->getPosition();    auto head_rect = Rect(head_point.x,head_point.y,20 ,20);    auto apple_point = this->apple->getPosition();    auto ap = Point(apple_point.x+10,apple_point.y+10);    if(head_rect.containsPoint(ap)){        log("Good eat!!");         auto body = Sprite::create("bo.png");        body->setAnchorPoint(Point(0,0));        body->setColor(Color3B(0,255,0));        this->snake.pushBack(body);        this->addChild(this->snake.at(this->snake.size()-1));        body->setPosition(this->snake.at(this->snake.size()-2)->getPosition());         //random set apple        auto winsize = Director::getInstance()->getVisibleSize();        auto x_l = winsize.width/20-1;        auto y_l = winsize.height/20-1;        while (true) {            srand((int)time(NULL)+(int)time(0));            this->apple->setPosition(Point( (rand() % ((int)x_l+1)) *20,(rand() % ((int)y_l+1))*20));            bool b = true;            for (auto i=0; i<this->snake.size(); i++) {                auto body_size = this->snake.at(i)->getContentSize();                auto body_point = this->snake.at(i)->getPosition();                auto body_rect = Rect(body_point.x,body_point.y,20 ,20);                auto apple_ppoint = this->apple->getPosition();                auto app = Point(apple_ppoint.x+10,apple_ppoint.y+10);                if(body_rect.containsPoint(app)){                    b=false;                }            }            if (b)                break;        }           testGameisOver(false);    }}

吃到苹果,加一节 应该很好理解。后面的代码用来改变苹果的位置,让蛇可以再吃一次。。所以本质上苹果没有被吃掉。。。只是跑了,不管,最后的函数用来测试游戏的胜负,吃到40节就赢啦!


*10.*接下来是怎么检测蛇挂了。。。真是不吉利,好吧,吃到自己或者碰到墙壁就结束游戏!具体见testGameisOver函数,每次move后要调用检测一下。

 //失败情况 1.撞墙 2.吃到自己 (移动后检测)         bool b = false;        if (snake.size()>2) {            for (auto i=1; i<this->snake.size(); i++) {                auto body_size = this->snake.at(i)->getContentSize();                auto body_point = this->snake.at(i)->getPosition();                auto body_rect = Rect(body_point.x,body_point.y,20 ,20);                auto head_point = this->snake.at(0)->getPosition();                auto app = Point(head_point.x+10,head_point.y+10);                if(body_rect.containsPoint(app)){                    b=true;                }            }        }         if (this->snake.at(0)->getPositionX() >= winsize.width || this->snake.at(0)->getPositionX() < 0 ||            this->snake.at(0)->getPositionY() >= winsize.height || this->snake.at(0)->getPositionY() < 0 || b)        {            //game over            unschedule(schedule_selector(HelloWorld::up_date));            _eventDispatcher->removeEventListenersForType(EventListener::Type::TOUCH_ONE_BY_ONE);            auto label = LabelTTF::create("GAME OVER", "Arial", 50);            label->setPosition(Point(winsize.width/2,winsize.height/2));            this->addChild(label, 1);            label->setScale(0);            label->runAction(ScaleTo::create(3, 1.5));            label->setOpacity(0);            label->runAction(FadeTo::create(1.5, 255));            this->runAction(Sequence::create(DelayTime::create(5),CallFunc::create(]{Director::getInstance()->replaceScene(HelloWorld::createScene());}), NULL));         }

*11.*胜负!
其实上面的代码已经显示出来!有一个label弹出来,我加了点动画,然后等个几秒 重新载入场景 ,test里面都是这么干的。。。。
截个输的图吧,赢得画面要花点时间才看得到。


*12.*其实到这里游戏已经基本上完成了,虽然有点简陋,而且在电脑上操作也不太方便,可以考虑加入上下左右的键盘控制,绘制两条对角直线等,这篇就这样吧,下一篇我会稍微完善一下,然后在win32 android 和mac iOS四个平台上运行。!真是赞!请大家支持Dz.Harry.Yang 谢谢大家!跟我一起来学 cocos2d-x 3.0吧!

声明:今天是第一天接触2dx3.0,有些地方写的不太好,希望高手不要喷阿!善意的提醒万分欢迎,


一起学习!!

上篇文章已经基本完成了一个贪吃蛇,虽然可以改进的地方还有很多,但是勉强他也算个游戏。
现在我们再加一点东西!然后就跨平台啊!超赞有木有!!


*1.*绘制对角线:
绘制这个的主要目的是方便用户控制,否者点击很容易失误,体验较坑!
这个很简单,我们只需要override一个函数。见代码

void HelloWorld::draw(cocos2d::Renderer* renderer, const kmMat4 &transform, bool transformUpdated){    //draw Line    Size visibleSize = Director::getInstance()->getVisibleSize();     glLineWidth(3);    DrawPrimitives::setDrawColor4B(255, 255,0, 20);    DrawPrimitives::drawLine(Point(0,0), Point(visibleSize.width,visibleSize.height));    DrawPrimitives::drawLine(Point(0,visibleSize.height), Point(visibleSize.width, 0));    CHECK_GL_ERROR_DEBUG();
}

效果有点奇怪 不过可以提醒用户,就这样吧。


好的,接下来是重头戏了!2dx是跨平台游戏引擎!果断开跨阿!!手上设备有限,先跨.mac,ios,win32,android四个平台。一个个来。
iOS就不截图了 一直是在iOS 模拟器里面测试的。
mac 先来,这个也简单 。
先换这个!

,然后我们点击运行!
我擦,出错了!说精灵的图片找不到,我们看看资源。。

原来是ios 现在要换mac了,看了Build Phases 确实少了bo.png将他加入,问题解决。


好的下一个是win32 平台,我换台电脑,这个mac 没有虚拟机。。。
。。。。。
好的换机完成,我将工程搞过来,现在的工程都是自由的 不用依赖原来的目录,真是赞!

拷贝过来 直接打开snake\proj.win32\snake.sln 然后运行一下···开始编译了···好慢····
又出错了····提醒要我保存成Unicode !凭我的多年看片的经验 !应该是编码的问题,嗯没错!
打开HelloWorldScene.cpp,保存成Unicode!哦了!


接下来是android平台了,这个比较关键!
发现snake\proj.android\里面有一个build_native.py 按照国际惯例,介货应该是用来编译android项目的,但是我不需要,我就想要个APK 。。。。。
于是乎我打开CMD 定位到项目目录,惨无人道的执行了cocos run -p android,屏幕一大堆字幕一阵乱跳!完事了,怎么模拟器没弹出来。。。纳闷了,按照估计惯例应该会有android模拟器出来,也许是没配置好,不管他。
搜索了一会。在snake目录下发现了一个叫做snake\bin\debug\android 下面发现了一个叫做s_nake-debug-unaligned.apk的文件!!!

DZ顿时两眼放光,心想,如此强烈的元素波动!简直堪比教廷的红衣主教的实力,DZ虎躯一震,双手已经放在了鼠标之上,随时准备了生死一搏,虽然刚才激烈的战斗使他的护身斗气都隐隐有些松动,甚至连气海里面的晶核都失去立刻以往耀眼的光芒,但是事到如今,似乎已经没有退路,一个受过风之守护祝福的魔法师的速度肯定远远快于现在的他!我擦 写穿越了···怎么回事,我在写教程··不是小说···


,赶紧回来。。
这个APK文件,对,把我的小山寨机连上,然后命令行定位到这个文件,执行adb install s_nake-debug-unaligned.apk 多次,都安装失败了!一怒之下,直接把这个文件拷到SD卡上,然后用手机安装,然后。。然后我就笑了。。。。

好的!至此,这个简陋的贪吃蛇在计划中的平台上都运行的很欢快。
这两天的学习也让我跟熟悉了2DX3.0的玩法,还是有点小小的收获的。

声明:本人菜鸟,哪里做的不对或者不周全,请不要喷,请友好的提醒 谢谢!!
篇幅有点短,做个广告:本人花费半个学期独立制作的网游Mage-mini 作为MAGE的附属小游戏,开发进入尾声,敬请期待,谢谢大家 撒花撒花

PS:本游戏的素材大部分是dz自己绘制,有小部分是度娘给我,我自己做过墙裂的处理,已经面目全非,如有仍然有雷同,纯属无奈,有任何侵权问题请联系我QQ:460418221。也欢迎大家同志们加好友交流技术,唠嗑请勿打扰(妹子除外!


)。

差点忘了,最后还要 附上游戏的APK!!!游戏的源码过一段时间会公布
最后,
小朋友冰天雪地果体螺旋跪求大家留言啊··················

小朋友,32个赞!!!

360度无死角图文解说,大家快快参与哦。教程都这么优秀,奖品可是不多了哦~:14::14::14:

:14::14:

:14::14:改天做个高级点的教程

:9::9:

喵~~~
虽然看不懂,不过帖子一定花了很长时间编辑的吧。辛苦!!!!

您的文章已被推荐到CocoaChina首页热门文章精选

为人民服务!我叫红领巾。

:3::3:谢谢大王!

我是来打酱油的 dz_yang 你的偶像是啦啦查查么 签名都是拉拉

:856:这文采,无敌了!女同事看到第一段笑喷了。

360°超炫赞,小弟学习了。

看起来很深奥的样子~给你58个赞~

坚持学习,好帖

:8:还以为有源码

:2::2::2:最后一行看成妹子勿扰了;