reworked rendering to transform sprites to pixel coordinates correctly
This commit is contained in:
parent
4fcb637bbb
commit
a841fa7c92
|
@ -64,6 +64,7 @@ static
|
|||
void _empty_assets() {
|
||||
AssetData* start = _assets;
|
||||
AssetData* end = _assets + _assets_len;
|
||||
|
||||
for(AssetData* asset = start; asset < end; ++asset) {
|
||||
asset->destructor(asset->asset);
|
||||
}
|
||||
|
|
32
src/camera.c
32
src/camera.c
|
@ -6,26 +6,30 @@ Camera g_camera;
|
|||
|
||||
void camera_init() {
|
||||
LOG_INFO("camera_init");
|
||||
g_camera.centre = ZeroVector;
|
||||
g_camera.width = 10;
|
||||
g_camera.transform = IdentityTransform;
|
||||
g_camera.fov = 10;
|
||||
}
|
||||
|
||||
static inline
|
||||
float _camera_height(Camera* self) {
|
||||
return self->width * ((float)g_render_resolution.y / (float)g_render_resolution.x);
|
||||
return self->fov * ((float)g_render_resolution.y / (float)g_render_resolution.x);
|
||||
}
|
||||
|
||||
static inline
|
||||
float _cam_to_world_conversion() {
|
||||
return g_render_resolution.x / g_camera.width;
|
||||
}
|
||||
SDL_FRect camera_world_to_pixel_rect(Camera* self, SDL_FRect* world_space) {
|
||||
Transform t = self->transform;
|
||||
t.rotation = 0;
|
||||
t.scale = OneVector;
|
||||
t = transform_invert(t);
|
||||
|
||||
SDL_FRect camera_world_to_screen_space(Camera* self, SDL_FRect* world_space) {
|
||||
float unit = _cam_to_world_conversion();
|
||||
return (SDL_FRect) {
|
||||
.x = (g_camera.centre.x - world_space->x + g_camera.width/2.0) * unit,
|
||||
.y = (g_camera.centre.y - world_space->y + _camera_height(&g_camera)/2.0) * unit,
|
||||
.w = world_space->w * unit,
|
||||
.h = world_space->h * unit
|
||||
Vector tl = {world_space->x + (self->fov / 2.0), world_space->y + (_camera_height(self) / 2.0)};
|
||||
Vector size = {world_space->w, world_space->h};
|
||||
|
||||
tl = vmulff(transform_point(&t, tl), g_render_resolution.x / self->fov);
|
||||
size = vmulff(vmulf(t.scale, size), g_render_resolution.x / self->fov);
|
||||
|
||||
|
||||
return (SDL_FRect){
|
||||
tl.x, tl.y,
|
||||
size.x, size.y
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
#define _fencer_camera_h
|
||||
|
||||
#include "vmath.h"
|
||||
#include "transform.h"
|
||||
#include <SDL2/SDL_rect.h>
|
||||
|
||||
struct Camera {
|
||||
Vector centre;
|
||||
float width;
|
||||
float fov;
|
||||
Transform transform;
|
||||
};
|
||||
|
||||
typedef struct Camera Camera;
|
||||
|
@ -16,6 +17,6 @@ extern Camera g_camera;
|
|||
|
||||
extern void camera_init();
|
||||
extern SDL_FRect camera_screen_to_world_space(Camera* self, SDL_FRect* camera_space);
|
||||
extern SDL_FRect camera_world_to_screen_space(Camera* self, SDL_FRect* world_space);
|
||||
extern SDL_FRect camera_world_to_pixel_rect(Camera* self, SDL_FRect* world_space);
|
||||
|
||||
#endif // !_fencer_camera_h
|
||||
|
|
18
src/fencer.c
18
src/fencer.c
|
@ -16,32 +16,32 @@ static Vector cam_speed = ZeroVector;
|
|||
|
||||
static
|
||||
void cam_move_h(int val) {
|
||||
cam_speed.x = -val * 0.01f;
|
||||
cam_speed.x = val * 0.1f;
|
||||
}
|
||||
static
|
||||
void cam_move_v(int val) {
|
||||
cam_speed.y = val * 0.01f;
|
||||
cam_speed.y = -val * 0.1f;
|
||||
}
|
||||
|
||||
static
|
||||
void play() {
|
||||
g_camera.fov = 40;
|
||||
spr_player_standing = spritesheet_load("assets/sprites/player.png", (IVector){128, 128});
|
||||
player = sprite_from_spritesheet(spr_player_standing, 0);
|
||||
sprite_set_origin(player, (Vector){0.5f, 1.0f});
|
||||
player_trans.scale = OneVector;
|
||||
assert(player != NULL && "Player failed to load");
|
||||
player_trans.scale = (Vector){4.f, 4.f};
|
||||
sprite_set_origin(player, (Vector){0.25f, 1.f});
|
||||
|
||||
level = level_load("level_0");
|
||||
assert(level != NULL && "Level failed to load");
|
||||
|
||||
input_add_axis_action(SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, &cam_move_h);
|
||||
input_add_axis_action(SDL_SCANCODE_DOWN, SDL_SCANCODE_UP, &cam_move_v);
|
||||
g_camera.width = 20;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
void tick() {
|
||||
g_camera.centre = vaddf(g_camera.centre, cam_speed);
|
||||
g_camera.transform.position = vaddf(g_camera.transform.position, cam_speed);
|
||||
player_trans.position = g_camera.transform.position;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -52,7 +52,7 @@ void draw() {
|
|||
|
||||
int main(int argc, char* argv[]) {
|
||||
struct ProgramSettings config = {
|
||||
.target_fps = 0, // unbounded speed
|
||||
.target_fps = 120,
|
||||
.title = "fencer",
|
||||
.view_resolution = {1920, 1080},
|
||||
.on_play = &play,
|
||||
|
|
|
@ -13,10 +13,9 @@ struct Level {
|
|||
asset_id asset_id;
|
||||
size_t level_iid;
|
||||
|
||||
Transform transform;
|
||||
Tilemap** tilemaps;
|
||||
|
||||
size_t tilemaps_len;
|
||||
|
||||
Vector player_start;
|
||||
};
|
||||
|
||||
|
@ -62,7 +61,8 @@ Level* level_from_json(cJSON* json) {
|
|||
return NULL;
|
||||
}
|
||||
*self = (Level) {
|
||||
.asset_id = store_asset(self, &_deallocate_level)
|
||||
.asset_id = store_asset(self, &_deallocate_level),
|
||||
.transform = IdentityTransform
|
||||
};
|
||||
|
||||
// fetch the instance id
|
||||
|
@ -125,6 +125,6 @@ void level_destroy(Level* self) {
|
|||
void level_draw(Level* self) {
|
||||
Tilemap** end = self->tilemaps + self->tilemaps_len;
|
||||
for(Tilemap** map = self->tilemaps; map != end; ++map) {
|
||||
tilemap_draw(*map);
|
||||
tilemap_draw(*map, self->transform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,19 +44,18 @@ void sprite_draw(Sprite* self, Transform transform) {
|
|||
SDL_Texture* texture = spritesheet_get_texture(self->spritesheet);
|
||||
SDL_Rect source = spritesheet_get_frame_rect(self->spritesheet, self->current_frame);
|
||||
|
||||
Vector left_top = vinvf(transform_point(&transform, self->origin));
|
||||
Vector left_top = transform_point(&transform, vinvf(self->origin));
|
||||
|
||||
SDL_FRect destination = (SDL_FRect) {
|
||||
left_top.x, left_top.y,
|
||||
transform.scale.x, transform.scale.y
|
||||
};
|
||||
|
||||
destination = camera_world_to_screen_space(&g_camera, &destination);
|
||||
|
||||
Vector origin = vmulff(vmulf(self->origin, transform.scale), 0.5f);
|
||||
destination = camera_world_to_pixel_rect(&g_camera, &destination);
|
||||
Vector origin = vmulf(self->origin, transform.scale);
|
||||
|
||||
SDL_RenderCopyExF(g_renderer, texture, &source, &destination,
|
||||
transform.rotation * 57.2958, &origin, SDL_FLIP_NONE);
|
||||
SDL_SetRenderDrawColor(g_renderer, 255, 255, 255, 255);
|
||||
}
|
||||
|
||||
Vector sprite_get_origin(Sprite* self) {
|
||||
|
|
|
@ -95,8 +95,8 @@ Tilemap* tilemap_from_autolayer(cJSON* json) {
|
|||
return self;
|
||||
}
|
||||
|
||||
void tilemap_draw(Tilemap* self) {
|
||||
Transform tiletrans = self->transform;
|
||||
void tilemap_draw(Tilemap* self, Transform transform) {
|
||||
Transform tiletrans = transform_apply(transform, self->transform);
|
||||
TileInstance* tile;
|
||||
|
||||
for(int i = 0; i < self->map_num; ++i) {
|
||||
|
|
|
@ -14,6 +14,6 @@ extern void tilemap_destroy(Tilemap* self);
|
|||
|
||||
extern void tilemap_set_tileset(Tilemap* self, Tileset* set);
|
||||
|
||||
extern void tilemap_draw(Tilemap* tilemap);
|
||||
extern void tilemap_draw(Tilemap* tilemap, Transform transform);
|
||||
|
||||
#endif // !_fencer_tilemap_h
|
||||
|
|
|
@ -37,12 +37,12 @@ Transform transform_invert(Transform a) {
|
|||
|
||||
static inline
|
||||
Vector transform_direction(Transform* self, Vector direction) {
|
||||
return vmulf(vrotatef(direction, self->rotation), self->scale);
|
||||
return vrotatef(direction, self->rotation);
|
||||
}
|
||||
|
||||
static inline
|
||||
Vector transform_point(Transform* self, Vector position) {
|
||||
return vaddf(transform_direction(self, position), self->position);
|
||||
return vaddf(vmulf(transform_direction(self, position), self->scale), self->position);
|
||||
}
|
||||
|
||||
#endif // !_fencer_transform_h
|
||||
|
|
Loading…
Reference in a new issue