Jump to content
  • Advertisement
Sign in to follow this  
Ariste

Problem with classes

This topic is 4844 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everyone. I just started working on my most ambitious project yet, a little 2D sidescrolling space shooter type game. My problem is that, although the program will compile, it immediately generates some sort of error when I try to run it and I get one of those "We're sorry, but <your program.exe> has encountered a problem..." message boxes. After some playing around, I've figured out that one of the problems (and hopefully the only problem) is with my classes. Basically whenever I try to declare an object of any of my classes in any program I get the same error. I'm going to post the source for both my game and the classes, but that's just in case anyone is feeling really generous and wants to read through it all :) If not, any input would still be welcome. Oh and as a side note: I know there's probably a bunch of bugs in the program, but it's kind of tough to fix them when you can't get the program to run in the first place =P Anyway, here's the source:
//MAIN GAME FILE SOURCE

#include <SDLFunc.h>
#include <ShooterClasses.h>
#include <time.h>
#include <math.h>

//Globals

SDL_Surface* screen;
SDL_Surface* background;

const int MAXENEMIES = 20;

int SCREENWIDTH = 1024;
int SCREENHEIGHT = 780;
int SCREENBPP = 32;

int BACKWIDTH;
int BACKHEIGHT;

float firstTime = 0;
float secondTime = 0;
float elapsedTime = 0;
float scroll = 0;
float currentTime = 0;

bool checkCollision(Sprite s1, Sprite s2)
{
     SDL_Rect rect1, rect2;
     
     rect1.x = s1.getX();
     rect1.y = s1.getY();
     rect1.w = s1.Animation[0].spriteRect.w;
     rect1.h = s1.Animation[0].spriteRect.h;
     
     rect2.x = s2.getX();
     rect2.y = s2.getY();
     rect2.w = s2.Animation[0].spriteRect.w;
     rect2.h = s2.Animation[0].spriteRect.h;
     
     if (((rect1.x + rect1.w) >= rect2.x) && (rect1.x <= (rect2.x + rect2.w)) //check X
         && (rect1.y >= rect2.y) && ((rect1.y + rect1.w) <= (rect2.y + rect2.w)))//check Y
                                     return true;
     
     else return false;
}

void SpriteBlit(Sprite s1, int x, int y, SDL_Surface* dest)
{
   SDL_Rect rect1;
   rect1.x = x;
   rect1.y = y;
   rect1.w = s1.Animation[s1.currentFrame].spriteRect.w;
   rect1.h = s1.Animation[s1.currentFrame].spriteRect.h; 
   
   SDL_BlitSurface(s1.Animation[s1.currentFrame].frame, 0, dest, &rect1);
   
   //if (s1.isAnimating == true) 
//    { 
//      if (s1.currentFrame > s1.numframes) currentFrame = 0;
//      else s1.currentFrame++;
//    }
}
  

void DrawIMG(SDL_Surface* img, int x, int y)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}

void DrawIMG(SDL_Surface* img, int srcX, int srcY, int srcW, int srcH, int destX, int destY)
{
  SDL_Rect src;
  SDL_Rect dest;
  
  src.x = srcX;
  src.y = srcY;
  
  dest.x = destX;
  dest.y = destY;
  dest.w = srcW;
  dest.h = srcH;
  SDL_BlitSurface(img, &src, screen, &dest);
}

void DrawScroll()
{
  // We first check, if the background has scrolled more than it's own
  // width. And if so, then we must draw 2 images on the screen:
  // the end of one scrolling background and the start of another.
  if(scroll > BACKWIDTH-SCREENWIDTH)
  {
    DrawIMG(background, 0, 0, (int)(BACKWIDTH-scroll), SCREENHEIGHT, (int)scroll, 0);
    DrawIMG(background, (int)(BACKWIDTH-scroll-1), 0, (int)(SCREENWIDTH - (BACKWIDTH-scroll)), SCREENHEIGHT,0,0);
  // If not then we draw only one background
  } else {
    DrawIMG(background, 0, 0, SCREENWIDTH, SCREENHEIGHT, (int)scroll, 0);
  }
}




bool done = false;

//For key presses
static Uint8 *keylist = SDL_GetKeyState(NULL);

//For events
SDL_Event event;

//Declare an array of enemies
Enemy Enemies[MAXENEMIES + 1];

//For background
SDL_Rect backRect;



int main(int argc, char* argv[])
{
    srand(time(NULL));
    
    //Initialize SDL and set exit condition
    SDL_INIT(VIDEO);
    atexit(SDL_Quit);
    
    //Initialize screen
    screen = SDL_SetVideoMode(SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SDL_HWSURFACE | SDL_ANYFORMAT | SDL_DOUBLEBUF);
    if (screen == NULL)
     {
       std::cout<<"Unable to set video mode"<<SDL_GetError();
       exit(1);
     }
     
     
     //Declare player class
     Player player;
     player.ship.initSprite("pictures/ship/info.txt");
     
     
     //Initialize background 
     background = SDL_LoadBMP("/pictures/repeat.bmp");
     BACKWIDTH  = background->w;
     BACKHEIGHT = background->h;
     
     //Declare and initialize array of enemies/bullets
     Enemy Enemies[MAXENEMIES];
     
     for (register int i = 0; i < MAXENEMIES; i++)
      {
         Enemies.ship.setX(rand() % 3000);
         Enemies.ship.setY(rand() % 1500);
         if (checkCollision(Enemies.ship, player.ship) == true) 
            {
              Enemies.ship.setX(1000); Enemies.ship.setY(SCREENHEIGHT/2);
            }
      }
      
      
      //BEGIN MAIN GAME LOOP
    while (done != true)
    {
      //Get the times    
      secondTime = SDL_GetTicks();
      elapsedTime = (secondTime - firstTime) * 0.1;
      firstTime = secondTime;
      currentTime += elapsedTime * 10;
      
      /*Begin Event Loop*/
      SDL_PollEvent(&event);
        switch (event.type)
        {
          case SDL_QUIT:
               done = true;
               break;
          case SDL_KEYDOWN:
               if (event.key.keysym.sym == SDLK_ESCAPE) 
                  done = true;
                  break;
               if (event.key.keysym.sym == SDLK_SPACE)
                  player.shoot();
                  break;
        }
      /*End Event Loop*/
      
      /*Begin Drawing Sequence*/
      DrawScroll();
      
      for (register int i = 0; i< MAXENEMIES; i++)
       {
         if (Enemies.isAlive == true) SpriteBlit(Enemies.ship, Enemies.ship.getX(), Enemies.ship.getY(), screen);
       }
       
      for (register int i = 0; i<MAXBULLETS; i++)
       {
         if (player.bullets.isActive == true) 
                  SpriteBlit(player.bullets.bullet, player.bullets.bullet.getX(), player.bullets.bullet.getY(), screen);
         
         for (register int j = 0; j < MAXENEMIES; j++)
          {
            if (Enemies[j].bullets.isActive == true)
                    SpriteBlit(Enemies[j].bullets.bullet, Enemies[j].bullets.bullet.getX(), 
                                                                Enemies[j].bullets.bullet.getY(), screen);
          } 
       }
       
       SpriteBlit(player.ship, player.ship.getX(), player.ship.getY(), screen);
       /*End Drawing Sequence*/
       
       /*Check enemies and repopulate if necessary*/
       for (register int i = 0; i < MAXENEMIES; i++)
        {
          if (Enemies.isAlive == false) 
           {
             if ((rand()%2) == 0) {Enemies.isAlive == true; Enemies.setHealth(50); Enemies.setSpeed(50); 
                                                      Enemies.setPower(50); Enemies.setShieldLevel(50);}
           }
        }
       
       
       /*Check for player input and move accordingly*/
       SDL_PumpEvents();
       
       if (keylist[SDLK_UP] && player.ship.getY() > 0) player.ship.addY(1);
       if (keylist[SDLK_DOWN] && player.ship.getY() < SCREENHEIGHT) player.ship.subtY(1);
       
       
       /*Computer AI and movement*/
       for (register int i = 0; i < MAXENEMIES; i++)
        {
          if (Enemies.isBlinking == true) {Enemies.ship.setY(
             (cos((Enemies.ship.getX() + rand() % 2)*0.0174532925) * 100) + SCREENHEIGHT / 2);}
          if (rand() % 2 == 0 && Enemies.isAlive == true) Enemies.shoot();
        }
        
       /*Check for bullet and ship collisions and adjust health accordingly*/
       for (register int i = 0; i < MAXENEMIES; i++)
        {
          for (register int j = 0; j < MAXBULLETS; j++)
           {
             if (checkCollision(Enemies.ship, player.bullets[j].bullet)) 
                        {Enemies.subtHealth(10); player.bullets[j].isActive = false;}
           }
        }
        
       for (register int i = 0; i < MAXENEMIES; i++)
        {
          for (register int j = 0; j < MAXBULLETS; j++)
           {
             if (checkCollision(Enemies.bullets[j].bullet, player.ship))
                        {player.subtHealth(10); Enemies.bullets[j].isActive = false;}
           
           }
        }          
        
       
      /*Check health of player and enemies and adjust game accordingly*/
      for (register int i = 0; i < MAXENEMIES; i++)
       {
         if (Enemies.getHealth() < 0) Enemies.isAlive = false;
       }
       
      if (player.getHealth() < 0 && player.getLives() > 0)  {player.subtLives(1); player.ship.isAnimating = true;}
      
      if (currentTime - elapsedTime > 3000)
       {
         player.ship.isAnimating = false;
         player.ship.currentFrame = 0;
       }
       
       
     /*Adjust the scroll variable*/
     scroll += elapsedTime;
     
     if (scroll > BACKWIDTH) scroll -= BACKWIDTH;
     
     /*Movement of objects*/
     player.ship.addX(player.getXVel());
     player.ship.addY(player.getYVel());
     
     
     for (register int i = 0; i < MAXENEMIES; i++)
      {
        Enemies.ship.addX(Enemies.getXVel());
        Enemies.ship.addX(Enemies.getYVel());
        
        for (register int j = 0; j < MAXBULLETS; j++)
         {
           player.bullets[j].bullet.addX(player.bullets[j].xVel);
           player.bullets[j].bullet.addY(player.bullets[j].yVel);
           
           Enemies.bullets[j].bullet.addX(Enemies.bullets[j].xVel);
           Enemies.bullets[j].bullet.addY(Enemies.bullets[j].yVel);
         }
      }
      
   }
   /************END MAIN GAME LOOP******************/       
}
//END MAIN

//CLASS HEADER FILE SOURCE

#include <SpriteMain.h>

const int MAXBULLETS = 50;


class Bullet
{
  public:
     Sprite bullet;
     
     int xVel;
     int yVel;
     
     bool isActive;

     Bullet();
};

Bullet::Bullet()
{
  bullet.initSprite("pictures/bullet/info.txt");
  
  isActive = false;
  xVel = 0;
  yVel = 0;
}
     

     

class Player
{
      private:        
         int health;
         int speed;
         int power;
         int shieldLevel;
         int xVel;
         int yVel;
         int lives;
         
         
      public:
        Sprite ship;
        
        Bullet bullets[MAXBULLETS + 1];
        
        int getHealth()      {return health;}
        int getSpeed()       {return speed;}
        int getPower()       {return power;}
        int getShieldLevel() {return shieldLevel;}
        int getXVel()        {return xVel;}
        int getYVel()        {return yVel;}
        int getLives()       {return lives;}
        
        void setHealth(int h)           {health = h;}
        void setSpeed(int s)            {speed = s;}
        void setPower(int p)            {power = p;}
        void setShieldLevel(int shield) {shieldLevel = shield;}
        void setXVel(int x)             {xVel = x;}
        void setYVel(int y)             {yVel = y;}
        void setLives(int l)            {lives = l;}
        
        void addHealth(int num) {health += num;}
        void addSpeed(int num)  {speed += num;}
        void addPower(int num)  {power =+ num;}
        void addShield(int num) {shieldLevel += num;}
        void addXVel(int num)   {xVel += num;}
        void addYVel(int num)   {yVel += num;}
        void addLives(int num)  {lives += num;}
        
        void subtHealth(int num) {health -= num;}
        void subtSpeed(int num)  {speed -= num;}
        void subtPower(int num)  {power -= num;}
        void subtShield(int num) {shieldLevel -= num;}
        void subtXVel(int num)   {xVel -= num;}
        void subtYVel(int num)   {yVel -= num;}
        void subtLives(int num)  {lives -= num;}
        
        void shoot();
        
        Player();
        Player(int h, int s, int p, int shield);
};

Player::Player() 
{
  health = 50;
  speed  = 50;
  power  = 50;
  shieldLevel = 50;
  xVel = 0;
  yVel = 0;
  lives = 5;
  
  for (register int i = 0; i < ship.numframes; i++) 
    {
      SDL_SetColorKey (ship.Animation.frame, SDL_SRCCOLORKEY, SDL_MapRGB(ship.Animation.frame->format, 0, 255, 0));  
    }          
}

Player::Player(int h, int s, int p, int shield)
{
  health = h;
  speed = s;
  power = p;
  shieldLevel = shield;
  xVel = 0;
  yVel = 0;
  lives = 5;
}

void Player::shoot()
{
  for (register int i; i < MAXBULLETS; i++)
   {
     if (bullets.isActive ==  false)
       {
         bullets.isActive = true;
         bullets.bullet.setX(ship.getX() + ship.Animation[0].frame->w);
         bullets.bullet.setY(ship.getY() + (ship.Animation[0].frame->h / 2));
         bullets.xVel = 2;
         bullets.yVel = 0;
       }
     break;
   }
}   


class Enemy
{
      private:         
         int health;
         int speed;
         int power;
         int shieldLevel;
         int xVel;
         int yVel;
         
         
      public:
        Sprite ship;
        
        Bullet bullets[MAXBULLETS + 1];
        
        bool isBlinking;
        bool isAlive;
        
        int getHealth()      {return health;}
        int getSpeed()       {return speed;}
        int getPower()       {return power;}
        int getShieldLevel() {return shieldLevel;}
        int getXVel() {return xVel;}
        int getYVel() {return yVel;}
        
        void setHealth(int h) {health = h;}
        void setSpeed(int s)  {speed = s;}
        void setPower(int p) {power = p;}
        void setShieldLevel(int shield) {shieldLevel = shield;}
        void setXVel(int x) {xVel = x;}
        void setYVel(int y) {yVel = y;}
        
        void addHealth(int num) {health += num;}
        void addSpeed(int num)  {speed += num;}
        void addPower(int num)  {power =+ num;}
        void addShield(int num) {shieldLevel += num;}
        void addXVel(int num)   {xVel += num;}
        void addYVel(int num)  {yVel += num;}
        
        void subtHealth(int num) {health -= num;}
        void subtSpeed(int num) {speed -= num;}
        void subtPower(int num)  {power -= num;}
        void subtShield(int num) {shieldLevel -= num;}
        void subtXVel(int num)   {xVel -= num;}
        void subtYVel(int num)   {yVel -= num;}
        
        
        void shoot();
        
        Enemy();
        Enemy(int h, int s, int p, int shield);
};

Enemy::Enemy() 
{             
  health = 50;
  speed  = 50;
  power  = 50;
  shieldLevel = 50;
  xVel = 0;
  yVel = 0;
  
  if (rand() % 2 == 0) isBlinking = true;
  else isBlinking = false;
  
  if (rand() % 2 == 0) isAlive = true;
  else isAlive = false;
  
  for (register int i = 0; i < ship.numframes; i++) 
    {
      SDL_SetColorKey (ship.Animation.frame, SDL_SRCCOLORKEY, SDL_MapRGB(ship.Animation.frame->format, 0, 255, 0));  
    }          
                 
}

Enemy::Enemy(int h, int s, int p, int shield)
{
  health = h;
  speed = s;
  power = p;
  shieldLevel = shield;
  xVel = 0;
  yVel = 0;
  
  if (rand() % 2 == 0) isBlinking = true;
  else isBlinking = false;
  
}

void Enemy::shoot()
{
  for (register int i; i < MAXBULLETS; i++)
   {
     if (bullets.isActive ==  false)
       {
         bullets.isActive = true;
         bullets.bullet.setX(ship.getX());
         bullets.bullet.setY(ship.getY() + (ship.Animation[0].frame->h / 2));
         bullets.xVel = -2;
         
         if (rand() % 2 == 0) bullets.yVel = 2;
         else bullets.yVel = -2;
       }
     break;
   }
} 


Hell, if anyone really needs it, here's my attempt at a Sprite class. I don't think it's the problem, but it can't hurt to put it here:
//SPRITE CLASS HEADER

#include <SDL/SDL.h>
#include <cstring>
#include <fstream>



struct SpriteFrame
{     
      SDL_Rect spriteRect;
      SDL_Surface* frame;
      int pause;
      int frameNumber;
      
      SpriteFrame();
};

SpriteFrame::SpriteFrame()
{
  frame = 0;
  pause = 0;
  frameNumber = 0;
}

class Sprite
{
      private:               
         int xPos;
         double yPos;
         
         float speed;
         long  lastUpdated;
         
      public:
         SpriteFrame* Animation;
         
         bool isAnimating;
         
         int currentFrame;
         int initSprite(char* directory);
         int numframes;
         
         void addX(int num) {xPos += num;}
         void addY(int num) {yPos += num;}
         void subtX(int num){xPos -= num;}
         void subtY(int num){yPos -= num;}
         void setX(int x)   {xPos  = x;}
         void setY(double y)   {yPos  = y;}
         void setPos(int x, int y) {xPos = x; yPos = y;}
         
         int getX() {return xPos;}
         double getY() {return yPos;}
         
         void startAnim()  {isAnimating = true;}
         void stopAnim()   {isAnimating = false;}
         void toggleAnim() {isAnimating = !isAnimating;}
         void rewind()     {currentFrame = 0;}
         
         void setSpeed(float num) {speed = num;}
         float getSpeed()         {return speed;}
         
         void setFrame(int number)     {currentFrame = number;}
         SpriteFrame getCurrentFrame() {return Animation[currentFrame];}

};


int Sprite::initSprite(char* directory)
{
    char filename[30];
    char buffer[50];
    int pause;
    int R, G, B;   
    int framenumber = 1;
    int numFrames;
    
    strcpy(directory, filename); 
    
    std::ifstream spriteInfo;
    spriteInfo.open(filename, std::ios::binary);
    if (spriteInfo.is_open() == false) return -1;
    
    spriteInfo.getline((char*)numFrames, 10);
    
    Animation = new SpriteFrame[numFrames];
    
    
    while (spriteInfo.eof() == false)
    {
      
      if (spriteInfo.peek() == '@') {spriteInfo.ignore(1, '@'); spriteInfo.ignore(); framenumber++;}
      
      spriteInfo.getline(buffer, 1000);      
      spriteInfo.getline((char*)pause, 1000);
      spriteInfo.getline((char*)R, 1000);
      spriteInfo.getline((char*)G, 1000);
      spriteInfo.getline((char*)B, 1000);
      spriteInfo.getline((char*)framenumber, 1000);
      
      Animation[framenumber].frame = SDL_LoadBMP(buffer);
      Animation[framenumber].pause = pause;
      SDL_SetColorKey(Animation[framenumber].frame, SDL_SRCCOLORKEY, SDL_MapRGB(Animation[framenumber].frame->format, R, G, B));
      Animation[framenumber].frameNumber = framenumber;
      Animation[framenumber].spriteRect.x = 50;
      Animation[framenumber].spriteRect.y = 500;
      Animation[framenumber].spriteRect.w = Animation[framenumber].frame->w;
      Animation[framenumber].spriteRect.h = Animation[framenumber].frame->h;
      
      xPos = Animation[framenumber].spriteRect.x;
      yPos = Animation[framenumber].spriteRect.y;
      
      numframes = numFrames;
      
      speed = 2;
      isAnimating = false;
      currentFrame = 0;
      }
      return 0;
}

Yes, I know, it's a lot of code, so any advice at all would be welcome. The only hints that I have as to what the problem may be is that A) Whenever I try to declare an object of a class that I created I get the same error problem and B) When I tried running the debugger (I'm still not really sure how it works, but I tried) I got a message saying that my program encountered a segmentation fault, which leads me to believe the problem may be with a stray pointer somewhere. Again, any help at all would be greatly appreciated. Thanks,

Share this post


Link to post
Share on other sites
Advertisement
Segmentation faults are caused when you try and read/write to memory that you shouldn't be - a stray pointer is often the cause. You might have a pointer

Foo * some_class;

That you assign to another class:

Bar another;
some_class = &another;

And then try to delete:

delete some_class; //segmentation default!


Or if you read past the bound of an array - this is much more common, at least for me! Try looking for things like this, and put in checks to make sure you won't read memory where you shouldn't. Good OO design should help prevent this. Sorry I can't be of more help, but if you output some checks to a console window or a file, you should be able to at least find out where it stops working. In fact, let me give it a try... One moment. I'm feeling nice here at 1:07 AM :)

//EDIT:
PS: What compiler are you using?

//EDIT2:
You probably have too much code in one header file. Try and organize it better - you'll make it easier on yourself and others, like me! :)

//FINAL EDIT:
I've looked through it. I didn't see anything really specific at first glance, although I found things like this:

for (register int i; i < MAXBULLETS; i++)

Now, firstly, I think that the register keyword usually gets optimised in there by the compiler - I've never used it in 3 years of programming so far, at least, not manually. Secondly, you didn't initialize i, and therin may lie your problem. Look for stuff like that. Hope it helps.

Share this post


Link to post
Share on other sites
You should try to narrow down the problem a lot more!
One way of making debugging easier would be if you implemented some sort of a logging system. Basically it means that each time you would do an output on the console, you write it to a textfile.
If the last message on the file would be, for example: "Creating Sprite.. ", You have come quite far :)

Anyway, your code might be a little too much for that many people to spend time on, however I just happened to notice this while scrolling:


int Sprite::initSprite(char* directory)
{
char filename[30];
char buffer[50];
int pause;
int R, G, B;
int framenumber = 1;
int numFrames;

strcpy(directory, filename); <<<---------- HERE





Exactly what you are doing there I'm not sure as the variable names might be slightly misleading, HOWEVER you are copying filename to directory. And since 'filename' is not initialized and 'directory' is, it will crap out. :)

strcpy has the parameters (destination, source), not (source, destination).
If you think that's weird, it's not.
destination = source; - Assignments are usually right to left, are they not? :)

Quote:
After some playing around, I've figured out that one of the problems (and hopefully the only problem)
Hey come on, get real! :P :)

Hopefully the error I noticed helps somewhat!

Best of luck,
/Cam

Share this post


Link to post
Share on other sites
Oh and btw, since you are using C++, maybe you should switch over to strings and vectors, rather than using char* and arrays in general. Reduces the risk of accessing the wrong places in memory, which you so well demonstrated is possible. :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!