0

{希望改进了我的帖子,请仍然建议您需要的任何其他代码,再次抱歉我如此无能,我决心克服这个问题,所以我真的很感谢你的时间!!!}

**编辑:感谢弗兰克在下面的回复,程序现在启动并绘制了三个敌人,但几秒钟后崩溃,因此下面的程序代码仍然适用,因为它基本上是移动循环,并且其中某处是仍然出错。

我意识到这是非常晦涩难懂的,我已尽力解释它,但如果没有人可以建议,那么它的几秒钟应该足以完成教程,并且在完成后对整个项目进行剖析并真正尝试打破它下来并尽可能多地学习。**

好的,所以我运行这个旨在创建新敌人的循环,然后将它们绘制到屏幕上,它现在可以工作了,但是在几秒钟后崩溃了。以下是调试所经历的步骤以及最后的调用堆栈(如果它在崩溃后显示的内容)。希望你能帮忙!

这是我正在关注的视频教程,我卡住了,找不到答案。一遍又一遍地检查代码。(完整的代码在帖子的底部(代码块),但我试图在这篇文章中包含尽可能多的信息)

函数是:
level->addEnemies(3);

在主game.cpp中看起来像:

    bool Game::run(void)
    {
        level = new Level(&drawArea, 30, 20);

        drawArea.createBackgroundTile(TILE_EMPTY, ' ');
        drawArea.createBackgroundTile(TILE_WALL, 219);

        drawArea.createSprite(SPRITE_PLAYER, 1);
        drawArea.createSprite(SPRITE_ENEMY, '$');

        player = new Character(level, &drawArea, 0);

        level->draw();
        level->addPlayer(player);
        level->addEnemies(3);        <-------- SKIPS TO THIS FUNC

        char key = ' ';

        startTime = timeGetTime();
        frameCount = 0;
        lastTime = 0;

        posx = 0;

        player->move(0,0);

        while (key != 'q')
        {
            while (!getInput(&key))
            {
               timerUpdate();
            }
            level->keyPress(key);
        }
        delete player;

        return true;
    }

完整的功能如下,请注意,当我从主游戏循环中删除这个 addEnemies 功能时,一切都运行得很好,没有崩溃,所以它与即将推出的功能有关。

    void Level::addEnemies(int num)
    {
        int i = num;

        while (i > 0)
    {
        int xpos = int(float(rand() % 100) / 100) * (width - 2) + 1;
        int ypos = int(float(rand() % 100) / 100) * (height - 2) + 1;

        if (level[xpos][ypos] != TILE_WALL)
        {
            Enemy *temp = new Enemy(this, drawArea, SPRITE_ENEMY, 
                           (float)xpos, float(ypos));

            temp->addGoal(player);

            addNPC((Sprite *)temp);

            i--;
            }
        }
    }

它通过此功能似乎没有任何问题。

此功能返回游戏循环并正常执行后,进入计时器更新没有任何问题。这是 timerUpdate 函数:

    void Game::timerUpdate(void)
    {

        double currentTime = timeGetTime() - lastTime;

         if (currentTime < GAME_SPEED)
            return;

        level->update();                   <--------SKIPS TO THIS FUNC

        frameCount++;


        lastTime = timeGetTime();
    }

这是 Level->Update() 函数:

    void Level::update(void)
    {
    for (Iter = npc.begin(); Iter != npc.end(); Iter++)
        {
            (*Iter)->idleUpdate();      <-------------SKIPS TO THIS FUNC

            if ((*Iter)->isAlive() == false)
            {
                Sprite *temp = *Iter;
                //kill the enemy
                Iter--;
                delete temp;
                npc.remove(temp);
            }
        }
    }

空闲更新():

    void Enemy::idleUpdate(void)
    {
        if (goal)
            simulateAI();    <------ Goes to this func
    }

模拟AI():

    void Enemy::simulateAI(void)
    {
        vector goal_pos = goal->getPosition();
        vector direction;

        direction.x = goal_pos.x - pos.x;
        direction.y = goal_pos.y - pos.y;

        float mag = sqrt(direction.x * direction.x + direction.y * direction.y);

        direction.x = direction.x / (mag);
        direction.y = direction.y / (mag);

        if (!move(direction.x, direction.y))   <------ SKIPS TO THIS FUNC
        {
            while (!move(rand() % 3 - 1, rand() % 3 - 1))
            {

            }
        }

移动功能:

    bool Sprite::move(float x, float y)
    {

        int xpos = (int)(pos.x +x);
        int ypos = (int)(pos.y +y);

        if (isValidLevelMove(xpos,ypos))      SKIPS TO THIS FUNC
        {
            //.....rest not needed

isValidMove 函数:

    bool Sprite::isValidLevelMove(int xpos, int ypos)
    {
        if (level->level[xpos][ypos] != TILE_WALL)  <-------------THIS LINE CRASHES!!
            return true;

        return false;
    }

我真的不知道哪里出了问题,以及为什么最后调用 stakc 显示 xpos 和 ypos 的超出范围数字如此之高。

这是完整的调用堆栈:

    #0 00402920 Sprite::isValidLevelMove (this=0x791498, xpos=-2147483648, ypos=-2147483648) (sprite.cpp:95)
    #1 00000000 0x00401750 in Enemy::move (this=0x791498, x=-nan(0x400000) (enemy.cpp:21)
    #2 00401892 Enemy::simulateAI (this=0x791498) (enemy.cpp:67)
    #3 004017E5 Enemy::idleUpdate (this=0x791498) (enemy.cpp:46)
    #4 0040226E Level::update (this=0x792e90) (level.cpp:86)
    #5 00401CB8 Game::timerUpdate (this=0x28fec0) (game.cpp:93)
    #6 00401BB5 Game::run (this=0x28fec0) (game.cpp:54)
    #7 0040258D main() (main.cpp:11)

这基本上告诉我 xpos 和 ypos 已经在这个过程中的某个地方被肢解了,这肯定会导致崩溃,因为它超出了绘图引擎宽度和高度的 [30][20] int 数组的范围。

另一个编辑:

这是 Sprite 类,如果有帮助,将在需要时进行更多编辑。

    enum
    {
        SPRITE_CLASSID,
        CHARACTER_CLASSID,
        ENEMY_CLASSID
    };

    struct vector
    {
        float x;
        float y;
    };

    class Sprite
    {
    public:
        Sprite(Level *l, DrawEngine *de, int s_index, float x = 1, float y = 1, int i_lives = 1);
        ~Sprite();

        vector getPosition(void);
        float getX(void);
        float getY(void);

        virtual void addLives(int num = 1);
        int getLives(void);
        bool isAlive(void);

        virtual void idleUpdate(void);

        virtual bool move(float x, float y);

    protected:
        Level *level;
        DrawEngine *drawArea;

        vector pos;

        int spriteIndex;
        int numLives;

        int classID;

        vector facingDirection;

        void draw(float x, float y);
        void erase(float x, float y);

        bool isValidLevelMove(int xpos, int ypos);

    };

无论如何,任何帮助,我都会非常感激,我知道我一定看起来完全没用,但我真的决心学习,你们能提供的任何帮助都是无价的!!!!

完整的代码文件(代码块):http ://www.mediafire.com/?5xz2seadmagbetb

4

1 回答 1

0

这可能不是实际问题,但可能是相关的。您在Level::addEnemies(int num)函数中创建随机位置的代码将始终返回1forxposypos

这是因为您应用演员表的方式。您似乎错过了最后一次转换为的括号int。我想你想要这样的东西:

int xpos = int((float(rand() % 100) / 100) * (width - 2)) + 1;

更新:

导致崩溃的代码位于您的simulateAI()函数中。和:

float mag = sqrt(direction.x * direction.x + direction.y * direction.y);

您计算两点之间的距离,但如果两点坐标相同,则距离为0

稍后:direction.x = direction.x / (mag);您按此势划分,0因此您的坐标将包含NaN。在你的bool Sprite::move(float x, float y)函数中,你将这些NaNs 转换为一个int会给你一些未定义的数字。使用这个数字,您试图访问您的数组,这将导致访问冲突,从而使您的程序崩溃。

所以首先要做的是检查零距离并以不同的方式处理。

于 2011-06-19T15:31:14.337 回答