崩溃,在控制台应用程序上,试图吸引敌人,出界(以下视频教程)

发布于 2024-11-16 09:53:11 字数 6258 浏览 4 评论 0原文

{希望改进我的帖子,仍然请建议您需要的任何其他代码,再次为我的无知感到抱歉,我决心克服这个问题,所以我真的很感谢您的时间!!!}< /strong>

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

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

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

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

该功能是:
关卡->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();
    }

This is the Level->Update() Func:

    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);
            }
        }
    }

idleUpdate():

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

simulateAI():

    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))
            {

            }
        }

move function:

    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 func:

    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

{Hopefully improved my post, please still suggest any other code you need, and once again im sorry for being so clueless, im determined to get past this problem though so i truly appreciate your time!!!}

**EDIT: thanks to Frank with his reply below, the program now starts and draws the three enemies, but just a few second later crashes, the program code below therefore is still applicable as its basically the move loop and somewhere in there something is still going wrong.

I realise this is extremely obscure and i have tried my best to explain it, but if noone can advise then the few second its up should be enough to complete the tutorial anyway and ill dissect the whole project after its finished and really try and break it down and learn as much as possible.**

Okay, so I run this loop designed to create new enemies, and then draw them onto the screen, it now works, but after a few second crashes. below is the steps the debugging goes through and the call stack at the end if what it displayed after the crash. hope you can help!

this is a video tutorial im following and im stuck, cant find the answer. checked the code over and over again. (the full code is at the bottom of the post (codeblocks,) but i have tried to include as much info as possible in this post)

the function is:
level->addEnemies(3);

which looks like in the main 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, '

the function in full is below, note that when i remove this addEnemies function from the main game loop everything runs perfectly fine with no crash, so it has something to do with the upcoming functions.

    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--;
            }
        }
    }

It gets through this function without any problems it seems.

After this function is goes back to the game loops and executes through fine, goes into timer update without any problems. Here is the timerUpdate function:

    void Game::timerUpdate(void)
    {

        double currentTime = timeGetTime() - lastTime;

         if (currentTime < GAME_SPEED)
            return;

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

        frameCount++;


        lastTime = timeGetTime();
    }

This is the Level->Update() Func:

    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);
            }
        }
    }

idleUpdate():

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

simulateAI():

    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))
            {

            }
        }

move function:

    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 func:

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

        return false;
    }

I really cant figure out where this goes wrong, and why at the end the call stakc shows such high out of bounds numbers for xpos adn ypos.

Here is the full call stack:

    #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)

which basically tells me xpos and ypos have been mutilated from somehere in thsi proccess and thats causeing the crash im sure because its way out of bounds from the [30][20] int array of the width and height of the drawengine.

ANOTHER EDIT:

Here is the Sprite class, if it helps, will edit in more if needed.

    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);

    };

anyway any help and i would be sooooo grateful, i know i must seem totally useless, but i rteally am determined to learn, and any help you guys can provide would be priceless!!!!

full code file (codeblocks) : http://www.mediafire.com/?5xz2seadmagbetb

); 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; }

the function in full is below, note that when i remove this addEnemies function from the main game loop everything runs perfectly fine with no crash, so it has something to do with the upcoming functions.

It gets through this function without any problems it seems.

After this function is goes back to the game loops and executes through fine, goes into timer update without any problems. Here is the timerUpdate function:

This is the Level->Update() Func:

idleUpdate():

simulateAI():

move function:

isValidMove func:

I really cant figure out where this goes wrong, and why at the end the call stakc shows such high out of bounds numbers for xpos adn ypos.

Here is the full call stack:

which basically tells me xpos and ypos have been mutilated from somehere in thsi proccess and thats causeing the crash im sure because its way out of bounds from the [30][20] int array of the width and height of the drawengine.

ANOTHER EDIT:

Here is the Sprite class, if it helps, will edit in more if needed.

anyway any help and i would be sooooo grateful, i know i must seem totally useless, but i rteally am determined to learn, and any help you guys can provide would be priceless!!!!

full code file (codeblocks) : http://www.mediafire.com/?5xz2seadmagbetb

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

爱你是孤单的心事 2024-11-23 09:53:11

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

这是因为您应用强制转换的方式。您似乎错过了最终转换为 int 的括号。我想你想要这样的东西:

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

更新:

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

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) 函数中,您将这些 NaN 转换为 int,这将为您提供一些未定义的值数字。使用此数字,您尝试访问您的数组,这将导致访问冲突,从而使您的程序崩溃。

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

This might not be the actual problem, but could be related. Your code to create a random position within your Level::addEnemies(int num) function will always return 1 for xpos and ypos.

This is because of the way you apply the casts. You seem to miss parenthesis for your final cast to int. I think you want something like this:

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

Update:

The code causing the crash is located in your simulateAI() function. With:

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

You calculate the distance between two points, but if the points have the same coordinates, the distance is 0.

Later with: direction.x = direction.x / (mag); you devide by this potential 0 and as a result your coordinates will contain NaN. Within your bool Sprite::move(float x, float y) function you cast these NaNs into an int which will give you some undefined number. With this number you are trying to access your array which will lead to the access violation that crashes your program.

So first thing to do is to check for a zero distance and handle that differently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文