Запутался в вектореитератор - PullRequest
0 голосов
/ 20 января 2019

У меня есть базовый класс cGameObject, который имеет виртуальную функцию update. Мне бы хотелось иметь много производных игровых объектов, каждый со своей специфической функцией update.

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

Что не так с моим итератором?

//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?
    }

Когда я запускаю это, выдается исключение: нарушение прав чтения. _Mycont был nullptr.

Не уверен, что делать.

выдана ошибка Заголовок класса 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 файл для заголовка // Включает в себя #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());
    }

Производный класс

включает "cGameObject.h"

класс BrickBall: общедоступный cGameObject { частное:

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

общественность: BrickBall (int iSize, int xPos, int yPos, bool bHori, bool bVert, int ImageID); виртуальный void Update () переопределить; переопределение виртуальной пустоты Collided (int OtherSpriteToCheck); };

    agk::Sync();

    return 0; // return 1 to close app
}


void app::End (void)
{

}

Базовый класс:

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

Базовый класс 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); 
    }
}

Заголовок производного класса:

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

Производный класс 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;
        }
    }
}

1 Ответ

0 голосов
/ 18 февраля 2019

Я не знаю причину вашей ошибки, но я получил именно эту ошибку, потому что у меня был итератор к вектору, затем я обновил вектор, затем я попытался разыменовать итератор (например, access * myIterator).Я новичок в C ++, но кажется, что если вы измените коллекцию после получения для нее итератора, ваш итератор больше не будет действительным.Вам нужно переназначить свой итератор туда, где он был.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...