Сбой в консольном приложении при попытке выманить врагов за пределы (после обучения vid) - PullRequest
0 голосов
/ 19 июня 2011

{Надеюсь, улучшил мой пост, пожалуйста, по-прежнему предлагайте любой другой код, который вам нужен, и еще раз прошу прощения за столь невежественный, я полон решимости преодолеть эту проблему, хотя я действительно ценю ваше время !!!}

** РЕДАКТИРОВАТЬ: благодаря Фрэнку с его ответом ниже, программа теперь запускается и рисует трех врагов, но через несколько секунд происходит сбой, поэтому код программы нижевсе еще применимо, поскольку это в основном цикл перемещения, и где-то там что-то все еще идет не так.

Я понимаю, что это крайне непонятно, и я изо всех сил пытался объяснить это, но если никто не может посоветовать, то нескольких секунд его должно быть достаточно, чтобы завершить урок в любом случае и плохо анализировать весь проект после его завершенияи действительно попробуй разбить его и выучить как можно больше. **

Хорошо, я запустил этот цикл, предназначенный для создания новых врагов, и затем нарисовал их на экране, теперь он работает, но посленесколько секунд вылетает.ниже приведены шаги, через которые проходит отладка, и стек вызовов в конце, если он отображался после сбоя.Надеюсь, что вы можете помочь!

Это видео-учебник, я следую, и я застрял, не могу найти ответ.проверял код снова и снова.(полный код находится внизу поста (кодовые блоки), но я постарался включить как можно больше информации в этот пост)

функция:
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);
            }
        }
    }

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

            }
        }

функция перемещения:

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

Я действительно не могу понять, где это идет не так, и почему в концестек вызовов показывает такие высокие числа за пределами для 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

1 Ответ

0 голосов
/ 19 июня 2011

Это не может быть реальной проблемой, но может быть связано.Ваш код для создания случайной позиции в вашей функции Level::addEnemies(int num) всегда будет возвращать 1 для xpos и ypos.

. Это связано с тем, как вы применяете приведение типов.Вы, кажется, пропускаете скобки для вашего окончательного приведения к 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) вы преобразуете эти NaN в int, что даст вам некоторое неопределенное число.С помощью этого номера вы пытаетесь получить доступ к вашему массиву, что приведет к нарушению прав доступа, которое приводит к сбою вашей программы.

Поэтому первое, что нужно сделать, это проверить нулевое расстояние и обработать его по-другому.

...