23#define SPRING_DAMP_NUMERATOR 179
24#define SPRING_DAMP_DENOM_SHIFT 8
25#define SPRING_DAMP_ROUNDING (1 << (SPRING_DAMP_DENOM_SHIFT - 1))
27OBJ_ATTR obj_buffer[MAX_SPRITES];
28OBJ_AFFINE* obj_aff_buffer = (OBJ_AFFINE*)obj_buffer;
30static Sprite* free_sprites[MAX_SPRITES] = {NULL};
31static bool free_affines[MAX_AFFINES] = {
false};
40static int s_sprite_tids[MAX_SPRITE_TYPE] = {0};
47static int s_sprite_starting_layers[MAX_SPRITE_TYPE] = {0};
50static const int s_sprite_counts[MAX_SPRITE_TYPE] = {
51 [CARD_SPRITE] = MAX_HAND_SIZE + MAX_SELECTION_SIZE,
52 [BLIND_TOKEN_SPRITE] = MAX_BLIND_TOKEN,
53 [SKIP_TAG_SPRITE] = MAX_SKIP_TAGS,
54 [JOKER_SPRITE] = MAX_ACTIVE_JOKERS,
57static const int s_sprite_sizes[MAX_SPRITE_TYPE] = {
58 [CARD_SPRITE] = CARD_SPRITE_TILES,
59 [BLIND_TOKEN_SPRITE] = BLIND_SPRITE_TILES,
60 [SKIP_TAG_SPRITE] = SKIP_TAG_SPRITE_TILES,
61 [JOKER_SPRITE] = JOKER_SPRITE_TILES,
62 [DECK_SPRITE] = CARD_SPRITE_TILES
68 return s_sprite_tids[sprite_type] + layer * s_sprite_sizes[sprite_type];
73 return s_sprite_starting_layers[sprite_type];
84 if (!free_sprites[sprite_index])
86 free_sprites[sprite_index] = sprite;
96 int aff_index = MAX_AFFINES;
98 for (
int i = 0; i < MAX_AFFINES; i++)
100 if (!free_affines[i])
102 free_affines[i] =
true;
108 if (aff_index == MAX_AFFINES)
110 POOL_FREE(
Sprite, sprite);
114 a1 = a1 | ATTR1_AFF_ID(aff_index);
116 sprite->
obj = &obj_buffer[sprite_index];
117 sprite->
aff = &obj_aff_buffer[aff_index];
118 obj_set_attr(sprite->
obj, a0, a1, ATTR2_PALBANK(pb) | tid);
119 obj_aff_identity(&obj_aff_buffer[aff_index]);
123 sprite->
obj = &obj_buffer[sprite_index];
124 obj_set_attr(sprite->
obj, a0, a1, ATTR2_PALBANK(pb) | tid);
127 sprite->
idx = sprite_index;
129 sprite->
mode = a0 & ATTR0_MODE_MASK;
139 obj_hide((*sprite)->obj);
141 if ((*sprite)->aff != NULL)
143 free_affines[(*sprite)->aff - obj_aff_buffer] =
false;
146 free_sprites[(*sprite)->idx] = NULL;
148 POOL_FREE(
Sprite, *sprite);
161 return (s16)(sprite->
obj - obj_buffer);
169 *width = obj_get_width(sprite->
obj);
178 *height = obj_get_height(sprite->
obj);
188 const u8* size = obj_get_size(sprite->
obj);
197 oam_init(obj_buffer, MAX_SPRITES);
200 for (
enum SpriteType sprite_type = 1; sprite_type < MAX_SPRITE_TYPE; sprite_type++)
202 s_sprite_tids[sprite_type] =
203 s_sprite_tids[sprite_type - 1] +
204 s_sprite_counts[sprite_type - 1] * s_sprite_sizes[sprite_type - 1];
205 s_sprite_starting_layers[sprite_type] =
206 s_sprite_starting_layers[sprite_type - 1] + s_sprite_counts[sprite_type - 1];
212 oam_copy(oam_mem, obj_buffer, MAX_SPRITES);
219 return (sprite->
obj->attr2 & ATTR2_PALBANK_MASK) >> ATTR2_PALBANK_SHIFT;
226 obj_hide(sprite->
obj);
233 obj_unhide(sprite->
obj, sprite->
mode);
241 sprite_object->
sprite = NULL;
243 sprite_object->
focused =
false;
261 sprite_object->
sprite = sprite;
283 sprite_object->
vx = 0;
284 sprite_object->vy = 0;
285 sprite_object->
tscale = FIX_ONE;
286 sprite_object->
scale = FIX_ONE;
287 sprite_object->
vscale = 0;
297static inline bool sprite_object_has_velocity(
const SpriteObject* sprite_object)
299 return sprite_object->
vx != 0 || sprite_object->vy != 0 || sprite_object->
vscale != 0 ||
303static inline bool sprite_object_at_target(
const SpriteObject* s)
308static inline bool is_sprite_object_static(
const SpriteObject* sprite_object)
310 return !sprite_object_has_velocity(sprite_object) && sprite_object_at_target(sprite_object);
313static inline IWRAM_CODE
void update_sprite_position(
SpriteObject* sprite_object)
315 sprite_object->
vx += ((sprite_object->
tx - sprite_object->
x) * g_game_vars.game_speed) / 8;
316 sprite_object->vy += ((sprite_object->ty - sprite_object->y) * g_game_vars.game_speed) / 8;
324 const FIXED epsilon = (FIX_ONE >> 6);
327 if (abs(sprite_object->
vx) < epsilon && abs(sprite_object->vy) < epsilon)
329 sprite_object->
vx = 0;
330 sprite_object->vy = 0;
332 sprite_object->
x = sprite_object->
tx;
333 sprite_object->y = sprite_object->ty;
337 sprite_object->
vx = (sprite_object->
vx * SPRING_DAMP_NUMERATOR + SPRING_DAMP_ROUNDING) >>
338 SPRING_DAMP_DENOM_SHIFT;
339 sprite_object->vy = (sprite_object->vy * SPRING_DAMP_NUMERATOR + SPRING_DAMP_ROUNDING) >>
340 SPRING_DAMP_DENOM_SHIFT;
342 sprite_object->
x += sprite_object->
vx;
343 sprite_object->y += sprite_object->vy;
347 if (abs(sprite_object->
vscale) < epsilon)
349 sprite_object->
vscale = 0;
355 (sprite_object->
vscale * SPRING_DAMP_NUMERATOR + SPRING_DAMP_ROUNDING) >>
356 SPRING_DAMP_DENOM_SHIFT;
361 if (abs(sprite_object->
vrotation) < epsilon)
369 (sprite_object->
vrotation * SPRING_DAMP_NUMERATOR + SPRING_DAMP_ROUNDING) >>
370 SPRING_DAMP_DENOM_SHIFT;
377 sprite_object->
scale,
378 sprite_object->
scale,
385 if (!is_sprite_object_static(sprite_object))
386 update_sprite_position(sprite_object);
401#define SPRITE_SHAKE_VSCALE 0.3f
402#define SPRITE_SHAKE_VROTATION 8.0f
407 sprite_object->
vscale = float2fx(SPRITE_SHAKE_VSCALE);
408 sprite_object->
vrotation = float2fx(SPRITE_SHAKE_VROTATION);
410 if (sound_id == UNDEFINED)
419 sprite_object->
vscale = strength;
422#define SPRITE_SWAY_VROTATION -10.0f
426 sprite_object->
vrotation = float2fx(SPRITE_SWAY_VROTATION);
432 if (to.x == UNDEFINED || to.y == UNDEFINED)
435 sprite_object->
tx = int2fx(to.x);
436 sprite_object->ty = int2fx(to.y);
443 return sprite_object->
sprite;
450 if (sprite_object->
focused == focus)
454 sprite_object->
focused = focus;
461 sprite_object->ty = sprite_object->ty + int2fx((focus ? -1 : 1) * SPRITE_FOCUS_RAISE_PX);
491static Rect sprite_object_get_text_rect_under(
SpriteObject* sprite_object)
502 height = CARD_SPRITE_SIZE_PX;
503 width = CARD_SPRITE_SIZE_PX;
506 ret_rect.left = fx2int(sprite_object->
tx);
507 ret_rect.top = fx2int(sprite_object->ty) + height +
TILE_SIZE;
508 ret_rect.right = ret_rect.left + width;
518 Rect text_rect = sprite_object_get_text_rect_under(sprite_object);
520 tte_printf(
"#{P:%d,%d; cx:0x%X000}%s", text_rect.left, text_rect.top, TTE_YELLOW_PB, text);
528 char price_str_buff[INT_MAX_DIGITS + 2];
529 snprintf(price_str_buff,
sizeof(price_str_buff),
"$%d", price);
537 Rect text_rect = sprite_object_get_text_rect_under(sprite_object);
540 text_rect.bottom = text_rect.bottom + SPRITE_FOCUS_RAISE_PX;
Utilities for using maxmod to play sound effects.
#define MM_BASE_PITCH_RATE
The default pitch rate for the sound effect played.
void play_sfx(mm_word id, mm_word rate, mm_byte volume)
Play a sound effect, wrapper for mmEffectEx() See https://maxmod.org/ref/functions/mm_sound_effect....
#define SFX_DEFAULT_VOLUME
Default volume for sound effects.
Game global game variables struct definition.
Graphic utility functions.
void update_text_rect_to_center_str(Rect *rect, const char *str, enum ScreenHorzDir bias_direction)
Updates a rect so a string is centered within it.
#define TILE_SIZE
Tile size in pixels, both height and width as tiles are square.
#define TTE_CHAR_SIZE
By default TTE characters occupy a single tile.
void tte_erase_rect_wrapper(Rect rect)
A wrapper for tte_erase_rect that would use the rect struct.
The core structure for items in the shop and inventory. Provides a common API for the shop and invent...
void * list_itr_next(ListItr *itr)
bool list_remove_data(List *list, void *data)
#define LIST_DEFAULT
Default list declaration for empty lists.
void list_push_back(List *list, void *data)
ListItr list_itr_create(List *list)
Interface to interact with the mgba logger.
Common functions to handle RNG manipulation. Using this interface has three goals:
u32 rng_get_u32(enum RngSequence key)
Get the next "randomly" generated number in the sequence corresponding to the given type.
Sprite system for Gbalatro.
bool sprite_object_get_dimensions(SpriteObject *sprite_object, int *width, int *height)
Get the width and height of SpriteObject's registered Sprite.
bool sprite_object_is_focused(SpriteObject *sprite_object)
Get the focused variable from a SpriteObject.
bool sprite_get_width(Sprite *sprite, int *width)
Get a Sprite's width.
INLINE void sprite_position(Sprite *sprite, int x, int y)
Set sprite position. Inlined for efficiency.
void sprite_object_unhide(SpriteObject *sprite_object)
Unhides the SpriteObject by manipulating ATTR0_HIDE in OAM. The sprite's ATTR0_MODE is maintained fro...
void sprite_object_set_focus(SpriteObject *sprite_object, bool focus)
Set the focus for SpriteObject Raises the object by SPRITE_FOCUS_RAISE_PX.
void sprite_object_init(SpriteObject *sprite_object)
Initialize a SpriteObject to a default state. Must be called only once per SpriteObject when it is cr...
void sprite_object_destroy(SpriteObject *sprite_object)
Destroy SpriteObject.
void sprite_object_print_price_under(SpriteObject *sprite_object, int price)
Print the price string directly beneath a SpriteObject. More specialized version of sprite_object_pri...
s16 sprite_get_layer(Sprite *sprite)
Get index of Sprite in the GBA object buffer.
void sprite_object_print_text_under(SpriteObject *sprite_object, const char text[])
Print the given string directly beneath a SpriteObject. This is used only for Cards for now.
int sprite_get_tid(enum SpriteType sprite_type, s16 layer)
Get the tile index of a certain SpriteType at a certain layer.
void sprite_init(void)
Initialize GBAlatro sprite system.
void sprite_object_bounce(SpriteObject *sprite_object, FIXED strength)
Make SpriteObject bounce by slightly increasing its size in an elastic way.
void sprite_object_reset_transform(SpriteObject *sprite_object)
Reset SpriteObject's transform back to default values.
int sprite_get_pb(const Sprite *sprite)
Get the palette bank of a Sprite.
bool sprite_object_get_width(SpriteObject *sprite_object, int *width)
Get a SpriteObject's width.
void sprite_object_set_sprite(SpriteObject *sprite_object, Sprite *sprite)
Register a Sprite to an associated SpriteObject.
void sprite_object_update_all(void)
Update all SpriteObjects, to be called once per frame in the main update loop.
void sprite_object_set_target(SpriteObject *sprite_object, BG_POINT to)
Set a SpriteObject's target position so that is slides across the screen between from the current pos...
bool sprite_get_dimensions(Sprite *sprite, int *width, int *height)
Get a Sprite's width and height.
bool sprite_object_get_height(SpriteObject *sprite_object, int *height)
Get a SpriteObject's height.
INLINE void sprite_object_position(SpriteObject *sprite_object, int x, int y)
Set sprite_object position. Inlined for efficiency.
void sprite_object_shake(SpriteObject *sprite_object, mm_word sound_id)
Shake SpriteObject on screen and play a sound.
Sprite * sprite_new(u16 a0, u16 a1, u32 tid, u32 pb, s16 sprite_index)
Allocate and retrieve a pointer to a valid Sprite.
void sprite_object_erase_text_under(SpriteObject *sprite_object)
Erase the text within the Rect directly beneath a SpriteObject. This is used only for Cards for now.
bool sprite_get_height(Sprite *sprite, int *height)
Get a Sprites's height.
void sprite_destroy(Sprite **sprite)
Destroy Sprite.
Sprite * sprite_object_get_sprite(SpriteObject *sprite_object)
Get a SpriteObject's registered Sprite.
SpriteType
The different types of sprites in the game.
void sprite_hide(Sprite *sprite)
Hides the sprite by manipulating ATTR0_HIDE in OAM.
void sprite_unhide(Sprite *sprite)
Unhides the sprite by manipulating ATTR0_HIDE in OAM. The sprite's ATTR0_MODE is maintained from the ...
int sprite_get_starting_layer(enum SpriteType sprite_type)
Get the starting layer of a certain type of sprite.
void sprite_object_sway(SpriteObject *sprite_object)
Make SpriteObject sway by slightly rotating on screen.
void sprite_draw(void)
Draw Sprites to screen, to be called once per frame.
IWRAM_CODE void sprite_object_update(SpriteObject *sprite_object)
Update a SpriteObject, to be called once per frame per active SpriteObject.
void sprite_object_hide(SpriteObject *sprite_object)
Hides the SpriteObject by manipulating ATTR0_HIDE in OAM.
A sprite object is a sprite that is focusable and movable in animation.
bool focused
Focused status (card specific, raise and lower card)
FIXED vscale
Scale velocity AKA the rate of change of scaling ops.
FIXED rotation
Actual rotation, in units for tonc's obj_aff_rotscale
FIXED trotation
Target rotation.
FIXED scale
Current Scale, in units for tonc's obj_aff_rotscale
Sprite * sprite
Sprite configuration info.
FIXED tscale
Target Scale.
FIXED vrotation
Rotation velocity.
Sprite struct for GBA hardware specifics.
OBJ_AFFINE * aff
GBA sprite affine matrices registers info.
s16 idx
Sprite index in memory managed by GBAlatro.
u16 mode
The mode of the sprite (regular, affine, etc.), set when the sprite is created corresponds to A0 & AT...
OBJ_ATTR * obj
GBA sprite attribute registers info (A0-A2)
Utilities relating around number string representation and protected arithmatic helper functions.
#define GBAL_RETURN_IF_NULL(param, ret_val)
Returns ret_val and prints a default error message if param is equal to NULL. Useful for checking arg...
#define RET_NONE
An empty return value for RETURN_IF macros when used in void functions Expands to nothing because mac...