removed references to old "Context" concepts and replaced with constants, declared camera functions

This commit is contained in:
Sara 2023-09-23 22:52:55 +02:00
parent 5b5b4c31fc
commit 5516a70d57
8 changed files with 129 additions and 99 deletions

24
src/camera.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef _fencer_camera_h
#define _fencer_camera_h
#include "vmath.h"
#include <SDL2/SDL_rect.h>
struct Camera {
Vector centre;
float width;
};
typedef struct Camera Camera;
// current world location of camera
extern Camera g_camera;
extern void camera_init();
// generate a screen-space rectangle that is exactly 1x1 in world units.
// With it's centre on the world origin.
extern SDL_FRect camera_calculate_world_unit_rect(Camera* self);
extern SDL_FRect camera_to_world_space(Camera* self, SDL_FRect* camera_space);
extern SDL_FRect camera_world_to_camera_space(Camera* self, SDL_FRect* world_space);
#endif // !_fencer_camera_h

View file

@ -5,7 +5,7 @@ int main(int argc, char* argv[]) {
struct ProgramSettings config = { struct ProgramSettings config = {
.target_fps = 0, // unbounded speed .target_fps = 0, // unbounded speed
.title = "fencer", .title = "fencer",
.view_resolution = {160, 140} .view_resolution = {1920, 1080}
}; };
return program_run(&config); return program_run(&config);
} }

View file

@ -1,14 +1,19 @@
#include "program.h" #include "program.h"
#include <SDL2/SDL_video.h> #include <SDL2/SDL_video.h>
#include <SDL2/SDL_image.h>
#include "tilemap.h"
SDL_Window* g_window;
double g_delta_time;
double g_frame_start;
struct Program g_program;
#define INITFLAGS SDL_INIT_EVENTS | SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER #define INITFLAGS SDL_INIT_EVENTS | SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER
int program_run(const struct ProgramSettings* settings) { int program_run(const struct ProgramSettings* settings) {
SDL_Init(INITFLAGS); SDL_Init(INITFLAGS);
g_program.window = SDL_CreateWindow( g_window = SDL_CreateWindow(
settings->title, settings->title,
SDL_WINDOWPOS_CENTERED_DISPLAY(0), SDL_WINDOWPOS_CENTERED_DISPLAY(0),
SDL_WINDOWPOS_CENTERED_DISPLAY(0), SDL_WINDOWPOS_CENTERED_DISPLAY(0),
@ -16,45 +21,55 @@ int program_run(const struct ProgramSettings* settings) {
settings->view_resolution.y, settings->view_resolution.y,
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE); SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
g_program.render_context = render_init(&g_program, settings); render_init(g_window, settings);
struct Tilemap map = tilemap_load("resources/box.tilemap.xml");
struct Tileset set = {
.texture = IMG_LoadTexture(g_renderer, "resources/ts_castle.png"),
.tile_size = {32, 32},
.shear = 10
};
SDL_QueryTexture(set.texture, NULL, NULL, &set.texture_resolution.x, &set.texture_resolution.y);
map.tileset = set;
for(;;) { for(;;) {
SDL_Delay(1); SDL_Delay(1);
program_handle_events(&g_program); program_handle_events();
render_present(g_program.render_context); tilemap_render(&map);
render_present();
} }
return 1; return 1;
} }
void program_quit(struct Program* self) { void program_quit() {
render_destroy(self->render_context); render_clean();
SDL_DestroyWindow(self->window); SDL_DestroyWindow(g_window);
SDL_Quit(); SDL_Quit();
exit(0); exit(0);
} }
void program_handle_events(struct Program* self) { void program_handle_events() {
SDL_Event event; SDL_Event event;
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
switch(event.type) { switch(event.type) {
default: break; default: break;
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
if(event.window.windowID == SDL_GetWindowID(self->window)) { if(event.window.windowID == SDL_GetWindowID(g_window)) {
program_handle_windowevent(self, &event.window); program_handle_windowevent(&event.window);
} }
break; break;
case SDL_QUIT: case SDL_QUIT:
program_quit(self); program_quit();
break; break;
} }
} }
} }
void program_handle_windowevent(struct Program* self, SDL_WindowEvent* event) { void program_handle_windowevent(SDL_WindowEvent* event) {
switch(event->type) { switch(event->type) {
default: default:
render_handle_resize(self->render_context); render_handle_resize();
break; break;
} }
} }

View file

@ -6,24 +6,19 @@
#include "vmath.h" #include "vmath.h"
#include "render.h" #include "render.h"
extern struct Program g_program;
struct ProgramSettings { struct ProgramSettings {
const char* title; const char* title;
IVector view_resolution; IVector view_resolution;
int target_fps; int target_fps;
}; };
struct Program { extern SDL_Window* g_window;
SDL_Window* window; extern double g_delta_time;
struct RenderContext* render_context; extern double g_frame_start;
double delta_time;
double start_frame;
};
extern int program_run(const struct ProgramSettings* settings); extern int program_run(const struct ProgramSettings* settings);
extern void program_quit(struct Program* self); extern void program_quit();
extern void program_handle_events(struct Program* self); extern void program_handle_events();
extern void program_handle_windowevent(struct Program* self, SDL_WindowEvent* event); extern void program_handle_windowevent(SDL_WindowEvent* event);
#endif // !_fencer_program_h #endif // !_fencer_program_h

View file

@ -3,83 +3,84 @@
#include <SDL2/SDL_pixels.h> #include <SDL2/SDL_pixels.h>
#include <SDL2/SDL_render.h> #include <SDL2/SDL_render.h>
struct RenderContext* render_init(const struct Program* program, const struct ProgramSettings* settings) { SDL_Renderer* g_renderer;
struct RenderContext* self = malloc(sizeof(struct RenderContext)); SDL_Texture* g_render_target;
SDL_Rect g_render_area;
IVector g_render_resolution;
void render_init(SDL_Window* window, const struct ProgramSettings* settings) {
// create renderer, needs to be able to target textures, preferably hardware accelerated // create renderer, needs to be able to target textures, preferably hardware accelerated
self->renderer = SDL_CreateRenderer(program->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); g_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
// create render target texture // create render target texture
self->render_target = SDL_CreateTexture( g_render_target = SDL_CreateTexture(
self->renderer, g_renderer,
SDL_PIXELFORMAT_ARGB32, SDL_PIXELFORMAT_ARGB32,
SDL_TEXTUREACCESS_TARGET, SDL_TEXTUREACCESS_TARGET,
settings->view_resolution.x, settings->view_resolution.y); settings->view_resolution.x, settings->view_resolution.y);
// store the desired view resolution // store the desired view resolution
self->render_resolution = settings->view_resolution; g_render_resolution = settings->view_resolution;
// get the destination area for rendering the target onto the window // get the destination area for rendering the target onto the window
render_calculate_render_area(self); render_calculate_render_area();
// clear target black // clear target black
SDL_SetRenderTarget(self->renderer, self->render_target); SDL_SetRenderTarget(g_renderer, g_render_target);
SDL_SetRenderDrawColor(self->renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
SDL_RenderClear(self->renderer); SDL_RenderClear(g_renderer);
return self;
} }
void render_destroy(struct RenderContext* self) { void render_clean() {
// clear up allocated SDL objects // clear up allocated SDL objects
SDL_DestroyTexture(self->render_target); SDL_DestroyTexture(g_render_target);
SDL_DestroyRenderer(self->renderer); SDL_DestroyRenderer(g_renderer);
} }
void render_present(struct RenderContext* self) { void render_present() {
// clear window white // clear window white
SDL_SetRenderTarget(self->renderer, NULL); SDL_SetRenderTarget(g_renderer, NULL);
SDL_SetRenderDrawColor(self->renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
SDL_RenderClear(self->renderer); SDL_RenderClear(g_renderer);
// copy render target // copy render target
SDL_Rect source_rect = {0, 0, self->render_resolution.x, self->render_resolution.y}; SDL_Rect source_rect = {0, 0, g_render_resolution.x, g_render_resolution.y};
SDL_RenderCopy(self->renderer, self->render_target, &source_rect, &self->render_area); SDL_RenderCopy(g_renderer, g_render_target, &source_rect, &g_render_area);
SDL_RenderPresent(self->renderer); SDL_RenderPresent(g_renderer);
// clear render target // clear render target
SDL_SetRenderTarget(self->renderer, self->render_target); SDL_SetRenderTarget(g_renderer, g_render_target);
SDL_SetRenderDrawColor(self->renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
SDL_RenderClear(self->renderer); SDL_RenderClear(g_renderer);
} }
void render_calculate_render_area(struct RenderContext* self) { void render_calculate_render_area() {
// get aspect ratios of both the window and the rendertexture // get aspect ratios of both the window and the rendertexture
IVector window_resolution = render_get_window_size(self); IVector window_resolution = render_get_window_size();
float window_aspect = (float)window_resolution.x / (float)window_resolution.y; float window_aspect = (float)window_resolution.x / (float)window_resolution.y;
float target_aspect = (float)self->render_resolution.x / (float)self->render_resolution.y; float target_aspect = (float)g_render_resolution.x / (float)g_render_resolution.y;
// calculate the largest area that will fit the entire rendertexture into the window space // calculate the largest area that will fit the entire rendertexture into the window space
self->render_area = (SDL_Rect) {0, 0, window_resolution.x, window_resolution.y}; g_render_area = (SDL_Rect) {0, 0, window_resolution.x, window_resolution.y};
if(window_aspect <= target_aspect) { if(window_aspect <= target_aspect) {
self->render_area.h = window_resolution.x / target_aspect; g_render_area.h = window_resolution.x / target_aspect;
self->render_area.y = (window_resolution.y - self->render_area.h) / 2; g_render_area.y = (window_resolution.y - g_render_area.h) / 2;
} else { } else {
self->render_area.w = window_resolution.y * target_aspect; g_render_area.w = window_resolution.y * target_aspect;
self->render_area.x += (window_resolution.x - self->render_area.w) / 2; g_render_area.x += (window_resolution.x - g_render_area.w) / 2;
} }
} }
IVector render_get_window_size(struct RenderContext* self) { IVector render_get_window_size() {
// select window as target (store target to reset) // select window as target (store target to reset)
SDL_Texture* target = SDL_GetRenderTarget(self->renderer); SDL_Texture* target = SDL_GetRenderTarget(g_renderer);
SDL_SetRenderTarget(self->renderer, NULL); SDL_SetRenderTarget(g_renderer, NULL);
// fetch output size (= window size) of renderer // fetch output size (= window size) of renderer
int window_width, window_height; int window_width, window_height;
SDL_GetRendererOutputSize(self->renderer, &window_width, &window_height); SDL_GetRendererOutputSize(g_renderer, &window_width, &window_height);
// reset render target // reset render target
SDL_SetRenderTarget(self->renderer, target); SDL_SetRenderTarget(g_renderer, target);
// construct IVector from fetched output size // construct IVector from fetched output size
return (IVector){window_width, window_height}; return (IVector){window_width, window_height};
} }
void render_handle_resize(struct RenderContext* self) { void render_handle_resize() {
render_calculate_render_area(self); render_calculate_render_area();
} }

View file

@ -5,32 +5,25 @@
#include <SDL2/SDL_rect.h> #include <SDL2/SDL_rect.h>
#include "vmath.h" #include "vmath.h"
struct Program;
struct ProgramSettings; struct ProgramSettings;
struct RenderContext { // renderer created from window in Program passed to render_init
// renderer created from window in Program passed to render_init extern SDL_Renderer* g_renderer;
SDL_Renderer* renderer; // render target
extern SDL_Texture* g_render_target;
// area of window to render render_target to
extern SDL_Rect g_render_area;
// size of render_target
extern IVector g_render_resolution;
// render target extern void render_init(SDL_Window* window, const struct ProgramSettings* settings);
SDL_Texture* render_target; extern void render_clean();
// area of window to render render_target to extern void render_present();
SDL_Rect render_area;
// size of render_target extern SDL_FRect render_calculate_unit_rect();
IVector render_resolution; extern void render_calculate_render_area();
extern IVector render_get_window_size();
// current world location of camera extern void render_handle_resize();
IVector camera_offset;
};
extern struct RenderContext* render_init(const struct Program* program, const struct ProgramSettings* settings);
extern void render_destroy(struct RenderContext* self);
extern void render_present(struct RenderContext* self);
extern void render_calculate_render_area(struct RenderContext* self);
extern IVector render_get_window_size(struct RenderContext* self);
extern void render_handle_resize(struct RenderContext* self);
#endif // !_fencer_render_h #endif // !_fencer_render_h

View file

@ -1,11 +1,9 @@
#include "tilemap.h" #include "tilemap.h"
#include "libxml/threads.h" #include "camera.h"
#include "libxml/tree.h"
#include "libxml/xmlstring.h"
#include "program.h" #include "program.h"
#include <SDL2/SDL_image.h>
#include <libxml/xinclude.h>
#include <stdio.h> #include <stdio.h>
#include <libxml/tree.h>
#include <SDL2/SDL_image.h>
#define XML(__str) (const xmlChar*)__str #define XML(__str) (const xmlChar*)__str
@ -135,7 +133,7 @@ struct Tileset tileset_load(const char* filename) {
} }
} while(n != ','); } while(n != ',');
self.texture = IMG_LoadTexture(g_program.render_context->renderer, texture_path); self.texture = IMG_LoadTexture(g_renderer, texture_path);
SDL_QueryTexture(self.texture, NULL, NULL, &self.texture_resolution.x, &self.texture_resolution.y); SDL_QueryTexture(self.texture, NULL, NULL, &self.texture_resolution.x, &self.texture_resolution.y);
self.shear = floor((float)self.texture_resolution.x / self.tile_size.x); self.shear = floor((float)self.texture_resolution.x / self.tile_size.x);
@ -169,14 +167,18 @@ SDL_Rect tileset_index_to_rect(struct Tileset* self, size_t index) {
return rect; return rect;
} }
void tilemap_render(struct Tilemap* self, struct RenderContext* render) { void tilemap_render(struct Tilemap* self) {
size_t num_tiles = self->dimensions.x * self->dimensions.y; size_t num_tiles = self->dimensions.x * self->dimensions.y;
SDL_Rect source_rect = {0, 0, self->tileset.tile_size.x, self->tileset.tile_size.y}; SDL_Rect source_rect = {0, 0, self->tileset.tile_size.x, self->tileset.tile_size.y};
SDL_Rect dest_rect = source_rect; SDL_FRect dest_rect = { .w = 1, .h = 1 };
for(int i = 0; i < num_tiles; ++i) { for(int i = 0; i < num_tiles; ++i) {
source_rect = tileset_index_to_rect(&self->tileset, self->tiles[i]); source_rect = tileset_index_to_rect(&self->tileset, self->tiles[i]);
dest_rect.x = (i % self->dimensions.x) * dest_rect.w; dest_rect.x = (i % self->dimensions.x) * dest_rect.w;
dest_rect.y = (i / self->dimensions.y) * dest_rect.h; dest_rect.y = (float)floor((float)i / self->dimensions.y) * dest_rect.h;
SDL_RenderCopy(render->renderer, self->tileset.texture, &source_rect, &dest_rect);
SDL_RenderCopyF(g_renderer, self->tileset.texture, &source_rect, &dest_rect);
} }
} }

View file

@ -22,6 +22,6 @@ extern struct Tilemap tilemap_load(const char* tilemap_file);
extern struct Tileset tileset_load(const char* filename); extern struct Tileset tileset_load(const char* filename);
extern SDL_Rect tileset_index_to_rect(struct Tileset* self, size_t index); extern SDL_Rect tileset_index_to_rect(struct Tileset* self, size_t index);
extern void tilemap_render(struct Tilemap* map, struct RenderContext* render); extern void tilemap_render(struct Tilemap* map);
#endif // !_fencer_tilemap_h #endif // !_fencer_tilemap_h