Problems with classes interacting

Started by
15 comments, last by evilsanta 17 years, 11 months ago
Hi, im currently writing a space invaders clone using allegro, I can fire and everything however im having trouble getting collisions to work, I currently have a enemy ship member function called isHit which makes the checks... well heres my code... I really need help with this.

#include <allegro.h>
#include <vector>   // To use the vector class
#include <algorithm>    // To use for_each
#include <functional>   // To use mem_fun_ref

#include "siheader.h"
using namespace std;

void init();
void deinit();

int main() {
    
	init();
    vector<Ship> ships;
    vector<bullet> bullets;
   // Create a new ship and add it to the end of the vector
   for (int x=50; x<750; x=x+35) {
       for (int y=20; y<200; y=y+35) {
           ships.push_back( Ship(x, y) );
       }
   } 
   //playervariables
   int player_x=400;
   int player_y=500;
   BITMAP *playerImage;
   playerImage = load_bitmap( "test.bmp", NULL);
   
   BITMAP *backGround;
   backGround = load_bitmap( "back.bmp", NULL); 
   
   


	while (!key[KEY_ESC]) {
		acquire_screen();
		draw_sprite(screen, backGround, 0,0);
		if (key[KEY_RIGHT]) {
           player_x=player_x+4;
        }
		if (key[KEY_LEFT]){
           if (player_x > 0){
              player_x=player_x-4;
           }
        }
		if (key[KEY_SPACE]) {
           bullets.push_back( bullet(player_x, player_y) );
        }
        for (int i = 0; i < ships.size(); i++) {
            ships.update();
        }
        for (int i = 0; i < bullets.size(); i++) {
            bullets.update();
            bullets.isDestroyed();
        }
        for (int i = 0; i < bullets.size(); i++) {
            for (int i = 0; i < ships.size(); i++) {
                ships.isHit(bullets.returnX);
            }
        }
		//for_each(ships.begin(), ships.end(), mem_fun_ref(&Ship::update));
		//for_each(bullets.begin(), bullets.end(), mem_fun_ref(&bullet::update));
           //bullets.erase(remove_if(bullets.begin(), bullets.end(), mem_fun_ref(&bullet::isDestroyed)), bullets.end());
		rotate_sprite(screen, playerImage, player_x+100, player_y-100, itofix(player_x));
		
		draw_sprite(screen, playerImage, player_x, player_y);
	

        textout_ex(screen, font, "BLAH", 10, 590,makecol(255, 255, 255), -1);
		release_screen();
	}

	deinit();
	return 0;
}
END_OF_MAIN()

void init() {
	int depth, res;
	allegro_init();
	depth = desktop_color_depth();
	if (depth == 0) depth = 32;
	set_color_depth(depth);
	res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
	if (res != 0) {
		allegro_message(allegro_error);
		exit(-1);
	}

	install_timer();
	install_keyboard();
	install_mouse();
	/* add other initializations here */
}

void deinit() {
	clear_keybuf();
	/* add other deinitializations here */
}

and heres the siheader include...

class Ship {
private:       // We don't want external code to access the coordinates directly
   int x, y;
public:        // We do want external code to be able to call these functions
   // This creates a Ship object with the appropriate coordinates
   Ship(int xpos,int ypos) : 
      x(xpos),  // Sets the ship's x to xpos
      y(ypos)   // Sets the ship's y to ypos

   {
      // No code is currently required here. 
      // Things may change as your class grows.
   }
   void update() { 
     circlefill( screen, x, y, 15, makecol(255,255,255));
     if (mouse_b & 1) {
        y=y+1;
     } 
   } 
   void isHit(bulletX){
        if (bulletX = x){
           exit(-1);
        }
   }  
};

class bullet {
private:       // We don't want external code to access the coordinates directly
   int x, y;
public:        // We do want external code to be able to call these functions
   // This creates a Ship object with the appropriate coordinates
   bullet(int xpos,int ypos) : 
      x(xpos),
      y(ypos) 
   {
      // No code is currently required here. 
      // Things may change as your class grows.
   }
   bool isDestroyed() {
       if (y<-10) {
          return true;
       }
       return false;
   }
   void update() { 
     circlefill( screen, x, y, 15, makecol(255,255,255));
     y=y-5;  
     //if (y<400) {
      //x=0;
      //y=0;
     //}
   }
   int returnX() {
       return x;
   }
};

Is there a better way to do this? Or any way to get it working?
Advertisement
Say, in the isHist function:

void isHit(bulletX){
if (bulletX = x){
exit(-1);
}
}

Why = and not == ??
I don't know what the idea behind the function, but if you use = instead of ==
you will always get true and the exit(-1) will be executed.
There is nothing that can't be solved. Just people that can't solve it. :)
Thanks for the reply, see I had gone a long period of not using C++ and using another language where just one = is valid, but I changed it and im still getting these errors...

Compiler: Default compilerBuilding Makefile: "C:\Documents and Settings\Dawn's\Desktop\Brian\Programming\C++\space invaders\Makefile.win"Executing  make...make.exe -f "C:\Documents and Settings\Dawn's\Desktop\Brian\Programming\C++\space invaders\Makefile.win" allg++.exe -D__DEBUG__ -c main.cpp -o main.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include"  -I"C:/Dev-Cpp/include/c++/3.4.2/backward"  -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32"  -I"C:/Dev-Cpp/include/c++/3.4.2"  -I"C:/Dev-Cpp/include"    -g3In file included from main.cpp:6:siheader.h:20: error: variable or field `isHit' declared voidsiheader.h:20: error: expected `;' before '(' tokensiheader.h:25: error: expected `;' before '}' tokenmain.cpp: In function `int _mangled_main()':main.cpp:58: error: 'class Ship' has no member named 'isHit'make.exe: *** [main.o] Error 1Execution terminated
I dont have allegro installed so I cant debug it, but the line

ships.isHit(bullets.returnX);

should be

ships.isHit(bullets.returnX());

and the function

void isHit(bulletX){
...

shoud be

void isHit(int bulletX){
...
Thanks, hadent noticed that, its working now with no errors, thanks much. :)
Ok now I have a new problem, in order to remove a vector element I need to cycle through them with iterators, I can iterate just fine to draw the bullets, and when I incorporated deleting after they got past a certain Y value I find that the program crashes when the last bullet is about to be deleted... this is hard to explane but heres the code thats causing the trouble (probably, as there are no error messages).


        for (bulletIter = bullets.begin(); bulletIter != bullets.end(); ++bulletIter) {            bulletIter->update();            if (bulletIter->isDestroyed()) {               bullets.erase(bulletIter);            }        }


and heres the member function isDestroyed...

   bool isDestroyed() {       if (y<110) {          return true;       }       return false;   }
Erasing an iterator invalidates that iterator, which means you cannot use it again.

However, std::vector::erase returns a brand new iterator which is valid and is pointing to the element next to the one you just erased.

for (bulletIter = bullets.begin(); bulletIter != bullets.end(); ++bulletIter) {            bulletIter->update();            if (bulletIter->isDestroyed()) {               bulletIter = bullets.erase(bulletIter);            }        }
You can make sure you dont erase anything from an already empty vector
if(bullets.size())for (bulletIter = bullets.begin(); bulletIter != bullets.end(); ++bulletIter)      {    bulletIter->update();    if (bulletIter->isDestroyed()) {        bullets.erase(bulletIter);    }}


If you try to erase from an empty vector the program seems to crash

edit:
rip-off's method might be slicker though
Quote:Original post by pulpfist
You can make sure you dont erase anything from an already empty vector
if(bullets.size())for (bulletIter = bullets.begin(); bulletIter != bullets.end(); ++bulletIter)      {    bulletIter->update();    if (bulletIter->isDestroyed()) {        bullets.erase(bulletIter);    }}


If you try to erase from an empty vector the program seems to crash


The original code will not "erase from an empty vector", as the condition "bulletIter != bullets.end()" would make it break the loop before the first iteration.
Thanks for the replies everyone, but neither option prevented it from crashing. :(

This topic is closed to new replies.

Advertisement