上手!2DX3.0我来啦!先做一个贪吃蛇练练手(第一弹)

来源:互联网 发布:全世界第一家网络银行 编辑:程序博客网 时间:2024/05/01 12:15

用 cocos2d-x 3.0rc1版本做一个贪吃蛇,顺便写一个教程,碰到问题就试着解决。第一次写,写的丑了莫怪,实用为主

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

环境:

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,有些地方写的不太好,希望高手不要喷阿!善意的提醒万分欢迎,可怜可怜可怜我只是个学生。。。还在学习阿!!

0 0