#include "arc/graphics/sprite.h" #include "renderer.h" #include "spritesheet.h" #include "arc/math/point.h" #include "arc/math/rectangle.h" #include "arc/std/errno.h" #include #include 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(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(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; }