进击贪吃蛇开发教程黑白格什么的弱爆了

直接进入正题,准备工作:环境搭建什么的不在本教程的范围内就不说了,接下准备图片资源什么的。背景图,LOGO,开始结束图片什么的。蛇的图片可没地找只好自己动手P了一个。包括头部躯干弯的,直的,尾巴。吃的的东西我准备了3个小球,用TP打包好。


新建cocos工程名为snake.打开工程.打开AppDelegate。.cpp文件加入1行如下设定屏幕尺寸新建载入场景用于载入资源代码如下

auto glview = director->getOpenGLView(); 

if(!glview) { 
glview = GLView::create("snake"); 
director->setOpenGLView(glview); 
} 
director->setOpenGLView(glview); 
//glview->setFrameSize(480,800); 
glview->setDesignResolutionSize(480,800, ResolutionPolicy::SHOW_ALL);

loadingsnece载入资源

void LoadingScene::onEnter(){
 // add background to current scene
 Sprite *background = Sprite::create("logo.png");
 Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
 background->setPosition(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2);
 
 this->addChild(background);
 // start ansyc method load the atlas.png
 Director::getInstance()->getTextureCache()->addImageAsync("ui.png", CC_CALLBACK_1(LoadingScene::loadingCallBack, this));
}
 SpriteFrameCache* cache = SpriteFrameCache::getInstance();
    cache->addSpriteFramesWithFile("ui.plist","ui.png");  

建立个蛇节snakenode类继承臼sprite䖵节的宽度为50,在这里我们跟据sprite里的gettag()决定snakenode的图片及方向,具体看代码

const int SNAKE_HEAD_UP=0;
const int SNAKE_HEAD_DOWN=2;
const int SNAKE_HEAD_LEFT=3;
const int SNAKE_HEAD_RIGHT=1;
const int SNAKE_BODY_UP=4;
const int SNAKE_BODY_DOWN=6;
const int SNAKE_BODY_LEFT=7;
const int SNAKE_BODY_RIGHT=5;
const int SNAKE_CORNER_LEFT_UP=16;
const int SNAKE_CORNER_LEFT_DOWN=18;
const int SNAKE_CORNER_UP_LEFT=19;
const int SNAKE_CORNER_UP_RIGHT=17;
const int SNAKE_TAIL_UP=8;
const int SNAKE_TAIL_DOWN=10;
const int SNAKE_TAIL_LEFT=11;
const int SNAKE_TAIL_RIGHT=9;
const int SNAKE_CORNER_RIGHT_UP=12;
const int SNAKE_CORNER_RIGHT_DOWN=14;
const int SNAKE_CORNER_DOWN_LEFT=15;
const int SNAKE_CORNER_DOWN_RIGHT=13;
void SnakeNode::setSnakeNode(int tag){
 this->setTag(tag);
 this->setSpriteFrame(this->getFrameNameByTag( tag));
 this->setSnakeNodeRotate();
}
void SnakeNode::setSnakeNodeRotate(){
 int tag=this->getTag();
  int rotate=90*(tag%4);
  if(tag==SNAKE_CORNER_RIGHT_UP||tag==SNAKE_CORNER_DOWN_LEFT)
  rotate=180;
  if(tag==SNAKE_CORNER_RIGHT_DOWN || tag==SNAKE_CORNER_UP_LEFT)
   rotate=90;
  if(tag==SNAKE_CORNER_LEFT_UP||tag==SNAKE_CORNER_DOWN_RIGHT)
   rotate=270;
  if(tag==SNAKE_CORNER_LEFT_DOWN||tag==SNAKE_CORNER_UP_RIGHT)
   rotate=0;
 
 this->setRotation(rotate);
}
SpriteFrame* SnakeNode::getFrameNameByTag(int tag){
 switch(tag){
 case SNAKE_HEAD_UP:
 case SNAKE_HEAD_DOWN:
 case SNAKE_HEAD_LEFT:
 case SNAKE_HEAD_RIGHT:
  return SpriteFrameCache::getInstance()->getSpriteFrameByName("snake_head.png");
 case SNAKE_BODY_UP:
 case SNAKE_BODY_DOWN:
 case SNAKE_BODY_LEFT:
 case SNAKE_BODY_RIGHT:
  return SpriteFrameCache::getInstance()->getSpriteFrameByName("snake_body.png");
 case SNAKE_CORNER_DOWN_LEFT:
 case SNAKE_CORNER_LEFT_DOWN:
 case SNAKE_CORNER_RIGHT_DOWN:
 case SNAKE_CORNER_UP_LEFT:
 case SNAKE_CORNER_DOWN_RIGHT:
 case SNAKE_CORNER_LEFT_UP:
 case SNAKE_CORNER_RIGHT_UP:
 case SNAKE_CORNER_UP_RIGHT:
  return SpriteFrameCache::getInstance()->getSpriteFrameByName("snake_corner.png");
 case SNAKE_TAIL_UP:
 case SNAKE_TAIL_DOWN:
 case SNAKE_TAIL_LEFT:
 case SNAKE_TAIL_RIGHT:
  return SpriteFrameCache::getInstance()->getSpriteFrameByName("snake_tail.png");
 }
 return NULL;
}

这里建立了一个snake类继承自node类,还是直接上代码

class Snake :
 public Node
{
public:
 Snake(void);
 ~Snake(void);
 CREATE_FUNC(Snake);
 void createSnake();
 void play();
 void setDirection(int direction);
 int  getDirection();
 bool IsDie(Rect rect);
 Vector<SnakeNode*> getSnakeNodes();
  void addSnakeNode();
  void resetSnake();
private:
 void setSnakeNode(Sprite *SnakeNode);
 Point getNext(); 
 int getInsertTag(int oldTag, int newTag);
 int direction;
 Vector<SnakeNode*> node; 
};

蛇的位置移动更新方式为头部向前移动一格,取出尾巴插入头的后面有点邪恶…根据头部的tag及控制的方向没置tag及图片,然后将vector的最后一个变成尾郜,当蛇吃到一个球时尾部不变,在头部后面插入一个新的snakenode。

void Snake::play(){
 SnakeNode *snakeNode=node.back();
 //int tag=snakeNode->getTag();
 snakeNode->setPosition(node.front()->getPosition());
 snakeNode->setSnakeNode(this->getInsertTag(node.front()->getTag(),this->getDirection()));
 node.insert(1,snakeNode);
 if(node.front()->getTag()!=this->getDirection()){
  node.front()->setTag(this->getDirection());   
  node.front()->setSnakeNodeRotate();
 }
 node.front()->setPosition(getNext());
 
 node.popBack();
 snakeNode=node.back();
 snakeNode->setSnakeNode(snakeNode->getTag()%4+8);
}

现在我们的贪吃蛇己经能够前进了,在GameLayer中我们这过触摸屏幕来控制蛇的移动方向.当头部方向为上下时触摸屏幕门左右邹分来控制,头部弓向为左右时通过判断屏幕上下控制,代码如下,

void GameLayer::setSnakeDirection(Point p){
 if(bSetDirection) return;
 if(snake->getDirection()%2==0){
  if(p.x>SCREEN_WIDTH/2)
   snake->setDirection(SNAKE_HEAD_RIGHT);
  else
   snake->setDirection(SNAKE_HEAD_LEFT);
 }
 else{
  if(p.y>SCREEN_HEIGHT/2)
   snake->setDirection(SNAKE_HEAD_UP);
  else
   snake->setDirection(SNAKE_HEAD_DOWN);
 }
 bSetDirection=true;
}

下面是判断蛇出界及碰到自己身体的代码

bool Snake::IsDie(Rect rect){
 
 if(!rect.containsPoint(node.front()->getPosition()))
  return true;
 Rect box=node.front()->getBoundingBox();
 auto point=node.front()->getPosition();
  point.x=point.x*SNAKE_WIDTH;
  point.y=point.y*SNAKE_WIDTH;
 for(SnakeNode *snakenode:node){
  if(snakenode->getTag()>SNAKE_HEAD_LEFT)
   if(snakenode->getBoundingBox().containsPoint(point))
    return true;
 }
 return false;
}

接下来我们要在屏幕上放置球了,要求球的位置不能被放在蛇的身上,下面的代码得到一个随机的位置及球

void GameLayer::setBall(){
 if(ball==NULL){
  ball=Sprite::create();
  this->addChild(ball,1);
 }
 vector<Point> tmpList;
 for(int i=1;i<SCREEN_WIDTH/SNAKE_WIDTH-1;i++)
  for(int j=1;j<SCREEN_HEIGHT/SNAKE_WIDTH-1;j++){
   Point point(i*SNAKE_WIDTH,j*SNAKE_WIDTH);
   if(!this->IsSnakeContainsBall(point))
    tmpList.push_back(point);
  }
  int tmpListSize=tmpList.size();   
   if(tmpListSize>0){
    
   int tmp=CCRANDOM_0_1()*(tmpListSize-1);
   ball->setPosition(tmpList.x,tmpList.y);
   String str;
   tmp=CCRANDOM_0_1()*3;
   switch (tmp){
   case 0:
    str="football.png";
    break;
   case 1:
    str="Volleyball.png";
    break;
   case 2:
    str="basketball.png";
    break;
   }
   ball->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(str._string));
   }
}

下面的代码是通过头部的buildingbox是否包含球的坐标点来判断是否吃到球

bool GameLayer::IsEatBall(){
 if(snake->getSnakeNodes().front()->boundingBox().containsPoint(ball->getPosition())){
  score++;
  return true;}
 return false;
}

贪吃蛇的主要部分就完成了,计分,难度设置,死亡动画,声效可自行添加

支持一个:2::2::2:

楼主你碉堡了。。。都自带美工了。。。感谢您的热心参与~

我玩了一下好像触摸判断方向还有点问题,判断不准确。:14::14::14:

不会哦。方向很正常哦,看了下面这张图你就明白

看起来感觉就不错 非常感谢分享

感谢楼主分享,楼主辛苦了,不过怎么没有发现源码