0

{私の投稿が改善されることを願っています。必要な他のコードを提案してください。また、無知で申し訳ありませんが、この問題を乗り越えることを決意しているので、お時間をいただきありがとうございます!!!}

**編集: 以下のフランクの返信に感謝します。プログラムが開始され、3 人の敵が描画されますが、わずか数秒後にクラッシュします。したがって、以下のプログラム コードは、基本的に移動ループとそこのどこかに何かがあるため、引き続き適用できます。まだ間違っています。

私はこれが非常に不明瞭であることを認識しており、説明するために最善を尽くしましたが、誰もアドバイスできない場合は、チュートリアルを完了するのに数秒で十分であり、終了後にプロジェクト全体を分析し、実際に試してみてくださいできるだけ多くのことを学びましょう**。

さて、新しい敵を作成するように設計されたこのループを実行し、それらを画面に描画すると、今は機能しますが、数秒後にクラッシュします. 以下は、デバッグが通過する手順と、クラッシュ後に表示された場合の最後のコールスタックです。あなたが助けてくれることを願っています!

これは私がフォローしているビデオチュートリアルであり、行き詰まっており、答えが見つかりません。コードを何度も確認しました。(完全なコードは投稿の下部にあります (コードブロック) が、この投稿にはできるだけ多くの情報を含めようとしました)

関数は次のとおり
です。 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() 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);
            }
        }
    }

アイドルアップデート():

    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 がこのプロセスのどこかから切断されたことを示しており、drawengine の幅と高さの [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)は、常に1forxposとを返しますypos

これは、キャストを適用する方法が原因です。への最終キャストの括弧が抜けているようですint。私はあなたがこのようなものが欲しいと思います:

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

アップデート:

クラッシュの原因となっているコードは、simulateAI()関数内にあります。と:

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

2 点間の距離を計算しますが、点の座標が同じ場合、距離は0です。

後で:direction.x = direction.x / (mag);このポテンシャルで割り算する0と、結果として座標に が含まれますNaN。関数内で、これらの を にbool Sprite::move(float x, float y)キャストすると、未定義の数値が得られます。この番号を使用して配列にアクセスしようとすると、プログラムがクラッシュするアクセス違反が発生します。NaNint

したがって、最初に行うことは、距離がゼロであることを確認し、それを別の方法で処理することです。

于 2011-06-19T15:31:14.337 に答える