#include "SDL.h"
class Camera {
public:
int m_width;
int m_height;
int m_cameraBorder;
int m_target_width;
int m_target_height;
float m_x, m_y;
SDL_Texture* m_targetTexture;
public:
Camera(SDL_Renderer* renderer, int width, int height, int border, SDL_BlendMode mode) {
m_width = width;
m_height = height;
m_cameraBorder = border;
m_target_width = width + border * 2;
m_target_height = height + border * 2;
m_x = 0;
m_y = 0;
m_targetTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET,
m_target_width, m_target_height);
SDL_SetTextureBlendMode(m_targetTexture, mode);
}
void Draw(SDL_Renderer* renderer, int windowHeight) {
float pixel_h = (float)windowHeight / m_height;
float correction_x = (int)m_x - m_x;
float correction_y = (int)m_y - m_y;
SDL_Rect dst = { (int)(correction_x * pixel_h - pixel_h * m_cameraBorder),
(int)(correction_y * pixel_h - pixel_h * m_cameraBorder),
(int)(m_target_width * pixel_h),
(int)(m_target_height * pixel_h) };
SDL_RenderCopy(renderer, m_targetTexture, NULL, &dst);
}
void Update(int xDirection, int yDirection) {
m_x += 0.5f * xDirection;
m_y += 0.5f * yDirection;
}
void CameraReset(SDL_Renderer* renderer, int width, int height, int border, SDL_BlendMode mode) {
m_width = width;
m_height = height;
m_cameraBorder = border;
m_target_width = width + border * 2;
m_target_height = height + border * 2;
SDL_DestroyTexture(m_targetTexture);
m_targetTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET,
m_target_width, m_target_height);
SDL_SetTextureBlendMode(m_targetTexture, mode);
}
~Camera() {
SDL_DestroyTexture(m_targetTexture);
}
};
class Sprite {
public:
int width;
int height;
float m_destX, m_destY;
SDL_Surface* surface;
SDL_Texture* texture;
public:
Sprite(SDL_Renderer* renderer, const char* filename) {
surface = SDL_LoadBMP(filename);
width = surface->w;
height = surface->h;
m_destX = 0;
m_destY = 0;
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
}
void DrawSprite(SDL_Renderer* renderer, Camera* camera, int x, int y) {
SDL_Rect destRect = { (int)(m_destX - camera->m_x) + camera->m_cameraBorder + x,
(int)(m_destY - camera->m_y) + camera->m_cameraBorder + y,
width, height };
SDL_RenderCopy(renderer, texture, NULL, &destRect);
}
~Sprite() {
SDL_DestroyTexture(texture);
}
};
int main(int argc, char** argv) {
const int Window_Width = 640;
const int Window_Height = 480;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
SDL_Window* window = SDL_CreateWindow("SDL Simple Camera", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, Window_Width, Window_Height, SDL_WINDOW_RESIZABLE);
SDL_assert(window);
SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1");
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
SDL_assert(renderer);
// Init
Camera camera = Camera(renderer, 160, 120, 1, SDL_BLENDMODE_BLEND);
SDL_assert(camera.m_targetTexture);
Sprite shopSprite = Sprite(renderer, "shop.bmp");
Sprite characterSprite = Sprite(renderer, "character.bmp");
int xDirection = 0;
int yDirection = 0;
SDL_Event event;
bool quit = false;
while (!quit) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
quit = true;
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
quit = true;
if (event.key.keysym.sym == SDLK_LEFT)
xDirection = -1;
if (event.key.keysym.sym == SDLK_RIGHT)
xDirection = 1;
if (event.key.keysym.sym == SDLK_UP)
yDirection = -1;
if (event.key.keysym.sym == SDLK_DOWN)
yDirection = 1;
if (event.key.keysym.sym == SDLK_r)
camera.CameraReset(renderer, 160, 120, 1, SDL_BLENDMODE_BLEND);
if (event.key.keysym.sym == SDLK_e)
camera.CameraReset(renderer, 640, 480, 1, SDL_BLENDMODE_BLEND);
break;
default:
xDirection = 0;
yDirection = 0;
break;
}
}
camera.Update(xDirection, yDirection);
// Camera target
SDL_SetRenderTarget(renderer, camera.m_targetTexture);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
SDL_RenderClear(renderer);
// Draw Sprite
shopSprite.DrawSprite(renderer, &camera, 0, 0);
characterSprite.DrawSprite(renderer, &camera, 116, 66);
// Screen target
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
SDL_RenderClear(renderer);
camera.Draw(renderer, Window_Height);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}