Thread: need help making a dot bounce up and down y axis in this prog

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    7

    need help making a dot bounce up and down y axis in this prog

    hi I have been going thrugh sdl tutoials and what the below program initially did was create 2 dot objects one moved via the arrow keys via events and the other did nothng and if one dot hit the other they correctly collided. Anyway I decided if I want to get a better understaning I would try and immplement a part that made the static dot bunce up and down on the y axis , this one wouldnt have events it would just bounce up and down indefinatelky and correctly handle a collision .........I couldnt get that working so I tried to move the dot to the bottom of the screen .......it moves but I dont see the movement in progress if you get what i mean .......by the time the screen shows the movement has been made. Can anyone help me get this ball bouncing or even just moving gradually from y 0 to y300 or something

    thanks
    david

    Code:
    #include "SDL/SDL.h"
    #include <string>
    #include <stdio.h>
    #include <vector>
    #include "SDL/SDL_image.h"
    
    //set global vars for screen width height and bts per pixel they are constants
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    const int SCREEN_BPP = 32;
    
    //The frame rate
    const int FRAMES_PER_SECOND = 20;
    
    
    //set dot attribs
    const int dot_h = 20;
    const int dot_w = 20;
    
    //set global surfaces
    SDL_Surface *dot = NULL;
    SDL_Surface *screen = NULL;
    
    //The event structure
    SDL_Event event;
    
    class Dot
    {
    private:
    	//the offsets of the dot
        int x,y;
    	//the velocity of dots
    	int xVel,yVel;
    //The collision boxes of the dot
        std::vector<SDL_Rect> box;
    
    
        
    	void move_collision_box();
    public:
    	//init dot objects vars in default constructor
    	Dot(int X,int Y);
    
    	//handles key presses and adjusts dots velocity
    	void handle_input();
    	void handle_inputboing();
    //moves the dot
    	void move(std::vector<SDL_Rect>&rects);
    	void bounce(std::vector<SDL_Rect>&rects);
    	//Shows the dot on the screen
        void show();
        
        //Gets the collision boxes returns a rect
        std::vector<SDL_Rect> &get_rects();
    
    
    
    };
    
    Dot::Dot(int X,int Y)
    {
    	//Initialize the offsets
        x = X;
        y = Y;
    
    	//Initialize the velocity
        xVel = 0;
        yVel = 0;
    	//resize vector to 11 to account for each row of the circles collision rect
    	box.resize(11);
    	 //Initialize the collision boxes' width and height
        box[ 0 ].w = 6;
        box[ 0 ].h = 1;
        
        box[ 1 ].w = 10;
        box[ 1 ].h = 1;
        
        box[ 2 ].w = 14;
        box[ 2 ].h = 1;
        
        box[ 3 ].w = 16;
        box[ 3 ].h = 2;
        
        box[ 4 ].w = 18;
        box[ 4 ].h = 2;
        
        box[ 5 ].w = 20;
        box[ 5 ].h = 6;
        
        box[ 6 ].w = 18;
        box[ 6 ].h = 2;
        
        box[ 7 ].w = 16;
        box[ 7 ].h = 2;
        
        box[ 8 ].w = 14;
        box[ 8 ].h = 1;
        
        box[ 9 ].w = 10;
        box[ 9 ].h = 1;
        
        box[ 10 ].w = 6;
        box[ 10 ].h = 1;
    	//Move the collision boxes to their proper spot
       move_collision_box();
    
    }
    
    void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
    {
        //Holds offsets
        SDL_Rect offset;
        
        //Get offsets
        offset.x = x;
        offset.y = y;
        
        //Blit
        SDL_BlitSurface( source, clip, destination, &offset );
    }
    
    
    void Dot::show()
    {
        //Show the dot
        apply_surface( x, y, dot, screen );
    }
    
    void Dot::move_collision_box()
    {
    	int row = 0;
    
    	for(int set = 0; set < box.size(); set++)
    	{
    		//center the collisionbox
    		box[set].x = x+(dot_w - box[set].w)/2;
    		box[set].y = y+row;
    		//move the row offset down the height of the collision box
    		row = row + box[set].h;
    	
    	}
    }
    
    void Dot::handle_inputboing()
    {
    	while(y < 90){
    		//Adjust the velocity
    		y=y +1;
    	
                //wait  
    			 y = y + 1;	
            
    		}
    
    
    }
    
    void Dot::handle_input()
    {
    	//if a key was pressed
    	if(event.type == SDL_KEYDOWN)
    	{
    			//switch arrow keys if arrow used adjust dots direction dependant on the arrow key pressed
    			switch(event.key.keysym.sym) //key object->key->key symbol obj container->actual symbol
    			{
    			case SDLK_UP: yVel = yVel - 1;break; //It is -1 because y axis goes bottom left to top left 20 19 18
    			case SDLK_DOWN: yVel = yVel + 1;break;
    			case SDLK_LEFT: xVel = xVel - 1;break;
    			case SDLK_RIGHT: xVel = xVel + 1;break;
     			}
    	}
    
    	else if(event.type == SDL_KEYUP) //if key was release we dont want prog to do nothing make shape move same again so it moves fluently
        {
    			 //Adjust the velocity
    			switch( event.key.keysym.sym )
    			{
    			case SDLK_UP: yVel = yVel + 1;break; //It is -1 because y axis goes bottom left to top left 20 19 18
    			case SDLK_DOWN: yVel = yVel - 1;break;
    			case SDLK_LEFT:	xVel = xVel + 1;break;
    			case SDLK_RIGHT: xVel = xVel - 1;break;
    			}
    	}
    
    	
    	
    }
    
    bool check_collision( std::vector<SDL_Rect> &A, std::vector<SDL_Rect> &B )
    {
        //The sides of the rectangles
        int leftA, leftB;
        int rightA, rightB;
        int topA, topB;
        int bottomA, bottomB;
    
        //Go through the A boxes
        for( int Abox = 0; Abox < A.size(); Abox++ )
        {
            //Calculate the sides of rect A
            leftA = A[ Abox ].x;
            rightA = A[ Abox ].x + A[ Abox ].w;
            topA = A[ Abox ].y;
            bottomA = A[ Abox ].y + A[ Abox ].h;
            
            //Go through the B boxes    
            for( int Bbox = 0; Bbox < B.size(); Bbox++ )
            {
                //Calculate the sides of rect B
                leftB = B[ Bbox ].x;
                rightB = B[ Bbox ].x + B[ Bbox ].w;
                topB = B[ Bbox ].y;
                bottomB = B[ Bbox ].y + B[ Bbox ].h;
                
                //If no sides from A are outside of B
                if( ( ( bottomA <= topB ) || ( topA >= bottomB ) || ( rightA <= leftB ) || ( leftA >= rightB ) ) == false )
                {
                    //A collision is detected
                    return true;
                }
            }
        }
    	 //If neither set of collision boxes touched
        return false;
    }
    
    void Dot::move(std::vector<SDL_Rect> &aRect)
    {
    
    	//Move the dot left or right
        x += xVel;
        
        //Move the collision boxes
        move_collision_box();
        
        //If the dot went too far to the left or right or has collided with the other dot
        if( ( x < 0 ) || ( x + dot_w > SCREEN_WIDTH ) || ( check_collision( box, aRect ) ) )
        {
            //Move back
            x -= xVel;
            move_collision_box();    
        }
        
        //Move the dot up or down
        y += yVel;
        
        //Move the collision boxes
        move_collision_box(); //every time dot moves collision box moves
        
        //If the dot went too far up or down or has collided with the other dot
        if( ( y < 0 ) || ( y + dot_h > SCREEN_HEIGHT ) || ( check_collision( box, aRect ) ) )
        {
            //Move back
            y -= yVel;
            move_collision_box();
        }   
    }
    
    void Dot::bounce(std::vector<SDL_Rect> &aRect)
    {
    
    
       bool bounce = true;
    
    
    	
    		   y = yVel +30;
    	   
        //If the dot went too far up or down or has collided with the other dot
        if( check_collision( box, aRect )  )
       {
       //Move back
         y -= yVel;
         move_collision_box();
        }
       
    }
    
    
    std::vector<SDL_Rect>& Dot::get_rects()
    {
    return box;
    }
    
    class Timer
    {
    private:
    	int startTicks;
    	int TicksAtPause;
    
    	//timer status
    	bool paused;
    	bool started;
    public:
    	//initialises timer object variables
    	Timer();
    	void start();
    	void stop();
    	void pause();
    	void unpause();
    	
    	//get the number of ticks since timer started or was paused
    	int getTicks();
    	 //Checks the status of the timer
        bool is_started();
        bool is_paused();    
    
    };
    
    Timer::Timer()
    {
    	startTicks = 0;
    	TicksAtPause = 0;
    	started = false;
    	paused = false;
    }
    
    void Timer::start()
    {
    	started = true;
    	paused = false;
    
    	//Get the current clock time
        startTicks = SDL_GetTicks();  
    }
    
    void Timer::stop()
    {
    	started = false;
    	paused = false;
    }
    
    void Timer::pause()
    {
    	//iuf timer is currently running
       if( ( started == true ) && ( paused == false ) )
        {
            //Pause the timer
            paused = true;
    
    		//then get the number of ticks  - the start ticks to get the ticks exactly when the timer was paused at
            TicksAtPause = SDL_GetTicks() - startTicks;
       }
    }
    
    void Timer::unpause()
    {
    	 //If the timer is paused
        if( paused == true )
        {
            //Unpause the timer
            paused = false;
        
            //Reset the starting ticks
            TicksAtPause = SDL_GetTicks() - TicksAtPause;
            
            //Reset the paused ticks
            TicksAtPause = 0;
    	}
    }
    
    int Timer::getTicks()
    {
    	 //If the timer is running
        if( started == true )
        {
            //If the timer is paused
            if( paused == true )
            {
                //Return the number of ticks when the the timer was paused
                return TicksAtPause;
            }
            else
            {
                //Return the current time minus the start time
                return SDL_GetTicks() - startTicks;
            }    
        }
        
        //If the timer isn't running
        return 0;    
    }
    
    SDL_Surface *load_image( std::string filename ) 
    {
        //The image that's loaded
        SDL_Surface* loadedImage = NULL;
        
        //The optimized surface that will be used
        SDL_Surface* optimizedImage = NULL;
        
        //Load the image
        loadedImage = IMG_Load( filename.c_str() );
        
        //If the image loaded
        if( loadedImage != NULL )
        {
            //Create an optimized surface
            optimizedImage = SDL_DisplayFormat( loadedImage );
            
            //Free the old surface
            SDL_FreeSurface( loadedImage );
            
            //If the surface was optimized
            if( optimizedImage != NULL )
            {
                //Color key surface
                SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
            }
        }
        
        //Return the optimized surface
        return optimizedImage;
    }
    
    
    
    //int SDL_Init(Uint32 flags);
    
    bool startsdl()
    {
    	//init sdl and check if started ok if not retuen false
    	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
    	{
          return false;
    	}
    
    	return true;
    }
    
    bool setup_screen()
    {
    	screen = SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE);
    	if(screen == NULL)
    	{
    	return false;
    	}
    	//set window caption
    	SDL_WM_SetCaption("Boucy Ball vs moving dot",NULL);
    
    return true;
    }
    
    
    bool load_files()
    {
        //Load the dot image
        dot = load_image( "dot.bmp" );
        
        //If there was a problem in loading the dot
        if( dot == NULL )
        {
            return false;    
        }
        
        //If everything loaded fine
        return true;
    }
    
    void quitsdl() 
    {
    SDL_Quit();
    
    }
    
    bool Timer::is_started()
    {
        return started;    
    }
    
    bool Timer::is_paused()
    {
        return paused;    
    }
    
    int main(int argc, char *args[])
    {
    	//quit prog status
    	bool quit = false;
    	
    	//make the dots
    	Dot abdot(50,50);
    	Dot movydot(0,0);
    	//setup the timer	
    	Timer fps;
    	//init sdl
    	if(startsdl() == false)
    	{
    		printf("sdl init failed \n");
    	    return 1;
    	}
    //create screen and test
    	if(setup_screen() == false)
    	{
    		printf("Screen setup crashed! \n\n");
    		return 1;
    	}
    
    	 //Load the files
        if( load_files() == false )
        {
            return 1;
        }
    
    	printf("sdl init worked \n");
        printf("screen setup is ok! \n");
    	 printf("images loaded to screen! \n");
    
    	
    
    	
    
    	
    	//game loop
    	while(quit == false)
    	{
    		//1st start and sort frame rate
    		fps.start();
            //do condiotion via event poller to handle user events
    		//while there events to handle
    		//there will be no events first time round so this while will be skipped initially
    		while(SDL_PollEvent(& event) )
    		{
    		 //handle events for the user movable dot
             movydot.handle_input();
    		 
            
    			 //if the user has Xed out the window
    			 if(event.type == SDL_QUIT)
    			 {
                  //set quit flag to true
    				 quit = true;
    			 }
    		}
    
    		//fill the screen white  screen->clip_rect is the rect on the screen you want to fill
    		
    		SDL_FillRect(screen,&screen->clip_rect,SDL_MapRGB(screen->format,0xFF,0xFF,0xFF));
    		movydot.move(abdot.get_rects()); //? get rects makes my 2nd dot the same as my first
            
    		     
            //Show the dots on the screen
    		abdot.handle_inputboing();
    	abdot.bounce(abdot.get_rects());
    
    		abdot.show();
    		movydot.show();
    		
    
    		 //Update the screen
            if( SDL_Flip( screen ) == -1 )
            {
                return 1;    
            }
    
    		//Cap the frame rate
            while( fps.getTicks() < 1000 / FRAMES_PER_SECOND )
            {
                //wait  
    				
            }
    
    	
    	}
    		//Clean up
    	quitsdl();
    
     
    	return 0;
    }

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Code:
    if (ball.y>some_max_value || ball.y<some_min_value) ball.vy*=-1;
    if (ball.x>some_max_value || ball.y<some_min_vale))  ball.vx*=-1;
    
    ball.x+=(ball.vx*ball.speed)*fFrameDelta;
    ball.y+=(ball.vy*ball.speed)*fFrameDelta;
    For 3D, figure out the intersection of the ball and plane. If they intersect, multiply ball's velocity vector by the normal vector of the plane. If the ball interpenetrates, find the distance to the plane (closest point on a line to a plane) and subtract the ball's position by this distance and then multiply the ball's velocity vector by the normal of the plane.

  3. #3
    Registered User
    Join Date
    Jul 2006
    Posts
    7
    Thanks for the help bubba im not sure how speed is worked out though? is it say an int of 5 and howwould I fit that in also what is *fFrameDelta a pointer to?

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    It's not a pointer, it's a multiplication:
    Code:
    (ball.vx*ball.speed)*fFrameDelta
    ->
    Code:
    ball.vx * ball.speed * fFrameDelta
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    .



    Grab your scroll bar with your mouse pointer. Now move your mouse around wildly!


    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    User
    Join Date
    Jan 2006
    Location
    Canada
    Posts
    499
    You should post longer code. Reading a few lines of code like you just posted is boring.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Grab your scroll bar with your mouse pointer. Now move your mouse around wildly!
    OMG!!! ROFLMAO!!!!



  8. #8
    Registered User
    Join Date
    Jul 2006
    Posts
    7
    ok say i do that

    ball.vx * ball.speed * fFrameDelta

    whats gonna happen as I see it the way my code is that by the time its displayed to the screen the movemnent is going to be made as this ball/dot doesnt move via events i want it to just bounce up and down indefinately. Okay frameDelta is getting multiplied but what data type is framedelta(I assume int ) ? what does that do, how would I bounce the 2nd dot in the program that I have referencing the variables relevant to the above program? Im new so I need as much info as possible

    Thanks
    David

  9. #9
    Registered User
    Join Date
    Jul 2006
    Posts
    7
    Code:
    int main(int argc, char *args[])
    {
    	int speed = 5;
    	int bdot_y =0;
    	int flag = 0;
    	//quit prog status
    	bool quit = false;
    	
    	//make the dots
    	Dot abdot(0,50);
    	Dot movydot(0,0);
    
    	//setup the timer	
    	Timer fps;
    	
    //set bouncing dot speed
    abdot.set_speed(speed);
    	//init sdl
    	if(startsdl() == false)
    	{
    		printf("sdl init failed \n");
    	    return 1;
    	}
    //create screen and test
    	if(setup_screen() == false)
    	{
    		printf("Screen setup crashed! \n\n");
    		return 1;
    	}
    
    	 //Load the files
        if( load_files() == false )
        {
            return 1;
        }
    
    	printf("sdl init worked \n");
        printf("screen setup is ok! \n");
    	 printf("images loaded to screen! \n");
    
    	
    
    	
    
    	
    	//game loop
    	while(quit == false)
    	{
    		//1st start and sort frame rate
    		fps.start();
    		mfps.start();
            //do condiotion via event poller to handle user events
    		//while there events to handle
    		//there will be no events first time round so this while will be skipped initially
    		while(SDL_PollEvent(& event) )
    		{
    		 //handle events for the user movable dot
             movydot.handle_input();
    		 
            
    			 //if the user has Xed out the window
    			 if(event.type == SDL_QUIT)
    			 {
                  //set quit flag to true
    				 quit = true;
    			 }
    		}
    
    		//fill the screen white  screen->clip_rect is the rect on the screen you want to fill
    		
    		SDL_FillRect(screen,&screen->clip_rect,SDL_MapRGB(screen->format,0xFF,0xFF,0xFF));
    		movydot.move(abdot.get_rects()); //? get rects makes my 2nd dot the same as my first
            
    		     
            //Show the dots on the screen
    	//	abdot.handle_inputboing();
    	//abdot.bounce(abdot.get_rects());
    
    	
    		//abdot.show();
    		
    		movydot.show();
    	if(flag == 0)
    	{
    	//	abdot.show();
    		flag = 1;
    	}
    		
    //abdot.bounce(movydot.get_rects());
    			abdot.show();
    			         //Yvel  speed                  ticks
    			//bdot_y+=(2 *    abdot.get_speed()) * fps.getTicks();
    
    				bdot_y+=(2 *    6 * fps.getTicks());
    		    abdot.set_y(bdot_y);
    			//Update the screen
            if( SDL_Flip( screen ) == -1 )
            {
                return 1;    
            }
    
    
    
    		//Cap the frame rate
            while( fps.getTicks() < 500 / FRAMES_PER_SECOND )
            {
    			
                //wait  
    	
    				
            }
    
    	
    		//ball.y+=(ball.vy*ball.speed)*fFrameDelta;
    
    		
    
    	
    	}
    		//Clean up
    	quitsdl();
    
     
    	return 0;
    }

    Ok I got it kind of working by doing this


    abdot.show();
    bdot_y+=(2 * 6 * fps.getTicks());
    abdot.set_y(bdot_y);
    //Update the screen
    if( SDL_Flip( screen ) == -1 )
    {
    return 1;
    }
    //Cap the frame rate
    while( fps.getTicks() < 1000 / FRAMES_PER_SECOND )
    {

    //wait


    }


    It dooesnt bounce but i dont have a problem with working out the boundries of the bounce so I just want it to go down the y axis past the end of the screen a bit more steadily ......its just at the momment its moving but not at equal rates it moves steady for a bit then jumps ahead ........how can i stop this? .......I did use that speed formula you gave me and that has got me a little further ahead once i have looked at it a bit ) so thanks alot but I still need some example based help with this

  10. #10
    Registered User
    Join Date
    Jul 2006
    Posts
    7
    Hi I just got the ball moving perfectly to the bottom of the screen .......I basicallly did
    abdot.set_y(abdot.get_y()+abdot.get_speed()); //get speed returning a single int

    Can someone tell explain to me why my makeshift (probably crap way) is working better than the formula I was given? Its just im sure I have read along the lines that ball.vx * ball.speed * fFrameDelta is indeed the done way to do things? also could someone please clarify is fFrameDelta meant to be frames per second or ticks

    Code:
    	//game loop
    	while(quit == false)
    	{
    		//1st start and sort frame rate
    		fps.start();
    		//mfps.start();
            //do condiotion via event poller to handle user events
    		//while there events to handle
    		//there will be no events first time round so this while will be skipped initially
    		while(SDL_PollEvent(& event) )
    		{
    		 //handle events for the user movable dot
             movydot.handle_input();
    		 
            
    			 //if the user has Xed out the window
    			 if(event.type == SDL_QUIT)
    			 {
                  //set quit flag to true
    				 quit = true;
    			 }
    		}
    
    		//fill the screen white  screen->clip_rect is the rect on the screen you want to fill
    		
    		SDL_FillRect(screen,&screen->clip_rect,SDL_MapRGB(screen->format,0xFF,0xFF,0xFF));
    		movydot.move(abdot.get_rects()); //? get rects makes my 2nd dot the same as my first
            
    		     
            //Show the dots on the screen
    		movydot.show();
    	   //abdot.bounce(movydot.get_rects());
    		abdot.show();
    	    abdot.set_y(abdot.get_y()+abdot.get_speed());
    		//Update the screen
            if( SDL_Flip( screen ) == -1 )
            {
                return 1;    
            }
    
    
    
    		//Cap the frame rate
            while( fps.getTicks() < 1000 / 20)
           {
    			
           //wait  
    	
    				
           }
    
    }

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    BTW:
    Code:
    		//Cap the frame rate
            while( fps.getTicks() < 1000 / 20)
           {
    			
           //wait  
    	
    				
           }
    You've probably noticed that that code uses up all your CPU. You might get better results by calling SDL_Delay() with the time left:
    Code:
    Uint32 start = SDL_GetTicks();
    Sint32 delay;
    // ... do stuff that takes a while ...
    delay = FRAMERATE-(SDL_GetTicks()-start);
    if(delay > 0) SDL_Delay(delay);
    There's a nice implemetation of frame-delaying in the SDL_gfx library.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed