新人初学cocos2d-x游戏开发,制作的小demo(贪吃蛇)

鄙人做iOS应用开发有一段时间了,一直对游戏开发有浓厚的兴趣,只是少了游戏入门的方法, 最近在论坛中看到了 极客学院的免费视频(好像是关联邮箱限免一天,我不是在给极客打广告哦,只是觉得视频确实不错.)才得以初窥门径.有些不足的地方希望大神们多多指教.闲话不多说,上代码

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class SnakeSprite;
class BodyScene;
class HelloWorld : public cocos2d::Layer
{
private:
    cocos2d::Size visibleSize;
    cocos2d::LayerColor *layerColorGB;
    SnakeSprite *snake;
    BodyScene *food;
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    CREATE_FUNC(HelloWorld);
    // 判断方向
    void handleDirect(cocos2d::Point point);
    // 创建背景
    void drawBackground();
    // 初始化蛇
    void initSnake();
    // 初始化食物
    BodyScene* createFood();
    // 长大
    void growUp();
};

#endif // __HELLOWORLD_SCENE_H__


#include "HelloWorldScene.h"
#include "SnakeScene.h"
#include "BodyScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::createWithPhysics();
    
    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
    scene->getPhysicsWorld()->setGravity(Vec2(0, 0));
    scene->getPhysicsWorld()->setSpeed(10);
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    visibleSize = Director::getInstance()->getVisibleSize();
    
    drawBackground();
    
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = (Touch *t, Event *e){
        if (e->getCurrentTarget()->getBoundingBox().containsPoint(t->getLocation())) {
            Point point = t->getPreviousLocation();
            this->handleDirect(point);
            return true;
        }
        return  false;
    };
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
    
    return true;
}

void HelloWorld::handleDirect(cocos2d::Point point)
{
    Direct d = snake->getDirect();
    Point p = snake->getPosition();
    short xx = point.x - p.x;
    short yy = (point.y - (visibleSize.height-visibleSize.width)/2) - p.y;
    
    Direct newDirect = d;
    switch (d) {
        case Up:
        {
            if (abs(xx) > abs(yy)) {
                if (xx > 0) {
                    // right
                    newDirect = Right;
                } else {
                    //left
                    newDirect = Left;
                }
            } else {
                if (yy < 0) {
                    // down
//                    newDirect = Down;
                }
            }
        }
            break;
        case Down:
        {
            if (abs(xx) > abs(yy)) {
                if (xx > 0) {
                    // right
                    newDirect = Right;
                } else {
                    //left
                    newDirect = Left;
                }
            } else {
                if (yy > 0) {
                    // up
//                    newDirect = Up;
                }
                
            }
        }
            break;
        case Left:
        {
            if (abs(yy) > abs(xx)) {
                if (yy > 0) {
                    // up
                    newDirect = Up;
                } else {
                    //down
                    newDirect = Down;
                }
            } else {
                if (xx > 0) {
                    // right
//                    newDirect = Right;
                }
                
            }
        }
            break;
        case Right:
        {
            if (abs(yy) > abs(xx)) {
                if (yy > 0) {
                    // up
                    newDirect = Up;
                } else {
                    //down
                    newDirect = Down;
                }
            } else {
                if (xx < 0) {
                    // left
//                    newDirect = Left;
                }
                
            }
        }
            break;
        default:
            newDirect = d;
            break;
    }
    
    snake->setDirect(newDirect);
}

void HelloWorld::drawBackground()
{
    int width = visibleSize.width;
    int height = visibleSize.height;
 
    layerColorGB = cocos2d::LayerColor::create(Color4B(200,200,200,255), width, width);
    layerColorGB->setPosition(Point(0, (visibleSize.height-visibleSize.width)/2));
    addChild(layerColorGB);
    
    width = width;
    height = width;
    
    int column = width/20;
    int row = height/20;
    for (int i = 0; i < row; i++) {
        int y = i * 20;
        Point p = Point(0, y);
        Size size = Size(width, 1);
        LayerColor *line = LayerColor::create(Color4B(255, 0, 255, 200), size.width, size.height);
        line->setPosition(p);
        layerColorGB->addChild(line);
    }
    
    for (int j = 0; j < column; j++) {
        int x = j *20;
        Point p = Point(x, 0);
        Size size = Size(1, height);
        LayerColor *line = LayerColor::create(Color4B(255, 0, 255, 200), size.width, size.height);
        line->setPosition(p);
        layerColorGB->addChild(line);
    }
    // 创建蛇
    initSnake();
}

void HelloWorld::initSnake(){
    snake = SnakeSprite::createSnake(1);
    // eat
    snake->onEat = (SnakeSprite *s, void * v){
        this->growUp();
    };
    // game over
    snake->reGameOver = ](void *v){
        Director::getInstance()->replaceScene(TransitionFade::create(1, HelloWorld::createScene()));
    };
    layerColorGB->addChild(snake);
    snake->start();
    // 创建食物
    this->createFood();
    snake->setFood(food);
}

BodyScene* HelloWorld::createFood(){
    // 加入随机整数
    srand((unsigned)time(NULL));
    int x = rand()%32 * 20+10;
    int y = rand()%32 * 20+10;
    x = MIN(x, 630);
    y = MIN(y, 630);
    Point position = Point(x,y);
    Size size = Size(20,20);
    
    food = BodyScene::createBody(position, size);
    layerColorGB->addChild(food);
    return food;
}

void HelloWorld::growUp(){
    __Array *bodys = snake->getBodys();
    __Array *newBodys = __Array::create();
    newBodys->addObject(food);
    
    food->removeFromParent();
    snake->addChild(food);
    newBodys->addObjectsFromArray(bodys);
    snake->setBodys(newBodys);
    
    createFood();
    snake->setFood(food);
}



#ifndef __Snake__SnakeScene__
#define __Snake__SnakeScene__
#include "cocos2d.h"

typedef enum : int {
    Up = 0,
    Down,
    Left,
    Right,
} Direct;
class BodyScene;
class SnakeSprite:public cocos2d::Sprite{
private:
    int number;
    cocos2d::__Array *bodys;
    Direct direct;
    cocos2d::Point position;    //
    BodyScene *food;// food 用来判断是否吃到食物
public:
    std::function onEat;
    std::function reGameOver;
    virtual bool init();
    // 创建方法
    static SnakeSprite *createSnake(int num);
    void enemyInit(int num);
    
    CREATE_FUNC(SnakeSprite);
    // get set 方向
    Direct getDirect();
    void setDirect(Direct d);
    // 跑的动作
    void run(float x);
    // 开始跑
    bool start();
    // 结束
    void end();
    
    void setPosition(cocos2d::Point p);
    cocos2d::Point getPosition();
    
    cocos2d::__Array *getBodys();
    void setBodys(cocos2d::__Array *bs);
    
    BodyScene *getFood();
    // 设置food 用来判断是否吃到食物
    void setFood(BodyScene *b);
    // 判断是否继续游戏
    bool GameOver();
    
//    void addBody();
};

#endif /* defined(__Snake__SnakeScene__) */

#include "SnakeScene.h"
#include "BodyScene.h"

#define BODY_WIDTH          20

USING_NS_CC;

bool SnakeSprite::init(){
    if ( !Sprite::init() )
    {
        return false;
    }
    
    return true;
}

SnakeSprite *SnakeSprite::createSnake(int num){
    
    SnakeSprite *enemy = new SnakeSprite();
    if (enemy && enemy->init()) {
        enemy->autorelease();
        enemy->enemyInit(num);
        return enemy;
    }
    CC_SAFE_DELETE(enemy);
    return NULL;
}

void SnakeSprite::enemyInit(int num){
    number = num;
    bodys = __Array::create();
    bodys->retain();
    Point position = Point((640-BODY_WIDTH)/2,(640-BODY_WIDTH)/2);
    Size size = Size(BODY_WIDTH, BODY_WIDTH);
    BodyScene *body = BodyScene::createBody(position, size);

    bodys->addObject(body);
    this ->addChild(body);
}

Direct SnakeSprite::getDirect()
{
    return direct;
}
void SnakeSprite::setDirect(Direct d)
{
    direct = d;
}

bool SnakeSprite::start(){
    this->schedule(schedule_selector(SnakeSprite::run), 0.2);
    return true;
}

void SnakeSprite::end(){
    this->unschedule(schedule_selector(SnakeSprite::run));
    CC_SAFE_DELETE(bodys);
}

void SnakeSprite::setPosition(cocos2d::Point p)
{
    position = p;
}

cocos2d::Point SnakeSprite::getPosition()
{
    return position;
}

cocos2d::__Array* SnakeSprite::getBodys(){
    return bodys;
}

void SnakeSprite::setBodys(cocos2d::__Array *bs)
{
    CC_SAFE_DELETE(bodys);
    bodys = __Array::create();
    bodys = bs;
    bodys->retain();
}

BodyScene *SnakeSprite::getFood()
{
    return food;
}
void SnakeSprite::setFood(BodyScene *b)
{
    CC_SAFE_RELEASE(food);
    food = b;
    food->retain();
}

// 1 2 3 4 5
void SnakeSprite::run(float x){
    
    int space = BODY_WIDTH;
    int count = (int)bodys->count();
    for (int i = count-1; i >= 0; i--) {
            BodyScene *body1 = (BodyScene *)bodys->getObjectAtIndex(i);
        if (i > 0) {
            BodyScene *body2 = (BodyScene *)bodys->getObjectAtIndex(i-1);
            body1->setPosition(body2->getPosition());
            
        } else {
            Point position = Point(body1->getPosition().x, body1->getPosition().y + space);
            switch (direct) {
                case Up:
                {
                    position = Point(body1->getPosition().x, body1->getPosition().y + space);
                }
                    break;
                case Down:
                {
                    position = Point(body1->getPosition().x, body1->getPosition().y - space);
                }
                    break;
                case Left:
                {
                    position = Point(body1->getPosition().x - space, body1->getPosition().y);
                }
                    break;
                case Right:
                {
                    position = Point(body1->getPosition().x+space, body1->getPosition().y);
                }
                    break;
                    
                default:
                    break;
            }
            setPosition(position);
            body1->setPosition(position);
        }
    }
    
    if (GameOver()) {
        end();
        reGameOver(NULL);
    }
}

bool SnakeSprite::GameOver(){
    
    BodyScene *first = (BodyScene *)bodys->getObjectAtIndex(0);
    for (int i = 1; i < bodys->count(); i++) {
        BodyScene *body = (BodyScene *)bodys->getObjectAtIndex(i);
        if (first->getPosition() == body->getPosition()) {
            return true;
        }
    }
    
    if (first->getPosition().x <= 0 || first->getPosition().y <= 0 || first->getPosition().x >= 640 || first->getPosition().y >= 640) {
        return true;
    }
    
    log("(x1=%f, y1=%f) (x2=%f, y2=%f)",first->getPosition().x, first->getPosition().y, food->getPosition().x, food->getPosition().y);
    if (first->getPosition() == food->getPosition()) {
        // eat
        onEat(this, NULL);
    }
    
    return false;
}




#ifndef __Snake__BodyScene__
#define __Snake__BodyScene__

#include "cocos2d.h"
class BodyScene:public cocos2d::Sprite{
private:
    int x, y;
    cocos2d::Point position;
    cocos2d::Size size;
    // 显示背景
    cocos2d::LayerColor *layerColorBG;
public:
    virtual bool init();
    
    CREATE_FUNC(BodyScene);
    
    static BodyScene *createBody(cocos2d::Point position, cocos2d::Size size);;
    static BodyScene *createBody(int x, int y, cocos2d::Size size);;
    void enemyInit(cocos2d::Point position, cocos2d::Size size);
};

#endif /* defined(__Snake__BodyScene__) */




#include "BodyScene.h"
USING_NS_CC;

bool BodyScene::init(){
    if (!Sprite::init()) {
        return false;
    }
    return true;
}

BodyScene * BodyScene::createBody(cocos2d::Point position, cocos2d::Size size)
{
    BodyScene *enemy = new BodyScene();
    if (enemy && enemy->init()) {
        enemy->autorelease();
        enemy->enemyInit(position, size);
        return enemy;
    }
    CC_SAFE_DELETE(enemy);
    return NULL;
}

BodyScene *BodyScene::createBody(int x, int y, cocos2d::Size size)
{
    BodyScene *enemy = new BodyScene();
    if (enemy && enemy->init()) {
        enemy->autorelease();
        enemy->enemyInit(cocos2d::Point(x,y), size);
        return enemy;
    }
    CC_SAFE_DELETE(enemy);
    return NULL;
}
void BodyScene::enemyInit(cocos2d::Point position, cocos2d::Size size)
{
    this->x = position.x;
    this->y = position.y;
    this->position = position;
    this->size = size;
    this->setContentSize(size);
    this->cocos2d::Node::setPosition(position);
    layerColorBG = cocos2d::LayerColor::create(Color4B(200, 0, 100, 255), size.width, size.height);
    layerColorBG->setPosition(0,0);
    this->addChild(layerColorBG);
}


```



源码:https://codeload.github.com/sfwan2014/SnakeDemo/zip/master,1