检查Snake是否在游戏中撞到了自己

时间:2011-08-05 14:57:22

标签: c++ opengl glfw

我正在用C ++编写Snake,使用OpenGL和GLFW。我试图实现一个游戏退出的功能,当蛇头撞到它的身体。 这是我写的Snake类的move()和CrashCheck()函数。 x_pos是一个浮点数组,用于存储蛇体段的x_coordinate。 y_pos与y_coordinate相同。长度是蛇的身体部分的数量,并且当蛇吃食物(尚未实施)时增加。 x_speed和y_speed存储沿轴的段的速度。蛇不能同时沿着两个轴移动;另外,float MAX_S = 0.00075;。我也包括了我的draw()函数。而Fix_Snake_x和Fix_Snake_y是重新调整蛇段的功能(因为它们不断分离并对游戏造成严重破坏)。我知道这是纠正问题的一种愚蠢的方法,所以如果你可以在move()函数中建议修复,那会有所帮助。

void draw(float win_aspect)
  {
    for(int a = 0; a < length; a++)
      {
        Fix_Snake_y();
        glBegin(GL_QUADS);
        glColor3f(1.0,0.0,0.0);
        glVertex2f(x_pos[a],y_pos[a]);
        glVertex2f((x_pos[a]+0.05),y_pos[a]);
        glVertex2f((x_pos[a]+0.05),y_pos[a]-0.05);
        glVertex2f(x_pos[a],y_pos[a] - 0.05);
        glEnd();
        Fix_Snake_x();
      }
  } 

void move()
  {
      for(int a = length ; a >= 0; a--)
        {
          if(a > 0)
            {
              if(x_pos[a] >= x_pos[a-1] && x_speed[a] < 0)
                {
                  x_pos[a] += -MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(x_pos[a] <= x_pos[a - 1])
                  {
                     x_speed [a] = 0;
                     if(y_pos[a] <= y_pos[a-1])
                     {
                          y_speed[a] = MAX_S;
                     }
                     else
                     {
                           y_speed[a] = -MAX_S;
                     }
                   }
                }
              if(x_pos[a] <= x_pos[a-1] && x_speed[a] > 0)
                {
                  x_pos[a] += MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(x_pos[a] >= x_pos[a - 1])
                    {
                      x_speed [a] = 0;
                      if(y_pos[a] <= y_pos[a-1])
                       {
                          y_speed[a] = MAX_S;
                       }
                      else
                        {
                          y_speed[a] = -MAX_S;
                        }
                    }
                }
              if(y_pos[a] <= y_pos[a-1] && y_speed[a] > 0)
                {
                  y_pos[a] += MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(y_pos[a] >= y_pos[a-1])
                    {
                      y_speed[a] = 0;
                      if(x_pos[a] >= x_pos[a-1])
                        {
                          x_speed[a] = -MAX_S;
                        }
                      if(x_pos[a] <= x_pos[a-1])
                        {
                          x_speed[a] = MAX_S;
                        }
                    }
                }
              if(y_pos[a] >= y_pos[a-1] && y_speed[a] < 0)
                {
                  y_pos[a] += -MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(y_pos[a] <= y_pos[a-1])
                    {
                      y_speed[a] = 0;
                      if(x_pos[a] >= x_pos[a-1])
                        {
                          x_speed[a] = -MAX_S;
                        }
                      if(x_pos[a] <= x_pos[a-1])
                        {
                          x_speed[a] = MAX_S;
                        }
                    }
                }
        }


          if(a == 0)
                {
                  x_pos[0] += x_speed[0];
                  y_pos[0] += y_speed[0];
                  Fix_Snake_y();
                  Fix_Snake_x();
                }
             CrashCheck();
            }
      }
      void CrashCheck()
      {
        for(int a = 1; a < length; a++)
          {
            if(y_speed[0] > 0 && y_speed[a] == 0)
              {
                if(x_pos[0] < x_pos[a] && x_pos[0] < x_pos[a] + 0.05)
                  {
                    if(y_pos[0] < y_pos[a] && y_pos[0] > y_pos[a] - 0.05)
                      {
                        exit(0);
                      }
                  }
              }
            else if(y_speed[0] < 0 && y_speed[a] == 0)
              {
                if(x_pos[0] > x_pos[a] && x_pos[0] < x_pos[a] + 0.05)
                  {
                    if(y_pos[0] < y_pos[a] && y_pos[0] > y_pos[a] - 0.05)
                      {
                        exit(0);
                      }
                  }
              }
          }
      }
void Fix_Snake_x()
  {
    for(int a = 1; a<length; a++)
      {
        if(a > 0)
          {
            if(x_pos[a] <= x_pos[a-1] - 0.05)
              {
                x_pos[a] = x_pos[a-1] - 0.05;
              }
            if(x_pos[a] >= x_pos[a -1] + 0.05)
              {
                x_pos[a] = x_pos[a-1] + 0.05;
              }
          }
      }
  }
  void Fix_Snake_y()
  {
    for(int a = 1; a < length; a++)
          {
            if(a > 0)
              {
                if(y_pos[a] <= y_pos[a-1] - 0.05)
                  {
                    y_pos[a] = y_pos[a-1] - 0.05;
                  }
                if(y_pos[a] >= y_pos[a-1] + 0.05)
                  {
                    y_pos[a] = y_pos[a-1] + 0.05;
                  }
              }
          }
  }

编辑: 新移动功能

for(int a = 0; a < length; a++)
        {
            if(a > 0)
              {
                if(x_speed[a] < 0 && x_pos[a] >= x_pos[a-1])
                  {
                    x_pos[a] += x_speed[a];
                    if(x_pos[a] == x_pos[a-1])
                      {
                        y_speed[a] = y_speed[a-1];
                        x_speed[a] = 0;
                        continue;
                      }
                  }
                if(x_speed[a] > 0 && x_pos[a] <= x_pos[a-1])
                  {
                    x_pos[a] += x_speed[a];
                    if(x_pos[a] == x_pos[a-1])
                      {
                        y_speed[a] = y_speed[a-1];
                        x_speed[a] = 0;
                        continue;
                      }
                  }
                if(y_speed[a] > 0 && y_pos[a] <= y_pos[a-1])
                  {
                    y_pos[a] += y_speed[a];
                    if(y_pos[a] == y_pos[a-1])
                      {
                        x_speed[a] = x_speed[a-1];
                        y_speed[a] = 0;
                      }
                  }
                if(y_speed[a] < 0 && y_pos[a] >= y_pos[a-1])
                  {
                    y_pos[a] += y_speed[a];
                    if(y_pos[a] == y_pos[a-1])
                      {
                        x_speed[a] = x_speed[a-1];
                        y_speed[a] = 0;
                      }
                  }
              }
            else
              {
                x_pos[0] += x_speed[0];
                y_pos[0] += y_speed[0];
              }
        }

造成一些问题。蛇打破它有太多的同时转弯。只有前两个块保持运动

2 个答案:

答案 0 :(得分:0)

我强烈建议您使用动态容器来保持蛇体的坐标。这允许您获取蛇新位置的坐标并在容器中搜索坐标。如果找到了这一点,蛇就会陷入其中。

同样,你可以拥有墙壁和街区的容器以及不属于董事会的其他实体。

另一种方法是使用网格数据结构(或矩阵),并在其中放置代表蛇体和其他障碍物的值。

答案 1 :(得分:0)

如果我是你,我会存储一个std::set,其中包含蛇无法进入的所有无效坐标。那将包括:

  • “playground”的边界
  • 障碍
  • 蛇的身体

然后对于蛇的每次移动,考虑到x / y速度,我首先尝试InsertLocation进入CInvalidPlaces,如果返回true那么我可以步,如果false那么蛇即将撞墙,边界或它自己的身体和“游戏”都可以完成。这是代码:

#include <set>
using namespace std;

typedef pair<int,int> tInvalidLocation;

struct ltSeCmp
{
    bool operator()(tInvalidLocation s1, tInvalidLocation s2) const
    {
        if (s1.first == s2.first) return s1.second > s2.second;
        return s1.first > s2.first;
    }
};

typedef set<tInvalidLocation, ltSeCmp> tInvalidLocations;

class CInvalidPlaces
{
private:
    tInvalidLocations mInvalid; //this set will hold all the invalid locations for the snake to go to
public:
    bool InsertLocation(tInvalidLocation iLoc)
    {
        if (mInvalid.find(iLoc) != mInvalid.end()) return false;    //check if the location is already in the set
        //we survived.. it's safe to go there :)
        mInvalid.insert(iLoc);
        return true;
    }
    bool RemoveLocation(tInvalidLocation iLoc)
    {
        if (mInvalid.find(iLoc)== mInvalid.end()) return false;
        mInvalid.insert(iLoc);
        return true;
    }
};

您还需要做的是:

  • 最初添加蛇的边距,所有障碍物和所有位置,就像它们从蛇开始的位置一样
  • 修改移动例程,这样当蛇移动时,它也必须使用CInvalidPlaces
  • RemoveLocation尾部移除
  • 实施蛇的“放大”之后,您还必须将CInvalidPlaces添加到额外的细分中。

如果需要,您可以在以下位置找到有关stl::set的详细信息:

HTH,
JP