please Help with my tetris clone in SDL

Started by
2 comments, last by Keeperofsoulz 17 years, 9 months ago
I'm having just a bit of trouble with this code the code generates a piece and is just supposed to make it fall like it would if you were playing a game (I'm not worried about collision or it stopping at the bottom yet) the problem is the piece doesn't fall unless I'm moving the mouse over the screen constantly, if I do this the piece does exactly what I want it to do I don't have any mouseover events in the code so I'm not sure if maybe it's having trouble processing loops or what it could be and I'm hoping someone can give me some advice here is the code

//headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
#include <vector>

//constants
const int SCREEN_HEIGHT = 480;
const int SCREEN_WIDTH = 640;
const int SCREEN_BPP = 32;
const int BLOCK_WIDTH = 20;
const int BLOCK_HEIGHT = 20;
const int FRAMES_PER_SECOND = 20;

//surfaces
SDL_Surface *screen;
SDL_Surface *BG;
SDL_Surface *block;
SDL_Event event;


//Piece Class
class Piece
{
    private:
    std::vector<SDL_Rect> piece;
    int type;
    int x, y;
    int x_vel, y_vel;
    public:
    Piece(int X, int Y);
    void piece_type();
    void piece_move(std::vector<SDL_Rect> &rects);
    void shift_boxes();
    void handle_input();
    void piece_show();
    void make_piece(int type);
    std::vector<SDL_Rect> &get_piece();

};
//Timer Class to keep the FPS in order
class Timer
{
    private:
    int startTicks;
    int pausedTicks;
    bool paused;
    bool started;
    
    public:
    Timer();
    void start();
    void stop();
    void pause();
    void unpause();
    int get_ticks();
    bool is_started();
    bool is_paused();    
};
//functions
//loading images function
SDL_Surface *load_image(std::string filename)
{
    SDL_Surface* loaded_image = NULL;
    SDL_Surface* optimized_image = NULL;
    
    loaded_image = IMG_Load(filename.c_str());
    
    if(loaded_image != NULL)
    {
        optimized_image = SDL_DisplayFormat(loaded_image);
        SDL_FreeSurface(loaded_image);
    }
    return optimized_image;
}

//applying surfaces function
void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface *destination)
{
    SDL_Rect offset;
    
    offset.x = x;
    offset.y = y;
    
    SDL_BlitSurface(source, NULL, destination, &offset);
}

//makes the piece fall
void Piece::handle_input()
{
    y_vel += BLOCK_HEIGHT;
}    

void Piece::piece_show()
{
    int i;
    for(i = 0; i < piece.size(); i++)
        apply_surface(piece.x, piece.y, block, screen);
            
}
//constructor
Piece::Piece(int X, int Y)
{
    type = -1;
    x = X; 
    y = Y; 
    x_vel = 0;
    y_vel = 0;
    
    piece.resize(4);
}
//creates a piece depending on what type is sent 
void Piece::make_piece(int type)
{
    int i = 0;
    switch(type)
    {
        case 1:
            
            piece[0].x = 290;
            piece[0].y = 0;
            piece[1].x = 310;
            piece[1].y = 0;
            piece[2].x = 330;
            piece[2].y = 0;
            piece[3].x = 310;
            piece[3].y = 20;
            break;
        case 2:
            piece[0].x = 300;
            piece[0].y = 0;
            piece[1].x = 320;
            piece[1].y = 0;
            piece[2].x = 300;
            piece[2].y = 20;
            piece[3].x = 320;
            piece[3].y = 20;
            break;
        case 3:
            piece[0].x = 310;
            piece[0].y = 0;
            piece[1].x = 310;
            piece[1].y = 20;
            piece[2].x = 310;
            piece[2].y = 40;
            piece[3].x = 310;
            piece[3].y = 60;
            break;
        case 4:
            piece[0].x = 310;
            piece[0].y = 0;
            piece[1].x = 330;
            piece[1].y = 0;
            piece[2].x = 290;
            piece[2].y = 20;
            piece[3].x = 310;
            piece[3].y = 20;
            break;
        
        
            
            
    }
}
//will generate a random peice ****not used yet****
void Piece::piece_type()
{
    type = rand() % 7;
    make_piece(type);
}
//goes through the parts of the piece and moves the piece
void Piece::piece_move(std::vector<SDL_Rect> &rects)
{
    int i;
    for(i = 0; i < piece.size(); i++)
        piece.y += y_vel;
}
std::vector<SDL_Rect> &Piece::get_piece()
{
    return piece;    
}

//Timer Construtor
Timer::Timer()
{
    startTicks = 0;
    pausedTicks = 0;
    paused = false;
    started = false;    
}

void Timer::start()
{
    started = true;
    paused = false;
    startTicks = SDL_GetTicks();    
}

void Timer::stop()
{
    started = false;
    paused = false;    
}

void Timer::pause()
{
    if( ( started == true ) && ( paused == false ) )
    {
        paused = true;
        pausedTicks = SDL_GetTicks() - startTicks;
    }
}

void Timer::unpause()
{
    if( paused == true )
    {
        paused = false;
        startTicks = SDL_GetTicks() - pausedTicks;
        pausedTicks = 0;
    }
}

int Timer::get_ticks()
{
    if( started == true )
        if( paused == true )
            return pausedTicks;
        else
            return SDL_GetTicks() - startTicks;
    return 0;    
}

bool Timer::is_started()
{
    return started;    
}

bool Timer::is_paused()
{
    return paused;    
}
//MAIN
int main(int argc, char* args[])
{
    bool quit = false;
    int type = -1;
    
    Piece my_piece(310, 0);
    Timer fps;
    
    //inits everything
    if(SDL_Init(SDL_INIT_EVERYTHING == -1))
        return 1;
    
    
    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
    
    if(screen == NULL)
        return 1;
        
    SDL_WM_SetCaption("Sir Tet", NULL);
    
    BG = load_image("bg.png");
    block = load_image("block.png");
    
    
     while( quit == false )
    {
        type =  1;
        fps.start();
        while( SDL_PollEvent( &event ) )
        {
            my_piece.handle_input();
            if( event.type == SDL_QUIT )
                quit = true;
        }
        apply_surface(0, 0, BG, screen);
                
        my_piece.make_piece(type);
        my_piece.piece_move(my_piece.get_piece());
        my_piece.piece_show();
                  
        
        
        
    
        if(SDL_Flip(screen) == -1)
            return 1;
        while( fps.get_ticks() < 10000 / FRAMES_PER_SECOND )
        {
            //wait    
        }
    }
    
    
    SDL_FreeSurface(BG);
    SDL_Quit();
    
    return 0;
}
    
    
    



I appreciate any comments/suggestions from anyone Thank you in advance KoS
Advertisement
You move the piece during the call to Piece::handleInput, which is only called when SDL_PollEvent has an event in the queue. There will be no event in the queue unless you're moving the mouse around or something, which is causing the unwanted behavior.

Moving the Piece::handleInput call outside your event loop should fix the problem, and I'd also suggest changing the name of the function - its a bit misleading.

EDIT: Additionally, you're calling Piece::make_piece every pass, which appears to reset the position of the piece at the top of the screen.
Ha....didn't notice that thank you very much my friend

after staring at the code for a couple hours straight things tend to get lost

:-) thank you again

KoS
ok could someone give me a little more help on this
I've got the piece to fall properly but now I'm having trouble getting it to stop

I have a "wall" on the bottom of the screen and I think I have the collision detection correct but it's not working so I obviously have something wrong
it doesn't stop on the wall it goes through the wall and appears back up top

[source = "cpp"]//headers#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include <string>#include <vector>//constantsconst int SCREEN_HEIGHT = 480;const int SCREEN_WIDTH = 640;const int SCREEN_BPP = 32;const int BLOCK_WIDTH = 20;const int BLOCK_HEIGHT = 20;const int FRAMES_PER_SECOND = 20;//surfacesSDL_Surface *screen;SDL_Surface *BG;SDL_Surface *block;SDL_Rect wall;SDL_Event event;//Piece Classclass Piece{    private:    std::vector<SDL_Rect> piece;    int type;    int x, y;    int x_vel, y_vel;    public:    Piece(int X, int Y);    void piece_type();    void piece_move(std::vector<SDL_Rect> &rects);    void shift_boxes();    void fall();    void piece_show();    void make_piece(int type);    std::vector<SDL_Rect> &get_piece();};//Timer Class to keep the FPS in orderclass Timer{    private:    int startTicks;    int pausedTicks;    bool paused;    bool started;        public:    Timer();    void start();    void stop();    void pause();    void unpause();    int get_ticks();    bool is_started();    bool is_paused();    };//functions//loading images functionSDL_Surface *load_image(std::string filename){    SDL_Surface* loaded_image = NULL;    SDL_Surface* optimized_image = NULL;        loaded_image = IMG_Load(filename.c_str());        if(loaded_image != NULL)    {        optimized_image = SDL_DisplayFormat(loaded_image);        SDL_FreeSurface(loaded_image);    }    return optimized_image;}//applying surfaces functionvoid apply_surface(int x, int y, SDL_Surface* source, SDL_Surface *destination){    SDL_Rect offset;        offset.x = x;    offset.y = y;        SDL_BlitSurface(source, NULL, destination, &offset);}//constructorPiece::Piece(int X, int Y){    type = -1;    x = X;     y = Y;     x_vel = 0;    y_vel = 0;        piece.resize(4);}//makes the piece fallvoid Piece::fall(){    y_vel += BLOCK_HEIGHT;}    void Piece::piece_show(){    int i;    for(i = 0; i < piece.size(); i++)        apply_surface(piece.x, piece.y, block, screen);            }//creates a piece depending on what type is sent void Piece::make_piece(int type){    int i = 0;    switch(type)    {        case 1:                        piece[0].x = 290;            piece[0].y = 0;            piece[1].x = 310;            piece[1].y = 0;            piece[2].x = 330;            piece[2].y = 0;            piece[3].x = 310;            piece[3].y = 20;            break;        case 2:            piece[0].x = 300;            piece[0].y = 0;            piece[1].x = 320;            piece[1].y = 0;            piece[2].x = 300;            piece[2].y = 20;            piece[3].x = 320;            piece[3].y = 20;            break;        case 3:            piece[0].x = 310;            piece[0].y = 0;            piece[1].x = 310;            piece[1].y = 20;            piece[2].x = 310;            piece[2].y = 40;            piece[3].x = 310;            piece[3].y = 60;            break;        case 4:            piece[0].x = 310;            piece[0].y = 0;            piece[1].x = 330;            piece[1].y = 0;            piece[2].x = 290;            piece[2].y = 20;            piece[3].x = 310;            piece[3].y = 20;            break;                                            }}//will generate a random peice ****not used yet****void Piece::piece_type(){    type = rand() % 7;    make_piece(type);}bool check_collision( SDL_Rect &A, SDL_Rect &B ){        int topB;    int bottomA;             bottomA = A.y + BLOCK_HEIGHT;    topB = B.y;         //If any of the sides from A are outside of B    if(bottomA <= topB)        return false;            return true;}//goes through the parts of the piece and moves the piecevoid Piece::piece_move(std::vector<SDL_Rect> &rects){    int i;    for(i = 3; i >= 0; i--)    {        piece.y += y_vel;        if((check_collision(piece, wall)))            piece.y -= y_vel;    }           }std::vector<SDL_Rect> &Piece::get_piece(){    return piece;    }//Timer ConstrutorTimer::Timer(){    startTicks = 0;    pausedTicks = 0;    paused = false;    started = false;    }void Timer::start(){    started = true;    paused = false;    startTicks = SDL_GetTicks();    }void Timer::stop(){    started = false;    paused = false;    }void Timer::pause(){    if( ( started == true ) && ( paused == false ) )    {        paused = true;        pausedTicks = SDL_GetTicks() - startTicks;    }}void Timer::unpause(){    if( paused == true )    {        paused = false;        startTicks = SDL_GetTicks() - pausedTicks;        pausedTicks = 0;    }}int Timer::get_ticks(){    if( started == true )        if( paused == true )            return pausedTicks;        else            return SDL_GetTicks() - startTicks;    return 0;    }bool Timer::is_started(){    return started;    }bool Timer::is_paused(){    return paused;    }//MAINint main(int argc, char* args[]){    bool quit = false;    int type = -1;        Piece my_piece(310, 0);    Timer fps;        //inits everything    if(SDL_Init(SDL_INIT_EVERYTHING == -1))        return 1;            screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);        if(screen == NULL)        return 1;            SDL_WM_SetCaption("Sir Tet", NULL);        BG = load_image("bg.png");    block = load_image("block.png");    wall.x = 0;    wall.y = 440;    wall.w = SCREEN_WIDTH;    wall.h = 40;         while( quit == false )    {        type =  1;        fps.start();        while( SDL_PollEvent( &event ) )        {                        if( event.type == SDL_QUIT )                quit = true;        }        apply_surface(0, 0, BG, screen);        SDL_FillRect( screen, &wall, SDL_MapRGB( screen->format, 0x77, 0x77, 0x77 ) );                        my_piece.make_piece(type);        my_piece.fall();        my_piece.piece_move(my_piece.get_piece());        my_piece.piece_show();                                                      if(SDL_Flip(screen) == -1)            return 1;        while( fps.get_ticks() < 10000 / FRAMES_PER_SECOND )        {            //wait            }    }            SDL_FreeSurface(BG);    SDL_Quit();        return 0;}            


Once again any suggestions are appreciated...I think my problem is I've stared at this code for way too long
gonna take a break and watch the soccer game

Thanks in Advance
KoS

This topic is closed to new replies.

Advertisement