GPWiki.org
GPWiki.org
It is currently Mon May 20, 2013 1:37 pm

All times are UTC




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: Scrolling background SDL
PostPosted: Mon Apr 30, 2012 7:34 am 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Hello there :)

After I finally got my Mario-Clone to work fine with the mechanics and tiles,
I want to do it side-scrolling.

Right now it works, but in a very bad way.
I draw ALL the tiles(500*20) to a SDL_Surface of the length of 500*15.
When moving to the right, I go through every tile and set x-=1.
While you can walk 30Pixel a second(game is limited to 30fps), that makes 120000 calculations per second,
just for the redrawing.
I want it more efficent(even though modern Computers should be able to do this).

My Idea is the following:
Having one SDL_Surface(background) where all tiles a drawn to.
Having a second SDL_Surface(view), having the size of 20*20 tiles.

Then there is a rect of size of view, painted from the background, to view.
After every step the player does, the copied rectangles x start value will change.
Doing it this way, I will save 119970 calculations / second.

Problem: I don't get it done?!
Tried to abstract the needed things to test it. Here is the code:
Spoiler: show
Code:
#include "SDL.h"
const int WINDOW_WIDTH = 100;
const int WINDOW_HEIGHT = 100;
const char* WINDOW_TITLE = "";

int main(int argc, char **argv)
{

   SDL_Init( SDL_INIT_VIDEO );

   SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_HWSURFACE | SDL_DOUBLEBUF );
   SDL_WM_SetCaption( WINDOW_TITLE, 0 );
    SDL_Surface* bg = SDL_SetVideoMode(WINDOW_WIDTH,WINDOW_HEIGHT,0,SDL_HWSURFACE | SDL_DOUBLEBUF);

    SDL_Surface* background_img = SDL_LoadBMP("test.bmp"); //500*100 image
    if(background_img == NULL)return -5;

SDL_Rect src;
    src.x =0; // the part, that shall be blittet
    src.y =0;
    src.w =100;
    src.h =100;

SDL_Rect ziel;
    ziel.x =0;
    ziel.y =0;
    ziel.w =100;
    ziel.h =100;

    SDL_BlitSurface(background_img , NULL, screen, NULL); //painting the image to the surface(screen)

SDL_Event event;
bool gameRunning;
   while (gameRunning)
   {
      if (SDL_PollEvent(&event))
      {
         if (event.type == SDL_QUIT)
         {
            gameRunning = false;
         }
         if (event.type == SDL_KEYDOWN)
         {
             SDLKey keyPressed = event.key.keysym.sym;
             switch(keyPressed)
             {
                 case SDLK_ESCAPE:
                        break;
                case SDLK_LEFT:
                src.x -=10;
                        break;
                case SDLK_RIGHT:
                src.x +=10;
                        break;
                default: break;
             }
         }
      }

  if(SDL_BlitSurface(screen,&src, bg,&ziel)==-2)return -4; //painting the part of screen given by rect(src)
  SDL_Flip(bg);

   }//end game running


   SDL_FreeSurface(background_img);
   SDL_Quit();

   return 0;
}


I really don't know where my mistake is.
Probably I am using the surface in a wrong way?

Thanks for your help:)

Aestond


Top
 Profile  
 
PostPosted: Mon Apr 30, 2012 8:47 am 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
I don't understand what the problem is, exactly. "don't get it done" means what?

The basic structure looks ok at first glimpse.
You may want to skip blitting if src.x did not change; repeatedly blitting the same image at 30fps is not so useful.
I am sure you can find more useful ways to spend your CPU time :)

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Mon Apr 30, 2012 11:11 am 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Quote:
"don't get it done" means what?


Yes, not that much information*gg*

The problem is, that the code compiles without errors.
The first blits(before changing x), is like it should be.
But after changing x, it will show the image i a totally wrong way, like it has been roated some degrees.
(Can't check out right now, what happens if I pass x as 10 in the beginning, but I will edit it later)


Top
 Profile  
 
PostPosted: Mon Apr 30, 2012 11:44 am 
Bytewise

Joined: Sun Oct 16, 2011 3:09 pm
Posts: 277
Location: Here (where else?)
Make sure you don't try to display non-existing parts of the image, ie add boundary checks to the code such that the displayed part always exists in the source image.

_________________
My project: Messing about in FreeRCT, dev blog, and IRC #freerct at oftc.net


Top
 Profile  
 
PostPosted: Tue May 01, 2012 12:42 pm 
Dexterous Droid
User avatar

Joined: Wed Aug 18, 2004 7:40 pm
Posts: 3735
Location: South Africa
Blitting from a double buffered surface seems like it could be dodgy? Have you tried
Code:
      if(SDL_BlitSurface(background_img,&src, bg,&ziel)==-2)return -4; //painting the part of screen given by rect(src)
      SDL_Flip(bg);

_________________
Whatever the mind can conceive and believe, it can achieve


Top
 Profile  
 
PostPosted: Tue May 01, 2012 3:57 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Even if it is not doublebuffered it doesn't work.
But your quoted way works.

So I will try it this way:
Taking an empty image, with a fixed width, drawing everything to that image and then blitting parts of that.

I will write here about fail and success^^


Top
 Profile  
 
PostPosted: Tue May 01, 2012 4:55 pm 
Dexterous Droid
User avatar

Joined: Wed Aug 18, 2004 7:40 pm
Posts: 3735
Location: South Africa
aestond wrote:
Even if it is not doublebuffered it doesn't work.
But your quoted way works.

So I will try it this way:
Taking an empty image, with a fixed width, drawing everything to that image and then blitting parts of that.

I will write here about fail and success^^

I can't see anything in the SDL docs that mentions how to use the SetVideoMode surface, but apparently BlitSurface can't be used on locked surfaces. Maybe check that the return value for SDL_BlitSurface is not == -1 (blit failed).

_________________
Whatever the mind can conceive and believe, it can achieve


Top
 Profile  
 
PostPosted: Sun May 13, 2012 4:45 pm 
Rookie

Joined: Sat May 12, 2012 5:52 am
Posts: 2
I have not gone through these set of tutorials, but if you look on the right, you will notice that it progresses to making a Mario style scrolling level in SDL. The code is nice and simple.

http://www.parallelrealities.co.uk/2011/09/basic-game-tutorial-1-opening-window.html

Also Lazyfoo has a nice tiling/scrolling example.

http://lazyfoo.net/


Top
 Profile  
 
PostPosted: Wed May 23, 2012 5:29 am 
Prolific Poster

Joined: Mon Mar 19, 2012 5:59 am
Posts: 19
Hello everyone, I take this thread because it's a sort of my issue. I need the background to move smoothly.
I have a sprite/character which responds to a keyboard event. The background scrolls as the sprite begins to move.
Actually the sprite remains in the same place, I change the sprite picture to emulate character movement, instead is the background wich moves.
Everything it's ok, but the background doesn't move smoothly since its x value is reset after the event keyboard (which indicates sprite movement).
Is there a technique to do this and avoid this 'step by step' effect?

Thanks and regards

kovi

input handler

Code:
void Caracter::handle_input(SDL_Event event)
{ //If a key was pressed
    if( event.type == SDL_KEYDOWN )
     { //Adjust the velocity

         switch( event.key.keysym.sym )
         {
           case SDLK_UP:
                         yVel = -(SPRITE_H/2);
                         salto = true;
                         break;
           case SDLK_DOWN:
                       //yVel = SPRITE_H / 2;
                       colision = true;
                       break;
           case SDLK_LEFT:
                           //xVel = xVel -(SPRITE_W / 2);
                           nro_clip++;
                           bgX += 50;  // velocidad de background
                           break;
           case SDLK_RIGHT:
                           if (salto)
                               xVel = xVel + (SPRITE_W / 2);
                           bgX -= 50;  // velocidad de background                           
                           nro_clip++;
                           break;
           case SDLK_RETURN:
                            score = !score;
                            break;
           default:
                    break;
        }
    }
    //If a key was released
    else if( event.type == SDL_KEYUP )
    { //Adjust the velocity
        nro_clip = 0;
        mover = false;
        switch( event.key.keysym.sym )
        {
            case SDLK_UP:
                         yVel += SPRITE_H + 150;                   
                          break;
            case SDLK_DOWN: //yVel -=  SPRITE_H;//SPRITE_H / 2;
                            colision = false;
                            break;
            case SDLK_LEFT: //xVel += SPRITE_W / 2;
                            break;
            case SDLK_RIGHT: //xVel -= SPRITE_W / 2;
                             //bgX -= 8;  // velocidad de background
                             break;
            default: break;
        }

    }
}


Game loop

Code:
while (!done)
    {
        //Start the frame timer
        fps.start();
        // message processing loop
        SDL_Event event;

        while (SDL_PollEvent(&event))
        {
            //Handle events for the dot
            car->handle_input(event); //If the user has Xed out the window
            if(event.key.keysym.sym == SDLK_ESCAPE)
               done = true;    //Quit the program
        }

     
       car->move();       

        if (nro_clip > 4)
            nro_clip = 1;

        //If the background has gone too far
        if( bgX <= -background->w )
        { //Reset the offset
            bgX = 0;
        }


        //Show the background deslizante

        apply_surface(bgX, bgY, background, buffer);
        apply_surface(bgX + background->w, bgY, background, buffer);

        car->show();

        // Other stuff

        }
       

        SDL_BlitSurface(buffer, NULL, screen,NULL);

        SDL_UpdateRect(screen, 0, 0, 0, 0);

        if (message!= NULL)
        {
            SDL_FreeSurface(message);
            message = NULL;
        }

        SDL_FillRect (buffer, NULL, SDL_MapRGB(buffer->format, 0,0,0));

        //Cap the frame rate
        cout << "fps.get_ticks " << fps.get_ticks() << endl;
        if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
        }

    }


Top
 Profile  
 
PostPosted: Thu May 24, 2012 8:03 pm 
Shake'n'Baker

Joined: Thu Dec 29, 2011 2:33 pm
Posts: 62
Two things I wonder about:
Quote:
bgX += 50;

Since you are blitting the same sprite, but with x+50,
it is common that it doesn't seem to be smooth.
Try x+1 or x+2, maybe that will be smooth. And if it is,
than that might be your problem.

Another thing I don't understand:
Quote:
apply_surface(bgX, bgY, background, buffer);
apply_surface(bgX + background->w, bgY, background, buffer);

Doesn't the second applying overwrite your first?
Probably won't help on the smoothnes problem :|

Hope it helps a bit.


Top
 Profile  
 
PostPosted: Thu May 24, 2012 10:54 pm 
Prolific Poster

Joined: Mon Mar 19, 2012 5:59 am
Posts: 19
Hi, now I am doing bgX -=20

The second
Code:
apply_surface(bgX + background->w, bgY, background, buffer);
is for when the bgX reaches the surface width, so it keeps the screen 'covered' by the background.
Despite of this, I tryeed to surpress it, but it didn't change a lot indeed.

Actually I think it has to do with the keyboard event and when/how the bgX coordinate is changing.

Thanks for your tip anyway :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group