tuxanci2-game
Game code/assets for tuxanci2
Log | Files | Refs | README | LICENSE

credits.c (9328B)


      1 #include <tuxanci2/display.h>
      2 #include <tuxanci2/shapes.h>
      3 #include <tuxanci2/text.h>
      4 #include <tuxanci2/screen.h>
      5 #include <tuxanci2/ft2.h>
      6 #include "screens.h"
      7 #include <stdint.h>
      8 #include <stdlib.h>
      9 #include "credits.h"
     10 #include "ta_files.h"
     11 
     12 #define TA_CREDITS_STAR_COUNT 512
     13 #define TA_CREDITS_TEXT_HOLD_FRAMES 128
     14 #define TA_CREDITS_ACCELERATION_FRAMES 512
     15 #define TA_CREDITS_FULL_SPEED 512
     16 #define TA_CREDITS_Z_ONE 65536
     17 #define TA_CREDITS_Z_NEAR 1638
     18 #define TA_CREDITS_TEXT_REFERENCE_SIZE 100
     19 #define TA_CREDITS_TEXT_IN_FRAMES 32
     20 #define TA_CREDITS_TEXT_OUT_FRAMES 32
     21 
     22 #define TA_CREDITS_TEXT_WIDTH_MARGIN 90
     23 #define TA_CREDITS_TEXT_HEIGHT_MARGIN 80
     24 
     25 typedef struct {
     26     int32_t x;
     27     int32_t y;
     28     int32_t z;
     29 } ta_credits_star;
     30 
     31 typedef struct {
     32     ta_text text;
     33     int32_t x;
     34     int32_t y;
     35 } ta_credits_entry;
     36 
     37 static const char *strings[] = {
     38     "Tuxánci",
     39     "2",
     40     "",
     41     "Version",
     42     "0.30.0",
     43     "Credits",
     44     "",
     45     "Current Developers",
     46     "",
     47     "Main Developer",
     48     "Connor Thomson (GNUfault)\n<connor@gnufault.org>",
     49     "",
     50     "Original Tuxánci Developers",
     51     "",
     52     "Former Main Developer",
     53     "Dušan Ďurech (Oroborus)\n<dusan.d@centrum.sk>",
     54     "",
     55     "Former Project manager, coordinator of the development, and website maintainer",
     56     "Michal Zima (xHire)\n<~{^_^}~/@semirocket.science>",
     57     "",
     58     "Former graphic designer and creator of arenas",
     59     "Jiří Helebrant (helb)\n<helb@helb.cz>",
     60     "",
     61     "Former programmer of server, some network stuff and other significant optimizations",
     62     "Tomáš Jedrzejek (ZeXx86)\n<zexx86@gmail.com>",
     63     "",
     64     "Former build system writer and ebuild maintainer",
     65     "Tomáš Chvátal (scarabeus)\n<tomas.chvatal@gmail.com>",
     66     "",
     67     "Former OpenGL rendering programming",
     68     "Petr Sýkora (Glubo)\n<petr.sykora@gmail.com>",
     69     "",
     70     "Former keyboard improver",
     71     "Karel Podvolecký (kapo)\n<karel.podvolecky@gmail.com>",
     72     "",
     73     "Former porter",
     74     "Petr L. (Timoo)\n<daac@post.cz>",
     75     "",
     76     "Former composer",
     77     "Roman Kabelka (CJ Neti)\n<neti@cjneti.net>",
     78     "",
     79     NULL
     80 };
     81 
     82 static ta_credits_star stars[TA_CREDITS_STAR_COUNT];
     83 static ta_credits_entry *credit_entries;
     84 static uint32_t credit_count;
     85 static uint32_t frame;
     86 static uint32_t random_state;
     87 static uint32_t credit_index;
     88 static uint32_t credit_frame;
     89 static uint32_t credit_text_color;
     90 
     91 static uint32_t random_next(void) {
     92     random_state ^= random_state << 13;
     93     random_state ^= random_state >> 17;
     94     random_state ^= random_state << 5;
     95     return random_state;
     96 }
     97 
     98 static int32_t random_coordinate(void) {
     99     return (int32_t)(random_next() & 0xffffu) - 32768;
    100 }
    101 
    102 static int32_t random_depth(void) {
    103     return 49152 + (int32_t)((random_next() & 0xffffu) * 16384u / 65535u);
    104 }
    105 
    106 static void star_reset(ta_credits_star *star, int32_t depth) {
    107     star->x = random_coordinate();
    108     star->y = random_coordinate();
    109     star->z = depth;
    110 }
    111 
    112 static void credit_advance(void) {
    113     credit_index++;
    114     credit_frame = 0;
    115     credit_text_color = 0;
    116 }
    117 
    118 static int credit_fits(const char *string, uint32_t size, uint32_t max_width, uint32_t max_height, uint32_t *width, uint32_t *height) {
    119     ta_text text = ta_text_create(string, size, 0xffffff, 0, 0);
    120 
    121     if (text == 0) {
    122         return -1;
    123     }
    124 
    125     *width = ta_text_width(text);
    126     *height = ta_text_height(text);
    127 
    128     ta_text_destroy(text);
    129 
    130     return *width <= max_width && *height <= max_height;
    131 }
    132 
    133 static uint32_t credit_find_size(const char *string) {
    134     uint32_t max_width = ta_display_width() * TA_CREDITS_TEXT_WIDTH_MARGIN / 100;
    135     uint32_t max_height = ta_display_height() * TA_CREDITS_TEXT_HEIGHT_MARGIN / 100;
    136     uint32_t width;
    137     uint32_t height;
    138     uint32_t size = TA_CREDITS_TEXT_REFERENCE_SIZE;
    139     uint32_t by_width;
    140     uint32_t by_height;
    141     int fits;
    142 
    143     if (credit_fits(string, size, max_width, max_height, &width, &height) < 0 || width == 0 || height == 0) {
    144         return size;
    145     }
    146 
    147     by_width = size * max_width / width;
    148     by_height = size * max_height / height;
    149     size = by_width < by_height ? by_width : by_height;
    150 
    151     if (size > TA_CREDITS_TEXT_REFERENCE_SIZE) {
    152         size = TA_CREDITS_TEXT_REFERENCE_SIZE;
    153     }
    154 
    155     if (size < 1) {
    156         size = 1;
    157     }
    158 
    159     while (size > 1) {
    160         fits = credit_fits(string, size, max_width, max_height, &width, &height);
    161 
    162         if (fits != 0) {
    163             break;
    164         }
    165 
    166         size--;
    167     }
    168 
    169     return size;
    170 }
    171 
    172 static void credit_create_all(void) {
    173     uint32_t i;
    174 
    175     credit_count = 0;
    176 
    177     while (strings[credit_count] != NULL) {
    178         credit_count++;
    179     }
    180 
    181     credit_entries = malloc(credit_count * sizeof(ta_credits_entry));
    182 
    183     if (credit_entries == NULL) {
    184         credit_count = 0;
    185         return;
    186     }
    187 
    188     for (i = 0; i < credit_count; i++) {
    189         ta_credits_entry *entry = &credit_entries[i];
    190 
    191         entry->text = 0;
    192         entry->x = 0;
    193         entry->y = 0;
    194 
    195         if (strings[i][0] == '\0') {
    196             continue;
    197         }
    198 
    199         entry->text = ta_text_create(strings[i], credit_find_size(strings[i]), 0, 0, 0);
    200 
    201         if (entry->text == 0) {
    202             continue;
    203         }
    204 
    205         entry->x = ((int32_t)ta_display_width() - (int32_t)ta_text_width(entry->text)) / 2;
    206         entry->y = ((int32_t)ta_display_height() - (int32_t)ta_text_height(entry->text)) / 2;
    207 
    208         if (entry->x < 0) {
    209             entry->x = 0;
    210         }
    211 
    212         if (entry->y < 0) {
    213             entry->y = 0;
    214         }
    215     }
    216 }
    217 
    218 static void credit_destroy_all(void) {
    219     uint32_t i;
    220 
    221     for (i = 0; i < credit_count; i++) {
    222         if (credit_entries[i].text != 0) {
    223             ta_text_destroy(credit_entries[i].text);
    224         }
    225     }
    226 
    227     free(credit_entries);
    228     credit_entries = NULL;
    229     credit_count = 0;
    230 }
    231 
    232 static void credit_draw(void) {
    233     ta_credits_entry *entry;
    234     uint32_t brightness;
    235     uint32_t color;
    236 
    237     if (credit_index >= credit_count) {
    238         ta_screen_switch(TA_SCREEN_MAIN_MENU);
    239         return;
    240     }
    241 
    242     entry = &credit_entries[credit_index];
    243 
    244     if (strings[credit_index][0] == '\0') {
    245         if (credit_frame >= TA_CREDITS_TEXT_HOLD_FRAMES) {
    246             credit_advance();
    247             return;
    248         }
    249 
    250         credit_frame++;
    251         return;
    252     }
    253 
    254     if (credit_frame < TA_CREDITS_TEXT_IN_FRAMES) {
    255         brightness = credit_frame * 255u / (TA_CREDITS_TEXT_IN_FRAMES - 1);
    256     } else if (credit_frame < TA_CREDITS_TEXT_IN_FRAMES + TA_CREDITS_TEXT_HOLD_FRAMES) {
    257         brightness = 255;
    258     } else {
    259         uint32_t phase = credit_frame - TA_CREDITS_TEXT_IN_FRAMES - TA_CREDITS_TEXT_HOLD_FRAMES;
    260 
    261         if (phase >= TA_CREDITS_TEXT_OUT_FRAMES) {
    262             credit_advance();
    263             return;
    264         }
    265 
    266         brightness = (TA_CREDITS_TEXT_OUT_FRAMES - 1 - phase) * 255u / (TA_CREDITS_TEXT_OUT_FRAMES - 1);
    267     }
    268 
    269     color = (brightness << 16) | (brightness << 8) | brightness;
    270 
    271     if (entry->text == 0) {
    272         credit_frame++;
    273         return;
    274     }
    275 
    276     if (credit_text_color != color) {
    277         if (ta_text_change_color(entry->text, color)) {
    278             credit_text_color = color;
    279         }
    280     }
    281 
    282     ta_text_draw(entry->text, (uint32_t)entry->x, (uint32_t)entry->y);
    283 
    284     credit_frame++;
    285 }
    286 
    287 void ta_screen_credits_init(void) {
    288     uint32_t i;
    289 
    290     if (ta_ft2_load(TA_FILE_CREDITS)) {
    291         ta_ft2_play();
    292     }
    293 
    294     random_state = 0x6d2b79f5u;
    295     frame = 0;
    296     credit_index = 0;
    297     credit_frame = 0;
    298     credit_text_color = 0;
    299 
    300     credit_create_all();
    301 
    302     for (i = 0; i < TA_CREDITS_STAR_COUNT; i++) {
    303         star_reset(&stars[i], random_depth());
    304     }
    305 }
    306 
    307 void ta_screen_credits_update(void) {
    308     int32_t width = (int32_t)ta_display_width();
    309     int32_t height = (int32_t)ta_display_height();
    310     int32_t center_x = width / 2;
    311     int32_t center_y = height / 2;
    312     int32_t shortest = width < height ? width : height;
    313     int32_t scale = shortest * 48 / 100;
    314     int32_t speed;
    315     uint32_t i;
    316 
    317     if (frame < TA_CREDITS_ACCELERATION_FRAMES) {
    318         speed = TA_CREDITS_FULL_SPEED * (int32_t)frame / TA_CREDITS_ACCELERATION_FRAMES;
    319     } else {
    320         speed = TA_CREDITS_FULL_SPEED;
    321     }
    322 
    323     ta_shapes_draw_pixel((uint32_t)width, (uint32_t)height, 0);
    324 
    325     for (i = 0; i < TA_CREDITS_STAR_COUNT; i++) {
    326         ta_credits_star *star = &stars[i];
    327         int32_t x;
    328         int32_t y;
    329         int32_t brightness;
    330         uint32_t color;
    331 
    332         star->z -= speed;
    333 
    334         if (star->z <= TA_CREDITS_Z_NEAR) {
    335             star_reset(star, TA_CREDITS_Z_ONE);
    336         }
    337 
    338         x = center_x + (star->x * scale * 2) / star->z;
    339         y = center_y + (star->y * scale * 2) / star->z;
    340 
    341         if (x < 0 || y < 0 || x >= width || y >= height) {
    342             star_reset(star, TA_CREDITS_Z_ONE);
    343             continue;
    344         }
    345 
    346         brightness = ((TA_CREDITS_Z_ONE - star->z) * 255) / (TA_CREDITS_Z_ONE - TA_CREDITS_Z_NEAR);
    347 
    348         if (brightness < 0) {
    349             brightness = 0;
    350         }
    351 
    352         if (brightness > 255) {
    353             brightness = 255;
    354         }
    355 
    356         color = ((uint32_t)brightness << 16) | ((uint32_t)brightness << 8) | (uint32_t)brightness;
    357 
    358         ta_shapes_draw_pixel((uint32_t)x, (uint32_t)y, color);
    359     }
    360 
    361     if (frame >= TA_CREDITS_ACCELERATION_FRAMES) {
    362         credit_draw();
    363     }
    364 
    365     frame++;
    366 }
    367 
    368 void ta_screen_credits_destroy(void) {
    369     credit_destroy_all();
    370 }