Permalänk
Medlem

C++ space shooter problem

Jag har ett prblem som jag inte lyckats hitta källan till. När jag skall avfyra ett skott (laser) så dyker det upp en kopia av mitt skepp (spriteObject). Jag har lyckats att få den att rita ut den rätta bilden också utöver skeppet.

När jag har avfyrat skottet så skall det färdas uppåt - y led och när skottet har lämnat rutan skall det gömmas. Detta händer inte utan de så kallade bilderna stannar kvar där skeppet är och stannar där.

Det är en hel del kod att gå igenom men tänkte om någon kunde lokalisera problemet.

PS: Kod för space tangenten är i Sprite::handle_input() i main samt i spel-loopen i main.
utöver det finns addBullet(), som adderar ett skott.
Min kod:
Sprite.h

#ifndef SPRITE_H #define SPRITE_H #include <SDL.h> #include <SDL_image.h> #include <string> const int SS_WIDTH = 52; const int SS_HEIGHT = 97; const int SCREEN_WIDTH_W = 1024; const int SCREEN_HEIGHT_H = 600; class Sprite{ public: Sprite(std::string name, std::string name_image, SDL_Surface* spriteImage); Sprite(); virtual ~Sprite(){} void setSpeed( int x, int y); void setPos( int x, int y ); int get_x_pos() const; int get_y_pos() const; void handle_input(); void move(); void show(); int init( SDL_Surface* img, int w, int h ); void draw(); void xadd(int nr) { x_pos += nr; } void yadd(int nr) { y_pos += nr; } void xsub(int nr) { x_pos -= nr; } void ysub(int nr) { y_pos -= nr; } private: std::string name, name_image; int x_pos, y_pos, x_speed, y_speed, lives, score, mDrawn; SDL_Surface* si; SDL_Rect box; }; #endif

Sprite.cpp

#include "sprite.h" Sprite::Sprite(void){} Sprite::Sprite(std::string name, std::string filename, SDL_Surface* spriteImage) :name(name), name_image(filename) { //si=IMG_Load(name_image.c_str()); si = spriteImage; x_pos = 500; y_pos = 480; x_speed = 0; y_speed = 0; } void Sprite::setSpeed(/*Sprite* temp,*/ int x, int y){ this->x_speed += x, this->y_speed += y; } int Sprite::get_x_pos() const{ return this->x_pos; } int Sprite::get_y_pos(/*Sprite* temp*/) const{ return this->y_pos; } int Sprite::init( SDL_Surface* img, int w, int h ) { si = img; box.x = x_pos; box.y = y_pos; box.w = w; box.h = h; return 0; } void Sprite::setPos( int x, int y ) { x_pos = x; y_pos = y; }

Main

#include <SDL.h> #include <SDL_image.h> #include <SDL_ttf.h> #include <SDL_mixer.h> #include "Sprite.h" #include "Loader.h" #include "Render.h" #include <string> #include <sstream> //Screen sizes const int SCREEN_WIDTH = 1000; const int SCREEN_HEIGHT = 800; const int SCREEN_BPP = 32; //Frames per second const int FRAMES_PER_SECOND = 60; #define BULLETS 10 //Dot sizes //const int DOT_HEIGHT = 20; //const int DOT_WIDTH = 20; //Spaceship sizes //const int SS_HEIGHT = 97; //const int SS_WIDTH = 52; //The surfaces SDL_Surface* screen = NULL; SDL_Surface* background = NULL; SDL_Surface* spriteObject = NULL; SDL_Surface* asteroids = NULL; SDL_Surface* message = NULL; SDL_Surface* lives = NULL; SDL_Surface* dot = NULL; SDL_Surface* wep = NULL; Sprite ship; Sprite bullets[BULLETS]; int bdraw[BULLETS]; //Stores event data to be used. SDL_Event event; //The portions of the sprite map to be blitted //Only use incase of sprite sheets. SDL_Rect astro[16]; //The fonts thats gonna be used. TTF_Font* font = NULL; TTF_Font* lfont = NULL; //The color of the font. SDL_Color textColor = { 255, 255, 255 }; //The Camera //SDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT }; //Sounds //Music Mix_Music* music = NULL; //Sound Effects Mix_Chunk* laser = NULL; Mix_Chunk* explosion = NULL; Mix_Chunk* GameOver = NULL; ////The dot that will move around on the screen //class Dot //{ //private: // //The X and Y offsets of the dot // int x, y; // //The velocity of the dot // int xVel, yVel; //public: // //Initiates the variables // Dot(); // //Takes the key presses and adjusts the dot's velocity // void handle_input(); // //Moves the dot // void move(); // //shows the dot on the screen // void show(); //}; /* //Button class class Button { private: //The attributes of the button SDL_Rect box; //The part of the button sprite sheet that will be shown SDL_Rect* clip; public: //Initialize the variables Button( int x, int y, int w, int h ); //Handles events and set the button's sprite region void handle_events(); //Shows the button on the screen void show(); }; */ //SDL_Surface* load_image(std::string filename) { // // //Temporary storage for the image that's loaded // SDL_Surface* loadedImage = NULL; // //The optimized image that will be used // SDL_Surface* optimizedImage = NULL; // //Load the image // loadedImage = IMG_Load( filename.c_str() ); // //If nothing went wrong in loading the image // if( loadedImage != NULL ) // { // //Create an optimized image // optimizedImage = SDL_DisplayFormat( loadedImage ); // //Free the old image // SDL_FreeSurface( loadedImage ); // } // /* // //If the optimized image was done just fine. // if( optimizedImage != NULL ) // { // //Map the color key // Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ); // //Sets all the pixels of color R 0, G 0xFF to be // //transparent // SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey ); // } // */ // //returns the optimized image // return optimizedImage; //} void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* astro = NULL, SDL_Rect* camera = NULL ) { //Make a temporary rectangle to hold the offsets SDL_Rect offset; //Give the offsets to the rectangle offset.x = x; offset.y = y; //Blit the surface SDL_BlitSurface( source, astro, destination, &offset ); } //Here is the initialization function. This function starts up SDL, sets up the window, //sets the caption and returns false if there are any errors. bool init() { if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) { return false; } //Set up screen screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE ); //check if screen loads correctly if( screen == NULL ) { return false; } //Initialize SDL_ttf if( TTF_Init() == -1 ) { return false; } ///Initialize SDL_mixer if( Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ) { return false; } //Set the window caption SDL_WM_SetCaption( "Space Invaders", NULL ); return true; } bool load_files() { //Load images spriteObject = load_image( "Images\\spaceship.png" ); background = load_image( "Images\\bigstar.png" ); asteroids = load_image( "Images\\asteroid-spread-sheet.png" ); dot = load_image( "Images\\dot.bmp" ); wep = load_image( "Images\\double-laser.png" ); //Open the font font = TTF_OpenFont( "Fonts\\SLANT.ttf", 20 ); lfont = TTF_OpenFont( "Fonts\\SLANT.ttf", 22 ); //If there was any error loading the images. if( spriteObject == NULL || background == NULL || asteroids == NULL || dot == NULL || wep == NULL ) { return false; } //If there was any error loading the fonts. if( font == NULL || lfont == NULL ) { return false; } //load music music = Mix_LoadMUS( "Sounds\\starship.wav" ); //If there was any error loading the music if( music == NULL ) { return false; } //Load sound effects laser = Mix_LoadWAV( "Sounds\\laser.wav" ); //If there was any error loading the sound effects. if( laser == NULL ) { return false; } //If everything loaded fine. return true; } void clean_up() { //Free's the loaded images SDL_FreeSurface( spriteObject ); SDL_FreeSurface( background ); SDL_FreeSurface( message ); SDL_FreeSurface( asteroids ); SDL_FreeSurface( dot ); SDL_FreeSurface( wep ); //Close the font that was used TTF_CloseFont( font ); TTF_CloseFont( lfont ); //Free the music files Mix_FreeMusic( music ); //Free the sound effects Mix_FreeChunk( laser ); //Quit SDL_mixer Mix_CloseAudio(); //Quit SDL_ttf TTF_Quit(); //Quit SDL SDL_Quit(); } /* Button::Button( int x, int y, int w, int h ) { //Set the button's attributes box.x = x; box.y = y; box.w = w; box.h = h; } void Button::handle_events() { //The mouse offset int x = 0, y = 0; //If a mouse button was pressed if( event.type == SDL_MOUSEBUTTONDOWN ) { //If the left mouse button was pressed if( event.button.button == SDL_BUTTON_LEFT ) { //Get the mouse offsets x = event.button.x; y = event.button.y; //If the mouse is over the button if( ( x > box.x ) && ( x < box.x + box.w ) && ( y > box.y ) && ( y < box.y + box.h ) ) { //Set the button sprite } } }} */ // The Timer void addBullet() { for( int i = 0; i < BULLETS; i++ ) { if(bdraw[i] == 0) { bullets[i].setPos(ship.get_x_pos()+3, ship.get_y_pos()+50); bdraw[i] = 1; return; } } } class Timer { private: //The clock time when the timer started int startTicks; //the ticks stored when the timer was paused int pausedTicks; //The timer status bool paused; bool started; public: //Initializes variables Timer(); //The various clock actions void start(); void stop(); void paus(); void unpause(); //Gets the timer´s time int get_ticks(); //checks the status of the timer bool is_started(); bool is_paused(); }; Timer::Timer() { //Initializes the variables startTicks = 0; pausedTicks = 0; paused = false; started = false; } void Timer::start() { //start the timer started = true; //Unpause the timer paused = false; //Get the current clock time startTicks = SDL_GetTicks(); } void Timer::stop() { //Stop the timer started = false; //Unpause the timer paused = false; } int Timer::get_ticks() { //If the timer is running if( started == true ) { //If the timer is paused if( paused == true ) { //Returns the number of ticks when //the timer was paused return pausedTicks; } else { //Returns the current time minus the start time return SDL_GetTicks() - startTicks; } } //If the timer isnt running return 0; } void Timer::paus() { //If the timer is running and isn't already paused if( (started == true ) && ( paused == false ) ) { //Pause the timer paused = true; //Calculate the paused ticks pausedTicks = SDL_GetTicks() - startTicks; } } void Timer::unpause() { //If the timer is paused if ( paused = true ) { //Unpause the timer paused = false; //Reset the starting ticks startTicks = SDL_GetTicks() - pausedTicks; //Reset the paused ticks pausedTicks = 0; } } bool Timer::is_started() { return started; } bool Timer::is_paused() { return paused; } //Dot::Dot() //{ // //Initializes the offsets // x = 0; // y = 0; // //Initializes the velocity // xVel = 0; // yVel = 0; //} //void Dot::handle_input() //{ // //If a key was pressed // if( event.type == SDL_KEYDOWN ) // { // //Adjust the velocity // switch( event.key.keysym.sym ) // { // case SDLK_UP: yVel -= DOT_HEIGHT / 2; break; // case SDLK_DOWN: yVel += DOT_HEIGHT / 2; break; // case SDLK_LEFT: xVel -= DOT_WIDTH / 2; break; // case SDLK_RIGHT: xVel += DOT_WIDTH / 2; break; // } // } // //If a key was released // else if( event.type == SDL_KEYUP ) // { // //Adjust the velocity // switch( event.key.keysym.sym ) // { // case SDLK_UP: yVel += DOT_HEIGHT / 2; break; // case SDLK_DOWN: yVel -= DOT_HEIGHT / 2; break; // case SDLK_LEFT: xVel += DOT_WIDTH / 2; break; // case SDLK_RIGHT: xVel -= DOT_WIDTH / 2; break; // } // } //} //void Dot::move() //{ // //Move the dot left or right // x += xVel; // //If the dot went too far to the left or right // if( ( x < 0 ) || ( x + DOT_WIDTH > SCREEN_WIDTH ) ) // { // //Move back // x -= xVel; // } // //Move the dot up or down // y += yVel; // //If the dot went too far up or down // if( ( y < 0 ) || ( y + DOT_HEIGHT > SCREEN_HEIGHT ) ) // { // //Move back // y -= yVel; // } //} //void Dot::show() //{ // //show the dot // apply_surface( x, y, dot, screen ); //} void render_Update() { apply_surface( 0, 0, background, screen ); apply_surface( 0, 0, asteroids, screen, &astro[ 0 ] ); apply_surface( 130, 20, asteroids, screen, &astro[ 1 ] ); apply_surface( 250, 75, asteroids, screen, &astro[ 2 ] ); apply_surface( 50, 150, asteroids, screen, &astro[ 3 ] ); apply_surface( 350, 30, asteroids, screen, &astro[ 4 ] ); apply_surface( 400, 170, asteroids, screen, &astro[ 5 ] ); apply_surface( 500, 50, asteroids, screen, &astro[ 6 ] ); apply_surface( 30, 300, asteroids, screen, &astro[ 7 ] ); apply_surface( 880, 0, asteroids, screen, &astro[ 8 ] ); apply_surface( 700, 300, asteroids, screen, &astro[ 9 ] ); apply_surface( 650, 175, asteroids, screen, &astro[ 10 ] ); apply_surface( 300, 300, asteroids, screen, &astro[ 11 ] ); apply_surface( 480, 300, asteroids, screen, &astro[ 12 ] ); apply_surface( 750, 0, asteroids, screen, &astro[ 13 ] ); apply_surface( 900, 150, asteroids, screen, &astro[ 14 ] ); apply_surface( 900, 300, asteroids, screen, &astro[ 15 ] ); apply_surface( 20, 560, message, screen ); apply_surface( 20, 580, lives, screen ); // Loop through all bullet-spots for(int i = 0; i < BULLETS; i++) //If we have a bullet in that spot, paint it. if(bdraw[i] == 1 ) { bullets[i].draw();} } void Sprite::handle_input() { //If a key was pressed if( event.type == SDL_KEYDOWN ) { //Adjust the speed switch( event.key.keysym.sym ) { case SDLK_UP: y_speed -= SS_HEIGHT / 20; break; case SDLK_DOWN: y_speed += SS_HEIGHT / 20; break; case SDLK_LEFT: x_speed -= SS_WIDTH / 20; break; case SDLK_RIGHT: x_speed += SS_WIDTH / 20; break; case SDLK_SPACE: addBullet(); } } //If a key was released else if( event.type == SDL_KEYUP ) { //Adjust the speed switch( event.key.keysym.sym ) { case SDLK_UP: y_speed += SS_HEIGHT / 20; break; case SDLK_DOWN: y_speed -= SS_HEIGHT / 20; break; case SDLK_LEFT: x_speed += SS_WIDTH / 20; break; case SDLK_RIGHT: x_speed -= SS_WIDTH / 20; break; } } } void Sprite::move() { //Move the SS left or right x_pos += x_speed; //If the SS went too far to the left or right if( ( x_pos < 0 ) || ( x_pos + SS_WIDTH > SCREEN_WIDTH ) ) { //Move back x_pos -= x_speed; } //Move the SS up or down y_pos += y_speed; //If the SS went too far up or down if( ( y_pos < 0 ) || ( y_pos + SS_HEIGHT > SCREEN_HEIGHT ) ) { //Move back y_pos -= y_speed; } // Loop through all bullets for(int i = 0; i > BULLETS; i++ ) { if(bdraw[i] == 1) // If they are visible { bullets[i].ysub(2); // Move them up 2 units at the time if(bullets[i].get_y_pos() < 0) // If they are outside the screen { bdraw[i] = 0; // hide them } } } } void Sprite::show() { apply_surface( x_pos, y_pos, spriteObject, screen ); } void shoot() { //Get position of spriteObject } bool check_Collision( SDL_Rect A, SDL_Rect B ) { //The sides of the rectangles int leftA, leftB; int rightA, rightB; int topA, topB; int bottomA, bottomB; //Calculate the sides of rect A leftA = A.x; rightA = A.x + A.w; topA = A.y; bottomA = A.y + A.h; //Calculate the sides of rect B leftB = B.x; rightB = B.x + B.w; topB = B.y; bottomB = B.y + B.h; //If any of the sides from A are outside of B if( bottomA <= topB ) { return false; } if( topA >= bottomB ) { return false; } if( rightA <= leftB ) { return false; } if( leftA <= rightB ) { return false; } //If none of the sides from A are outside B return true; } bool check_Collision( Sprite* tmp, SDL_Rect rect ) { int leftRect, rightRect, topRect, bottomRect; leftRect = rect.x; rightRect = rect.x + rect.w; topRect = rect.y; bottomRect = rect.y + rect.h; //check for collision if( ( tmp->get_x_pos() + SS_WIDTH ) <= ( leftRect ) ) { return false; } if( ( tmp->get_x_pos() ) <= ( rightRect ) ) { return false; } if( ( tmp->get_y_pos() + SS_HEIGHT ) <= ( topRect ) ) { return false; } if( ( tmp->get_y_pos() ) >= ( bottomRect ) ) { return false; } return true; } void Sprite::draw() { if( mDrawn == 0 ) mDrawn = 1; SDL_Rect dest; dest.x = x_pos; dest.y = y_pos; /*SDL_BlitSurface(si, NULL, screen, & dest);*/ apply_surface(x_pos, y_pos, wep, screen ); } int main( int argc, char* args[] ) { /*********************************************************************/ //Initialize the sprites //Sprite s1("spaceship", "spaceship-sprite.gif", spriteObject); /*********************************************************************/ //Make sure the program waits for quit. bool quit = false; ship.init(spriteObject, SS_WIDTH, SS_HEIGHT); ship.setPos(500, 600); for(int i = 0; i < BULLETS; i++ ) bullets[i].init( wep, 35, 39 ); //Keep track of the current frame. int frame = 0; //Weather or not to cap the frame rate bool cap = true; //The frame rate regulator Timer fps; //Calls the init and file loading methods. if( init() == false ) return 1; if( load_files() == false ) return 1; //Render the fonts message = TTF_RenderText_Solid( font, "Score:", textColor ); lives = TTF_RenderText_Solid( lfont, "Lives:", textColor ); //If there was an error rendering the text if( message == NULL || lives == NULL ) { return 1; } /*************************************************************************/ //Sprite s1("spaceship", "spaceship.png", spriteObject); /************************************************************************/ //Take the rects from the sprite sheet. astro[ 0 ].x = 0; astro[ 0 ].y = 0; astro[ 0 ].w = 128; astro[ 0 ].h = 128; astro[ 1 ].x = 128; astro[ 1 ].y = 0; astro[ 1 ].w = 128; astro[ 1 ].h = 128; astro[ 2 ].x = 256; astro[ 2 ].y = 0; astro[ 2 ].w = 128; astro[ 2 ].h = 128; astro[ 3 ].x = 384; astro[ 3 ].y = 0; astro[ 3 ].w = 128; astro[ 3 ].h = 128; astro[ 4 ].x = 0; astro[ 4 ].y = 128; astro[ 4 ].w = 128; astro[ 4 ].h = 128; astro[ 5 ].x = 0; astro[ 5 ].y = 256; astro[ 5 ].w = 128; astro[ 5 ].h = 128; astro[ 6 ].x = 0; astro[ 6 ].y = 384; astro[ 6 ].w = 128; astro[ 6 ].h = 128; astro[ 7 ].x = 128; astro[ 7 ].y = 128; astro[ 7 ].w = 128; astro[ 7 ].h = 128; astro[ 8 ].x = 128; astro[ 8 ].y = 256; astro[ 8 ].w = 128; astro[ 8 ].h = 128; astro[ 9 ].x = 128; astro[ 9 ].y = 384; astro[ 9 ].w = 128; astro[ 9 ].h = 128; astro[ 10 ].x = 256; astro[ 10 ].y = 128; astro[ 10 ].w = 128; astro[ 10 ].h = 128; astro[ 11 ].x = 256; astro[ 11 ].y = 256; astro[ 11 ].w = 128; astro[ 11 ].h = 128; astro[ 12 ].x = 256; astro[ 12 ].y = 384; astro[ 12 ].w = 128; astro[ 12 ].h = 128; astro[ 13 ].x = 384; astro[ 13 ].y = 128; astro[ 13 ].w = 128; astro[ 13 ].h = 128; astro[ 14 ].x = 384; astro[ 14 ].y = 256; astro[ 14 ].w = 128; astro[ 14 ].h = 128; astro[ 15 ].x = 384; astro[ 15 ].y = 384; astro[ 15 ].w = 128; astro[ 15 ].h = 128; //Main loop- will keep going until the user sets quit to true. while( quit == false ) { //Start the frame timer fps.start(); //If there is no music playing if( Mix_PlayingMusic() == 0 ) { //Play the music if( Mix_PlayMusic( music, -1 ) == -1 ) { return 1; } } //While there's an event to handle while( SDL_PollEvent( &event ) ) { ship.handle_input(); switch(event.type) { case SDL_QUIT://If the user presses X ( close ). //Quits the program quit = true; break; case SDL_KEYDOWN: switch( event.key.keysym.sym ) { case SDLK_SPACE: { //Play laser sound if( Mix_PlayChannel( 0, laser, 0 ) == -1 ) { return 1; }//Lasers position } } } } ship.move(); //Bullet collision render_Update(); //Render the dot on screen //myDot.show(); ship.show(); for(int i = 0; i < BULLETS; i++) bullets[i].show(); //Update Screen if( SDL_Flip( screen ) == -1 ) { return 1; } //Increment the frame counter frame++; //If we want to cap the frame rate if( ( cap == true ) && ( fps.get_ticks() < 1000 / FRAMES_PER_SECOND ) ) { //Sleep the remaining frame time SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() ); } } clean_up(); return 0; }

//Tackar för svar

Sandric

Permalänk
Hedersmedlem

Ett gott tillfälle att lära känna sin debugger kanske?

Permalänk
Medlem

jadu när jag försöker använda den så fattar jag inte mycket, blir bara en massa tecken

Permalänk
Hedersmedlem
Skrivet av Sandric:

jadu när jag försöker använda den så fattar jag inte mycket, blir bara en massa tecken

Testa till exempel att lägga till några brytpunkter (tryck på F9 när du står på den intressanta raden) för att se om till exempel Sprite::move() anropas (och vad som då händer) eller vad den gör.