#include "sprite.h" #include "camera.h" #include "debug.h" #include "render.h" #include "spritesheet.h" #include #include struct Sprite { // The animation sheet to sample sprites from. Spritesheet* spritesheet; // The current frame of animation. size_t tile_index; // The local transformation of this sprite. Vector origin; SDL_RendererFlip flip_state; }; Sprite* sprite_new_empty() { Sprite* self = malloc(sizeof(Sprite)); ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for new sprite."); *self = (Sprite){ .spritesheet = NULL, .tile_index = 0, .origin = ZeroVector, .flip_state = SDL_FLIP_NONE, }; return self; } Sprite* sprite_from_spritesheet(Spritesheet* sheet, size_t initial_frame) { Sprite* self = sprite_new_empty(); self->spritesheet = sheet; self->origin = VectorFrom(0.5f); self->tile_index = initial_frame; return self; } void sprite_destroy(Sprite* self) { free(self); } void sprite_draw(Sprite* self, Transform transform) { SDL_Texture* texture = spritesheet_get_texture(self->spritesheet); SDL_Rect source = spritesheet_get_tile_rect(self->spritesheet, self->tile_index); Vector origin = self->origin; if(self->flip_state && SDL_FLIP_HORIZONTAL) { origin.x = 1.0f-origin.x; } if((self->flip_state & SDL_FLIP_VERTICAL) != 0) { origin.y = 1.0f-origin.y; } Vector left_top = transform_point(&transform, vinvf(origin)); SDL_FRect destination = (SDL_FRect) { left_top.x, left_top.y, transform.scale.x, transform.scale.y }; destination = camera_world_to_pixel_rect(&g_camera, &destination); origin = vmulf(origin, transform.scale); SDL_RenderCopyExF(g_renderer, texture, &source, &destination, transform.rotation * 57.2958, &origin, self->flip_state); SDL_SetRenderDrawColor(g_renderer, 255, 255, 255, 255); } Vector sprite_get_origin(Sprite* self) { return self->origin; } void sprite_set_origin(Sprite* self, Vector origin) { self->origin = origin; } size_t sprite_get_tile(const Sprite* self) { return self->tile_index; } void sprite_set_tile(Sprite* self, size_t frame) { self->tile_index = frame % spritesheet_get_tile_count(self->spritesheet); } Spritesheet* sprite_get_spritesheet(const Sprite* self) { return self->spritesheet; } void sprite_set_spritesheet(Sprite* self, Spritesheet* spritesheet) { self->spritesheet = spritesheet; } void sprite_flip_horizontal(Sprite* self, int horizontal) { if(horizontal) { self->flip_state |= SDL_FLIP_HORIZONTAL; } else { self->flip_state &= ~SDL_FLIP_HORIZONTAL; } } void sprite_flip_vertical(Sprite* self, int vertical) { if(vertical) { self->flip_state |= SDL_FLIP_VERTICAL; } else { self->flip_state &= ~SDL_FLIP_VERTICAL; } }