Need Simple Image scrolling sample


#1

Hi

I am new SDL project.

I have image with size of 1000 width and 1000 height. I want to scroll the image horizontally (Right to Left and Left to Right) till image width reach the screen start position.

Does anybody has sample code, please share with me. Many Thanks.


#2

Here’s a complete code example for scrolling an image file back and forth on the screen.
The scrolling direction changes whenever each edge of the texture is reached.
Read through all the code and make sure that you understand what everything does, and ask for anything that you’re unsure about.

Click here to view the code
#include <iostream>

#include <SDL.h>
#include <SDL_image.h>

#define WINDOW_WIDTH	(800)
#define WINDOW_HEIGHT	(600)

// The camera's different states
enum class ECameraState
{
	CAMERA_STILL = 0,
	CAMERA_SCROLLING_LEFT,
	CAMERA_SCROLLING_RIGHT,
	NUM_CAMERA_STATES
};

// Simple struct to hold camera data
struct SCamera
{
	SCamera(void)
	: XPosition(0.0f)
	, YPosition(0.0f)
	, Velocity(0.0f)
	, Quad({0, 0, 0, 0})
	, State(ECameraState::CAMERA_STILL)
	{

	}

	SCamera(const float NewXPosition, const float NewYPosition, const float NewVelocity, const SDL_Rect& rNewQuad, const ECameraState NewState)
	: XPosition(NewXPosition)
	, YPosition(NewYPosition)
	, Velocity(NewVelocity)
	, Quad(rNewQuad)
	, State(NewState)
	{

	}

	float			XPosition;
	float			YPosition;
	float			Velocity;
	SDL_Rect		Quad;
	ECameraState	State;
};

// Simple struct to hold texture data
struct STexture
{
	STexture(void)
	: pTexture(nullptr)
	, Quad({0, 0, 0, 0})
	{

	}

	STexture(SDL_Texture* pNewTexture, const SDL_Rect& rNewQuad)
	: pTexture(pNewTexture)
	, Quad(rNewQuad)
	{

	}

	SDL_Texture*	pTexture;
	SDL_Rect		Quad;
};

//////////////////////////////////////////////////////////////////////////

// Function declarations

bool			InitializeSDL(void);
void			DeinitializeSDL(void);
bool			Create(void);
void			Destroy(void);
void			HandleEvents(void);
void			Update(void);
void			Render(void);
SDL_Texture*	CreateTexture(const std::string& rPath);

//////////////////////////////////////////////////////////////////////////

SDL_Window*		pWindow = nullptr;
SDL_Renderer*	pRenderer = nullptr;

SDL_Event Event;

SCamera Camera;

STexture* pBackgroundTexture;

double DeltaTime = 0.0;
double OldTime = 0.0;
double NewTime = 0.0;

bool Running = true;

//////////////////////////////////////////////////////////////////////////

bool InitializeSDL()
{
	if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		std::cout << "Failed to initialize SDL. " << SDL_GetError() << std::endl;

		return false;
	}

	std::cout << "SDL successfully initialized" << std::endl;

	if(IMG_Init(IMG_INIT_PNG | IMG_INIT_TIF) == 0)
	{
		std::cout << "Failed to initialize SDL_Image. " << IMG_GetError() << std::endl;

		return false;
	}

	std::cout << "SDL_Image successfully initialized" << std::endl;

	if(SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1") == 0)
		std::cout << "Failed to set the render scale quality. " << SDL_GetError() << std::endl;

	std::cout << "SDL render scale quality successfully set to \"linear\"" << std::endl;

	pWindow = SDL_CreateWindow("SDL image scroller", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

	if(!pWindow)
	{
		std::cout << "Failed to create the SDL window. " << SDL_GetError() << std::endl;

		return false;
	}

	std::cout << "SDL window successfully created" << std::endl;

	pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);

	if(!pRenderer)
	{
		std::cout << "Failed to create the SDL renderer. " << SDL_GetError() << std::endl;

		return false;
	}

	std::cout << "SDL renderer successfully created" << std::endl;

	if(SDL_SetRenderDrawColor(pRenderer, 192, 192, 192, 0xFF) == -1)
		std::cout << "Failed to set the SDL render draw color. " << SDL_GetError() << std::endl;

	else
		std::cout << "SDL render draw color successfully set" << std::endl;

	return true;
}

void DeinitializeSDL()
{
	if(pRenderer)
	{
		SDL_DestroyRenderer(pRenderer);
		pRenderer = nullptr;
	}

	if(pWindow)
	{
		SDL_DestroyWindow(pWindow);
		pWindow = nullptr;
	}

	IMG_Quit();
	SDL_Quit();
}

bool Create(void)
{
	// Create the texture

	SDL_Texture* pSDLTexture = CreateTexture("Data/Textures/Image.png");

	if(!pSDLTexture)
		return false;

	int TextureWidth;
	int TextureHeight;

	SDL_QueryTexture(pSDLTexture, nullptr, nullptr, &TextureWidth, &TextureHeight);

	SDL_Rect TextureQuad = {0, 0, TextureWidth, TextureHeight};

	pBackgroundTexture = new STexture(pSDLTexture, TextureQuad);

	//////////////////////////////////////////////////////////////////////////

	// Create the camera

	SDL_Rect CameraQuad = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};

	Camera = SCamera(0.0f, 0.0f, 128.0f, CameraQuad, ECameraState::CAMERA_SCROLLING_RIGHT);

	return true;
}

void Destroy(void)
{
	SDL_DestroyTexture(pBackgroundTexture->pTexture);
	pBackgroundTexture->pTexture = nullptr;

	delete pBackgroundTexture;
	pBackgroundTexture = nullptr;
}

void HandleEvents(void)
{
	while(SDL_PollEvent(&Event))
	{
		switch(Event.type)
		{
			case SDL_QUIT:
			{
				Running = false;

				break;
			}

			case SDL_KEYDOWN:
			{
				switch(Event.key.keysym.sym)
				{
					case SDLK_ESCAPE:
					{
						Running = false;

						break;
					}
				}
			}
		}
	}
}

void Update()
{
	HandleEvents();

	NewTime = SDL_GetTicks();
	DeltaTime = (NewTime - OldTime) / 1000.0;
	OldTime = NewTime;

	// If the camera's state is currently scroll left,  decrease the camera's position each frame
	// If the camera's state is currently scroll right, increase the camera's position each frame
	Camera.XPosition += ((Camera.State == ECameraState::CAMERA_SCROLLING_LEFT) ? -Camera.Velocity : Camera.Velocity) * (float)DeltaTime;

	// When the camera reaches the far left side of the texture, change the camera state to scroll right
	if(Camera.XPosition < 0.0f)
	{
		Camera.XPosition = 0.0f;

		Camera.State = ECameraState::CAMERA_SCROLLING_RIGHT;
	}

	// When the camera reaches the far right side of the texture, change the camera state to scroll left
	else if(Camera.XPosition > (float)((pBackgroundTexture->Quad.x + pBackgroundTexture->Quad.w) - Camera.Quad.w))
	{
		Camera.XPosition = (float)((pBackgroundTexture->Quad.x + pBackgroundTexture->Quad.w) - Camera.Quad.w);

		Camera.State = ECameraState::CAMERA_SCROLLING_LEFT;
	}
}

void Render()
{
	SDL_RenderClear(pRenderer);

	// Offset the texture's position relative to the camera
	// When the camera moves, for example, to the right, move the texture to the left and vice versa
	const SDL_Rect TextureQuad = {	pBackgroundTexture->Quad.x - (int)Camera.XPosition,
									pBackgroundTexture->Quad.y - (int)Camera.YPosition,
									pBackgroundTexture->Quad.w,
									pBackgroundTexture->Quad.h};

	SDL_RenderCopy(pRenderer, pBackgroundTexture->pTexture, nullptr, &TextureQuad);

	SDL_RenderPresent(pRenderer);
}

SDL_Texture* CreateTexture(const std::string& rPath)
{
	SDL_Surface* pSurface = IMG_Load(rPath.c_str());

	if(!pSurface)
	{
		std::cout << "Failed to create SDL surface. " << IMG_GetError() << std::endl;

		return nullptr;
	}

	SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);

	SDL_FreeSurface(pSurface);
	pSurface = nullptr;

	if(!pTexture)
	{
		std::cout << "Failed to create SDL texture. " << SDL_GetError() << std::endl;

		return nullptr;
	}

	return pTexture;
}

int main(int argc, char *argv[])
{
	if(InitializeSDL())
	{
		if(Create())
		{
			while(Running)
			{
				Update();
				Render();

				SDL_Delay(1);
			}

			Destroy();
		}

		DeinitializeSDL();
	}

	return 0;
}

#3

HI

Thanks for yor quick response. Much appreciated.

Will check and update you.


#4

Hi

I just change the following

#define WINDOW_WIDTH (1920)
#define WINDOW_HEIGHT (1080)

and used following image but its not scrolling its flickering very fast.

Please check and update me.

Many Thanks.


#5

Are all those separate images combined into 1 single image file?

If the image file(s) you’re trying to scroll through is 1000 in width, then it’s obvious why the flickering occurs. The camera width is bigger than the image file - the camera width is automatically set to the window width, which in your case is 1920, which means that camera is trying to compensate the right scrolling movement. Either lower the size of the conceptual camera or use a wider image file. The camera width always has to be the same size as (or smaller than) the image file the camera should scroll through.


#6

Yes. its a single image. Okay will do the same and update you…