summaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-04-23 23:05:06 +0200
committerBad Diode <bd@badd10de.dev>2021-04-23 23:05:06 +0200
commitf652b2a9c76194ee285e001e6b04a7dc585e8993 (patch)
treecd76eb7c838d57fb5fc54fc89861385a8c67f052 /src/main.c
parent74d6b52636ecdd560995f22dff5b29a59fc62d5d (diff)
downloadgba-experiments-f652b2a9c76194ee285e001e6b04a7dc585e8993.tar.gz
gba-experiments-f652b2a9c76194ee285e001e6b04a7dc585e8993.zip
First steps to replace the input overlay
VRAM and rom consumption was too big with the previous input overlay. Trying to separate button sprites into multiple states. Sprites can now be composed of multiple objects.
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c415
1 files changed, 239 insertions, 176 deletions
diff --git a/src/main.c b/src/main.c
index 4dd2554..e74df00 100644
--- a/src/main.c
+++ b/src/main.c
@@ -142,6 +142,33 @@ rgb15(u32 red, u32 green, u32 blue ) {
142#define OBJ_AFFINE_PC(N) *((vs16*)(MEM_OAM + 6 + 8 * 2 + 8 * 4 * (N))) 142#define OBJ_AFFINE_PC(N) *((vs16*)(MEM_OAM + 6 + 8 * 2 + 8 * 4 * (N)))
143#define OBJ_AFFINE_PD(N) *((vs16*)(MEM_OAM + 6 + 8 * 3 + 8 * 4 * (N))) 143#define OBJ_AFFINE_PD(N) *((vs16*)(MEM_OAM + 6 + 8 * 3 + 8 * 4 * (N)))
144 144
145// OBJ_ATTR_0 parameters
146#define OBJ_Y_COORD(N) ((N) & 0xFF)
147#define OBJ_NORMAL (0x00 << 0x8)
148#define OBJ_AFFINE (0x01 << 0x8)
149#define OBJ_HIDDEN (0x02 << 0x8)
150#define OBJ_AFFINE_2X (0x03 << 0x8)
151#define OBJ_ALPHA_BLEND (0x01 << 0xA)
152#define OBJ_WINDOW (0x02 << 0xA)
153#define OBJ_SHAPE_SQUARE (0x00 << 0xE)
154#define OBJ_SHAPE_WIDE (0x01 << 0xE)
155#define OBJ_SHAPE_TALL (0x02 << 0xE)
156
157// OBJ_ATTR_1 parameters
158#define OBJ_X_COORD(N) ((N) & 0x1FF)
159#define OBJ_AFFINE_IDX(N) ((N) << 0x9)
160#define OBJ_H_FLIP (0x01 << 0xC)
161#define OBJ_V_FLIP (0x01 << 0xD)
162#define OBJ_SIZE_SMALL (0x00 << 0xE)
163#define OBJ_SIZE_MID (0x01 << 0xE)
164#define OBJ_SIZE_BIG (0x02 << 0xE)
165#define OBJ_SIZE_HUGE (0x03 << 0xE)
166
167// OBJ_ATTR_2 parameters
168#define OBJ_TILE_INDEX(N) ((N) & 0x3FF)
169#define OBJ_PRIORITY(N) ((N) << 0xA)
170#define OBJ_PAL_BANK(N) ((N) << 0xC)
171
145// Using bd-font, an 8x8 bitmap font. 172// Using bd-font, an 8x8 bitmap font.
146static void 173static void
147put_char(int x, int y, Color clr, u8 chr) { 174put_char(int x, int y, Color clr, u8 chr) {
@@ -504,6 +531,15 @@ typedef struct ButtonSprite {
504 BtnState state; 531 BtnState state;
505} ButtonSprite; 532} ButtonSprite;
506 533
534typedef struct MultiSprite {
535 ObjState *sprites;
536 AnimationEntry **animations;
537 int frame;
538 size_t n_obj;
539 size_t n_frames;
540 BtnState state;
541} MultiSprite;
542
507#define NUM_SPRITES 128 543#define NUM_SPRITES 128
508 544
509Sprite sprites[NUM_SPRITES]; 545Sprite sprites[NUM_SPRITES];
@@ -550,6 +586,73 @@ load_packed_sprite_data(u32 *sprite_data, size_t n_tiles, size_t n_frames) {
550 return sprite_counter++; 586 return sprite_counter++;
551} 587}
552 588
589void
590init_button_sprite(MultiSprite *btn) {
591 for (size_t i = 0; i < btn->n_obj; ++i) {
592 btn->sprites[i].id = load_packed_sprite_data(
593 btn->sprites[i].data,
594 btn->sprites[i].n_tiles,
595 btn->sprites[i].frames);
596 btn->sprites[i].base_tile = sprites[btn->sprites[i].id].tile_start;
597 }
598}
599
600void
601button_tick(MultiSprite *btn) {
602 // Nothing to do here.
603 if (btn->state == BTN_STATE_IDLE) {
604 return;
605 }
606
607 // Reset animation state.
608 if (btn->state == BTN_STATE_PRESSED && btn->frame != 0) {
609 btn->frame = 0;
610 }
611
612 // Continue the animation.
613 if (btn->state == BTN_STATE_HOLD || btn->state == BTN_STATE_PRESSED ) {
614 if(btn->frame < btn->n_frames - 1) {
615 btn->frame++;
616 }
617 }
618
619 // Finish the animation and return to idle.
620 if (btn->state == BTN_STATE_RELEASED) {
621 if (btn->frame > 0 && btn->frame < btn->n_frames - 1) {
622 btn->frame++;
623 } else {
624 btn->frame = 0;
625 btn->state = BTN_STATE_IDLE;
626 }
627 }
628 for (size_t i = 0; i < btn->n_obj; ++i) {
629 AnimationEntry anim_frame = btn->animations[i][btn->frame];
630 int x = btn->sprites[i].x + anim_frame.x_offset;
631 int y = btn->sprites[i].y + anim_frame.y_offset;
632 int base_tile = btn->sprites[i].base_tile + anim_frame.tile_offset;
633
634 // Clear the previous x/y coordinate and base tiles.
635 btn->sprites[i].obj_attr_0 &= ~0xFF;
636 btn->sprites[i].obj_attr_1 &= ~0x1FF;
637 btn->sprites[i].obj_attr_2 &= ~0x3FF;
638
639 // Update x/y/tile and hidden state from the animations.
640 btn->sprites[i].obj_attr_0 |= OBJ_Y_COORD(y);
641 btn->sprites[i].obj_attr_1 |= OBJ_X_COORD(x);
642 btn->sprites[i].obj_attr_2 |= base_tile;
643 if (anim_frame.hidden) {
644 btn->sprites[i].obj_attr_0 |= OBJ_HIDDEN;
645 } else {
646 btn->sprites[i].obj_attr_0 &= ~OBJ_HIDDEN;
647 }
648
649 // Update OBJ attributes.
650 OBJ_ATTR_0(btn->sprites[i].id) = btn->sprites[i].obj_attr_0;
651 OBJ_ATTR_1(btn->sprites[i].id) = btn->sprites[i].obj_attr_1;
652 OBJ_ATTR_2(btn->sprites[i].id) = btn->sprites[i].obj_attr_2;
653 }
654}
655
553int main(void) { 656int main(void) {
554 657
555 // Add colors to the sprite color palette. Tiles with color number 0 are 658 // Add colors to the sprite color palette. Tiles with color number 0 are
@@ -586,93 +689,152 @@ int main(void) {
586 int buttons_x = SCREEN_WIDTH / 2; 689 int buttons_x = SCREEN_WIDTH / 2;
587 int buttons_y = SCREEN_HEIGHT / 2; 690 int buttons_y = SCREEN_HEIGHT / 2;
588 ButtonSprite btn_b = { 691 ButtonSprite btn_b = {
589 .id = load_packed_sprite_data(&gba_btn_b_data, 16, 7), 692 .id = load_packed_sprite_data(&gba_btn_b_data, 4, 1),
590 .x = buttons_x + 32, 693 .x = buttons_x + 32,
591 .y = buttons_y + 32, 694 .y = buttons_y + 32,
592 .frame = 0, 695 .frame = 0,
593 .state = BTN_STATE_IDLE, 696 .state = BTN_STATE_IDLE,
594 }; 697 };
595 OBJ_ATTR_0(btn_b.id) = btn_b.y; 698 OBJ_ATTR_0(btn_b.id) = btn_b.y;
596 OBJ_ATTR_1(btn_b.id) = btn_b.x | (1 << 0xF); 699 OBJ_ATTR_1(btn_b.id) = btn_b.x | (1 << 0xE);
597 OBJ_ATTR_2(btn_b.id) = sprites[btn_b.id].tile_start; 700 OBJ_ATTR_2(btn_b.id) = sprites[btn_b.id].tile_start;
598 701
599 ButtonSprite btn_a = { 702 ButtonSprite btn_a = {
600 .id = load_packed_sprite_data(&gba_btn_a_data, 16, 7), 703 .id = load_packed_sprite_data(&gba_btn_a_data, 4, 1),
601 .x = buttons_x + 32 + 20, 704 .x = buttons_x + 32 + 20,
602 .y = buttons_y + 32 - 16, 705 .y = buttons_y + 32 - 16,
603 .frame = 0, 706 .frame = 0,
604 .state = BTN_STATE_IDLE, 707 .state = BTN_STATE_IDLE,
605 }; 708 };
606 OBJ_ATTR_0(btn_a.id) = btn_a.y; 709 OBJ_ATTR_0(btn_a.id) = btn_a.y;
607 OBJ_ATTR_1(btn_a.id) = btn_a.x | (1 << 0xF); 710 OBJ_ATTR_1(btn_a.id) = btn_a.x | (1 << 0xE);
608 OBJ_ATTR_2(btn_a.id) = sprites[btn_a.id].tile_start; 711 OBJ_ATTR_2(btn_a.id) = sprites[btn_a.id].tile_start;
609 712
610 ButtonSprite btn_down = {
611 .id = load_packed_sprite_data(&gba_btn_down_data, 16, 7),
612 .x = buttons_x - 64 - 16,
613 .y = buttons_y + 32,
614 .frame = 0,
615 .state = BTN_STATE_IDLE,
616 };
617 OBJ_ATTR_0(btn_down.id) = btn_down.y;
618 OBJ_ATTR_1(btn_down.id) = btn_down.x | (1 << 0xF);
619 OBJ_ATTR_2(btn_down.id) = sprites[btn_down.id].tile_start;
620
621 ButtonSprite btn_up = { 713 ButtonSprite btn_up = {
622 .id = load_packed_sprite_data(&gba_btn_up_data, 16, 7), 714 .id = load_packed_sprite_data(&gba_btn_updown_data, 4, 1),
623 .x = buttons_x - 64 - 16, 715 .x = buttons_x - 64 - 16,
624 .y = buttons_y + 32 - 18, 716 .y = buttons_y + 32 - 18,
625 .frame = 0, 717 .frame = 0,
626 .state = BTN_STATE_IDLE, 718 .state = BTN_STATE_IDLE,
627 }; 719 };
628 OBJ_ATTR_0(btn_up.id) = btn_up.y; 720 OBJ_ATTR_0(btn_up.id) = btn_up.y;
629 OBJ_ATTR_1(btn_up.id) = btn_up.x | (1 << 0xF); 721 OBJ_ATTR_1(btn_up.id) = btn_up.x | (1 << 0xE);
630 OBJ_ATTR_2(btn_up.id) = sprites[btn_up.id].tile_start; 722 OBJ_ATTR_2(btn_up.id) = sprites[btn_up.id].tile_start;
631 723
632 ButtonSprite btn_left = { 724 ButtonSprite btn_left = {
633 .id = load_packed_sprite_data(&gba_btn_left_data, 16, 7), 725 .id = load_packed_sprite_data(&gba_btn_leftright_data, 4, 1),
634 .x = buttons_x - 64 - 16 - 12, 726 .x = buttons_x - 64 - 16 - 10,
635 .y = buttons_y + 32 - 10, 727 .y = buttons_y + 32 - 10,
636 .frame = 0, 728 .frame = 0,
637 .state = BTN_STATE_IDLE, 729 .state = BTN_STATE_IDLE,
638 }; 730 };
639 OBJ_ATTR_0(btn_left.id) = btn_left.y; 731 OBJ_ATTR_0(btn_left.id) = btn_left.y;
640 OBJ_ATTR_1(btn_left.id) = btn_left.x | (1 << 0xF); 732 OBJ_ATTR_1(btn_left.id) = btn_left.x | (1 << 0xE);
641 OBJ_ATTR_2(btn_left.id) = sprites[btn_left.id].tile_start; 733 OBJ_ATTR_2(btn_left.id) = sprites[btn_left.id].tile_start;
642 734
643 ButtonSprite btn_right = { 735 ButtonSprite btn_right = {
644 .id = load_packed_sprite_data(&gba_btn_right_data, 16, 7), 736 .id = load_packed_sprite_data(&gba_btn_leftright_data, 4, 1),
645 .x = buttons_x - 64 - 16 + 11, 737 .x = buttons_x - 64 - 16 + 11,
646 .y = buttons_y + 32 - 10, 738 .y = buttons_y + 32 - 10,
647 .frame = 0, 739 .frame = 0,
648 .state = BTN_STATE_IDLE, 740 .state = BTN_STATE_IDLE,
649 }; 741 };
650 OBJ_ATTR_0(btn_right.id) = btn_right.y; 742 OBJ_ATTR_0(btn_right.id) = btn_right.y;
651 OBJ_ATTR_1(btn_right.id) = btn_right.x | (1 << 0xF); 743 OBJ_ATTR_1(btn_right.id) = btn_right.x | (1 << 0xE) | (1 << 0xC);
652 OBJ_ATTR_2(btn_right.id) = sprites[btn_right.id].tile_start; 744 OBJ_ATTR_2(btn_right.id) = sprites[btn_right.id].tile_start;
653 745
654 ButtonSprite btn_l = { 746 ButtonSprite btn_l = {
655 .id = load_packed_sprite_data(&gba_btn_l_data, 16, 7), 747 .id = load_packed_sprite_data(&gba_btn_l_data, 2, 1),
656 .x = buttons_x - 64 - 28, 748 .x = buttons_x - 64 - 28,
657 .y = buttons_y - 32 - 20, 749 .y = buttons_y - 32 - 20,
658 .frame = 0, 750 .frame = 0,
659 .state = BTN_STATE_IDLE, 751 .state = BTN_STATE_IDLE,
660 }; 752 };
661 OBJ_ATTR_0(btn_l.id) = btn_l.y; 753 OBJ_ATTR_0(btn_l.id) = btn_l.y | (1 << 0xE);
662 OBJ_ATTR_1(btn_l.id) = btn_l.x | (1 << 0xF); 754 OBJ_ATTR_1(btn_l.id) = btn_l.x;
663 OBJ_ATTR_2(btn_l.id) = sprites[btn_l.id].tile_start; 755 OBJ_ATTR_2(btn_l.id) = sprites[btn_l.id].tile_start;
664 756
665 ButtonSprite btn_r = { 757 ButtonSprite btn_r = {
666 .id = load_packed_sprite_data(&gba_btn_r_data, 16, 7), 758 .id = load_packed_sprite_data(&gba_btn_r_data, 2, 1),
667 .x = buttons_x + 32 + 20, 759 .x = buttons_x + 32 + 20,
668 .y = buttons_y - 32 - 20, 760 .y = buttons_y - 32 - 20,
669 .frame = 0, 761 .frame = 0,
670 .state = BTN_STATE_IDLE, 762 .state = BTN_STATE_IDLE,
671 }; 763 };
672 OBJ_ATTR_0(btn_r.id) = btn_r.y; 764 OBJ_ATTR_0(btn_r.id) = btn_r.y | (1 << 0xE);
673 OBJ_ATTR_1(btn_r.id) = btn_r.x | (1 << 0xF); 765 OBJ_ATTR_1(btn_r.id) = btn_r.x;
674 OBJ_ATTR_2(btn_r.id) = sprites[btn_r.id].tile_start; 766 OBJ_ATTR_2(btn_r.id) = sprites[btn_r.id].tile_start;
675 767
768 ButtonSprite btn_start = {
769 .id = load_packed_sprite_data(&gba_btn_startselect_data, 2, 2),
770 .x = buttons_x - 10,
771 .y = buttons_y + 40,
772 .frame = 0,
773 .state = BTN_STATE_IDLE,
774 };
775 OBJ_ATTR_0(btn_start.id) = btn_start.y | (1 << 0xE);
776 OBJ_ATTR_1(btn_start.id) = btn_start.x;
777 OBJ_ATTR_2(btn_start.id) = sprites[btn_start.id].tile_start;
778
779 ButtonSprite btn_select = {
780 .id = load_packed_sprite_data(&gba_btn_startselect_data, 2, 2),
781 .x = buttons_x - 32,
782 .y = buttons_y + 40,
783 .frame = 0,
784 .state = BTN_STATE_IDLE,
785 };
786 OBJ_ATTR_0(btn_select.id) = btn_select.y | (1 << 0xE);
787 OBJ_ATTR_1(btn_select.id) = btn_select.x;
788 OBJ_ATTR_2(btn_select.id) = sprites[btn_select.id].tile_start;
789
790 MultiSprite buttons[] = {
791 {
792 .frame = 0,
793 .n_obj = 3,
794 .n_frames = 8,
795 .state = BTN_STATE_RELEASED,
796 .animations = &btn_down_animation,
797 .sprites = &(ObjState[]){
798 {
799 .id = 0,
800 .x = buttons_x - 64 - 16,
801 .y = buttons_y + 29,
802 .data = &gba_btn_updown_data,
803 .n_tiles = 4,
804 .frames = 1,
805 .obj_attr_0 = 0,
806 .obj_attr_1 = OBJ_V_FLIP | OBJ_SIZE_MID,
807 .obj_attr_2 = 0
808 },
809 {
810 .id = 0,
811 .x = buttons_x - 64 - 16,
812 .y = buttons_y + 29,
813 .data = &gba_btn_down_shadow_data,
814 .n_tiles = 2,
815 .frames = 1,
816 .obj_attr_0 = OBJ_SHAPE_WIDE,
817 .obj_attr_1 = OBJ_SIZE_SMALL,
818 .obj_attr_2 = 0
819 },
820 {
821 .id = 0,
822 .x = buttons_x - 64 - 16,
823 .y = buttons_y + 29,
824 .data = &gba_btn_fx_downup,
825 .n_tiles = 4,
826 .frames = 4,
827 .obj_attr_0 = OBJ_SHAPE_WIDE,
828 .obj_attr_1 = OBJ_SIZE_MID,
829 .obj_attr_2 = 0
830 },
831 },
832 },
833 };
834 for (size_t i = 0; i < sizeof(buttons) / sizeof(MultiSprite); ++i) {
835 init_button_sprite(&buttons[i]);
836 }
837
676 int frame_counter = 0; 838 int frame_counter = 0;
677 int x = 0; 839 int x = 0;
678 int y = 0; 840 int y = 0;
@@ -680,149 +842,46 @@ int main(void) {
680 wait_vsync(); 842 wait_vsync();
681 poll_keys(); 843 poll_keys();
682 844
683 if (key_pressed(KEY_B)) { 845 // if (key_pressed(KEY_B)) {
684 btn_b.frame = 0; 846 // btn_b.frame = 0;
685 btn_b.state = BTN_STATE_PRESSED; 847 // btn_b.state = BTN_STATE_PRESSED;
686 } else if (key_hold(KEY_B)) { 848 // } else if (key_hold(KEY_B)) {
687 size_t n_frames = animation_states[btn_b.state]->n_frames; 849 // if (btn_b.frame < btn_b.n_frames - 1) {
688 if (btn_b.frame < n_frames - 1) { 850 // btn_b.frame++;
689 btn_b.frame++; 851 // }
690 } 852 // } else {
691 } else { 853 // // Finish the animation and reset idle state.
692 // Finish the animation and reset idle state. 854 // if (btn_b.frame > 0 && btn_b.frame < btn_b.n_frames - 1) {
693 size_t n_frames = animation_states[btn_b.state]->n_frames; 855 // btn_b.frame++;
694 if (btn_b.frame > 0 && btn_b.frame < n_frames - 1) { 856 // } else {
695 btn_b.frame++; 857 // btn_b.frame = 0;
696 } else { 858 // btn_b.state = BTN_STATE_IDLE;
697 btn_b.frame = 0; 859 // }
698 btn_b.state = BTN_STATE_IDLE; 860 // }
699 } 861 // if (key_pressed(KEY_A)) {
700 } 862 // btn_a.frame = 0;
701 if (key_pressed(KEY_A)) { 863 // btn_a.state = BTN_STATE_PRESSED;
702 btn_a.frame = 0; 864 // } else if (key_hold(KEY_A)) {
703 btn_a.state = BTN_STATE_PRESSED; 865 // size_t n_frames = animation_states[btn_a.state]->n_frames;
704 } else if (key_hold(KEY_A)) { 866 // if (btn_a.frame < n_frames - 1) {
705 size_t n_frames = animation_states[btn_a.state]->n_frames; 867 // btn_a.frame++;
706 if (btn_a.frame < n_frames - 1) { 868 // }
707 btn_a.frame++; 869 // } else {
708 } 870 // // Finish the animation and reset idle state.
709 } else { 871 // size_t n_frames = animation_states[btn_a.state]->n_frames;
710 // Finish the animation and reset idle state. 872 // if (btn_a.frame > 0 && btn_a.frame < n_frames - 1) {
711 size_t n_frames = animation_states[btn_a.state]->n_frames; 873 // btn_a.frame++;
712 if (btn_a.frame > 0 && btn_a.frame < n_frames - 1) { 874 // } else {
713 btn_a.frame++; 875 // btn_a.frame = 0;
714 } else { 876 // btn_a.state = BTN_STATE_IDLE;
715 btn_a.frame = 0; 877 // }
716 btn_a.state = BTN_STATE_IDLE; 878 // }
717 }
718 }
719 if (key_pressed(KEY_DOWN)) { 879 if (key_pressed(KEY_DOWN)) {
720 btn_down.frame = 0; 880 buttons[0].state = BTN_STATE_PRESSED;
721 btn_down.state = BTN_STATE_PRESSED;
722 } else if (key_hold(KEY_DOWN)) { 881 } else if (key_hold(KEY_DOWN)) {
723 size_t n_frames = animation_states[btn_down.state]->n_frames; 882 buttons[0].state = BTN_STATE_HOLD;
724 if (btn_down.frame < n_frames - 1) {
725 btn_down.frame++;
726 }
727 } else {
728 // Finish the animation and reset idle state.
729 size_t n_frames = animation_states[btn_down.state]->n_frames;
730 if (btn_down.frame > 0 && btn_down.frame < n_frames - 1) {
731 btn_down.frame++;
732 } else {
733 btn_down.frame = 0;
734 btn_down.state = BTN_STATE_IDLE;
735 }
736 }
737 if (key_pressed(KEY_UP)) {
738 btn_up.frame = 0;
739 btn_up.state = BTN_STATE_PRESSED;
740 } else if (key_hold(KEY_UP)) {
741 size_t n_frames = animation_states[btn_up.state]->n_frames;
742 if (btn_up.frame < n_frames - 1) {
743 btn_up.frame++;
744 }
745 } else {
746 // Finish the animation and reset idle state.
747 size_t n_frames = animation_states[btn_up.state]->n_frames;
748 if (btn_up.frame > 0 && btn_up.frame < n_frames - 1) {
749 btn_up.frame++;
750 } else {
751 btn_up.frame = 0;
752 btn_up.state = BTN_STATE_IDLE;
753 }
754 }
755 if (key_pressed(KEY_LEFT)) {
756 btn_left.frame = 0;
757 btn_left.state = BTN_STATE_PRESSED;
758 } else if (key_hold(KEY_LEFT)) {
759 size_t n_frames = animation_states[btn_left.state]->n_frames;
760 if (btn_left.frame < n_frames - 1) {
761 btn_left.frame++;
762 }
763 } else {
764 // Finish the animation and reset idle state.
765 size_t n_frames = animation_states[btn_left.state]->n_frames;
766 if (btn_left.frame > 0 && btn_left.frame < n_frames - 1) {
767 btn_left.frame++;
768 } else {
769 btn_left.frame = 0;
770 btn_left.state = BTN_STATE_IDLE;
771 }
772 }
773 if (key_pressed(KEY_RIGHT)) {
774 btn_right.frame = 0;
775 btn_right.state = BTN_STATE_PRESSED;
776 } else if (key_hold(KEY_RIGHT)) {
777 size_t n_frames = animation_states[btn_right.state]->n_frames;
778 if (btn_right.frame < n_frames - 1) {
779 btn_right.frame++;
780 }
781 } else {
782 // Finish the animation and reset idle state.
783 size_t n_frames = animation_states[btn_right.state]->n_frames;
784 if (btn_right.frame > 0 && btn_right.frame < n_frames - 1) {
785 btn_right.frame++;
786 } else {
787 btn_right.frame = 0;
788 btn_right.state = BTN_STATE_IDLE;
789 }
790 }
791 if (key_pressed(KEY_L)) {
792 btn_l.frame = 0;
793 btn_l.state = BTN_STATE_PRESSED;
794 } else if (key_hold(KEY_L)) {
795 size_t n_frames = animation_states[btn_l.state]->n_frames;
796 if (btn_l.frame < n_frames - 1) {
797 btn_l.frame++;
798 }
799 } else { 883 } else {
800 // Finish the animation and reset idle state. 884 buttons[0].state = BTN_STATE_RELEASED;
801 size_t n_frames = animation_states[btn_l.state]->n_frames;
802 if (btn_l.frame > 0 && btn_l.frame < n_frames - 1) {
803 btn_l.frame++;
804 } else {
805 btn_l.frame = 0;
806 btn_l.state = BTN_STATE_IDLE;
807 }
808 }
809 if (key_pressed(KEY_R)) {
810 btn_r.frame = 0;
811 btn_r.state = BTN_STATE_PRESSED;
812 } else if (key_hold(KEY_R)) {
813 size_t n_frames = animation_states[btn_r.state]->n_frames;
814 if (btn_r.frame < n_frames - 1) {
815 btn_r.frame++;
816 }
817 } else {
818 // Finish the animation and reset idle state.
819 size_t n_frames = animation_states[btn_r.state]->n_frames;
820 if (btn_r.frame > 0 && btn_r.frame < n_frames - 1) {
821 btn_r.frame++;
822 } else {
823 btn_r.frame = 0;
824 btn_r.state = BTN_STATE_IDLE;
825 }
826 } 885 }
827 886
828 if (key_hold(KEY_DOWN)) { 887 if (key_hold(KEY_DOWN)) {
@@ -838,17 +897,21 @@ int main(void) {
838 x += 3; 897 x += 3;
839 } 898 }
840 899
841 OBJ_ATTR_2(btn_b.id) = sprites[btn_b.id].tile_start + animation_states[btn_b.state]->tile_offsets[btn_b.frame]; 900 // OBJ_ATTR_2(btn_b.id) = sprites[btn_b.id].tile_start + animation_states[btn_b.state]->tile_offsets[btn_b.frame];
842 OBJ_ATTR_2(btn_a.id) = sprites[btn_a.id].tile_start + animation_states[btn_a.state]->tile_offsets[btn_a.frame]; 901 // OBJ_ATTR_2(btn_a.id) = sprites[btn_a.id].tile_start + animation_states[btn_a.state]->tile_offsets[btn_a.frame];
843 OBJ_ATTR_2(btn_up.id) = sprites[btn_up.id].tile_start + animation_states[btn_up.state]->tile_offsets[btn_up.frame]; 902 // OBJ_ATTR_2(btn_up.id) = sprites[btn_up.id].tile_start + animation_states[btn_up.state]->tile_offsets[btn_up.frame];
844 OBJ_ATTR_2(btn_down.id) = sprites[btn_down.id].tile_start + animation_states[btn_down.state]->tile_offsets[btn_down.frame]; 903 // // OBJ_ATTR_2(btn_down.id) = sprites[btn_down.id].tile_start + animation_states[btn_down.state]->tile_offsets[btn_down.frame];
845 OBJ_ATTR_2(btn_left.id) = sprites[btn_left.id].tile_start + animation_states[btn_left.state]->tile_offsets[btn_left.frame]; 904 // OBJ_ATTR_2(btn_left.id) = sprites[btn_left.id].tile_start + animation_states[btn_left.state]->tile_offsets[btn_left.frame];
846 OBJ_ATTR_2(btn_right.id) = sprites[btn_right.id].tile_start + animation_states[btn_right.state]->tile_offsets[btn_right.frame]; 905 // OBJ_ATTR_2(btn_right.id) = sprites[btn_right.id].tile_start + animation_states[btn_right.state]->tile_offsets[btn_right.frame];
847 OBJ_ATTR_2(btn_l.id) = sprites[btn_l.id].tile_start + animation_states[btn_l.state]->tile_offsets[btn_l.frame]; 906 // OBJ_ATTR_2(btn_l.id) = sprites[btn_l.id].tile_start + animation_states[btn_l.state]->tile_offsets[btn_l.frame];
848 OBJ_ATTR_2(btn_r.id) = sprites[btn_r.id].tile_start + animation_states[btn_r.state]->tile_offsets[btn_r.frame]; 907 // OBJ_ATTR_2(btn_r.id) = sprites[btn_r.id].tile_start + animation_states[btn_r.state]->tile_offsets[btn_r.frame];
849 frame_counter++; 908 frame_counter++;
850 BG_H_SCROLL_0 = x; 909 BG_H_SCROLL_0 = x;
851 BG_V_SCROLL_0 = y; 910 BG_V_SCROLL_0 = y;
911
912 for (size_t i = 0; i < sizeof(buttons) / sizeof(MultiSprite); ++i) {
913 button_tick(&buttons[i]);
914 }
852 }; 915 };
853 916
854 return 0; 917 return 0;