archeus/packages/graphics/sdl3/sprite.c
2025-03-26 18:26:02 -06:00

126 lines
3.9 KiB
C

#include "arc/graphics/sprite.h"
#include "spritesheet.h"
#include "arc/math/point.h"
#include "arc/math/rectangle.h"
#include "arc/std/errno.h"
#include <stdlib.h>
#include <SDL3/SDL.h>
void ARC_Sprite_Create(ARC_Sprite **sprite, ARC_Spritesheet *spritesheet, ARC_Array frames){
*sprite = (ARC_Sprite *)malloc(sizeof(ARC_Sprite));
(*sprite)->spritesheet = spritesheet;
(*sprite)->frames = frames;
(*sprite)->frameIndex = 0;
(*sprite)->angle = 0.0;
(*sprite)->origin = (ARC_FPoint){ 0.0, 0.0 };
//called this way to also set the alpha mod
ARC_Sprite_SetOpacity(*sprite, 1.0f);
(*sprite)->axis = ARC_SPRITE_AXIS_NONE;
(*sprite)->animationCurrentTime = 0.0f;
(*sprite)->animationTime = 1.0f / 24.0f;
}
void ARC_Sprite_Destroy(ARC_Sprite *sprite){
free(sprite);
}
void ARC_Sprite_Copy(ARC_Sprite **newSprite, ARC_Sprite *oldSprite){
*newSprite = (ARC_Sprite *)malloc(sizeof(ARC_Sprite));
(*newSprite)->spritesheet = oldSprite->spritesheet;
(*newSprite)->frames = oldSprite->frames;
(*newSprite)->frameIndex = oldSprite->frameIndex;
(*newSprite)->angle = oldSprite->angle;
(*newSprite)->origin = oldSprite->origin;
(*newSprite)->opacity = oldSprite->opacity;
}
void ARC_Sprite_Render(ARC_Sprite *sprite, ARC_Renderer *renderer, ARC_FRect renderBounds){
SDL_RenderTexture((SDL_Renderer *)renderer, sprite->spritesheet->texture, (SDL_FRect *)(sprite->frames.data + sprite->frameIndex), (SDL_FRect *)&renderBounds);
}
void ARC_Sprite_RenderAt(ARC_Sprite *sprite, ARC_Renderer *renderer, ARC_FPoint point, double scale){
ARC_FRect sourceRect = ((ARC_FRect *)(sprite->frames.data))[sprite->frameIndex];
//TODO: check that this works
ARC_FRect destinationRect = {
(point.x - sprite->origin.x) * scale,
(point.y - sprite->origin.y) * scale,
sourceRect.w * scale,
sourceRect.h * scale
};
//TODO: probably want to optomize this
SDL_FlipMode flip = SDL_FLIP_NONE;
if(sprite->axis & ARC_SPRITE_AXIS_X){
flip |= SDL_FLIP_HORIZONTAL;
}
if(sprite->axis & ARC_SPRITE_AXIS_Y){
flip |= SDL_FLIP_VERTICAL;
}
SDL_RenderTextureRotated((SDL_Renderer *)renderer, sprite->spritesheet->texture, (SDL_FRect *)&sourceRect, (SDL_FRect *)&destinationRect, sprite->angle, (SDL_FPoint *)&(sprite->origin), flip);
}
void ARC_Sprite_IterateFrame(ARC_Sprite *sprite){
sprite->frameIndex++;
if(sprite->frameIndex == sprite->frames.size){
sprite->frameIndex = 0;
}
}
void ARC_Sprite_AnimateFrame(ARC_Sprite *sprite, float deltatime){
sprite->animationCurrentTime += deltatime;
if(sprite->animationCurrentTime >= sprite->animationTime){
sprite->animationCurrentTime -= sprite->animationTime;
ARC_Sprite_IterateFrame(sprite);
}
}
void ARC_Sprite_SetFrameIndex(ARC_Sprite *sprite, uint32_t index){
if(sprite->frames.size <= index){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("in ARC_Sprite_SetFrameIndex(sprite, %d); index out of bounds", index);
return;
}
sprite->frameIndex = index;
}
void ARC_Sprite_SetAngle(ARC_Sprite *sprite, double angle){
sprite->angle = angle;
}
void ARC_Sprite_SetOrigin(ARC_Sprite *sprite, ARC_FPoint origin){
sprite->origin = origin;
}
void ARC_Sprite_SetOpacity(ARC_Sprite *sprite, float opacity){
sprite->opacity = opacity;
if(sprite->spritesheet != NULL){
SDL_SetTextureAlphaMod((SDL_Texture *)sprite->spritesheet->texture, sprite->opacity);
}
}
void ARC_Sprite_SetFrameRate(ARC_Sprite *sprite, float rate){
sprite->animationCurrentTime = 0;
sprite->animationTime = rate;
}
uint32_t ARC_Sprite_GetFrameIndex(ARC_Sprite *sprite){
return sprite->frameIndex;
}
ARC_FRect *ARC_Sprite_GetBounds(ARC_Sprite *sprite){
return (ARC_FRect *)sprite->frames.data + sprite->frameIndex;
}
ARC_Array ARC_Sprite_GetAllBounds(ARC_Sprite *sprite){
return sprite->frames;
}