Help with scrolling

Greetings,
I’m curious if I am implementing this correctly. I am trying to scroll some
clouds across the screen and when they hit the edge, they will wrap back around.
I first tried blitting off screen, but I noticed it would not accept negative
values. Instead it adjusted them to positive values and then performed the
blit. I eventually got it to work by first creating an oversized surface in
memory and blitting a clipped region from that surface to the screen, after
updating and blitting the clouds on to the new surface I created in memory. The
following is a list of my code. I just want to know if this is the correct way
of doing this or if there is an easier/more efficient way of wrapping and object
back around after it goes off screen. Thank you.********************************************************************************

#include <stdlib.h>
#include <SDL/SDL.h>

//SDL global variables
SDL_Surface *screen;
SDL_Event event;

//graphics
SDL_Surface *background;
SDL_Surface *cloud;
SDL_Surface *temp;

//Timing vars
Uint32 prior;
Uint32 current;
Uint32 elapsed;

//sprite info
SDL_Rect Position1 = {200,400,384,256};
SDL_Rect Position2 = {500,100,384,256};
SDL_Rect Position3 = {800,500,384,256};
SDL_Rect screenSize = {400,0,1024,768};

//function prototypes
void render(Uint32 time);

// Entry point
int main(int argc, char *argv[])
{
// Initialize SDL’s subsystems
if ( SDL_Init(SDL_INIT_EVERYTHING) == -1 )
{
fprintf(stderr, “Unable to init SDL: %s\n”, SDL_GetError());
exit(1);
}

// Register SDL_Quit to be called at exit
atexit(SDL_Quit);

// Attempt to create a 1024x768 window with 32bit pixels, full screen and HW

accelerated.
screen = SDL_SetVideoMode(1024, 768, 32, SDL_FULLSCREEN);

//load images
background = SDL_LoadBMP("sky.bmp");
cloud = SDL_LoadBMP("cloud.bmp");

//set up a back buffer
temp = SDL_CreateRGBSurface(SDL_HWSURFACE, 1824, 768, 32, 0, 0, 0, 0);

//make cloud transparent
SDL_SetColorKey(cloud, SDL_SRCCOLORKEY, 0);


prior = SDL_GetTicks(); //get start time

// Main loop: loop forever.
while (1)
{
	current = SDL_GetTicks(); //get elapsed time

	//update graphics
	render(elapsed = current - prior);

	// Poll for events, and handle the ones we care about.
	while (SDL_PollEvent(&event)) 
	{
		switch (event.type) 
		{
			case SDL_KEYDOWN:
				break;
			case SDL_KEYUP:
				// If escape is pressed, return (and thus, quit)
				if (event.key.keysym.sym == SDLK_ESCAPE)
					return(0);
				break;
			case SDL_QUIT:
				return(0);
		}
	}
}

}

void render(time)
{
//lock screen if needed
if(SDL_MUSTLOCK(temp)) {
if(SDL_LockSurface(temp) < 0)
return;
}

if(time >= 50) //update sprites
{
	prior = current; //reset time
	
	Position1.x += 1;
	Position2.x += 1;
	Position3.x += 1;
}

//blit the images
//blit background
SDL_BlitSurface(background, NULL, temp, &screenSize);

//blit clouds
SDL_BlitSurface(cloud, NULL, temp, &Position1);
SDL_BlitSurface(cloud, NULL, temp, &Position2);
SDL_BlitSurface(cloud, NULL, temp, &Position3);

if(SDL_MUSTLOCK(temp)) {
	SDL_UnlockSurface(temp);
}


//lock screen if needed
if(SDL_MUSTLOCK(screen)) {
	if(SDL_LockSurface(screen) < 0) 
		return;
}
//blit temp buffer to screen
SDL_BlitSurface(temp, &screenSize, screen, NULL);

if(SDL_MUSTLOCK(screen)) {
	SDL_UnlockSurface(screen);
}


// Tell SDL to update the whole screen
SDL_Flip(screen);

//check if cloud position needed to be reset
if(Position1.x == 1424)
	Position1.x = 16;
if(Position2.x == 1424)
	Position2.x = 16;
if(Position3.x == 1424)
	Position3.x = 16;

}

it does accept negative values. however, the destination rectangle is
actaully modified to show the clipped co-ordinates of the blit. you
need to store the destination and copy it to the rect for blitting.

see http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fBlitSurface for
details, this line specifically:

"The final blit rectangle is saved in dstrect after all clipping is
performed (srcrect is not modified)."On 12/20/05, Student wrote:

Greetings,
I’m curious if I am implementing this correctly. I am trying to scroll some
clouds across the screen and when they hit the edge, they will wrap back around.
I first tried blitting off screen, but I noticed it would not accept negative
values. Instead it adjusted them to positive values and then performed the
blit. I eventually got it to work by first creating an oversized surface in
memory and blitting a clipped region from that surface to the screen, after
updating and blitting the clouds on to the new surface I created in memory. The
following is a list of my code. I just want to know if this is the correct way
of doing this or if there is an easier/more efficient way of wrapping and object
back around after it goes off screen. Thank you.


#include <stdlib.h>
#include <SDL/SDL.h>

//SDL global variables
SDL_Surface *screen;
SDL_Event event;

//graphics
SDL_Surface *background;
SDL_Surface *cloud;
SDL_Surface *temp;

//Timing vars
Uint32 prior;
Uint32 current;
Uint32 elapsed;

//sprite info
SDL_Rect Position1 = {200,400,384,256};
SDL_Rect Position2 = {500,100,384,256};
SDL_Rect Position3 = {800,500,384,256};
SDL_Rect screenSize = {400,0,1024,768};

//function prototypes
void render(Uint32 time);

// Entry point
int main(int argc, char *argv[])
{
// Initialize SDL’s subsystems
if ( SDL_Init(SDL_INIT_EVERYTHING) == -1 )
{
fprintf(stderr, “Unable to init SDL: %s\n”, SDL_GetError());
exit(1);
}

    // Register SDL_Quit to be called at exit
    atexit(SDL_Quit);

    // Attempt to create a 1024x768 window with 32bit pixels, full screen and HW

accelerated.
screen = SDL_SetVideoMode(1024, 768, 32, SDL_FULLSCREEN);

    //load images
    background = SDL_LoadBMP("sky.bmp");
    cloud = SDL_LoadBMP("cloud.bmp");

    //set up a back buffer
    temp = SDL_CreateRGBSurface(SDL_HWSURFACE, 1824, 768, 32, 0, 0, 0, 0);

    //make cloud transparent
    SDL_SetColorKey(cloud, SDL_SRCCOLORKEY, 0);


    prior = SDL_GetTicks(); //get start time

    // Main loop: loop forever.
    while (1)
    {
            current = SDL_GetTicks(); //get elapsed time

            //update graphics
            render(elapsed = current - prior);

            // Poll for events, and handle the ones we care about.
            while (SDL_PollEvent(&event))
            {
                    switch (event.type)
                    {
                            case SDL_KEYDOWN:
                                    break;
                            case SDL_KEYUP:
                                    // If escape is pressed, return (and thus, quit)
                                    if (event.key.keysym.sym == SDLK_ESCAPE)
                                            return(0);
                                    break;
                            case SDL_QUIT:
                                    return(0);
                    }
            }
    }

}

void render(time)
{
//lock screen if needed
if(SDL_MUSTLOCK(temp)) {
if(SDL_LockSurface(temp) < 0)
return;
}

    if(time >= 50) //update sprites
    {
            prior = current; //reset time

            Position1.x += 1;
            Position2.x += 1;
            Position3.x += 1;
    }

    //blit the images
    //blit background
    SDL_BlitSurface(background, NULL, temp, &screenSize);

    //blit clouds
    SDL_BlitSurface(cloud, NULL, temp, &Position1);
    SDL_BlitSurface(cloud, NULL, temp, &Position2);
    SDL_BlitSurface(cloud, NULL, temp, &Position3);

    if(SDL_MUSTLOCK(temp)) {
            SDL_UnlockSurface(temp);
    }


    //lock screen if needed
    if(SDL_MUSTLOCK(screen)) {
            if(SDL_LockSurface(screen) < 0)
                    return;
    }
    //blit temp buffer to screen
    SDL_BlitSurface(temp, &screenSize, screen, NULL);

    if(SDL_MUSTLOCK(screen)) {
            SDL_UnlockSurface(screen);
    }


    // Tell SDL to update the whole screen
    SDL_Flip(screen);

    //check if cloud position needed to be reset
    if(Position1.x == 1424)
            Position1.x = 16;
    if(Position2.x == 1424)
            Position2.x = 16;
    if(Position3.x == 1424)
            Position3.x = 16;

}


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

( 160+ lines of quote removed )

it does accept negative values.

cough Please trim quotes when replying, thanks :slight_smile:

-bill!On Wed, Dec 21, 2005 at 01:20:15AM +0000, Brian Barrett wrote:

Could be a gmail-habit of Brian … it does some “quote hiding” automagically :)On 12/21/05, Bill Kendrick wrote:

On Wed, Dec 21, 2005 at 01:20:15AM +0000, Brian Barrett wrote:

( 160+ lines of quote removed )

it does accept negative values.

cough Please trim quotes when replying, thanks :slight_smile:

-bill!


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

yeah, whoops. sorry bout that, will do in future…On 12/21/05, Olof Bjarnason <olof.bjarnason at gmail.com> wrote:

Could be a gmail-habit of Brian … it does some “quote hiding” automagically :slight_smile:

Perhaps I was not clear with my question initially. I understand what the API
is saying, or maybe I don’t and I need someone to give me a different
perspective to look at this from. However, what I want to know is if there is
anyway to pass a negative value to the *dstrect so I can have a certain portion
of an image drawn to the screen without having to do it with some other form of
logic through the *srcrect. I know *srcrect takes negative values so I can clip
a certain region of my source image and I know *dstrect only uses the x and y
data to position the image on the destination surface. I have tried sending
negative values for *dstrect, but the computer always ignores it and adjusts the
coordinate back to zero if it had been negative initially. What I want to know
is if there is anyway to blit an image from a source without clipping it in
anyway and then position it in the destination surface (which is the actual
screen in my case), where it is slightly off screen, so it gets clipped
automatically and only shows the portion relevant to the screen’s size. I know
how to get by this, but it would be a lot easier if there is a method similar to
what I am describing where all I have to do is say, “Hey computer, here is an
image, I want you to draw it at (-200, 400) and it is 600 pixels wide and 200
pixels high. Figure out how it will look on a 1024x768 screen whose initial
point is (0,0).” That is what I am going for. Any comments or suggestions
would be appreciated, source code examples are even better. Thanks.

hopefully this example will show you your error
the first time you blit, you can have negative values. however, if you
do not refresh those values you will lose them. you need to store the
positions seperatly from the SDL_Rects that SDL_BlitSurface(…);
accepts…

#include "SDL.h"
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *screen = SDL_SetVideoMode(640,480,32,0);
SDL_Surface *surf = SDL_LoadBMP(“big.bmp”);
SDL_Rect dest;/// = {-50,-50,0,0};
dest.x = -50; dest.y = -50;
SDL_FillRect(screen, NULL, 0);
SDL_BlitSurface( surf, NULL, screen, &dest );

SDL_Event event;
int cont = 1;
while( cont )
{
    while (SDL_PollEvent(&event) )
    {
        if( event.type == SDL_QUIT )
        {
            cont = 0;
        }
        if( event.type == SDL_KEYDOWN )
        {
            SDL_FillRect(screen, NULL, 0);
            SDL_BlitSurface( surf, NULL, screen, &dest );
        }
        if( event.type == SDL_KEYUP )
        {
            dest.x = -50;
            dest.y = -50;
            SDL_FillRect(screen, NULL, 0);
            SDL_BlitSurface( surf, NULL, screen, &dest );
        }
    }
    SDL_Flip( screen );
}
SDL_Quit();
return 0;

}

Actually that helps a lot; I now understand what you were talking about earlier.
I hope I didn’t frustrate you too much :slight_smile: