
In this tutorial we will use helper structs for the camera and the player:
struct Vec2 {
float x, y;
};
struct Camera {
Vec2 position;
int width, height;
};
struct Player {
SDL_FRect rect;
float speed;
};
We can also make the windows resizable with SDL_WINDOW_RESIZABLE :
SDL_Window* window = SDL_CreateWindow("SDL3 Camera Demo", 800, 600, SDL_WINDOW_RESIZABLE);
if (!window) {
SDL_Log("Failed to create window: %s", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_Surface *bg = IMG_Load("bg.png");
SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, bg);
SDL_DestroySurface(bg);
For this example I will use the background of the pokemon world: bg.png
const int WORLD_WIDTH = tex->w;
const int WORLD_HEIGHT = tex->h;
Player player = { {100, 100, 32, 32}, 300.0f };
Camera camera = { {0, 0}, 800, 600 };
Uint64 currentTime = SDL_GetTicks();
float delta = (currentTime - lastTime) / 1000.0f;
lastTime = currentTime;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_EVENT_QUIT)
running = false;
if (e.type == SDL_EVENT_WINDOW_RESIZED) {
SDL_GetWindowSize(window, &camera.width, &camera.height);
}
}
We also need to use the keyboard for the player movement:
const bool* keys = SDL_GetKeyboardState(NULL);
if (keys[SDL_SCANCODE_W]) player.rect.y -= player.speed * delta;
if (keys[SDL_SCANCODE_S]) player.rect.y += player.speed * delta;
if (keys[SDL_SCANCODE_A]) player.rect.x -= player.speed * delta;
if (keys[SDL_SCANCODE_D]) player.rect.x += player.speed * delta;
The player cannot move outside the world:
if (player.rect.x < 0) player.rect.x = 0;
if (player.rect.y < 0) player.rect.y = 0;
if (player.rect.x + player.rect.w > WORLD_WIDTH) player.rect.x = WORLD_WIDTH - player.rect.w;
if (player.rect.y + player.rect.h > WORLD_HEIGHT) player.rect.y = WORLD_HEIGHT - player.rect.h;
We update the camera position to the center of the player:
camera.position.x = player.rect.x + player.rect.w / 2 - camera.width / 2;
camera.position.y = player.rect.y + player.rect.h / 2 - camera.height / 2;
if (camera.position.x < 0) camera.position.x = 0;
if (camera.position.y < 0) camera.position.y = 0;
if (camera.position.x + camera.width > WORLD_WIDTH)
camera.position.x = WORLD_WIDTH - camera.width;
if (camera.position.y + camera.height > WORLD_HEIGHT)
camera.position.y = WORLD_HEIGHT - camera.height;
SDL_FRect worldBounds = {
-camera.position.x,
-camera.position.y,
(float)WORLD_WIDTH,
(float)WORLD_HEIGHT
};
SDL_RenderTexture(renderer, tex, NULL, &worldBounds);
SDL_FRect screenPlayer = {
player.rect.x - camera.position.x,
player.rect.y - camera.position.y,
player.rect.w,
player.rect.h
};
SDL_SetRenderDrawColor(renderer, 200, 50, 50, 255);
SDL_RenderFillRect(renderer, &screenPlayer);
You can download the full project:
Need another OS ? => Windows, Mac, Linux