检查蛇是不是在游戏中撞到自己[关闭]
Posted
技术标签:
【中文标题】检查蛇是不是在游戏中撞到自己[关闭]【英文标题】:Check if the Snake bangs into itself in game [closed]检查蛇是否在游戏中撞到自己[关闭] 【发布时间】:2011-08-05 14:57:22 【问题描述】:我正在使用 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];
导致了一些问题。蛇打破它有太多的同时转弯。只有前两个方块保持运动
【问题讨论】:
你的问题是,“我的代码中导致蛇的身体分离的问题在哪里?” 属于 gamedev.stackexchange.com 【参考方案1】:如果我是你,我会存储一个std::set
,其中包含蛇无法到达的所有无效坐标。这将包括:
然后对于蛇的每一次移动,考虑到 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;
;
你还需要做的是:
最初添加边距、所有障碍物和蛇的所有位置,就像它们从蛇开始的位置一样 修改移动例程,这样当蛇移动时,它也必须使用RemoveLocation
从CInvalidPlaces
中移除它的尾巴
在实现蛇的“放大”后,您还必须向CInvalidPlaces
添加额外的段。
如果需要,您可以在以下位置找到有关 stl::set
的更多信息:
HTH,日本
【讨论】:
【参考方案2】:我强烈建议您使用动态容器来保存蛇身体的坐标。这允许您获取蛇新位置的坐标并在容器中搜索坐标。如果找到该点,则蛇已经撞到自己了。
同样,您可以为墙和块以及其他不属于棋盘的实体的点提供容器。
另一种方法是使用网格数据结构(或矩阵),并在其中放置代表蛇体和其他障碍物的值。
【讨论】:
容器是动态的。它存储蛇体的当前位置。搜索方法是个好主意,但问题是搜索精确坐标永远不会给出精确匹配。也许我应该尝试匹配块中心的坐标? @viraj,您无法获得完全匹配的主要问题是您没有分离模型和视图。如果你使用网格,蛇要么在里面,要么不在。浮点坐标应该只用于显示蛇,而不是用于游戏逻辑。这也有助于解决分离问题。 @viraj:网格不应该有浮点值。标准化为某个整数值。正如 Karl 所说,您需要一些将网格映射(绘制)到屏幕上的功能。 @Thomas Matthews 我也应该使用整数坐标来移动蛇,对吧? @viraj:从历史上看,蛇在网格上移动。网格有一个整数(非浮点)行数和列数。蛇的头部和其他身体部分各占一个细胞。直到你得到所有的算法工作,将显示视为一个正方形网格。可能是质量较差的图形;但在所有算法正常工作后,这些都可以改进。以上是关于检查蛇是不是在游戏中撞到自己[关闭]的主要内容,如果未能解决你的问题,请参考以下文章