0

我正在使用 OpenGL 和 GLFW 用 C++ 编写 Snake。我正在尝试实现一个游戏退出的功能,当蛇头撞到它的身体时。这是我编写的 Snake 类的 move() 和 CrashCheck() 函数。x_pos 是一个浮点数组,存储了蛇身的一段 x_coordinate。y_pos 与 y_coordinate 相同。length 是蛇的身体节段数,当蛇吃东西时会增加(尚未实现)。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];
              }
        }

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

4

2 回答 2

0

我强烈建议您使用动态容器来保存蛇身体的坐标。这允许您获取蛇新位置的坐标并在容器中搜索坐标。如果找到该点,则蛇已撞到自己。

同样,您可以为墙和块以及其他不属于棋盘的实体的点提供容器。

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

于 2011-08-05T15:58:25.907 回答
0

如果我是你,我会将 astd::set与所有蛇无法到达的无效坐标一起存储。这将包括:

  • “操场”的边界
  • 障碍
  • 蛇的身体

然后对于蛇的每一次移动,考虑到我首先尝试InsertLocation进入的 x/y 速度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额外的部分。

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

HTH,
太平绅士

于 2011-08-05T16:50:31.543 回答