C ++函数无法按预期工作

时间:2015-03-20 18:48:15

标签: c++ debugging

所以我知道这是一个非常广泛的主题,但我不确定如何描述它,我不知道错误在哪里。所以我在控制台窗口制作一个游戏,一个roguelike-rpg,(我还没有做过随机地牢,但是我已经用其他语言完成了。)而且我'我在处理墙壁方面遇到了问题。

我有一个名为placeMeeting(REAL X, REAL Y)的函数用于检查碰撞,但它似乎返回了错误的值,我无法告诉你原因。我定义了几个宏:#define AND &&#define REAL double

这是功能:

bool GlobalClass::placeMeeting(REAL X, REAL Y)
{
    //The return value -- False until proven otherwise
    bool collision = false;

    //Loop through all walls to check for a collision
    for(int i = 0; i < wallCount; i++)
    {
        //If there was a collision, 'say' so
        if (X == wallX[ i ] AND Y == wallY[ i ])
        {
            //Set 'collision' to true
            collision = true;
        }
    }

    return collision;
}

但奇怪的是,它只是在显示屏幕时不起作用。即使没有显示,玩家也会与他们碰撞。更奇怪的是,只展示了第一面墙。 这是墙的定义:

int wallCount;

//Array of walls
REAL wallX[ 1 ];
REAL wallY[ 1 ];

wallCount  = 1;
//Basic wall stuff; basically just a placeholder
wallX[ 0 ] = 10;
wallY[ 0 ] = 10;

所以我有一个用于渲染屏幕的函数(当然在控制台窗口中)。它看起来像这样:

for (int y = oGlobal.viewY; y < oGlobal.viewY + oGlobal.viewHeight; y++)
{
    //The inner 'x' loop of the view
    for(int x = oGlobal.viewX; x < oGlobal.viewX + oGlobal.viewWidth; x++)
    {
        //Call the function to check this spot and print what it returns
        screen += oGlobal.checkSpot(x, y);
    }
}

这不是整个功能,只是实际屏幕刷新。屏幕后&#39;被打印到屏幕上,以减少缓冲时间。当然,checkSpot:

STRING GlobalClass::checkSpot(REAL x, REAL y)
{
    STRING spriteAtSpot;

    //First check for the player
    if (x == oPlayer.x AND y == oPlayer.y)
    {
        spriteAtSpot = oPlayer.sprite;
    }
    else if (placeMeeting(x, y)) //ITS TEH WALL SUCKAS
    {
        spriteAtSpot = WALL_SPRITE;
    }
    else //Nothing here, return a space
    {
        spriteAtSpot = EMPTY_SPRITE;
    }

    //Return the sprite
    return spriteAtSpot;
}

我知道很多代码,但我真的不知道我搞砸了。

我真的很感激任何帮助!

P.S。这是一张有助于理解的图片 http://i.imgur.com/8XnaHIt.png

3 个答案:

答案 0 :(得分:1)

我不确定我是否遗漏了某些东西,但由于类似流氓的游戏是基于磁贴的,是否有必要使X和Y值加倍?我记得被告知双打很难比较,因为即使你认为它们应该是平等的,它们可能会略微偏离,导致比较,当你认为它会恢复正确时返回假。

答案 1 :(得分:1)

我不确定我们是否有足够的代码来调试它,但我开发了类似Rogue的控制台游戏,这是我的$ .02 ......

  1. 重新开始。你好像是以非OO的方式做这件事(GlobalClass?)。考虑诸如Level(聚合整个级别),DungeonObject(基本上是关卡中的每个空间;它是可以从Wall,Player等继承的基类)之类的对象。这样做可以使编程更容易。
  2. 拥抱吮吸。 C ++语法可能会很糟糕,但是你反对它的次数越多,学习起来就越困难。使用&amp;&amp;和内置的数据类型。它不会花很长时间习惯。
  3. 类似胭脂的位置基本上是基于整数的。对x,y位置使用整数,而不是双精度(最大的内置数据类型)。它不仅效率更高,而且更容易找到调试。
  4. 从小开始。从一个5 x 5的地下城水平开始,以掌握基础知识。然后,如果你已经正确设计了它,那么扩展到10x10或25x25就会容易得多。
  5. 这就是我开发游戏的方式;我希望它有所帮助。

答案 2 :(得分:1)

除了使用double而不是int之外,我在你的墙壁定义中看到了一些奇怪的东西:

int wallCount;

//Array of walls
REAL wallX[ 1 ];
REAL wallY[ 1 ];

wallCount  = 1;
//Basic wall stuff; basically just a placeholder
wallX[ 0 ] = 10;
wallY[ 0 ] = 10;

您正在定义一个名为wallCount的变量,稍后您可以使用该变量在placeMeeting函数中浏览数组元素:

//Loop through all walls to check for a collision
for(int i = 0; i < wallCount; i++)

那么为什么不使用wallCount来定义数组的大小?当然你不能使用那种语法,因为静态数组的大小必须在编译时知道,所以你应该使用newstd::vector,但你仍然不应该有变量定义数组的长度,然后在实际创建数组时使用另一个值,如果你不能保持它们对齐,它就是bug的来源。例如,你可以这样做:

const int wallCount = 1;
int* wallX = new int[wallCount];
int* wallY = new int[wallCount];

但是有一个更大的问题:为什么要创建大小为1的数组?你只有一面墙!拥有大小为1的数组并没有多大意义,除非你打算使用另一个值但是为了调试目的而将它减少到1。但是,你写了这个:

  

更奇怪的是,只显示了第一面墙。

那是因为你只有一面墙!

顺便说一句,您设计数据的方式并不是我要使用的方式。从您的checkSpot我明白这一点:oPlayer.xoPlayer.y是您的播放器的坐标,xy是您需要的磁贴坐标绘制(并且您需要选择适当的精灵)。如果您的地图中有3个墙,则必须在wallX中放置3个值,在wallY中放置3个,并且必须确保将2个数组保持“对齐”(如果您的坐标为第二个墙是例如x = 10和y = 20,你可能会感到困惑,或者有错误的代码,而不是将其保存为

wallX[1] = 10;
wallY[1] = 20;
你可以写

wallX[1] = 10;
wallY[2] = 20; // wrong index!

因此它是另一个错误的来源),更糟糕的是,你必须检查它们是否与其他对象的其他数组一致:例如,你可以拥有门,然后按照你的方法进行{{1 }和doorX[],你怎么能确定你在同一个地方没有墙和门?就像,如果你有

doorY[]

它与墙在同一个地方,错误并不明显,因为您必须交叉检查所有数组才能找到它。所以我建议改为doorX[0] = 10; doorY[0] = 20; ,并且在x = 10和y = 20时有一个墙可以使用level[height][width]。这将确保每个图块只有一个对象。此外,检查碰撞会更快:通过你的方法,如果你有50个墙,你需要50个检查;与我的一起,你总是只需要一个。好的,在这些游戏中,性能肯定不是问题,但我认为你应该考虑我的方法(当然,除非有其他理由更喜欢你的)。