简体   繁体   中英

Confused about Vector<type*> iterator

I have a base class cGameObject which has a virtual update function. I wish to have many derived game objects each with their own specific update function.

I want to add the derived gameobjects to a vector and iterate through them to call each of their update methods.

What is wrong with my iterator?

//In Header file
std::vector <cGameObject*> vGameObjs;
std::vector <cGameObject*>::iterator Iter;
cGameObject *AGameObj;

/In cpp file - add object pointer to vector
AGameObj = new BrickBat(128, 32, (1024 - 128) / 2, 768 - 64, 0);
vGameObjs.push_back(AGameObj);
AGameObj = new BrickBall(64, 512, 384, 1, 1, 0);
vGameObjs.push_back(AGameObj);

//Iterator Crashing??
for (Iter = vGameObjs.begin(); Iter != vGameObjs.end(); ++Iter)
{
    //Call Each Objects Update() method here?
    }

When I run this, it throws an exception: read access violation. _Mycont was nullptr.

Not sure what to do.

error thrown Header of Class App Class:

#ifndef _H_AGK_TEMPLATE_
#define _H_AGK_TEMPLATE_

// Link to GDK libraries
#include "AGK.h"
#include "Brickbat.h"
#include "BrickBall.h"
#include "cGameObject.h"
#include <vector>

#define DEVICE_WIDTH 1024
#define DEVICE_HEIGHT 768
#define DEVICE_POS_X 32
#define DEVICE_POS_Y 32
#define FULLSCREEN false

// used to make a more unique folder for the write path
#define COMPANY_NAME "BitMaNip:Play"

// Global values for the app
class app
{
    public:

        // constructor
        app() { memset ( this, 0, sizeof(app)); }

        // main app functions - mike to experiment with a derived class for this..
        void Begin( void );
        int Loop( void );
        void End( void );

    private:
        //Vector of GameObject Pointers;
        std::vector <cGameObject*> vGameObjs;
        //Iterator of GameObjects
        std::vector <cGameObject*>::iterator Iter;


        BrickBat *MyBat;
        BrickBall *MyBall;

        cGameObject *AGameObj;


};

extern app App;

#endif

// Allow us to use the LoadImage function name
#ifdef LoadImage
 #undef LoadImage
#endif

cpp file for Header // Includes #include "template.h" #include "cGameObject.h" #include

// Namespace
using namespace AGK;

app App;

void app::Begin(void)
{
    agk::SetVirtualResolution (DEVICE_WIDTH, DEVICE_HEIGHT);
    agk::SetClearColor( 151,170,204 ); // light blue
    agk::SetSyncRate(60,0);
    agk::SetScissor(0,0,0,0);

    //Test
    /*BrickBall = agk::CreateSprite(0);
    agk::SetSpriteSize(BrickBall, 64, 64);
    agk::SetSpriteColor(BrickBall, 255, 255, 255, 255);
    xPos = (DEVICE_WIDTH - 64) / 2;
    yPos = (DEVICE_HEIGHT - 64) / 2;
    agk::SetSpritePosition(BrickBall, xPos , yPos  );
    xDir = 1;
    yDir = 1;
    iSpeed = 8;*/



    MyBat = new BrickBat(128, 32, (1024-128)/2, 768-64, 0);

    AGameObj = new BrickBat(128, 32, (1024 - 128) / 2, 768 - 64, 0);
    vGameObjs.push_back(AGameObj);

    MyBall = new BrickBall(64, 512, 384, 1, 1, 0);

    AGameObj = new BrickBall(64, 512, 384, 1, 1, 0);
    vGameObjs.push_back(AGameObj);

}

int app::Loop (void)
{
    agk::Print( agk::ScreenFPS() );

    if (agk::GetRawKeyState(37) == 1)
    {
        MyBat->MoveLeft();
    }

    if (agk::GetRawKeyState(39) == 1)
    {
        MyBat->MoveRight();
    }

    MyBat->Update();
    MyBall->Update();
    MyBall->Collided(MyBat->iGetBatID());


    for (Iter = vGameObjs.begin(); Iter != vGameObjs.end(); ++Iter)
    {
        //(*Iter)->Update();
        //(*Iter)->Collided(MyBat->iGetBatID());
    }

Derived class

include "cGameObject.h"

class BrickBall: public cGameObject { private:

bool bHoriDir;
bool bVertDir;
int iSpeed;
bool bPause;    //in case game is paused

public: BrickBall(int iSize, int xPos, int yPos, bool bHori, bool bVert, int ImageID); virtual void Update() override; virtual void Collided(int OtherSpriteToCheck) override; };

    agk::Sync();

    return 0; // return 1 to close app
}


void app::End (void)
{

}

Base Class:

#pragma once
class cGameObject
{
protected:
    bool bInit = false;
    int iSprID;
    int iImageID;
    int iXPos;
    int iYPos;
    int iAngle;
    int iAlpha;
    int iWidth;
    int iHeight;
    int iColour;

    //Movement
    float fDeltaX;
    float fDeltaY;

    //Animation
    int iAniType;   //Type of animation
                    //0 = No Animation
                    //1 = Repeating Loop of Frames (All image is animation)
                    //2 = 

    int iFrameW;        //Width of Animation Frame
    int iFrameH;        //Height of Animation frame
    int iFPS;       //Animation Delay
    int iNumFrames; //Number of animation frames
    int iAniCount;  //Frame Counter

public:
    // set up default for constructor
    cGameObject(int width = 16, int height = 16, int xPos = 0, int yPos = 0, int ImageID = 0);

    void SetPosition(int ixPos, int iyPos);
    void SetSize(int iWidth, int iHeight);
    void SetWidth(int Width);
    void SetAngle(int iAngle);
    void SetTransparency(int iAlpha);
    void SetAnimation(int Type, int FrameW, int FrameH, int FPS, int NumFrames);

    virtual void Collided(int OtherSpriteToCheck) {};

    virtual void Update() {};

    int iGetWidth();
    int iGetHeight();
    int iGetX();
    int iGetY();
    int iGetSprID();

    ~cGameObject();
};

Base Class cpp

    #include "cGameObject.h"
#include "agk.h"


void cGameObject::SetAngle(int iAngle)
{
    if (bInit == true)
    {
        if (iAngle > 0 && iAngle < 359)
        {
            agk::SetSpriteAngle(iSprID, iAngle);
        }
    }
}

//cGameObject::cGameObject(int width, int height, int xPos, int yPos, const char * szImageFile)
cGameObject::cGameObject(int width, int height, int xPos, int yPos, int ImageID)
{
    bInit = true;
    iImageID = 0;
    /*if (std::strlen(szImageFile) > 0)
    {
        iImageID = agk::LoadImage(szImageFile);
        if (iImageID < 1)
        {
            bInit = false;
        }
    }*/
    iColour = agk::MakeColor(255, 255, 255);

    //init animation code
    iAniType = 0;   //Type of animation
    iFrameW = 64;       //Width of Animation Frame
    iFrameH = 64;       //Height of Animation frame
    iFPS = 10;      //Animation Delay
    iNumFrames = 1; //Number of animation frames
    iAniCount = 0;  //Frame Counter


    iSprID = agk::CreateSprite(iImageID);
    if (iSprID < 1)
    {
        bInit = false;
    }
    else
    {
        agk::SetSpriteSize(iSprID, width, height);
        agk::SetSpritePosition(iSprID, xPos, yPos);
        fDeltaX = 4.0;
        fDeltaY = 4.0;

    }

}



void cGameObject::SetPosition(int ixPos, int iyPos)
{
    if (bInit == true)
    {
        agk::SetSpritePosition(iSprID, ixPos, iyPos);
    }
}

void cGameObject::SetSize(int iWidth, int iHeight)
{
    if (bInit == true)
    {
        if (iWidth > 0 && iWidth < 1024 && iHeight > 0 && iHeight < 1024)
        {
            agk::SetSpriteSize(iSprID, iWidth, iHeight);
        }
    }
}

void cGameObject::SetWidth(int Width)
{
    if (bInit == true)
    {
        agk::GetSpriteWidth(Width);
    }
}

void cGameObject::SetTransparency(int iAlpha)
{
    if (bInit == true)
    {
        if (iAlpha > 0 && iAlpha < 256)
        {
            agk::SetSpriteTransparency(iSprID, iAlpha);
        }
    }
}

void cGameObject::SetAnimation(int Type, int FrameW, int FrameH, int FPS, int NumFrames)
{
    //Animation
    iAniType = Type;
    iFrameW = FrameW;       //Width of Animation Frame
    iFrameH = FrameH;       //Height of Animation frame
    iFPS = FPS;             //Animation Delay
    iNumFrames = NumFrames; //Number of animation frames
    iAniCount = 0;          //Frame Counter

    agk::SetSpriteAnimation(iSprID, iFrameW, iFrameH, iNumFrames);

    if (iAniType > 0)
    {
        agk::PlaySprite(iSprID, iFPS);
    }
}


int cGameObject::iGetWidth()
{
    if (bInit == true)
    {
        return agk::GetSpriteWidth(iSprID);
    }
    else
    {
        return 0;
    }
}

int cGameObject::iGetHeight()
{
    if (bInit == true)
    {
        return agk::GetSpriteHeight(iSprID);
    }
    else
    {
        return 0;
    }
}

int cGameObject::iGetX()
{
    if (bInit == true)
    {
        return agk::GetSpriteX(iSprID);
    }
    else
    {
        return 0;
    }
}

int cGameObject::iGetY()
{
    if (bInit == true)
    {
        return agk::GetSpriteY(iSprID);
    }
    else
    {
        return 0;
    }
}

int cGameObject::iGetSprID()
{
    if (bInit == true)
    {
        return iSprID;
    }
    else
    {
        return 0;
    }
}

cGameObject::~cGameObject()
{
    if (bInit == true)
    {
        agk::DeleteSprite(iSprID); 
    }
}

Derived Class Header:

#include "cGameObject.h"

class BrickBall: public cGameObject
{
private:

    bool bHoriDir;
    bool bVertDir;
    int iSpeed;
    bool bPause;    //in case game is paused


public:
    BrickBall(int iSize, int xPos, int yPos, bool bHori, bool bVert, int ImageID);
    virtual void Update() override;
    virtual void Collided(int OtherSpriteToCheck) override;
};

Derived Class cpp

#include "BrickBall.h"

BrickBall::BrickBall(int Size, int xPos, int yPos, bool bHori, bool bVert, int ImageID):cGameObject(Size, Size, xPos, yPos, ImageID)
{
    iWidth = Size;
    iHeight = Size;
    iXPos = xPos;
    iYPos = yPos;
    bHoriDir = bHori;
    bVertDir = bVert;
    /*iSprID = agk::CreateSprite(0);
    agk::SetSpriteColor(iSprIdx, 255, 255, 255, 255);
    //agk::SetSpriteSize(iSprIdx, iSize, iSize);
    agk::SetSpriteSize(iSprIdx, 64, 64);
    //agk::SetSpritePosition(iSprIdx, ixPos, iyPos);
    agk::SetSpritePosition(iSprIdx, ixPos, iyPos);
    bInit = true;*/
    iSpeed = 8;

}

void BrickBall::Update()
{
    if (bInit==true)// && BatID > 0)
    {
        //Move Ball
        agk::SetSpriteColor(iSprID, 100, 100, 100, 255);

        agk::PrintC("BallX:");
        agk::Print(iXPos);

        if (bHoriDir == 1)  //Right
        {
            iXPos = iXPos + iSpeed;
            if (iXPos > 1024 - iWidth)
            {
                bHoriDir = 0;
            }
        }
        else
        {
            iXPos = iXPos - iSpeed;
            if (iXPos < 0)
            {
                bHoriDir = 1;
            }
        }

        if (bVertDir == 1)  //down
        {
            iYPos = iYPos + iSpeed;
            if (iYPos > 768 - 64)
            {
                bVertDir = 0;
            }
        }
        else
        {
            iYPos = iYPos - iSpeed;
            if (iYPos < 0)
            {
                bVertDir = 1;
            }
        }

        agk::SetSpritePosition(iSprID, iXPos, iYPos);

        //END Move Ball
        //Bat2Ball Collisions
        /*if (agk::GetSpriteCollision(iSprID, BatID))
        {
            //We have collided. 
            //As Ball is bigger than the gap below the bat must have hit top or sides
            //so just flip the vertcal direction
            if (bVertDir == 1)
            {
                bVertDir = 0;
            }
        }*/
    }

}

void BrickBall::Collided(int OtherSpriteToCheck)
{
    if (agk::GetSpriteCollision(iSprID, OtherSpriteToCheck))
    {
        if (bVertDir == 1)
        {
            bVertDir = 0;
        }
    }
}

I don't know the cause of your error, but I got this exact error because I had an iterator to a vector, then I updated the vector, then I tried to dereference the iterator (eg access *myIterator). I'm new to C++, but it seems that if you alter a collection after getting an iterator for it, your iterator is no longer valid. You need to repoint your iterator to wherever it was.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM