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

用 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值