From fa126a32866d70fce9ece84bc6557b85de91c9ef Mon Sep 17 00:00:00 2001 From: Tuomas Virtanen Date: Mon, 30 Sep 2024 01:05:59 +0300 Subject: [PATCH] opengl: Make rest of the game use the new renderer (mostly) --- src/console/console.c | 24 +- src/console/console_type.h | 2 - src/formats/fonts.c | 15 +- src/formats/fonts.h | 9 +- src/formats/palette.c | 65 +- src/formats/palette.h | 5 +- src/game/gui/dialog.c | 14 +- src/game/gui/gauge.c | 180 ++--- src/game/gui/menu.c | 2 +- src/game/gui/menu_background.c | 15 +- src/game/gui/pilotpic.c | 2 +- src/game/gui/progressbar.c | 52 +- src/game/gui/progressbar.h | 14 +- src/game/gui/spritebutton.c | 10 +- src/game/gui/spriteimage.c | 2 +- src/game/gui/text_render.c | 65 +- src/game/gui/text_render.h | 35 +- src/game/gui/textbutton.c | 44 +- src/game/gui/textbutton.h | 3 +- src/game/gui/textinput.c | 16 +- src/game/gui/textselector.c | 7 +- src/game/gui/textslider.c | 7 +- src/game/gui/trn_menu.c | 4 +- src/game/gui/trnselect.c | 6 +- src/game/objects/har.c | 16 +- src/game/protos/object.c | 23 +- src/game/protos/object.h | 6 +- src/game/scenes/arena.c | 11 +- src/game/scenes/credits.c | 4 - src/game/scenes/cutscene.c | 12 +- src/game/scenes/intro.c | 4 - src/game/scenes/mainmenu.c | 4 - src/game/scenes/mainmenu/menu_audio.c | 2 +- src/game/scenes/mainmenu/menu_configuration.c | 2 +- src/game/scenes/mainmenu/menu_connect.c | 2 +- src/game/scenes/mainmenu/menu_gameplay.c | 2 +- src/game/scenes/mainmenu/menu_input.c | 2 +- src/game/scenes/mainmenu/menu_keyboard.c | 2 +- src/game/scenes/mainmenu/menu_listen.c | 2 +- src/game/scenes/mainmenu/menu_main.c | 2 +- src/game/scenes/mainmenu/menu_net.c | 2 +- src/game/scenes/mainmenu/menu_presskey.c | 6 +- src/game/scenes/mainmenu/menu_video.c | 2 +- src/game/scenes/mainmenu/menu_video_confirm.c | 2 +- src/game/scenes/mechlab.c | 6 +- src/game/scenes/mechlab/lab_dash_main.c | 6 +- src/game/scenes/mechlab/lab_dash_newplayer.c | 4 +- src/game/scenes/mechlab/lab_dash_trnselect.c | 2 +- src/game/scenes/mechlab/lab_menu_confirm.c | 4 +- src/game/scenes/mechlab/lab_menu_customize.c | 72 +- .../mechlab/lab_menu_difficultyselect.c | 4 +- src/game/scenes/mechlab/lab_menu_main.c | 4 +- src/game/scenes/mechlab/lab_menu_select.c | 4 +- src/game/scenes/mechlab/lab_menu_trade.c | 2 +- src/game/scenes/mechlab/lab_menu_training.c | 6 +- src/game/scenes/melee.c | 641 +++++++++--------- src/game/scenes/newsroom.c | 12 +- src/game/scenes/openomf.c | 4 - src/game/scenes/scoreboard.c | 21 +- src/game/scenes/vs.c | 11 +- src/game/utils/har_screencap.c | 32 +- src/game/utils/har_screencap.h | 2 +- src/game/utils/score.c | 4 +- src/resources/bk.c | 12 +- src/resources/fonts.c | 10 +- src/resources/sprite.c | 4 +- 66 files changed, 755 insertions(+), 818 deletions(-) diff --git a/src/console/console.c b/src/console/console.c index 30759604d..961b4a20b 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -183,7 +183,6 @@ void console_output_render() { int x = 0; int y = 0; unsigned int lines = 0; - const color textcolor = color_create(121, 121, 121, 255); for(unsigned int i = con->output_pos; i != con->output_tail && lines < 15; i = BUFFER_INC(i)) { char c = con->output[i]; @@ -193,7 +192,7 @@ void console_output_render() { lines++; } else { // TODO add word wrapping? - font_render_char(&font_small, c, x, y + con->ypos - 100, textcolor); + font_render_char(&font_small, c, x, y + con->ypos - 100, TEXT_MEDIUM_GREEN); x += font_small.w; } } @@ -206,8 +205,6 @@ int console_init() { con->isopen = 0; con->ownsinput = 0; con->ypos = 0; - con->ticks = 0; - con->dir = 0; con->input[0] = '\0'; con->output[0] = '\0'; con->output_head = 0; @@ -313,13 +310,11 @@ void console_render() { con->input[0] = '\0'; con->histpos_changed = 0; } - video_render_sprite(&con->background, -1, con->ypos - 101, BLEND_ALPHA, 0); - int t = con->ticks / 2; + video_draw(&con->background, -1, con->ypos - 101); // input line - font_render(&font_small, con->input, 0, con->ypos - 7, color_create(121, 121, 121, 255)); + font_render(&font_small, con->input, 0, con->ypos - 7, TEXT_MEDIUM_GREEN); // cursor - font_render(&font_small, CURSOR_STR, strlen(con->input) * font_small.w, con->ypos - 7, - color_create(121 - t, 121 - t, 121 - t, 255)); + font_render(&font_small, CURSOR_STR, strlen(con->input) * font_small.w, con->ypos - 7, TEXT_BLINKY_GREEN); console_output_render(); } } @@ -336,17 +331,6 @@ void console_tick() { con->ypos = 0; } } - if(!con->dir) { - con->ticks++; - } else { - con->ticks--; - } - if(con->ticks > 120) { - con->dir = 1; - } - if(con->ticks == 0) { - con->dir = 0; - } } void console_add_cmd(const char *name, command_func func, const char *doc) { diff --git a/src/console/console_type.h b/src/console/console_type.h index 309ccd3b9..8e4cf5355 100644 --- a/src/console/console_type.h +++ b/src/console/console_type.h @@ -19,8 +19,6 @@ typedef struct { int isopen; int ownsinput; int ypos; - unsigned int ticks; - unsigned int dir; hashmap cmds; // string -> command } console; diff --git a/src/formats/fonts.c b/src/formats/fonts.c index 796d21b1d..dfff8e846 100644 --- a/src/formats/fonts.c +++ b/src/formats/fonts.c @@ -57,7 +57,7 @@ int sd_font_save(const sd_font *font, const char *file) { return SD_SUCCESS; } -int sd_font_decode(const sd_font *font, sd_rgba_image *o, uint8_t ch, uint8_t r, uint8_t g, uint8_t b) { +int sd_font_decode(const sd_font *font, sd_vga_image *o, uint8_t ch, uint8_t color) { if(font == NULL || o == NULL || ch >= 224) { return SD_INVALID_INPUT; } @@ -66,16 +66,13 @@ int sd_font_decode(const sd_font *font, sd_rgba_image *o, uint8_t ch, uint8_t r, for(int i = 0; i < font->h; i++) { for(int k = font->h - 1; k >= 0; k--) { if(font->chars[ch].data[i] & (1 << k)) { - o->data[t++] = r; - o->data[t++] = g; - o->data[t++] = b; - o->data[t++] = (uint8_t)255; + o->data[t] = color; + o->stencil[t] = 1; } else { - o->data[t++] = 0; - o->data[t++] = 0; - o->data[t++] = 0; - o->data[t++] = 0; + o->data[t] = 0; + o->stencil[t] = 0; } + t++; } } return SD_SUCCESS; diff --git a/src/formats/fonts.h b/src/formats/fonts.h index 44dea7717..06b7fd31c 100644 --- a/src/formats/fonts.h +++ b/src/formats/fonts.h @@ -11,6 +11,7 @@ #define SD_FONTS_H #include "formats/rgba_image.h" +#include "vga_image.h" #include #ifdef __cplusplus @@ -92,13 +93,11 @@ int sd_font_save(const sd_font *font, const char *filename); * \retval SD_SUCCESS Success. * * \param font Font struct pointer. - * \param surface Image surface to save to. Must be preallocated! + * \param surface Image surface to save to. Must be pre-allocated! * \param ch Character to load. Must be 0 <= ch <= 224. - * \param r Red color index (0 - 0xFF) - * \param g Green color index (0 - 0xFF) - * \param b Blue color index (0 - 0xFF) + * \param color Color palette index (0 - 0xFF) */ -int sd_font_decode(const sd_font *font, sd_rgba_image *surface, uint8_t ch, uint8_t r, uint8_t g, uint8_t b); +int sd_font_decode(const sd_font *font, sd_vga_image *surface, uint8_t ch, uint8_t color); #ifdef __cplusplus } diff --git a/src/formats/palette.c b/src/formats/palette.c index d7c38891b..ec16c1a70 100644 --- a/src/formats/palette.c +++ b/src/formats/palette.c @@ -2,11 +2,22 @@ #include "formats/altpal.h" #include "formats/error.h" #include "utils/allocator.h" -#include "video/color.h" -#include #include #include +#define COLOR_6TO8(color) ((color * 255.0) / 63.0) +#define COLOR_8TO6(color) ((color * 63.0) / 255.0) + +// Inserted to range 250 - 255. +static const int menu_colors[6][3] = { + {0, 0, 42}, // 0, 0, 170 + {0, 0, 60}, // 0, 0, 242 + {0, 0, 22}, // 0, 0, 89 + {0, 63, 0 }, // 0, 255, 0 + {0, 30, 0 }, // 0, 121, 0 + {20, 63, 20}, // 80, 255, 80 +}; + int palette_create(palette *pal) { if(pal == NULL) { return SD_INVALID_INPUT; @@ -30,13 +41,6 @@ unsigned char palette_resolve_color(uint8_t r, uint8_t g, uint8_t b, const palet return 0; } -color palette_lookup_color(uint8_t i, const palette *pal) { - uint8_t red = pal->data[i][0] & 0xff; - uint8_t green = pal->data[i][1] & 0xff; - uint8_t blue = pal->data[i][2] & 0xff; - return color_create(red, green, blue, 255); -} - int palette_to_gimp_palette(const palette *pal, const char *filename) { sd_writer *w; const unsigned char *d; @@ -110,13 +114,22 @@ int palette_from_gimp_palette(palette *pal, const char *filename) { return SD_SUCCESS; } +void palette_set_menu_colors(palette *pal) { + // Set the default menu colors. These are always set for the default (0) palette. + for(int i = 0; i < 6; i++) { + pal->data[250 + i][0] = COLOR_6TO8(menu_colors[i][0]); + pal->data[250 + i][1] = COLOR_6TO8(menu_colors[i][1]); + pal->data[250 + i][2] = COLOR_6TO8(menu_colors[i][2]); + } +} + int palette_load_range(sd_reader *reader, palette *pal, int index_start, int index_count) { char d[3]; for(int i = index_start; i < index_start + index_count; i++) { sd_read_buf(reader, d, 3); - pal->data[i][0] = ((d[0] << 2) | ((d[0] & 0x30) >> 4)); - pal->data[i][1] = ((d[1] << 2) | ((d[1] & 0x30) >> 4)); - pal->data[i][2] = ((d[2] << 2) | ((d[2] & 0x30) >> 4)); + pal->data[i][0] = COLOR_6TO8(d[0]); + pal->data[i][1] = COLOR_6TO8(d[1]); + pal->data[i][2] = COLOR_6TO8(d[2]); } return SD_SUCCESS; } @@ -125,9 +138,9 @@ int palette_mload_range(memreader *reader, palette *pal, int index_start, int in char d[3]; for(int i = index_start; i < index_start + index_count; i++) { memread_buf(reader, d, 3); - pal->data[i][0] = ((d[0] << 2) | ((d[0] & 0x30) >> 4)); - pal->data[i][1] = ((d[1] << 2) | ((d[1] & 0x30) >> 4)); - pal->data[i][2] = ((d[2] << 2) | ((d[2] & 0x30) >> 4)); + pal->data[i][0] = COLOR_6TO8(d[0]); + pal->data[i][1] = COLOR_6TO8(d[1]); + pal->data[i][2] = COLOR_6TO8(d[2]); } return SD_SUCCESS; } @@ -143,9 +156,9 @@ void palette_save_range(sd_writer *writer, const palette *pal, int index_start, for(int i = index_start; i < index_start + index_count; i++) { d = pal->data[i]; // for some reason, we need to mask off the high bits or the bitshift doesn't work - sd_write_ubyte(writer, (d[0] & 0xff) >> 2); - sd_write_ubyte(writer, (d[1] & 0xff) >> 2); - sd_write_ubyte(writer, (d[2] & 0xff) >> 2); + sd_write_ubyte(writer, COLOR_8TO6(d[0])); + sd_write_ubyte(writer, COLOR_8TO6(d[1])); + sd_write_ubyte(writer, COLOR_8TO6(d[2])); } } @@ -154,9 +167,9 @@ void palette_msave_range(memwriter *writer, const palette *pal, int index_start, for(int i = index_start; i < index_start + index_count; i++) { d = pal->data[i]; // for some reason, we need to mask off the high bits or the bitshift doesn't work - memwrite_ubyte(writer, (d[0] & 0xff) >> 2); - memwrite_ubyte(writer, (d[1] & 0xff) >> 2); - memwrite_ubyte(writer, (d[2] & 0xff) >> 2); + memwrite_ubyte(writer, COLOR_8TO6(d[0])); + memwrite_ubyte(writer, COLOR_8TO6(d[1])); + memwrite_ubyte(writer, COLOR_8TO6(d[2])); } } @@ -168,8 +181,8 @@ void palette_save(sd_writer *writer, const palette *pal) { void palette_load_player_colors(palette *dst, palette *src, int player) { // only load 47 palette colors, skipping the first one // because that seems to be ignored by the original - int dstoff = (player * 48) + 1; - memcpy(dst->data + dstoff, src->data + 1, 47 * 3); + int dst_offset = (player * 48) + 1; + memcpy(dst->data + dst_offset, src->data + 1, 47 * 3); } void palette_load_player_cutscene_colors(palette *dst, palette *src) { @@ -180,9 +193,9 @@ void palette_load_player_cutscene_colors(palette *dst, palette *src) { } } -void palette_set_player_color(palette *pal, int player, int srccolor, int dstcolor) { - int dst = dstcolor * 16 + player * 48; - int src = srccolor * 16; +void palette_set_player_color(palette *pal, int player, int src_color, int dst_color) { + int dst = dst_color * 16 + player * 48; + int src = src_color * 16; char iz[3]; memcpy(iz, pal->data, 3); if(altpals) { diff --git a/src/formats/palette.h b/src/formats/palette.h index 30381f48a..18e47f08d 100644 --- a/src/formats/palette.h +++ b/src/formats/palette.h @@ -65,8 +65,6 @@ void palette_free(palette *pal); */ unsigned char palette_resolve_color(uint8_t r, uint8_t g, uint8_t b, const palette *pal); -color palette_lookup_color(uint8_t i, const palette *pal); - /*! \brief Exports palette to GIMP palette file. * * Exports a palette to GIMP palette format (GPL). Palette remappings are NOT @@ -96,6 +94,7 @@ int palette_to_gimp_palette(const palette *pal, const char *filename); */ int palette_from_gimp_palette(palette *pal, const char *filename); +void palette_set_menu_colors(palette *pal); int palette_mload_range(memreader *reader, palette *pal, int index_start, int index_count); int palette_load_range(sd_reader *reader, palette *pal, int index_start, int index_count); int palette_load(sd_reader *reader, palette *pal); @@ -104,7 +103,7 @@ void palette_save_range(sd_writer *writer, const palette *pal, int index_start, void palette_save(sd_writer *writer, const palette *pal); void palette_load_player_colors(palette *dst, palette *src, int player); void palette_load_player_cutscene_colors(palette *dst, palette *src); -void palette_set_player_color(palette *pal, int player, int sourcecolor, int destcolor); +void palette_set_player_color(palette *pal, int player, int src_color, int dst_color); void palette_copy(palette *dst, const palette *src, int index_start, int inde_count); #ifdef __cplusplus diff --git a/src/game/gui/dialog.c b/src/game/gui/dialog.c index 6b76dc5cd..c7c12633d 100644 --- a/src/game/gui/dialog.c +++ b/src/game/gui/dialog.c @@ -12,12 +12,12 @@ void dialog_create(dialog *dlg, dialog_style style, const char *text, int x, int text_settings tconf; text_defaults(&tconf); tconf.font = FONT_BIG; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; text_settings tconf_desc; text_defaults(&tconf_desc); tconf_desc.font = FONT_SMALL; - tconf_desc.cforeground = COLOR_DARK_GREEN; + tconf_desc.cforeground = TEXT_MEDIUM_GREEN; dlg->x = x; dlg->y = y; @@ -36,15 +36,15 @@ void dialog_create(dialog *dlg, dialog_style style, const char *text, int x, int if(style == DIALOG_STYLE_YES_NO) { dlg->yes = textbutton_create(&tconf, "YES", COM_ENABLED, NULL, NULL); dlg->no = textbutton_create(&tconf, "NO", COM_ENABLED, NULL, NULL); - textbutton_set_border(dlg->yes, COLOR_BLUE); - textbutton_set_border(dlg->no, COLOR_BLUE); + textbutton_set_border(dlg->yes, TEXT_MEDIUM_GREEN); + textbutton_set_border(dlg->no, TEXT_MEDIUM_GREEN); component_layout(dlg->yes, x + 54, x + h + 6, 8, 8); component_layout(dlg->no, x + 114, x + h + 6, 8, 8); component_select(dlg->yes, 1); dlg->result = DIALOG_RESULT_YES_OK; } else if(style == DIALOG_STYLE_OK) { dlg->ok = textbutton_create(&tconf, "OK", COM_ENABLED, NULL, NULL); - textbutton_set_border(dlg->ok, COLOR_BLUE); + textbutton_set_border(dlg->ok, TEXT_MEDIUM_GREEN); component_layout(dlg->ok, x + 84, x + h + 6, 8, 8); component_select(dlg->ok, 1); dlg->result = DIALOG_RESULT_YES_OK; @@ -76,7 +76,7 @@ void dialog_render(dialog *dlg) { if(!dlg->visible) { return; } - video_render_sprite(&dlg->background, dlg->x, dlg->y, BLEND_ALPHA, 0); + video_draw(&dlg->background, dlg->x, dlg->y); if(dlg->yes) { component_render(dlg->yes); } @@ -86,7 +86,7 @@ void dialog_render(dialog *dlg) { if(dlg->ok) { component_render(dlg->ok); } - font_render_wrapped_shadowed(&font_small, dlg->text, dlg->x + 15, dlg->y + 3, MAX_WIDTH, COLOR_GREEN, + font_render_wrapped_shadowed(&font_small, dlg->text, dlg->x + 15, dlg->y + 3, MAX_WIDTH, TEXT_MEDIUM_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); } diff --git a/src/game/gui/gauge.c b/src/game/gui/gauge.c index fdfe4e03f..e984438d8 100644 --- a/src/game/gui/gauge.c +++ b/src/game/gui/gauge.c @@ -5,131 +5,97 @@ #include "video/surface.h" #include "video/video.h" -/* GIMP RGBA C-Source image dump (gauge_small_off.c) */ -static const struct { +typedef struct { unsigned int width; unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ - unsigned char pixel_data[3 * 3 * 4 + 1]; -} gauge_small_off_img = { - 3, - 3, - 4, - "\0\207\0\377\0\\\0\377\0" - "1\0\377\0\\\0\377\0,\0\377\0\10\0\377\0-\0\377" - "\0" - "6\0\377\0\14\0\377", + unsigned char data[24]; // 24 is the biggest pixel_image we make +} pixel_image; + +// Palette indices used: +// 0, 255, 0 = 0xA7 +// 0, 223, 0 = 0xA6 +// 0, 190, 0 = 0xA5 +// 0, 157, 0 = 0xA4 +// 0, 125, 0 = 0xA3 +// 0, 93, 0 = 0xA2 +// 0, 60, 0 = 0xA1 +// 0, 32, 0 = 0xA0 + +// clang-format off +static const pixel_image gauge_small_off_img = { + .width = 3, + .height = 3, + .data = { + 0xA3, 0xA2, 0xA1, + 0xA2, 0xA1, 0xA0, + 0xA1, 0xA0, 0xA0 + } }; -/* GIMP RGBA C-Source image dump (gauge_small_on.c) */ -static const struct { - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ - unsigned char pixel_data[3 * 3 * 4 + 1]; -} gauge_small_on_img = { - 3, - 3, - 4, - "\0\377\0\377\0\370\0\377\0\314\0\377\0\317\0\377\0\241\0\377\0y\0\377\0y" - "\0\377\0N\0\377\0#\0\377", +static const pixel_image gauge_small_on_img = { + .width = 3, + .height = 3, + .data = { + 0xA7, 0xA6, 0xA5, + 0xA5, 0xA4, 0xA3, + 0xA3, 0xA2, 0xA1 + } }; -/* GIMP RGBA C-Source image dump (gauge_big_on.c) */ -static const struct { - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ - unsigned char pixel_data[8 * 3 * 4 + 1]; -} gauge_big_on_img = { - 8, - 3, - 4, - "\0\377\0\377\0\364\0\377\0\366\0\377\0\366\0\377\0\366\0\377\0\366\0\377" - "\0\373\0\377\0\314\0\377\0\317\0\377\0\235\0\377\0\241\0\377\0\241\0\377" - "\0\241\0\377\0\241\0\377\0\246\0\377\0y\0\377\0y\0\377\0J\0\377\0N\0\377" - "\0N\0\377\0N\0\377\0N\0\377\0S\0\377\0#\0\377", +static const pixel_image gauge_big_on_img = { + .width = 8, + .height = 3, + .data = { + 0xA7, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA5, + 0xA5, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA3, + 0xA3, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA1 + } }; -/* GIMP RGBA C-Source image dump (gauge_big_off.c) */ -static const struct { - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ - unsigned char pixel_data[8 * 3 * 4 + 1]; -} gauge_big_off_img = { - 8, - 3, - 4, - "\0\207\0\377\0X\0\377\0\\\0\377\0\\\0\377\0\\\0\377\0\\\0\377\0a\0\377\0" - "" - "1\0\377\0\\\0\377\0(\0\377\0-\0\377\0-\0\377\0-\0\377\0-\0\377\0" - "1\0\377" - "\0\10\0\377\0-\0\377\0" - "2\0\377\0" - "2\0\377\0" - "2\0\377\0" - "2\0\377\0" - "2\0\377" - "\0" - "6\0\377\0\14\0\377", +static const pixel_image gauge_big_off_img = { + .width = 8, + .height = 3, + .data = { + 0xA3, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA1, + 0xA2, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA0, + 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA0 + } }; +// clang-format on + // Local small gauge type typedef struct { int size; int lit; gauge_type type; - surface *img; + surface on; + surface off; } gauge; -static void gauge_update(component *c) { - gauge *g = widget_get_obj(c); +static void surface_from_pix_img(surface *sur, const pixel_image *pix) { + surface_create_from_data(sur, pix->width, pix->height, pix->data); +} - // Create ON & OFF surface from gimp C exports - surface on; - surface off; - int move; - if(g->type == GAUGE_SMALL) { - move = 3; - surface_create_from_data(&on, SURFACE_TYPE_RGBA, 3, 3, (const char *)gauge_small_on_img.pixel_data); - surface_create_from_data(&off, SURFACE_TYPE_RGBA, 3, 3, (const char *)gauge_small_off_img.pixel_data); - } else { - move = 8; - surface_create_from_data(&on, SURFACE_TYPE_RGBA, 8, 3, (const char *)gauge_big_on_img.pixel_data); - surface_create_from_data(&off, SURFACE_TYPE_RGBA, 8, 3, (const char *)gauge_big_off_img.pixel_data); - } +static void gauge_render(component *c) { + gauge *g = widget_get_obj(c); - surface_clear(g->img); - // Blit required stuff to cached surface int k = 0; - int x = 0; + int x = c->x; for(; k < g->lit; k++) { - surface_rgba_blit(g->img, &on, x, 0); - x += move; + video_draw(&g->on, x, c->y); + x += g->on.w; } for(; k < g->size; k++) { - surface_rgba_blit(g->img, &off, x, 0); - x += move; + video_draw(&g->off, x, c->y); + x += g->on.w; } - - // Free up unnecessary surfaces - surface_free(&on); - surface_free(&off); - - // Force cached texture update! - surface_force_refresh(g->img); -} - -static void gauge_render(component *c) { - gauge *g = widget_get_obj(c); - video_render_sprite(g->img, c->x, c->y, BLEND_ALPHA, 0); } static void gauge_free(component *c) { gauge *g = widget_get_obj(c); - surface_free(g->img); - omf_free(g->img); + surface_free(&g->on); + surface_free(&g->off); omf_free(g); } @@ -137,7 +103,6 @@ void gauge_set_lit(component *c, int lit) { gauge *g = widget_get_obj(c); if(lit != g->lit) { g->lit = lit; - gauge_update(c); } } @@ -158,7 +123,6 @@ void gauge_set_size(component *c, int size) { if(g->lit > g->size) { g->lit = g->size; } - gauge_update(c); } } @@ -174,18 +138,20 @@ component *gauge_create(gauge_type type, int size, int lit) { local->type = type; local->lit = clamp(lit, 0, size); - // Initialize image - local->img = omf_calloc(1, sizeof(surface)); - int pix = ((type == GAUGE_BIG) ? 8 : 3) * size; - surface_create(local->img, SURFACE_TYPE_RGBA, pix, 3); - component_set_size_hints(c, pix, 3); + // Initialize surfaces + if(local->type == GAUGE_SMALL) { + surface_from_pix_img(&local->on, &gauge_small_on_img); + surface_from_pix_img(&local->off, &gauge_small_off_img); + component_set_size_hints(c, gauge_small_on_img.width * size, gauge_small_on_img.height); + } else { + surface_from_pix_img(&local->on, &gauge_big_on_img); + surface_from_pix_img(&local->off, &gauge_big_off_img); + component_set_size_hints(c, gauge_small_on_img.width * size, gauge_small_on_img.height); + } // Set callbacks widget_set_obj(c, local); widget_set_render_cb(c, gauge_render); widget_set_free_cb(c, gauge_free); - - // Update graphics - gauge_update(c); return c; } diff --git a/src/game/gui/menu.c b/src/game/gui/menu.c index 66579ccda..ae0c33434 100644 --- a/src/game/gui/menu.c +++ b/src/game/gui/menu.c @@ -90,7 +90,7 @@ static void menu_render(component *c) { // Otherwise handle this component iterator it; component **tmp; - video_render_sprite(m->bg, c->x, c->y, BLEND_ALPHA, 0); + video_draw(m->bg, c->x, c->y); vector_iter_begin(&s->objs, &it); while((tmp = iter_next(&it)) != NULL) { component_render(*tmp); diff --git a/src/game/gui/menu_background.c b/src/game/gui/menu_background.c index 57b910377..47638ea85 100644 --- a/src/game/gui/menu_background.c +++ b/src/game/gui/menu_background.c @@ -1,13 +1,12 @@ #include "game/gui/menu_background.h" -#include "video/color.h" #include "video/image.h" -#define COLOR_MENU_LINE color_create(0, 0, 89, 255) -#define COLOR_MENU_BORDER color_create(0, 0, 243, 255) -#define COLOR_MENU_LINE2 color_create(0, 0, 125, 255) -#define COLOR_MENU_BORDER1 color_create(0, 158, 0, 255) -#define COLOR_MENU_BORDER2 color_create(0, 93, 0, 255) -#define COLOR_MENU_BG color_create(4, 4, 16, 210) +#define COLOR_MENU_LINE 252 +#define COLOR_MENU_BORDER 251 +#define COLOR_MENU_LINE2 250 +#define COLOR_MENU_BORDER1 253 +#define COLOR_MENU_BORDER2 254 +#define COLOR_MENU_BG 0 void menu_background_create(surface *s, int w, int h) { image img; @@ -45,7 +44,7 @@ void menu_background2_create(surface *s, int w, int h) { void menu_background_border_create(surface *s, int w, int h) { image img; image_create(&img, w, h); - image_clear(&img, color_create(0, 0, 0, 0)); + image_clear(&img, 0); image_rect(&img, 0, 0, w - 1, h - 1, COLOR_MENU_BORDER); surface_create_from_image(s, &img); image_free(&img); diff --git a/src/game/gui/pilotpic.c b/src/game/gui/pilotpic.c index b31abbf20..341eead71 100644 --- a/src/game/gui/pilotpic.c +++ b/src/game/gui/pilotpic.c @@ -19,7 +19,7 @@ typedef struct { static void pilotpic_render(component *c) { pilotpic *g = widget_get_obj(c); if(g->img != NULL) { - video_render_sprite(g->img->data, c->x, c->y, BLEND_ALPHA, 0); + video_draw(g->img->data, c->x, c->y); } } diff --git a/src/game/gui/progressbar.c b/src/game/gui/progressbar.c index d3e73edb5..f95bc99dd 100644 --- a/src/game/gui/progressbar.c +++ b/src/game/gui/progressbar.c @@ -9,33 +9,33 @@ #include "video/video.h" const progressbar_theme _progressbar_theme_health = { - .border_topleft_color = {60, 0, 60, 255}, - .border_bottomright_color = {178, 0, 223, 255}, - .bg_color = {89, 40, 101, 255}, - .bg_color_alt = {89, 40, 101, 255}, - .int_topleft_color = {255, 0, 0, 255}, - .int_bottomright_color = {158, 0, 0, 255}, - .int_bg_color = {255, 56, 109, 255}, + .border_topleft_color = 0xB9, + .border_bottomright_color = 0xBE, + .bg_color = 0xF9, + .bg_color_alt = 0xF9, + .int_topleft_color = 0xB7, + .int_bottomright_color = 0xB4, + .int_bg_color = 0xF6, }; const progressbar_theme _progressbar_theme_endurance = { - .border_topleft_color = {60, 0, 60, 255}, - .border_bottomright_color = {178, 0, 223, 255}, - .bg_color = {89, 40, 101, 255}, - .bg_color_alt = {178, 0, 223, 255}, - .int_topleft_color = {24, 117, 138, 255}, - .int_bottomright_color = {0, 69, 93, 255}, - .int_bg_color = {97, 150, 186, 255}, + .border_topleft_color = 0xB9, + .border_bottomright_color = 0xBE, + .bg_color = 0xF9, + .bg_color_alt = 0xBE, + .int_topleft_color = 0xE2, + .int_bottomright_color = 0xE0, + .int_bg_color = 0xF8, }; const progressbar_theme _progressbar_theme_melee = { - .border_topleft_color = {0, 96, 0, 255}, - .border_bottomright_color = {0, 96, 0, 255}, - .bg_color = {80, 220, 80, 0 }, - .bg_color_alt = {80, 220, 80, 0 }, - .int_topleft_color = {0, 255, 0, 255}, - .int_bottomright_color = {0, 125, 0, 255}, - .int_bg_color = {0, 190, 0, 255}, + .border_topleft_color = 0xA2, + .border_bottomright_color = 0xA2, + .bg_color = 0, + .bg_color_alt = 0, + .int_topleft_color = 0xA7, + .int_bottomright_color = 0xA3, + .int_bg_color = 0xA5, }; typedef struct { @@ -96,24 +96,22 @@ static void progressbar_render(component *c) { bar->block = omf_calloc(1, sizeof(surface)); } surface_create_from_image(bar->block, &tmp); - surface_force_refresh(bar->block); image_free(&tmp); } else { omf_free(bar->block); } } - // Render backgrond (flashing or not) + // Render background (flashing or not) if(bar->state) { - video_render_sprite(bar->background_alt, c->x, c->y, BLEND_ALPHA, 0); + video_draw(bar->background_alt, c->x, c->y); } else { - video_render_sprite(bar->background, c->x, c->y, BLEND_ALPHA, 0); + video_draw(bar->background, c->x, c->y); } // Render block if(bar->block != NULL) { - video_render_sprite(bar->block, c->x + (bar->orientation == PROGRESSBAR_LEFT ? 0 : c->w - bar->block->w + 1), - c->y, BLEND_ALPHA, 0); + video_draw(bar->block, c->x + (bar->orientation == PROGRESSBAR_LEFT ? 0 : c->w - bar->block->w + 1), c->y); } } diff --git a/src/game/gui/progressbar.h b/src/game/gui/progressbar.h index 507456957..0b09993f5 100644 --- a/src/game/gui/progressbar.h +++ b/src/game/gui/progressbar.h @@ -5,13 +5,13 @@ #include "video/color.h" typedef struct { - color border_topleft_color; - color border_bottomright_color; - color bg_color; - color bg_color_alt; - color int_topleft_color; - color int_bottomright_color; - color int_bg_color; + uint8_t border_topleft_color; + uint8_t border_bottomright_color; + uint8_t bg_color; + uint8_t bg_color_alt; + uint8_t int_topleft_color; + uint8_t int_bottomright_color; + uint8_t int_bg_color; } progressbar_theme; extern const progressbar_theme _progressbar_theme_health; diff --git a/src/game/gui/spritebutton.c b/src/game/gui/spritebutton.c index 211480752..85226c58a 100644 --- a/src/game/gui/spritebutton.c +++ b/src/game/gui/spritebutton.c @@ -6,8 +6,6 @@ #include "game/gui/widget.h" #include "utils/allocator.h" #include "utils/log.h" -#include "utils/miscmath.h" -#include "video/color.h" #include "video/video.h" typedef struct { @@ -25,16 +23,12 @@ typedef struct { static void spritebutton_render(component *c) { spritebutton *sb = widget_get_obj(c); - sizer *s = component_get_obj(c->parent); - int opacity = clamp(s->opacity * 255, 0, 255); if(c->is_disabled) { - video_render_sprite_flip_scale_opacity_tint(sb->img, c->x, c->y, BLEND_ALPHA, 0, 0, 1.0, 1.0, opacity, - color_create(128, 128, 128, 255)); + video_draw_offset(sb->img, c->x, c->y, 5, 0x5F); } else if(sb->active) { - video_render_sprite(sb->img, c->x, c->y, BLEND_ALPHA, 0); + video_draw(sb->img, c->x, c->y); } if(sb->text) { - sb->tconf.opacity = opacity; text_render(&sb->tconf, c->x, c->y, c->w, c->h, sb->text); } } diff --git a/src/game/gui/spriteimage.c b/src/game/gui/spriteimage.c index e26d67f2c..5e271dc36 100644 --- a/src/game/gui/spriteimage.c +++ b/src/game/gui/spriteimage.c @@ -12,7 +12,7 @@ typedef struct { static void spriteimage_render(component *c) { spriteimage *sb = widget_get_obj(c); - video_render_sprite(sb->img, c->x, c->y, BLEND_ALPHA, 0); + video_draw(sb->img, c->x, c->y); } static void spriteimage_free(component *c) { diff --git a/src/game/gui/text_render.c b/src/game/gui/text_render.c index f0c6e1af1..0d7da88d5 100644 --- a/src/game/gui/text_render.c +++ b/src/game/gui/text_render.c @@ -2,13 +2,13 @@ #include #include "game/gui/text_render.h" +#include "utils/log.h" #include "utils/vector.h" #include "video/video.h" void text_defaults(text_settings *settings) { memset(settings, 0, sizeof(text_settings)); - settings->cforeground = color_create(0xFF, 0xFF, 0xFF, 0xFF); - settings->opacity = 0xFF; + settings->cforeground = 0xFF; } void text_render_char(const text_settings *settings, int x, int y, char ch) { @@ -31,26 +31,20 @@ void text_render_char(const text_settings *settings, int x, int y, char ch) { } // Handle shadows if necessary - float of = settings->opacity / 255.0f; if(settings->shadow & TEXT_SHADOW_RIGHT) - video_render_sprite_flip_scale_opacity_tint(*sur, x + 1, y, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, of * 80, - settings->cforeground); + video_draw_offset(*sur, x + 1, y, 0xC0, 255); if(settings->shadow & TEXT_SHADOW_LEFT) - video_render_sprite_flip_scale_opacity_tint(*sur, x - 1, y, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, of * 80, - settings->cforeground); + video_draw_offset(*sur, x - 1, y, 0xC0, 255); if(settings->shadow & TEXT_SHADOW_BOTTOM) - video_render_sprite_flip_scale_opacity_tint(*sur, x, y + 1, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, of * 80, - settings->cforeground); + video_draw_offset(*sur, x, y + 1, 0xC0, 255); if(settings->shadow & TEXT_SHADOW_TOP) - video_render_sprite_flip_scale_opacity_tint(*sur, x, y - 1, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, of * 80, - settings->cforeground); + video_draw_offset(*sur, x, y - 1, 0xC0, 255); - // Handle the font face itself - video_render_sprite_flip_scale_opacity_tint(*sur, x, y, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, settings->opacity, - settings->cforeground); + // Draw the actual font + video_draw_offset(*sur, x, y, settings->cforeground, 255); } -int text_find_max_strlen(int maxchars, const char *ptr) { +int text_find_max_strlen(int max_chars, const char *ptr) { int i; int len = strlen(ptr); @@ -65,8 +59,8 @@ int text_find_max_strlen(int maxchars, const char *ptr) { // Walk through the rest of the string int last_space = i; - int max = maxchars + i; - int lstart = i; + int max = max_chars + i; + int line_start = i; for(; i < len; i++) { // If we detect newline, this line ends here if(ptr[i] == '\n') @@ -76,7 +70,7 @@ int text_find_max_strlen(int maxchars, const char *ptr) { if(i >= max) { if(ptr[i] == ' ') { // If we are at valid end character (space), end here return i; - } else if(last_space != lstart) { + } else if(last_space != line_start) { return last_space; } } else if(ptr[i] == ' ') { @@ -244,11 +238,11 @@ void text_render(const text_settings *settings, int x, int y, int w, int h, cons /// ---------------- OLD RENDERER FUNCTIONS --------------------- -void font_render_char(const font *font, char ch, int x, int y, color c) { +void font_render_char(const font *font, char ch, int x, int y, uint8_t c) { font_render_char_shadowed(font, ch, x, y, c, 0); } -void font_render_char_shadowed(const font *font, char ch, int x, int y, color c, int shadow_flags) { +void font_render_char_shadowed(const font *font, char ch, int x, int y, uint8_t c, int shadow_flags) { // Make sure code is valid int code = ch - 32; surface **sur = NULL; @@ -261,23 +255,23 @@ void font_render_char_shadowed(const font *font, char ch, int x, int y, color c, // Handle shadows if necessary if(shadow_flags & TEXT_SHADOW_RIGHT) - video_render_sprite_flip_scale_opacity_tint(*sur, x + 1, y, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, 80, c); + video_draw_offset(*sur, x + 1, y, 0xC0, 255); if(shadow_flags & TEXT_SHADOW_LEFT) - video_render_sprite_flip_scale_opacity_tint(*sur, x - 1, y, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, 80, c); + video_draw_offset(*sur, x - 1, y, 0xC0, 255); if(shadow_flags & TEXT_SHADOW_BOTTOM) - video_render_sprite_flip_scale_opacity_tint(*sur, x, y + 1, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, 80, c); + video_draw_offset(*sur, x, y + 1, 0xC0, 255); if(shadow_flags & TEXT_SHADOW_TOP) - video_render_sprite_flip_scale_opacity_tint(*sur, x, y - 1, BLEND_ALPHA, 0, FLIP_NONE, 1.0f, 1.0f, 80, c); + video_draw_offset(*sur, x, y - 1, 0xC0, 255); // Handle the font face itself - video_render_sprite_tint(*sur, x, y, c, 0); + video_draw_offset(*sur, x, y, c, 255); } -void font_render_len(const font *font, const char *text, int len, int x, int y, color c) { +void font_render_len(const font *font, const char *text, int len, int x, int y, uint8_t c) { font_render_len_shadowed(font, text, len, x, y, c, 0); } -void font_render_len_shadowed(const font *font, const char *text, int len, int x, int y, color c, int shadow_flags) { +void font_render_len_shadowed(const font *font, const char *text, int len, int x, int y, uint8_t c, int shadow_flags) { int pos_x = x; for(int i = 0; i < len; i++) { font_render_char_shadowed(font, text[i], pos_x, y, c, shadow_flags); @@ -285,21 +279,21 @@ void font_render_len_shadowed(const font *font, const char *text, int len, int x } } -void font_render(const font *font, const char *text, int x, int y, color c) { +void font_render(const font *font, const char *text, int x, int y, uint8_t c) { int len = strlen(text); font_render_len(font, text, len, x, y, c); } -void font_render_shadowed(const font *font, const char *text, int x, int y, color c, int shadow_flags) { +void font_render_shadowed(const font *font, const char *text, int x, int y, uint8_t c, int shadow_flags) { int len = strlen(text); font_render_len_shadowed(font, text, len, x, y, c, shadow_flags); } -void font_render_wrapped(const font *font, const char *text, int x, int y, int w, color c) { +void font_render_wrapped(const font *font, const char *text, int x, int y, int w, uint8_t c) { font_render_wrapped_shadowed(font, text, x, y, w, c, 0); } -void font_render_wrapped_internal(const font *font, const char *text, int x, int y, int max_w, color c, +void font_render_wrapped_internal(const font *font, const char *text, int x, int y, int max_w, uint8_t c, int shadow_flags, int only_size, int *out_w, int *out_h) { int len = strlen(text); int has_newline = 0; @@ -395,18 +389,17 @@ void font_render_wrapped_internal(const font *font, const char *text, int x, int } } -void font_render_wrapped_shadowed(const font *font, const char *text, int x, int y, int w, color c, int shadow_flags) { +void font_render_wrapped_shadowed(const font *font, const char *text, int x, int y, int w, uint8_t c, + int shadow_flags) { int tmp; font_render_wrapped_internal(font, text, x, y, w, c, shadow_flags, 0, &tmp, &tmp); } void font_get_wrapped_size(const font *font, const char *text, int max_w, int *out_w, int *out_h) { - static color c = {0}; - font_render_wrapped_internal(font, text, 0, 0, max_w, c, 0, 1, out_w, out_h); + font_render_wrapped_internal(font, text, 0, 0, max_w, 0, 0, 1, out_w, out_h); } void font_get_wrapped_size_shadowed(const font *font, const char *text, int max_w, int shadow_flag, int *out_w, int *out_h) { - static color c = {0}; - font_render_wrapped_internal(font, text, 0, 0, max_w, c, shadow_flag, 1, out_w, out_h); + font_render_wrapped_internal(font, text, 0, 0, max_w, 0, shadow_flag, 1, out_w, out_h); } diff --git a/src/game/gui/text_render.h b/src/game/gui/text_render.h index 390af17b2..12c8b8eb3 100644 --- a/src/game/gui/text_render.h +++ b/src/game/gui/text_render.h @@ -1,11 +1,19 @@ #ifndef TEXT_RENDER_H #define TEXT_RENDER_H -#include "resources/fonts.h" -#include "video/color.h" #include #include +#include "resources/fonts.h" +#include "utils/str.h" +#include "video/color.h" + +#define TEXT_DARK_GREEN 0xFE +#define TEXT_MEDIUM_GREEN 0xFE +#define TEXT_BLINKY_GREEN 0xFF +#define TEXT_BLACK 0 +#define TEXT_TRN_BLUE 0xAB + typedef enum { TEXT_TOP = 0, @@ -40,13 +48,11 @@ enum TEXT_SHADOW_BOTTOM = 0x2, TEXT_SHADOW_LEFT = 0x4, TEXT_SHADOW_RIGHT = 0x8, - TEXT_SHADOW_HORIZONTAL = 0xC, - TEXT_SHADOW_VERTICAL = 0x3, TEXT_SHADOW_ALL = 0xF }; typedef struct { - color cforeground; + uint8_t cforeground; text_valign valign; text_halign halign; text_padding padding; @@ -55,13 +61,12 @@ typedef struct { uint8_t shadow; uint8_t cspacing; uint8_t lspacing; - uint8_t opacity; bool wrap; } text_settings; // New text rendering functions void text_defaults(text_settings *settings); -int text_find_max_strlen(int maxchars, const char *ptr); +int text_find_max_strlen(int max_chars, const char *ptr); int text_find_line_count(text_direction dir, int cols, int rows, int len, const char *text); void text_render_char(const text_settings *settings, int x, int y, char ch); void text_render(const text_settings *settings, int x, int y, int w, int h, const char *text); @@ -71,13 +76,13 @@ int text_char_width(const text_settings *settings); void font_get_wrapped_size(const font *font, const char *text, int max_w, int *out_w, int *out_h); void font_get_wrapped_size_shadowed(const font *font, const char *text, int max_w, int shadow_flag, int *out_w, int *out_h); -void font_render_char(const font *font, char ch, int x, int y, color c); -void font_render_char_shadowed(const font *font, char ch, int x, int y, color c, int shadow_flags); -void font_render_len(const font *font, const char *text, int len, int x, int y, color c); -void font_render_len_shadowed(const font *font, const char *text, int len, int x, int y, color c, int shadow_flags); -void font_render(const font *font, const char *text, int x, int y, color c); -void font_render_shadowed(const font *font, const char *text, int x, int y, color c, int shadow_flags); -void font_render_wrapped(const font *font, const char *text, int x, int y, int w, color c); -void font_render_wrapped_shadowed(const font *font, const char *text, int x, int y, int w, color c, int shadow_flags); +void font_render_char(const font *font, char ch, int x, int y, uint8_t c); +void font_render_char_shadowed(const font *font, char ch, int x, int y, uint8_t c, int shadow_flags); +void font_render_len(const font *font, const char *text, int len, int x, int y, uint8_t c); +void font_render_len_shadowed(const font *font, const char *text, int len, int x, int y, uint8_t c, int shadow_flags); +void font_render(const font *font, const char *text, int x, int y, uint8_t c); +void font_render_shadowed(const font *font, const char *text, int x, int y, uint8_t c, int shadow_flags); +void font_render_wrapped(const font *font, const char *text, int x, int y, int w, uint8_t c); +void font_render_wrapped_shadowed(const font *font, const char *text, int x, int y, int w, uint8_t c, int shadow_flags); #endif // TEXT_RENDER_H diff --git a/src/game/gui/textbutton.c b/src/game/gui/textbutton.c index 02367dab2..1226c49d8 100644 --- a/src/game/gui/textbutton.c +++ b/src/game/gui/textbutton.c @@ -11,22 +11,18 @@ typedef struct { char *text; text_settings tconf; - int ticks; - int dir; - int border_enabled; int border_created; - color border_color; + uint8_t border_color; surface border; textbutton_click_cb click_cb; void *userdata; } textbutton; -void textbutton_set_border(component *c, color col) { +void textbutton_set_border(component *c, uint8_t color) { textbutton *tb = widget_get_obj(c); - tb->border_enabled = 1; - tb->border_color = col; + tb->border_color = color; if(tb->border_created) { // destroy the old border first surface_free(&tb->border); @@ -37,12 +33,6 @@ void textbutton_set_border(component *c, color col) { int fsize = text_char_width(&tb->tconf); int width = chars * fsize; menu_background_border_create(&tb->border, width + 6, fsize + 3); - tb->border_created = 1; -} - -void textbutton_remove_border(component *c) { - textbutton *tb = widget_get_obj(c); - tb->border_enabled = 0; } void textbutton_set_text(component *c, const char *text) { @@ -58,18 +48,17 @@ static void textbutton_render(component *c) { // Select color and render if(component_is_selected(c)) { - int t = tb->ticks / 2; - tb->tconf.cforeground = color_create(80 - t, 220 - t * 2, 80 - t, 255); + tb->tconf.cforeground = TEXT_BLINKY_GREEN; } else if(component_is_disabled(c)) { - tb->tconf.cforeground = color_create(121, 121, 121, 255); + tb->tconf.cforeground = 0xC0; } else { - tb->tconf.cforeground = COLOR_DARK_GREEN; + tb->tconf.cforeground = TEXT_MEDIUM_GREEN; } text_render(&tb->tconf, c->x, c->y, c->w, c->h, tb->text); // Border - if(tb->border_enabled) { - video_render_sprite(&tb->border, c->x - 2, c->y - 2, BLEND_ALPHA, 0); + if(tb->border_created) { + video_draw(&tb->border, c->x - 2, c->y - 2); } } @@ -87,24 +76,8 @@ static int textbutton_action(component *c, int action) { return 1; } -static void textbutton_tick(component *c) { - textbutton *tb = widget_get_obj(c); - if(!tb->dir) { - tb->ticks++; - } else { - tb->ticks--; - } - if(tb->ticks > 120) { - tb->dir = 1; - } - if(tb->ticks == 0) { - tb->dir = 0; - } -} - static void textbutton_free(component *c) { textbutton *tb = widget_get_obj(c); - if(tb->border_created) { surface_free(&tb->border); } @@ -126,7 +99,6 @@ component *textbutton_create(const text_settings *tconf, const char *text, int d widget_set_render_cb(c, textbutton_render); widget_set_action_cb(c, textbutton_action); - widget_set_tick_cb(c, textbutton_tick); widget_set_free_cb(c, textbutton_free); return c; diff --git a/src/game/gui/textbutton.h b/src/game/gui/textbutton.h index a1a212100..692d0cd1e 100644 --- a/src/game/gui/textbutton.h +++ b/src/game/gui/textbutton.h @@ -8,8 +8,7 @@ typedef void (*textbutton_click_cb)(component *c, void *userdata); component *textbutton_create(const text_settings *tconf, const char *text, int disabled, textbutton_click_cb cb, void *userdata); -void textbutton_set_border(component *c, color col); +void textbutton_set_border(component *c, uint8_t color); void textbutton_set_text(component *c, const char *text); -void textbutton_remove_border(component *c); #endif // TEXTBUTTON_H diff --git a/src/game/gui/textinput.c b/src/game/gui/textinput.c index caf7ceaa3..0683830ae 100644 --- a/src/game/gui/textinput.c +++ b/src/game/gui/textinput.c @@ -9,9 +9,9 @@ #include "video/image.h" #include "video/video.h" -#define COLOR_MENU_LINE color_create(0, 0, 89, 255) -#define COLOR_MENU_BORDER color_create(0, 0, 243, 255) -#define COLOR_MENU_BG color_create(4, 4, 16, 210) +#define COLOR_MENU_LINE 252 +#define COLOR_MENU_BORDER 251 +#define COLOR_MENU_BG 0 typedef struct { char *text; @@ -29,12 +29,12 @@ static void textinput_render(component *c) { int chars = strlen(tb->buf); if(tb->bg_enabled) { - video_render_sprite(&tb->sur, c->x + (c->w - tb->sur.w) / 2, c->y - 2, BLEND_ALPHA, 0); + video_draw(&tb->sur, c->x + (c->w - tb->sur.w) / 2, c->y - 2); } if(component_is_selected(c)) { if(chars > 0) { - tb->tconf.cforeground = color_create(80, 220, 80, 255); + tb->tconf.cforeground = TEXT_BLINKY_GREEN; tb->buf[chars] = '\x7F'; tb->buf[chars + 1] = 0; text_render(&tb->tconf, c->x, c->y, c->w, c->h, tb->buf); @@ -42,17 +42,17 @@ static void textinput_render(component *c) { } } else if(component_is_disabled(c)) { if(chars > 0) { - tb->tconf.cforeground = color_create(121, 121, 121, 255); + tb->tconf.cforeground = 0xC0; text_render(&tb->tconf, c->x, c->y, c->w, c->h, tb->buf); } } else { if(chars > 0) { - tb->tconf.cforeground = COLOR_DARK_GREEN; + tb->tconf.cforeground = TEXT_MEDIUM_GREEN; text_render(&tb->tconf, c->x, c->y, c->w, c->h, tb->buf); } } if(chars == 0) { - tb->tconf.cforeground = color_create(121, 121, 121, 255); + tb->tconf.cforeground = 0xC0; text_render(&tb->tconf, c->x, c->y, c->w, c->h, tb->text); } } diff --git a/src/game/gui/textselector.c b/src/game/gui/textselector.c index d9ad2c047..29928957f 100644 --- a/src/game/gui/textselector.c +++ b/src/game/gui/textselector.c @@ -64,12 +64,11 @@ static void textselector_render(component *c) { // Render text if(component_is_selected(c)) { - int t = tb->ticks / 2; - tb->tconf.cforeground = color_create(80 - t, 220 - t * 2, 80 - t, 255); + tb->tconf.cforeground = TEXT_BLINKY_GREEN; } else if(component_is_disabled(c)) { - tb->tconf.cforeground = color_create(121, 121, 121, 255); + tb->tconf.cforeground = 0xC0; } else { - tb->tconf.cforeground = COLOR_DARK_GREEN; + tb->tconf.cforeground = TEXT_MEDIUM_GREEN; } text_render(&tb->tconf, c->x, c->y, c->w, c->h, buf); } diff --git a/src/game/gui/textslider.c b/src/game/gui/textslider.c index 8e743054a..4a70f75ae 100644 --- a/src/game/gui/textslider.c +++ b/src/game/gui/textslider.c @@ -38,12 +38,11 @@ static void textslider_render(component *c) { } if(component_is_selected(c)) { - int t = tb->ticks / 2; - tb->tconf.cforeground = color_create(80 - t, 220 - t * 2, 80 - t, 255); + tb->tconf.cforeground = TEXT_BLINKY_GREEN; } else if(component_is_disabled(c)) { - tb->tconf.cforeground = color_create(121, 121, 121, 255); + tb->tconf.cforeground = 0xC0; } else { - tb->tconf.cforeground = COLOR_DARK_GREEN; + tb->tconf.cforeground = TEXT_MEDIUM_GREEN; } text_render(&tb->tconf, c->x, c->y, c->w, c->h, str_c(&txt)); str_free(&txt); diff --git a/src/game/gui/trn_menu.c b/src/game/gui/trn_menu.c index 36d419a2c..4157cd617 100644 --- a/src/game/gui/trn_menu.c +++ b/src/game/gui/trn_menu.c @@ -262,9 +262,7 @@ static void trnmenu_render(component *c) { // Render button sheet if(m->button_sheet) { - video_render_sprite_flip_scale_opacity_tint(m->button_sheet, m->sheet_x, m->sheet_y, BLEND_ALPHA, 0, FLIP_NONE, - 1.0f, 1.0f, clamp(s->opacity * 255, 0, 255), - color_create(0xFF, 0xFF, 0xFF, 0xFF)); + video_draw(m->button_sheet, m->sheet_x, m->sheet_y); } // Handle components diff --git a/src/game/gui/trnselect.c b/src/game/gui/trnselect.c index 06f46f0c8..662b74363 100644 --- a/src/game/gui/trnselect.c +++ b/src/game/gui/trnselect.c @@ -26,7 +26,7 @@ typedef struct { static void trnselect_render(component *c) { trnselect *g = widget_get_obj(c); - video_render_sprite(g->img->data, c->x + g->img->pos.x, c->y + g->img->pos.y, BLEND_ALPHA, 0); + video_draw(g->img->data, c->x + g->img->pos.x, c->y + g->img->pos.y); if(g->label) { component_render(g->label); } @@ -86,10 +86,10 @@ void load_description(component **c, const char *desc) { tconf.halign = TEXT_CENTER; tconf.valign = TEXT_MIDDLE; if(color >= 0) { - tconf.cforeground = palette_lookup_color(color, video_get_base_palette()); + tconf.cforeground = color; } else { // WAR invitational seems to use this color, none is specified - tconf.cforeground = palette_lookup_color(0xa5, video_get_base_palette()); + tconf.cforeground = 0xa5; } if(*c) { diff --git a/src/game/objects/har.c b/src/game/objects/har.c index 0afa02104..46c01901e 100644 --- a/src/game/objects/har.c +++ b/src/game/objects/har.c @@ -403,6 +403,7 @@ void cb_har_spawn_object(object *parent, int id, vec2i pos, vec2f vel, uint8_t f object_set_animation(obj, &move->ani); object_set_gravity(obj, g / 256.0f); object_set_pal_offset(obj, object_get_pal_offset(parent)); + object_set_pal_limit(obj, object_get_pal_limit(parent)); // Set all projectiles to their own layer + har layer object_set_layers(obj, LAYER_PROJECTILE | (h->player_id == 0 ? LAYER_HAR2 : LAYER_HAR1)); // To avoid projectile-to-projectile collisions, set them to same group @@ -746,6 +747,7 @@ void har_spawn_scrap(object *obj, vec2i pos, int amount) { object_set_stl(scrap, object_get_stl(obj)); object_set_gravity(scrap, 1); object_set_pal_offset(scrap, object_get_pal_offset(obj)); + object_set_pal_limit(obj, object_get_pal_limit(obj)); object_set_layers(scrap, LAYER_SCRAP); object_dynamic_tick(scrap); object_set_shadow(scrap, 1); @@ -922,11 +924,11 @@ void har_debug(object *obj) { image img; surface_to_image(&h->cd_debug, &img); - color c = color_create(0, 255, 0, 255); - color red = color_create(0, 255, 0, 255); - color blank = color_create(0, 0, 0, 0); + uint8_t c = 0xCF; + uint8_t red = 0xCF; + uint8_t blank = 0; - // video_render_sprite(&h->cd_debug, 0, 0, 0, 0); + // video_draw(&h->cd_debug, 0, 0); if(obj->cur_sprite == NULL) { return; @@ -976,8 +978,7 @@ void har_debug(object *obj) { image_set_pixel(&img, pos_a.x, pos_a.y, red); - surface_force_refresh(&h->cd_debug); // Force refresh for the texture - video_render_sprite(&h->cd_debug, 0, 0, 0, 0); + video_draw(&h->cd_debug, 0, 0); } #endif // DEBUGMODE @@ -2222,6 +2223,7 @@ int har_create(object *obj, af *af_data, int dir, int har_id, int pilot_id, int // Set palette offset 0 for player1, 48 for player2 object_set_pal_offset(obj, player_id * 48); + object_set_pal_limit(obj, (player_id + 1) * 48); // Object related stuff object_set_gravity(obj, local->fall_speed); @@ -2254,7 +2256,7 @@ int har_create(object *obj, af *af_data, int dir, int har_id, int pilot_id, int #ifdef DEBUGMODE object_set_debug_cb(obj, har_debug); - surface_create(&local->cd_debug, SURFACE_TYPE_RGBA, 320, 200); + surface_create(&local->cd_debug, 320, 200); surface_clear(&local->cd_debug); #endif diff --git a/src/game/protos/object.c b/src/game/protos/object.c index 220bd1b21..780fe59b4 100644 --- a/src/game/protos/object.c +++ b/src/game/protos/object.c @@ -60,6 +60,7 @@ void object_create(object *obj, game_state *gs, vec2i pos, vec2f vel) { obj->cur_surface = NULL; obj->cur_remap = -1; obj->pal_offset = 0; + obj->pal_limit = 255; obj->halt = 0; obj->halt_ticks = 0; obj->stride = 1; @@ -90,6 +91,10 @@ void object_create(object *obj, game_state *gs, vec2i pos, vec2f vel) { obj->pal_transform = NULL; } +void object_create_static(object *obj, game_state *gs) { + object_create(obj, gs, vec2i_create(0, 0), vec2f_create(0, 0)); +} + /** * \brief Serializes the object to a buffer. * @@ -116,6 +121,7 @@ int object_serialize(object *obj, serial *ser) { serial_write_int32(ser, random_get_seed(&obj->rand_state)); serial_write_int8(ser, obj->cur_animation->id); serial_write_int8(ser, obj->pal_offset); + serial_write_int8(ser, obj->pal_limit); serial_write_int8(ser, obj->hit_frames); serial_write_int8(ser, obj->can_hit); @@ -172,6 +178,7 @@ int object_unserialize(object *obj, serial *ser, game_state *gs) { random_seed(&obj->rand_state, serial_read_int32(ser)); uint8_t animation_id = serial_read_int8(ser); uint8_t pal_offset = serial_read_int8(ser); + uint8_t pal_limit = serial_read_int8(ser); int8_t hit_frames = serial_read_int8(ser); int8_t can_hit = serial_read_int8(ser); @@ -231,6 +238,7 @@ int object_unserialize(object *obj, serial *ser, game_state *gs) { object_set_gravity(obj, gravity); object_set_repeat(obj, repeat); object_set_pal_offset(obj, pal_offset); + object_set_pal_limit(obj, pal_limit); obj->hit_frames = hit_frames; obj->can_hit = can_hit; @@ -420,8 +428,9 @@ void object_render(object *obj) { } // Render - video_render_sprite_flip_scale_opacity_tint(obj->cur_surface, x, y, rstate->blendmode, obj->pal_offset, flipmode, - obj->x_percent, obj->y_percent, opacity, tint); + video_render_sprite_flip_scale_opacity_tint(obj->cur_surface, x, y, rstate->blendmode, obj->pal_offset, + obj->pal_limit, flipmode, obj->x_percent, obj->y_percent, opacity, + tint); } void object_render_shadow(object *obj) { @@ -449,7 +458,8 @@ void object_render_shadow(object *obj) { // the shadows seem a bit blobbier and shadow-y for(int i = 0; i < 2; i++) { video_render_sprite_flip_scale_opacity_tint(obj->cur_sprite->data, x + i, y + i, BLEND_ALPHA, obj->pal_offset, - flipmode, 1.0, scale_y, 65, color_create(0, 0, 0, 255)); + obj->pal_limit, flipmode, 1.0, scale_y, 65, + color_create(0, 0, 0, 255)); } } @@ -697,6 +707,13 @@ int object_get_pal_offset(const object *obj) { return obj->pal_offset; } +void object_set_pal_limit(object *obj, int limit) { + obj->pal_limit = limit; +} +int object_get_pal_limit(const object *obj) { + return obj->pal_limit; +} + void object_set_halt_ticks(object *obj, int ticks) { obj->halt = (ticks > 0); obj->halt_ticks = ticks; diff --git a/src/game/protos/object.h b/src/game/protos/object.h index 62a3e197f..79fb95dae 100644 --- a/src/game/protos/object.h +++ b/src/game/protos/object.h @@ -101,6 +101,7 @@ struct object_t { const object *attached_to; uint8_t pal_offset; + uint8_t pal_limit; uint8_t cur_remap; uint8_t halt; int16_t halt_ticks; @@ -133,6 +134,7 @@ struct object_t { }; void object_create(object *obj, game_state *gs, vec2i pos, vec2f vel); +void object_create_static(object *obj, game_state *gs); void object_render(object *obj); void object_render_shadow(object *obj); void object_debug(object *obj); @@ -141,7 +143,6 @@ void object_dynamic_tick(object *obj); void object_set_tick_pos(object *obj, int tick); void object_move(object *obj); int object_palette_transform(object *obj, screen_palette *pal); -void object_render(object *obj); void object_collide(object *a, object *b); int object_act(object *obj, int action); int object_finished(object *obj); @@ -217,6 +218,9 @@ int object_is_rewind_tag_disabled(const object *obj); void object_set_pal_offset(object *obj, int offset); int object_get_pal_offset(const object *obj); +void object_set_pal_limit(object *obj, int limit); +int object_get_pal_limit(const object *obj); + vec2i object_get_size(const object *obj); vec2i object_get_pos(const object *obj); vec2f object_get_vel(const object *obj); diff --git a/src/game/scenes/arena.c b/src/game/scenes/arena.c index 68c6ccf3f..4bce9eea7 100644 --- a/src/game/scenes/arena.c +++ b/src/game/scenes/arena.c @@ -35,7 +35,7 @@ #include "video/surface.h" #include "video/video.h" -#define TEXT_COLOR color_create(186, 250, 250, 255) +#define TEXT_COLOR 0xC7 #define HAR1_START_POS 110 #define HAR2_START_POS 211 @@ -995,6 +995,7 @@ void arena_dynamic_tick(scene *scene, int paused) { object_set_animation(scrap, &af_get_move(h->af_data, anim_no)->ani); object_set_gravity(scrap, 0.4f); object_set_pal_offset(scrap, object_get_pal_offset(h_obj)); + object_set_pal_limit(scrap, object_get_pal_limit(h_obj)); object_set_layers(scrap, LAYER_SCRAP); object_set_shadow(scrap, 1); object_dynamic_tick(scrap); @@ -1131,7 +1132,7 @@ void arena_render_overlay(scene *scene) { // Render menu (if visible) if(local->menu_visible) { guiframe_render(local->game_menu); - video_render_sprite(&local->sur, 10, 150, BLEND_ALPHA, 0); + video_draw(&local->sur, 10, 150); } } @@ -1336,7 +1337,7 @@ int arena_create(scene *scene) { text_settings tconf; text_defaults(&tconf); tconf.font = FONT_BIG; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_DARK_GREEN; tconf.halign = TEXT_CENTER; // Arena menu @@ -1470,10 +1471,6 @@ int arena_create(scene *scene) { local->rec = NULL; } - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - // All done! return 0; } diff --git a/src/game/scenes/credits.c b/src/game/scenes/credits.c index 2be810d70..9a0bbd83f 100644 --- a/src/game/scenes/credits.c +++ b/src/game/scenes/credits.c @@ -63,9 +63,5 @@ int credits_create(scene *scene) { scene_set_startup_cb(scene, credits_startup); scene_set_input_poll_cb(scene, credits_input_tick); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - return 0; } diff --git a/src/game/scenes/cutscene.c b/src/game/scenes/cutscene.c index 2989d9a8b..3ef65b6f4 100644 --- a/src/game/scenes/cutscene.c +++ b/src/game/scenes/cutscene.c @@ -95,7 +95,6 @@ void cutscene_startup(scene *scene, int id, int *m_load, int *m_repeat) { } else if(scene->id == SCENE_END2 && (id == 1 || id == 11)) { *m_load = 1; } - video_render_bg_separately(false); } int cutscene_create(scene *scene) { @@ -115,7 +114,7 @@ int cutscene_create(scene *scene) { local->text_x = 10; local->text_y = 5; local->text_width = 300; - local->text_conf.cforeground = COLOR_YELLOW; + local->text_conf.cforeground = 0xF8; break; case SCENE_END1: @@ -123,7 +122,7 @@ int cutscene_create(scene *scene) { local->text_x = 10; local->text_y = 157; local->text_width = 300; - local->text_conf.cforeground = COLOR_RED; + local->text_conf.cforeground = 0xFD; // Pilot face animation *ani = &bk_get_info(&scene->bk_data, 3)->ani; @@ -147,8 +146,9 @@ int cutscene_create(scene *scene) { local->text_x = 10; local->text_y = 160; local->text_width = 300; - local->text_conf.cforeground = COLOR_GREEN; + local->text_conf.cforeground = 0xF8; break; + case SCENE_NORTHAM: case SCENE_KATUSHAI: case SCENE_WAR: @@ -177,9 +177,7 @@ int cutscene_create(scene *scene) { local->text_x = 10; local->text_y = 160; local->text_width = 300; - - local->text_conf.cforeground = palette_lookup_color(248, video_get_base_palette()); - + local->text_conf.cforeground = 0xF8; break; } diff --git a/src/game/scenes/intro.c b/src/game/scenes/intro.c index eeaef15bf..b80e38d86 100644 --- a/src/game/scenes/intro.c +++ b/src/game/scenes/intro.c @@ -75,9 +75,5 @@ int intro_create(scene *scene) { scene_set_startup_cb(scene, intro_startup); scene_set_anim_prio_override_cb(scene, intro_anim_override); - // Render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(true); - return 0; } diff --git a/src/game/scenes/mainmenu.c b/src/game/scenes/mainmenu.c index 1a305b6a8..2232cfd07 100644 --- a/src/game/scenes/mainmenu.c +++ b/src/game/scenes/mainmenu.c @@ -154,10 +154,6 @@ int mainmenu_create(scene *scene) { // Music and renderer audio_play_music(PSM_MENU); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - // All done return 0; } diff --git a/src/game/scenes/mainmenu/menu_audio.c b/src/game/scenes/mainmenu/menu_audio.c index 7c90715ea..f515c1fbe 100644 --- a/src/game/scenes/mainmenu/menu_audio.c +++ b/src/game/scenes/mainmenu/menu_audio.c @@ -94,7 +94,7 @@ component *menu_audio_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; // Create menu and its header component *menu = menu_create(11); diff --git a/src/game/scenes/mainmenu/menu_configuration.c b/src/game/scenes/mainmenu/menu_configuration.c index 4d5953fd0..604b3fea0 100644 --- a/src/game/scenes/mainmenu/menu_configuration.c +++ b/src/game/scenes/mainmenu/menu_configuration.c @@ -36,7 +36,7 @@ component *menu_configuration_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); menu_attach(menu, label_create(&tconf, "CONFIGURATION")); diff --git a/src/game/scenes/mainmenu/menu_connect.c b/src/game/scenes/mainmenu/menu_connect.c index def847f61..27bbc0654 100644 --- a/src/game/scenes/mainmenu/menu_connect.c +++ b/src/game/scenes/mainmenu/menu_connect.c @@ -180,7 +180,7 @@ component *menu_connect_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); menu_attach(menu, label_create(&tconf, "CONNECT TO SERVER")); diff --git a/src/game/scenes/mainmenu/menu_gameplay.c b/src/game/scenes/mainmenu/menu_gameplay.c index aaaede24f..3c9f3988a 100644 --- a/src/game/scenes/mainmenu/menu_gameplay.c +++ b/src/game/scenes/mainmenu/menu_gameplay.c @@ -23,7 +23,7 @@ component *menu_gameplay_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); menu_attach(menu, label_create(&tconf, "GAMEPLAY")); diff --git a/src/game/scenes/mainmenu/menu_input.c b/src/game/scenes/mainmenu/menu_input.c index fd593264e..859ef05c3 100644 --- a/src/game/scenes/mainmenu/menu_input.c +++ b/src/game/scenes/mainmenu/menu_input.c @@ -184,7 +184,7 @@ component *menu_input_create(scene *s, int player_id) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); menu_attach(menu, label_create(&tconf, "CHOOSE INPUT")); diff --git a/src/game/scenes/mainmenu/menu_keyboard.c b/src/game/scenes/mainmenu/menu_keyboard.c index 914b14607..68bc318fd 100644 --- a/src/game/scenes/mainmenu/menu_keyboard.c +++ b/src/game/scenes/mainmenu/menu_keyboard.c @@ -131,7 +131,7 @@ guiframe *menu_keyboard_create(scene *s, int selected_player) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; local->frame = guiframe_create(25, 5, 270, 140); component *menu = menu_create(11); diff --git a/src/game/scenes/mainmenu/menu_listen.c b/src/game/scenes/mainmenu/menu_listen.c index f1d589e8f..97c21714b 100644 --- a/src/game/scenes/mainmenu/menu_listen.c +++ b/src/game/scenes/mainmenu/menu_listen.c @@ -140,7 +140,7 @@ component *menu_listen_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; // Create the menu component *menu = menu_create(11); diff --git a/src/game/scenes/mainmenu/menu_main.c b/src/game/scenes/mainmenu/menu_main.c index 190394194..e91a0e9c2 100644 --- a/src/game/scenes/mainmenu/menu_main.c +++ b/src/game/scenes/mainmenu/menu_main.c @@ -95,7 +95,7 @@ component *menu_main_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_DARK_GREEN; component *menu = menu_create(11); menu_attach(menu, textbutton_create(&tconf, "ONE PLAYER GAME", COM_ENABLED, mainmenu_1v1, s)); diff --git a/src/game/scenes/mainmenu/menu_net.c b/src/game/scenes/mainmenu/menu_net.c index bad2b39f4..27135b57f 100644 --- a/src/game/scenes/mainmenu/menu_net.c +++ b/src/game/scenes/mainmenu/menu_net.c @@ -28,7 +28,7 @@ component *menu_net_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); menu_attach(menu, label_create(&tconf, "NETWORK PLAY")); diff --git a/src/game/scenes/mainmenu/menu_presskey.c b/src/game/scenes/mainmenu/menu_presskey.c index 3cad2978b..4f24de2ab 100644 --- a/src/game/scenes/mainmenu/menu_presskey.c +++ b/src/game/scenes/mainmenu/menu_presskey.c @@ -65,7 +65,7 @@ void menu_presskey_tick(component *c) { if(local->warn_timeout == 0) { for(int i = 0; i < 2; i++) { text_settings *tconf = label_get_text_settings(local->text[i]); - tconf->cforeground = COLOR_DARK_GREEN; + tconf->cforeground = TEXT_MEDIUM_GREEN; } } } @@ -90,7 +90,7 @@ void menu_presskey_tick(component *c) { // Set texts to red as a warning for(int m = 0; m < 2; m++) { text_settings *tconf = label_get_text_settings(local->text[m]); - tconf->cforeground = color_create(121, 0, 0, 255); + tconf->cforeground = 0xF6; } local->warn_timeout = 50; return; @@ -114,7 +114,7 @@ component *menu_presskey_create(char **key) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); local->text[0] = label_create(&tconf, "PRESS A KEY FOR"); diff --git a/src/game/scenes/mainmenu/menu_video.c b/src/game/scenes/mainmenu/menu_video.c index f177bc519..c70ff9d07 100644 --- a/src/game/scenes/mainmenu/menu_video.c +++ b/src/game/scenes/mainmenu/menu_video.c @@ -122,7 +122,7 @@ component *menu_video_create(scene *s) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; // Create menu and its header component *menu = menu_create(11); diff --git a/src/game/scenes/mainmenu/menu_video_confirm.c b/src/game/scenes/mainmenu/menu_video_confirm.c index ddd4290b8..60cd00486 100644 --- a/src/game/scenes/mainmenu/menu_video_confirm.c +++ b/src/game/scenes/mainmenu/menu_video_confirm.c @@ -70,7 +70,7 @@ component *menu_video_confirm_create(scene *s, settings_video *old_settings) { text_defaults(&tconf); tconf.font = FONT_BIG; tconf.halign = TEXT_CENTER; - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *menu = menu_create(11); menu_attach(menu, label_create(&tconf, "ACCEPT RESOLUTION?")); diff --git a/src/game/scenes/mechlab.c b/src/game/scenes/mechlab.c index 5c5d5e75b..b1bc67dfd 100644 --- a/src/game/scenes/mechlab.c +++ b/src/game/scenes/mechlab.c @@ -455,7 +455,7 @@ int mechlab_create(scene *scene) { tconf.font = FONT_SMALL; tconf.halign = TEXT_CENTER; tconf.valign = TEXT_MIDDLE; - tconf.cforeground = color_create(255, 255, 0, 255); + tconf.cforeground = TEXT_DARK_GREEN; local->hint = label_create(&tconf, "HINTY"); component_set_pos_hints(local->hint, 32, 131); @@ -480,9 +480,5 @@ int mechlab_create(scene *scene) { scene_set_free_cb(scene, mechlab_free); scene_set_dynamic_tick_cb(scene, mechlab_tick); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - return 0; } diff --git a/src/game/scenes/mechlab/lab_dash_main.c b/src/game/scenes/mechlab/lab_dash_main.c index e5975aed8..6618f2436 100644 --- a/src/game/scenes/mechlab/lab_dash_main.c +++ b/src/game/scenes/mechlab/lab_dash_main.c @@ -165,18 +165,18 @@ component *lab_dash_main_create(scene *s, dashboard_widgets *dw) { text_settings tconf_dark; text_defaults(&tconf_dark); tconf_dark.font = FONT_SMALL; - tconf_dark.cforeground = color_create(0, 200, 0, 255); + tconf_dark.cforeground = TEXT_DARK_GREEN; text_settings tconf_light; text_defaults(&tconf_light); tconf_light.font = FONT_SMALL; - tconf_light.cforeground = color_create(50, 240, 50, 255); + tconf_light.cforeground = TEXT_BLINKY_GREEN; text_settings tconf_light_centered; text_defaults(&tconf_light_centered); tconf_light_centered.font = FONT_SMALL; tconf_light_centered.halign = TEXT_CENTER; - tconf_light_centered.cforeground = color_create(50, 240, 50, 255); + tconf_light_centered.cforeground = TEXT_BLINKY_GREEN; // Pilot image dw->photo = pilotpic_create(PIC_PLAYERS, 0); diff --git a/src/game/scenes/mechlab/lab_dash_newplayer.c b/src/game/scenes/mechlab/lab_dash_newplayer.c index 1d4e1ae76..395531ce7 100644 --- a/src/game/scenes/mechlab/lab_dash_newplayer.c +++ b/src/game/scenes/mechlab/lab_dash_newplayer.c @@ -14,7 +14,7 @@ component *lab_dash_newplayer_create(scene *s, newplayer_widgets *nw) { text_defaults(&tconf); tconf.font = FONT_SMALL; tconf.halign = TEXT_CENTER; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Background name box animation *main_sheets = &bk_get_info(&s->bk_data, 1)->ani; @@ -25,7 +25,7 @@ component *lab_dash_newplayer_create(scene *s, newplayer_widgets *nw) { xysizer_attach(xy, label_create(&tconf, lang_get(192)), 110, 43, 100, 50); // Input field - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; nw->input = textinput_create(&tconf, "Name", ""); component_select(nw->input, 1); textinput_enable_background(nw->input, 0); diff --git a/src/game/scenes/mechlab/lab_dash_trnselect.c b/src/game/scenes/mechlab/lab_dash_trnselect.c index d20527fa9..11616ab44 100644 --- a/src/game/scenes/mechlab/lab_dash_trnselect.c +++ b/src/game/scenes/mechlab/lab_dash_trnselect.c @@ -32,7 +32,7 @@ component *lab_dash_trnselect_create(scene *s, trnselect_widgets *tw) { text_defaults(&tconf); tconf.font = FONT_SMALL; tconf.halign = TEXT_CENTER; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Pilot image tw->trnselect = trnselect_create(); diff --git a/src/game/scenes/mechlab/lab_menu_confirm.c b/src/game/scenes/mechlab/lab_menu_confirm.c index 5cb73650f..802761fce 100644 --- a/src/game/scenes/mechlab/lab_menu_confirm.c +++ b/src/game/scenes/mechlab/lab_menu_confirm.c @@ -39,7 +39,7 @@ component *lab_menu_confirm_create(scene *s, lab_menu_select_cb yes, void *yesda text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; tconf.valign = TEXT_MIDDLE; tconf.halign = TEXT_CENTER; @@ -73,7 +73,7 @@ component *lab_menu_confirm_create(scene *s, lab_menu_select_cb yes, void *yesda trnmenu_attach(menu, button); // Add text label - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *label = label_create(&tconf, title); component_set_pos_hints(label, 10, 155); component_set_size_hints(label, 300, 10); diff --git a/src/game/scenes/mechlab/lab_menu_customize.c b/src/game/scenes/mechlab/lab_menu_customize.c index 6ae07810c..adb0af756 100644 --- a/src/game/scenes/mechlab/lab_menu_customize.c +++ b/src/game/scenes/mechlab/lab_menu_customize.c @@ -28,77 +28,77 @@ static uint32_t har_prices[11] = {20000, 36000, 26000, 28000, 29000, 32000, 2500 // negative values means the upgrade is unavailable at that level int32_t arm_leg_prices[11][10] = { - // jaguar + // jaguar {0, 760, 2280, 5320, 9120, 13680, 22800, 38000, 57000, -1 }, - // shadow + // shadow {0, 800, 2400, 5600, 9600, 14400, 24000, 40000, 60000, 96000 }, - // thorn + // thorn {0, 700, 2100, 4900, 8400, 12600, 21000, 35000, 52500, 84000 }, - // pyros + // pyros {0, 800, 2400, 5600, 9600, 14400, 24000, 40000, 60000, -1 }, - // electra + // electra {0, 1000, 3000, 7000, 12000, 18000, 30000, 50000, 75000, 120000}, - // katana + // katana {0, 660, 1980, 4620, 7920, 11880, 19800, 3300, 49500, -1 }, - // shredder + // shredder {0, 840, 2520, 5880, 10080, 15120, 25200, 42000, 63000, -1 }, - // flail + // flail {0, 740, 2220, 5180, 8880, 13320, 22200, 37000, -1, -1 }, - // gargoyle + // gargoyle {0, 900, 2700, 6300, 10800, 16200, 27000, 45000, 67500, 108000}, - // chronos + // chronos {0, 720, 2160, 5040, 8640, 12960, 21600, 36000, -1, -1 }, - // nova + // nova {0, 1400, 4200, 9800, 16800, 25200, 42000, 70000, -1, -1 } }; int32_t stun_resistance_prices[11][10] = { - // jaguar + // jaguar {0, 1140, 3420, 7980, 13680, 20520, 34200, 57000, 85500, -1}, - // shadow + // shadow {0, 1200, 3600, 8400, 14400, 21600, 36000, -1, -1, -1}, - // thorn + // thorn {0, 1050, 3150, 7350, 12600, 18900, 31500, 52500, 78750, -1}, - // pyros + // pyros {0, 1200, 3600, 8400, 14400, 21600, 36000, -1, -1, -1}, - // electra + // electra {0, 1500, 4500, 10500, 18000, 27000, 45000, 75000, -1, -1}, - // katana + // katana {0, 990, 2970, 6930, 11880, 17820, 29700, -1, -1, -1}, - // shredder + // shredder {0, 1260, 3780, 8820, 15120, 22680, 37800, -1, -1, -1}, - // flail + // flail {0, 1110, 3330, 7770, 13320, 19980, 33300, 55500, -1, -1}, - // gargoyle + // gargoyle {0, 1350, 4050, 9450, 16200, 24300, 40500, 67500, -1, -1}, - // chronos + // chronos {0, 1080, 3240, 7560, 12960, 19440, 32400, 54000, -1, -1}, - // nova + // nova {0, 2100, 6300, 14700, 25200, 37800, 63000, -1, -1, -1} }; int32_t armor_prices[][10] = { - // jaguar + // jaguar {0, 1900, 5700, 13300, 22800, 34200, -1, -1, -1, -1 }, - // shadow + // shadow {0, 2000, 6000, 14000, 24000, 36000, 60000, 100000, -1, -1 }, - // thorn + // thorn {0, 1750, 5250, 12250, 21000, 31500, 52500, 87500, -1, -1 }, - // pyros + // pyros {0, 2000, 6000, 14000, 24000, 36000, 60000, 100000, 150000, -1 }, - // electra + // electra {0, 2500, 7500, 17500, 30000, 45000, 75000, -1, -1, -1 }, - // katana + // katana {0, 1650, 4950, 11550, 19800, 29700, 49500, 82500, 123750, -1 }, - // shredder + // shredder {0, 2100, 6300, 14700, 25200, 37800, 63000, -1, -1, -1 }, - // flail + // flail {0, 1850, 5550, 12950, 22200, 33300, 55500, 92500, 138750, 222000}, - // gargoyle + // gargoyle {0, 2250, 6750, 15750, 27000, 40500, 67500, -1, -1, -1 }, - // chronos + // chronos {0, 1800, 5400, 12600, 21600, 32400, 54000, -1, -1, -1 }, - // nova + // nova {0, 3500, 10500, 24500, 42000, 63000, 105000, 175000, -1, -1 } }; @@ -739,7 +739,7 @@ component *lab_menu_customize_create(scene *s) { text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Init GUI buttons with locations from the "select" button sprites for(int i = 0; i < animation_get_sprite_count(main_buttons); i++) { @@ -777,13 +777,13 @@ component *lab_menu_customize_create(scene *s) { tconf.halign = TEXT_LEFT; tconf.valign = TEXT_TOP; tconf.lspacing = 2; - tconf.cforeground = color_create(0, 200, 0, 255); + tconf.cforeground = 0xA5; label1 = label_create(&tconf, ""); component_set_size_hints(label1, 90, 80); component_set_pos_hints(label1, 210, 150); trnmenu_attach(menu, label1); - tconf.cforeground = color_create(0, 255, 0, 255); + tconf.cforeground = 0xA7; label2 = label_create(&tconf, ""); component_set_size_hints(label2, 90, 80); component_set_pos_hints(label2, 210, 158); diff --git a/src/game/scenes/mechlab/lab_menu_difficultyselect.c b/src/game/scenes/mechlab/lab_menu_difficultyselect.c index 664e23385..5a055c82e 100644 --- a/src/game/scenes/mechlab/lab_menu_difficultyselect.c +++ b/src/game/scenes/mechlab/lab_menu_difficultyselect.c @@ -64,7 +64,7 @@ component *lab_menu_difficultyselect_create(scene *s) { text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Init GUI buttons with locations from the "select" button sprites for(int i = 0; i < animation_get_sprite_count(main_buttons); i++) { @@ -85,7 +85,7 @@ component *lab_menu_difficultyselect_create(scene *s) { } // Add text label - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; component *label = label_create(&tconf, "SELECT A DIFFICULTY LEVEL"); component_set_pos_hints(label, 87, 155); component_set_size_hints(label, 150, 10); diff --git a/src/game/scenes/mechlab/lab_menu_main.c b/src/game/scenes/mechlab/lab_menu_main.c index 379124cae..42202d2ca 100644 --- a/src/game/scenes/mechlab/lab_menu_main.c +++ b/src/game/scenes/mechlab/lab_menu_main.c @@ -111,7 +111,7 @@ void lab_menu_main_delete(component *c, void *userdata) { } static const button_details details_list[] = { - // CB, Text, Text align, Halign, Valigh, Pad top, Pad bottom, Pad left, Pad right, Disable by default + // CB, Text, Text align, Halign, Valigh, Pad top, Pad bottom, Pad left, Pad right, Disable by default {lab_menu_main_arena, "ARENA", TEXT_HORIZONTAL, TEXT_CENTER, TEXT_TOP, 2, 0, 0, 0, COM_DISABLED}, {lab_menu_main_training_enter, "TRAINING COURSES", TEXT_HORIZONTAL, TEXT_CENTER, TEXT_MIDDLE, 0, 0, 28, 0, COM_DISABLED }, @@ -243,7 +243,7 @@ component *lab_menu_main_create(scene *s, bool character_loaded) { text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Init GUI buttons with locations from the "select" button sprites for(int i = 0; i < animation_get_sprite_count(main_buttons); i++) { diff --git a/src/game/scenes/mechlab/lab_menu_select.c b/src/game/scenes/mechlab/lab_menu_select.c index 2e1f125fd..454acb7d4 100644 --- a/src/game/scenes/mechlab/lab_menu_select.c +++ b/src/game/scenes/mechlab/lab_menu_select.c @@ -43,7 +43,7 @@ component *lab_menu_select_create(scene *s, lab_menu_select_cb select, void *sel text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; lab_menu_select_t *selector = omf_calloc(1, sizeof(lab_menu_select_t)); selector->cb = select; @@ -88,7 +88,7 @@ component *lab_menu_select_create(scene *s, lab_menu_select_cb select, void *sel // TODO the left-right buttons apply on focus, not select // Add text label - tconf.cforeground = COLOR_DARK_GREEN; + tconf.cforeground = TEXT_MEDIUM_GREEN; // TODO interpolate %s in the string here with blank component *label = label_create(&tconf, lang_get(title)); component_set_pos_hints(label, 87, 155); diff --git a/src/game/scenes/mechlab/lab_menu_trade.c b/src/game/scenes/mechlab/lab_menu_trade.c index 75fa1fa85..a47746b29 100644 --- a/src/game/scenes/mechlab/lab_menu_trade.c +++ b/src/game/scenes/mechlab/lab_menu_trade.c @@ -237,7 +237,7 @@ component *lab_menu_trade_create(scene *s) { text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Init GUI buttons with locations from the "select" button sprites for(int i = 0; i < animation_get_sprite_count(main_buttons); i++) { diff --git a/src/game/scenes/mechlab/lab_menu_training.c b/src/game/scenes/mechlab/lab_menu_training.c index ae724899a..cfa4735a5 100644 --- a/src/game/scenes/mechlab/lab_menu_training.c +++ b/src/game/scenes/mechlab/lab_menu_training.c @@ -177,7 +177,7 @@ component *lab_menu_training_create(scene *s) { text_settings tconf; text_defaults(&tconf); tconf.font = FONT_SMALL; - tconf.cforeground = color_create(0, 0, 123, 255); + tconf.cforeground = TEXT_TRN_BLUE; // Init GUI buttons with locations from the "select" button sprites for(int i = 0; i < animation_get_sprite_count(main_buttons); i++) { @@ -212,13 +212,13 @@ component *lab_menu_training_create(scene *s) { tconf.direction = TEXT_HORIZONTAL; tconf.halign = TEXT_LEFT; tconf.valign = TEXT_TOP; - tconf.cforeground = color_create(0, 200, 0, 255); + tconf.cforeground = 0xA5; label1 = label_create(&tconf, ""); component_set_size_hints(label1, 90, 110); component_set_pos_hints(label1, 200, 148); trnmenu_attach(menu, label1); - tconf.cforeground = color_create(0, 255, 0, 255); + tconf.cforeground = 0xA7; label2 = label_create(&tconf, ""); component_set_size_hints(label2, 90, 110); component_set_pos_hints(label2, 200, 186); diff --git a/src/game/scenes/melee.c b/src/game/scenes/melee.c index 0037d8e61..e30cfd260 100644 --- a/src/game/scenes/melee.c +++ b/src/game/scenes/melee.c @@ -20,22 +20,50 @@ #include "video/video.h" #define MAX_STAT 20 - -typedef struct melee_local_t { - int selection; // 0 for player, 1 for HAR - int row_a, row_b; // 0 or 1 - int column_a, column_b; // 0-4 - int done_a, done_b; // 0-1 - - object bigportrait1; - object bigportrait2; +#define TEXT_GREEN 0xA6 +#define RED_CURSOR_INDEX 0xF6 +#define BLUE_CURSOR_INDEX 0xF7 +#define VIOLET_CURSOR_INDEX 0xF8 + +typedef struct { + int x; + int y; + int disabled_offset; + surface enabled; + surface disabled; +} portrait; + +typedef struct { + int row; + int column; + bool done; +} cursor_data; + +#define CURSOR_INDEX(local, player) (5 * local->cursor[player].row + local->cursor[player].column) +#define CURSOR_A_DONE(local) (local->cursor[0].done) +#define CURSOR_B_DONE(local) (local->cursor[1].done) +#define CURSORS_MATCH(local) \ + (local->cursor[0].column == local->cursor[1].column && local->cursor[0].row == local->cursor[1].row) +#define CURSORS_DONE(local) (local->cursor[0].done && local->cursor[1].done) +#define CURSOR_NOVA_SELECT(local, player) (local->cursor[player].row == 1 && local->cursor[player].column == 2) + +typedef enum +{ + PILOT_SELECT = 0, + HAR_SELECT = 1 +} selection_page; + +typedef struct { + cursor_data cursor[2]; + selection_page page; + + object big_portrait_1; + object big_portrait_2; object player2_placeholder; object unselected_har_portraits; - object pilots[10]; - - object harportraits_player1[10]; - object harportraits_player2[10]; + portrait pilot_portraits[10]; + portrait har_portraits[10]; object har_player1[10]; object har_player2[10]; @@ -47,15 +75,11 @@ typedef struct melee_local_t { int pilot_id_a; int pilot_id_b; - surface feh; - surface bleh; + surface bg_player_stats; + surface bg_player_bio; surface select_hilight; - unsigned int ticks; - unsigned int hartick; - unsigned int pulsedir; - object *harplayer_a; - object *harplayer_b; + unsigned int ticks; // nova selection cheat unsigned char har_selected[2][10]; @@ -64,30 +88,12 @@ typedef struct melee_local_t { void handle_action(scene *scene, int player, int action); -void mask_sprite(surface *vga, int x, int y, int w, int h) { - for(int i = 0; i < vga->h; i++) { - for(int j = 0; j < vga->w; j++) { - int offset = (i * vga->w) + j; - if((i < y || i > y + h) || (j < x || j > x + w)) { - vga->stencil[offset] = 0; - } else { - if(vga->data[offset] == -48) { - // strip out the black pixels - vga->stencil[offset] = 0; - } else { - vga->stencil[offset] = 1; - } - } - } - } -} - void melee_free(scene *scene) { melee_local *local = scene_get_userdata(scene); game_player *player2 = game_state_get_player(scene->gs, 1); - surface_free(&local->feh); - surface_free(&local->bleh); + surface_free(&local->bg_player_stats); + surface_free(&local->bg_player_bio); surface_free(&local->select_hilight); for(int i = 0; i < 2; i++) { component_free(local->bar_power[i]); @@ -96,25 +102,39 @@ void melee_free(scene *scene) { } for(int i = 0; i < 10; i++) { - object_free(&local->pilots[i]); - object_free(&local->harportraits_player1[i]); + surface_free(&local->har_portraits[i].enabled); + surface_free(&local->har_portraits[i].disabled); object_free(&local->har_player1[i]); if(player2->selectable) { - object_free(&local->harportraits_player2[i]); object_free(&local->har_player2[i]); } } object_free(&local->player2_placeholder); object_free(&local->unselected_har_portraits); - object_free(&local->bigportrait1); + object_free(&local->big_portrait_1); if(player2->selectable) { - object_free(&local->bigportrait2); + object_free(&local->big_portrait_2); } omf_free(local); scene_set_userdata(scene, local); } +static void set_cursor_colors(int offset) { + palette *pal = video_get_base_palette(); + int base = 120; + pal->data[RED_CURSOR_INDEX][0] = base + offset; + pal->data[RED_CURSOR_INDEX][1] = 0; + pal->data[RED_CURSOR_INDEX][2] = 0; + pal->data[BLUE_CURSOR_INDEX][0] = 0; + pal->data[BLUE_CURSOR_INDEX][1] = 0; + pal->data[BLUE_CURSOR_INDEX][2] = base + offset; + pal->data[VIOLET_CURSOR_INDEX][0] = base + offset; + pal->data[VIOLET_CURSOR_INDEX][1] = 0; + pal->data[VIOLET_CURSOR_INDEX][2] = base + offset; + video_force_pal_refresh(); +} + void melee_tick(scene *scene, int paused) { melee_local *local = scene_get_userdata(scene); game_player *player1 = game_state_get_player(scene->gs, 0); @@ -145,34 +165,24 @@ void melee_tick(scene *scene, int paused) { } while((i = i->next)); } - if(!local->pulsedir) { - local->ticks++; - } else { - local->ticks--; - } - if(local->ticks > 120) { - local->pulsedir = 1; - } - if(local->ticks == 0) { - local->pulsedir = 0; - } - local->hartick++; - if(local->selection == 1 && local->hartick > 10) { - local->hartick = 0; - object_dynamic_tick(&local->har_player1[5 * local->row_a + local->column_a]); + if(local->page == HAR_SELECT && local->ticks % 10 == 1) { + object_dynamic_tick(&local->har_player1[CURSOR_INDEX(local, 0)]); if(player2->selectable) { - object_dynamic_tick(&local->har_player2[5 * local->row_b + local->column_b]); + object_dynamic_tick(&local->har_player2[CURSOR_INDEX(local, 1)]); } } + + // Tick cursor colors + local->ticks++; + double rate = ((double)local->ticks) / 25.0; + int num = round((sin(rate) + 1.0) * 64); + set_cursor_colors(num); } void refresh_pilot_stats(melee_local *local) { - int current_a = 5 * local->row_a + local->column_a; - int current_b = 5 * local->row_b + local->column_b; pilot p_a, p_b; - - pilot_get_info(&p_a, current_a); - pilot_get_info(&p_b, current_b); + pilot_get_info(&p_a, CURSOR_INDEX(local, 0)); + pilot_get_info(&p_b, CURSOR_INDEX(local, 1)); progressbar_set_progress(local->bar_power[0], (p_a.power * 100) / MAX_STAT); progressbar_set_progress(local->bar_agility[0], (p_a.agility * 100) / MAX_STAT); progressbar_set_progress(local->bar_endurance[0], (p_a.endurance * 100) / MAX_STAT); @@ -185,16 +195,9 @@ void handle_action(scene *scene, int player, int action) { game_player *player1 = game_state_get_player(scene->gs, 0); game_player *player2 = game_state_get_player(scene->gs, 1); melee_local *local = scene_get_userdata(scene); - int *row, *column, *done; - if(player == 1) { - row = &local->row_a; - column = &local->column_a; - done = &local->done_a; - } else { - row = &local->row_b; - column = &local->column_b; - done = &local->done_b; - } + int *row = &local->cursor[player - 1].row; + int *column = &local->cursor[player - 1].column; + bool *done = &local->cursor[player - 1].done; if(*done) { return; @@ -238,19 +241,19 @@ void handle_action(scene *scene, int player, int action) { case ACT_PUNCH: *done = 1; audio_play_sound(20, 0.5f, 0.0f, 2.0f); - if(local->done_a && (local->done_b || !player2->selectable)) { - local->done_a = 0; - local->done_b = 0; - if(local->selection == 0) { - local->selection = 1; - local->pilot_id_a = 5 * local->row_a + local->column_a; - local->pilot_id_b = 5 * local->row_b + local->column_b; + if(CURSOR_A_DONE(local) && (CURSOR_B_DONE(local) || !player2->selectable)) { + local->cursor[0].done = 0; + local->cursor[1].done = 0; + if(local->page == PILOT_SELECT) { + local->page = HAR_SELECT; + local->pilot_id_a = CURSOR_INDEX(local, 0); + local->pilot_id_b = CURSOR_INDEX(local, 1); // nova selection cheat local->har_selected[0][local->pilot_id_a] = 1; local->har_selected[1][local->pilot_id_b] = 1; - object_select_sprite(&local->bigportrait1, local->pilot_id_a); + object_select_sprite(&local->big_portrait_1, local->pilot_id_a); // update the player palette palette *base_pal = video_get_base_palette(); pilot p_a; @@ -265,7 +268,7 @@ void handle_action(scene *scene, int player, int action) { palette_load_player_colors(base_pal, &player1->pilot->palette, 0); if(player2->selectable) { - object_select_sprite(&local->bigportrait2, local->pilot_id_b); + object_select_sprite(&local->big_portrait_2, local->pilot_id_b); // update the player palette pilot_get_info(&p_a, local->pilot_id_b); player2->pilot->endurance = p_a.endurance; @@ -291,17 +294,17 @@ void handle_action(scene *scene, int player, int action) { nova_activated[i] = 0; } } - if(nova_activated[0] && local->row_a == 1 && local->column_a == 2) { + if(nova_activated[0] && CURSOR_NOVA_SELECT(local, 0)) { player1->pilot->har_id = HAR_NOVA; } else { - player1->pilot->har_id = 5 * local->row_a + local->column_a; + player1->pilot->har_id = CURSOR_INDEX(local, 0); } player1->pilot->pilot_id = local->pilot_id_a; if(player2->selectable) { - if(nova_activated[1] && local->row_b == 1 && local->column_b == 2) { + if(nova_activated[1] && CURSOR_NOVA_SELECT(local, 1)) { player2->pilot->har_id = HAR_NOVA; } else { - player2->pilot->har_id = 5 * local->row_b + local->column_b; + player2->pilot->har_id = CURSOR_INDEX(local, 1); } player2->pilot->pilot_id = local->pilot_id_b; } else { @@ -337,15 +340,15 @@ void handle_action(scene *scene, int player, int action) { break; } - if(local->selection == 0) { - object_select_sprite(&local->bigportrait1, 5 * local->row_a + local->column_a); + if(local->page == PILOT_SELECT) { + object_select_sprite(&local->big_portrait_1, CURSOR_INDEX(local, 0)); if(player2->selectable) { - object_select_sprite(&local->bigportrait2, 5 * local->row_b + local->column_b); + object_select_sprite(&local->big_portrait_2, CURSOR_INDEX(local, 1)); } } // nova selection cheat - if(local->selection == 1) { + if(local->page == HAR_SELECT) { local->har_selected[player - 1][5 * (*row) + *column] = 1; } @@ -365,16 +368,15 @@ void melee_input_tick(scene *scene) { if(i->type == EVENT_TYPE_ACTION) { if(i->event_data.action == ACT_ESC) { audio_play_sound(20, 0.5f, 0.0f, 2.0f); - if(local->selection == 1) { + if(local->page == HAR_SELECT) { // restore the player selection - local->column_a = local->pilot_id_a % 5; - local->row_a = local->pilot_id_a / 5; - local->column_b = local->pilot_id_b % 5; - local->row_b = local->pilot_id_b / 5; - - local->selection = 0; - local->done_a = 0; - local->done_b = 0; + local->cursor[0].column = local->pilot_id_a % 5; + local->cursor[0].row = local->pilot_id_a / 5; + local->cursor[0].done = 0; + local->cursor[1].column = local->pilot_id_b % 5; + local->cursor[1].row = local->pilot_id_b / 5; + local->cursor[1].done = 0; + local->page = PILOT_SELECT; } else { game_state_set_next(scene->gs, SCENE_MENU); } @@ -400,167 +402,249 @@ void melee_input_tick(scene *scene) { controller_free_chain(p2); } -void render_highlights(scene *scene) { - melee_local *local = scene_get_userdata(scene); - game_player *player2 = game_state_get_player(scene->gs, 1); - int trans; - if(player2->selectable && local->row_a == local->row_b && local->column_a == local->column_b) { - video_render_sprite_tint(&local->select_hilight, 11 + (62 * local->column_a), 115 + (42 * local->row_a), - color_create(250 - local->ticks, 0, 250 - local->ticks, 0), 0); +static void draw_highlight(const melee_local *local, const cursor_data *cursor, int offset) { + int x = 11 + (62 * cursor->column); + int y = 115 + (42 * cursor->row); + video_draw_offset(&local->select_hilight, x, y, offset, 255); +} + +static void render_highlights(const melee_local *local, bool player2_is_selectable) { + if(player2_is_selectable && CURSORS_MATCH(local)) { + draw_highlight(local, &local->cursor[0], VIOLET_CURSOR_INDEX); } else { - if(player2->selectable) { - if(local->done_b) { - trans = 250; - } else { - trans = 250 - local->ticks; - } - video_render_sprite_tint(&local->select_hilight, 11 + (62 * local->column_b), 115 + (42 * local->row_b), - color_create(0, 0, trans, 0), 0); + if(player2_is_selectable) { + draw_highlight(local, &local->cursor[1], BLUE_CURSOR_INDEX); } - if(local->done_a) { - trans = 250; - } else { - trans = 250 - local->ticks; - } - video_render_sprite_tint(&local->select_hilight, 11 + (62 * local->column_a), 115 + (42 * local->row_a), - color_create(trans, 0, 0, 0), 0); + draw_highlight(local, &local->cursor[0], RED_CURSOR_INDEX); } } -void melee_render(scene *scene) { - melee_local *local = scene_get_userdata(scene); - game_player *player2 = game_state_get_player(scene->gs, 1); - int current_a = 5 * local->row_a + local->column_a; - int current_b = 5 * local->row_b + local->column_b; +static void render_disabled_portraits(const portrait *portraits) { + for(int i = 0; i < 10; i++) { + const portrait *p = &portraits[i]; + video_draw_offset(&p->disabled, p->x, p->y, p->disabled_offset, 255); + } +} + +static void render_enabled_portrait(const portrait *portraits, cursor_data *cursor) { + const portrait *p = &portraits[5 * cursor->row + cursor->column]; + video_draw(&p->enabled, p->x, p->y); +} - if(local->selection == 0) { - video_render_sprite(&local->feh, 70, 0, BLEND_ALPHA, 0); - video_render_sprite(&local->bleh, 0, 62, BLEND_ALPHA, 0); +static void render_pilot_select(melee_local *local, bool player2_is_selectable) { + int current_a = CURSOR_INDEX(local, 0); + int current_b = CURSOR_INDEX(local, 1); + video_draw(&local->bg_player_stats, 70, 0); + video_draw(&local->bg_player_bio, 0, 62); + + // player bio + font_render_wrapped_shadowed(&font_small, lang_get(135 + current_a), 4, 66, 152, TEXT_GREEN, + TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); + // player stats + font_render_shadowed(&font_small, lang_get(216), 74 + 27, 4, TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); + font_render_shadowed(&font_small, lang_get(217), 74 + 19, 22, TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); + font_render_shadowed(&font_small, lang_get(218), 74 + 12, 40, TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); + component_render(local->bar_power[0]); + component_render(local->bar_agility[0]); + component_render(local->bar_endurance[0]); + + if(player2_is_selectable) { + video_draw(&local->bg_player_stats, 320 - 70 - local->bg_player_stats.w, 0); + video_draw(&local->bg_player_bio, 320 - local->bg_player_bio.w, 62); // player bio - font_render_wrapped_shadowed(&font_small, lang_get(135 + current_a), 4, 66, 152, COLOR_GREEN, - TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); + font_render_wrapped_shadowed(&font_small, lang_get(135 + current_b), 320 - local->bg_player_bio.w + 4, 66, 152, + TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); // player stats - font_render_shadowed(&font_small, lang_get(216), 74 + 27, 4, COLOR_GREEN, + font_render_shadowed(&font_small, lang_get(216), 320 - 66 - local->bg_player_stats.w + 27, 4, TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - font_render_shadowed(&font_small, lang_get(217), 74 + 19, 22, COLOR_GREEN, + font_render_shadowed(&font_small, lang_get(217), 320 - 66 - local->bg_player_stats.w + 19, 22, TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - font_render_shadowed(&font_small, lang_get(218), 74 + 12, 40, COLOR_GREEN, + font_render_shadowed(&font_small, lang_get(218), 320 - 66 - local->bg_player_stats.w + 12, 40, TEXT_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - component_render(local->bar_power[0]); - component_render(local->bar_agility[0]); - component_render(local->bar_endurance[0]); - - if(player2->selectable) { - video_render_sprite(&local->feh, 320 - 70 - local->feh.w, 0, BLEND_ALPHA, 0); - video_render_sprite(&local->bleh, 320 - local->bleh.w, 62, BLEND_ALPHA, 0); - // player bio - font_render_wrapped_shadowed(&font_small, lang_get(135 + current_b), 320 - local->bleh.w + 4, 66, 152, - COLOR_GREEN, TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - // player stats - font_render_shadowed(&font_small, lang_get(216), 320 - 66 - local->feh.w + 27, 4, COLOR_GREEN, - TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - font_render_shadowed(&font_small, lang_get(217), 320 - 66 - local->feh.w + 19, 22, COLOR_GREEN, - TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - font_render_shadowed(&font_small, lang_get(218), 320 - 66 - local->feh.w + 12, 40, COLOR_GREEN, - TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - component_render(local->bar_power[1]); - component_render(local->bar_agility[1]); - component_render(local->bar_endurance[1]); - } else { - // 'choose your pilot' - font_render_wrapped_shadowed(&font_small, lang_get(187), 160, 97, 160, COLOR_GREEN, - TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - } + component_render(local->bar_power[1]); + component_render(local->bar_agility[1]); + component_render(local->bar_endurance[1]); + } else { + // 'choose your pilot' + font_render_wrapped_shadowed(&font_small, lang_get(187), 160, 97, 160, TEXT_GREEN, + TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); } object_render(&local->player2_placeholder); - if(local->selection == 0) { - // player 1 name - font_render_wrapped_shadowed(&font_small, lang_get(20 + current_a), 0, 52, 66, COLOR_BLACK, + // player 1 name + font_render_wrapped_shadowed(&font_small, lang_get(20 + current_a), 0, 52, 66, TEXT_BLACK, + TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + + if(player2_is_selectable) { + // player 2 name + font_render_wrapped_shadowed(&font_small, lang_get(20 + current_b), 320 - 66, 52, 66, TEXT_BLACK, TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + } - if(player2->selectable) { - // player 2 name - font_render_wrapped_shadowed(&font_small, lang_get(20 + current_b), 320 - 66, 52, 66, COLOR_BLACK, - TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); - } + render_highlights(local, player2_is_selectable); + render_disabled_portraits(local->pilot_portraits); + render_enabled_portrait(local->pilot_portraits, &local->cursor[0]); + object_render(&local->big_portrait_1); + if(player2_is_selectable) { + render_enabled_portrait(local->pilot_portraits, &local->cursor[0]); + object_render(&local->big_portrait_2); + } +} - render_highlights(scene); - for(int i = 0; i < 10; i++) { - object_render(&local->pilots[i]); - } - object_render(&local->bigportrait1); - if(player2->selectable) { - object_render(&local->bigportrait2); - } - } else { - // render the stupid unselected HAR portraits before anything - // so we can render anything else on top of them - object_render(&local->unselected_har_portraits); - render_highlights(scene); +static void render_har_select(melee_local *local, bool player2_is_selectable) { + object_render(&local->player2_placeholder); + + // render the stupid unselected HAR portraits before anything + // so we can render anything else on top of them + render_highlights(local, player2_is_selectable); + render_disabled_portraits(local->har_portraits); + + // currently selected player + object_render(&local->big_portrait_1); + + // currently selected HAR + render_enabled_portrait(local->har_portraits, &local->cursor[0]); + object_render(&local->har_player1[CURSOR_INDEX(local, 0)]); + + // player 1 name + font_render_wrapped_shadowed(&font_small, lang_get(20 + local->pilot_id_a), 0, 52, 66, TEXT_BLACK, + TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + + if(player2_is_selectable) { + // player 2 name + font_render_wrapped_shadowed(&font_small, lang_get(20 + local->pilot_id_b), 320 - 66, 52, 66, TEXT_BLACK, + TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); // currently selected player - object_render(&local->bigportrait1); + object_render(&local->big_portrait_2); // currently selected HAR - object_render(&local->harportraits_player1[5 * local->row_a + local->column_a]); - object_render(&local->har_player1[5 * local->row_a + local->column_a]); + render_enabled_portrait(local->har_portraits, &local->cursor[1]); + object_render(&local->har_player2[CURSOR_INDEX(local, 1)]); + + // render HAR name (Har1 VS. Har2) + str vs_text; + str_from_format(&vs_text, "%s VS. %s", har_get_name(CURSOR_INDEX(local, 0)), + har_get_name(CURSOR_INDEX(local, 1))); + font_render_wrapped_shadowed(&font_small, str_c(&vs_text), 80, 107, 150, TEXT_BLACK, + TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + str_free(&vs_text); + } else { + // 'choose your HAR' + font_render_wrapped_shadowed(&font_small, lang_get(186), 160, 97, 160, TEXT_MEDIUM_GREEN, + TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - // player 1 name - font_render_wrapped_shadowed(&font_small, lang_get(20 + local->pilot_id_a), 0, 52, 66, COLOR_BLACK, + // render HAR name + font_render_wrapped_shadowed(&font_small, har_get_name(CURSOR_INDEX(local, 0)), 130, 107, 66, TEXT_BLACK, TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + } +} - if(player2->selectable) { - // player 2 name - font_render_wrapped_shadowed(&font_small, lang_get(20 + local->pilot_id_b), 320 - 66, 52, 66, COLOR_BLACK, - TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); - - // currently selected player - object_render(&local->bigportrait2); - - // currently selected HAR - object_render(&local->harportraits_player2[5 * local->row_b + local->column_b]); - object_render(&local->har_player2[5 * local->row_b + local->column_b]); - - // render HAR name (Har1 VS. Har2) - str vstext; - str_from_format(&vstext, "%s VS. %s", har_get_name(5 * local->row_a + local->column_a), - har_get_name(5 * local->row_b + local->column_b)); - font_render_wrapped_shadowed(&font_small, str_c(&vstext), 80, 107, 150, COLOR_BLACK, - TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); - str_free(&vstext); - } else { - // 'choose your HAR' - font_render_wrapped_shadowed(&font_small, lang_get(186), 160, 97, 160, COLOR_GREEN, - TEXT_SHADOW_RIGHT | TEXT_SHADOW_BOTTOM); - - // render HAR name - font_render_wrapped_shadowed(&font_small, har_get_name(5 * local->row_a + local->column_a), 130, 107, 66, - COLOR_BLACK, TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); - } +void melee_render(scene *scene) { + melee_local *local = scene_get_userdata(scene); + game_player *player2 = game_state_get_player(scene->gs, 1); + + if(local->page == PILOT_SELECT) { + render_pilot_select(local, player2->selectable); + } else { + render_har_select(local, player2->selectable); } if(player2->selectable) { + int text_x = 8; chr_score *s1 = game_player_get_score(game_state_get_player(scene->gs, 0)); chr_score *s2 = game_player_get_score(game_state_get_player(scene->gs, 1)); - char winstext[48]; - snprintf(winstext, 48, "Wins: %d", s1->wins); - font_render_shadowed(&font_small, winstext, 8, 107, COLOR_BLACK, TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); - snprintf(winstext, 48, "Wins: %d", s2->wins); - font_render_shadowed(&font_small, winstext, 312 - (strlen(winstext) * font_small.w), 107, COLOR_BLACK, + str wins_text_a, wins_text_b; + str_from_format(&wins_text_a, "Wins: %d", s1->wins); + str_from_format(&wins_text_b, "Wins: %d", s2->wins); + font_render_shadowed(&font_small, str_c(&wins_text_a), text_x, 107, TEXT_BLACK, + TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + text_x = 312 - str_size(&wins_text_b) * font_small.w; + font_render_shadowed(&font_small, str_c(&wins_text_a), text_x, 107, TEXT_BLACK, TEXT_SHADOW_TOP | TEXT_SHADOW_LEFT); + str_free(&wins_text_a); + str_free(&wins_text_b); } } -int melee_create(scene *scene) { - char bitmap[51 * 36 * 4]; +static void load_pilot_portraits(scene *scene, melee_local *local) { + sprite *current; + portrait *target; + animation *pilots_enabled = &bk_get_info(&scene->bk_data, 3)->ani; + for(int i = 0; i < 10; i++) { + target = &local->pilot_portraits[i]; + + // Copy the face image in full color (shown when selected) + current = animation_get_sprite(pilots_enabled, i); + target->x = current->pos.x; + target->y = current->pos.y; + surface_create_from(&target->enabled, current->data); + + // Copy the face image in dimmed color (shown when not selected) + surface_create_from(&target->disabled, &target->enabled); + surface_compress_index_blocks(&target->disabled, 0x60, 0xA0, 64, 16); + surface_compress_index_blocks(&target->disabled, 0xA0, 0xD0, 8, 3); + surface_compress_index_blocks(&target->disabled, 0xD0, 0xE0, 16, 3); + surface_compress_index_blocks(&target->disabled, 0xE0, 0xF0, 8, 2); + surface_compress_remap(&target->disabled, 0xF0, 0xF7, 0xB6, 3); + } +} + +static void load_har_portraits(scene *scene, melee_local *local) { + sprite *current; + portrait *target; + int row, col; + animation *har_portraits = &bk_get_info(&scene->bk_data, 1)->ani; + for(int i = 0; i < 10; i++) { + row = i / 5; + col = i % 5; + target = &local->har_portraits[i]; + + // Copy the HAR image in full color (shown when selected) + current = animation_get_sprite(har_portraits, 0); + target->x = current->pos.x + 62 * col; + target->y = current->pos.y + 42 * row; + surface_create_from_surface(&target->enabled, 51, 36, 62 * col, 42 * row, current->data); + surface_generate_stencil(&target->enabled, 0xD0); + + // Copy the enabled image, and compress the colors to grayscale + surface_create_from(&target->disabled, &target->enabled); + surface_convert_to_grayscale(&target->disabled, video_get_pal_ref(), 0xD0, 0xDF); + } +} + +static void load_hars(scene *scene, melee_local *local, bool player2_is_selectable) { + animation *ani; + for(int i = 0; i < 10; i++) { + ani = &bk_get_info(&scene->bk_data, 18 + i)->ani; + object_create(&local->har_player1[i], scene->gs, vec2i_create(110, 95), vec2f_create(0, 0)); + object_set_animation(&local->har_player1[i], ani); + object_select_sprite(&local->har_player1[i], 0); + object_set_repeat(&local->har_player1[i], 1); + + if(player2_is_selectable) { + ani = &bk_get_info(&scene->bk_data, 18 + i)->ani; + object_create(&local->har_player2[i], scene->gs, vec2i_create(210, 95), vec2f_create(0, 0)); + object_set_animation(&local->har_player2[i], ani); + object_select_sprite(&local->har_player2[i], 0); + object_set_repeat(&local->har_player2[i], 1); + object_set_direction(&local->har_player2[i], OBJECT_FACE_LEFT); + object_set_pal_offset(&local->har_player2[i], 48); + object_set_pal_limit(&local->har_player2[i], 96); + } + } +} +int melee_create(scene *scene) { // Init local data melee_local *local = omf_calloc(1, sizeof(melee_local)); scene_set_userdata(scene, local); + local->cursor[1].row = 0; + local->cursor[1].column = 4; + game_player *player1 = game_state_get_player(scene->gs, 0); game_player *player2 = game_state_get_player(scene->gs, 1); @@ -573,20 +657,13 @@ int melee_create(scene *scene) { palette_set_player_color(mpal, 0, 8, 2); video_force_pal_refresh(); - memset(&bitmap, 255, 51 * 36 * 4); - local->ticks = 0; - local->pulsedir = 0; - local->selection = 0; - local->row_a = 0; - local->column_a = 0; - local->row_b = 0; - local->column_b = 4; - local->done_a = 0; - local->done_b = 0; - - menu_background2_create(&local->feh, 90, 61); - menu_background2_create(&local->bleh, 160, 43); - surface_create_from_data(&local->select_hilight, SURFACE_TYPE_RGBA, 51, 36, bitmap); + menu_background2_create(&local->bg_player_stats, 90, 61); + menu_background2_create(&local->bg_player_bio, 160, 43); + + // Create a black surface for the highlight box. We modify the palette in renderer. + unsigned char *black = omf_calloc(1, 51 * 36); + surface_create_from_data(&local->select_hilight, 51, 36, black); + omf_free(black); // set up the magic controller hooks if(player1_ctrl && player2_ctrl) { @@ -599,78 +676,33 @@ int melee_create(scene *scene) { } } - animation *ani; - sprite *spr; - for(int i = 0; i < 10; i++) { - ani = &bk_get_info(&scene->bk_data, 3)->ani; - object_create(&local->pilots[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); - object_set_animation(&local->pilots[i], ani); - object_select_sprite(&local->pilots[i], i); - - ani = &bk_get_info(&scene->bk_data, 18 + i)->ani; - object_create(&local->har_player1[i], scene->gs, vec2i_create(110, 95), vec2f_create(0, 0)); - object_set_animation(&local->har_player1[i], ani); - object_select_sprite(&local->har_player1[i], 0); - object_set_repeat(&local->har_player1[i], 1); - - int row = i / 5; - int col = i % 5; - spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0)); - mask_sprite(spr->data, 62 * col, 42 * row, 51, 36); - ani = create_animation_from_single(spr, spr->pos); - object_create(&local->harportraits_player1[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); - object_set_animation(&local->harportraits_player1[i], ani); - object_select_sprite(&local->harportraits_player1[i], 0); - object_set_animation_owner(&local->harportraits_player1[i], OWNER_OBJECT); - if(player2->selectable) { - spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0)); - mask_sprite(spr->data, 62 * col, 42 * row, 51, 36); - ani = create_animation_from_single(spr, spr->pos); - object_create(&local->harportraits_player2[i], scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); - object_set_animation(&local->harportraits_player2[i], ani); - object_select_sprite(&local->harportraits_player2[i], 0); - object_set_animation_owner(&local->harportraits_player2[i], OWNER_OBJECT); - object_set_pal_offset(&local->harportraits_player2[i], 48); - - ani = &bk_get_info(&scene->bk_data, 18 + i)->ani; - object_create(&local->har_player2[i], scene->gs, vec2i_create(210, 95), vec2f_create(0, 0)); - object_set_animation(&local->har_player2[i], ani); - object_select_sprite(&local->har_player2[i], 0); - object_set_repeat(&local->har_player2[i], 1); - object_set_direction(&local->har_player2[i], OBJECT_FACE_LEFT); - object_set_pal_offset(&local->har_player2[i], 48); - } - } - - ani = &bk_get_info(&scene->bk_data, 4)->ani; - object_create(&local->bigportrait1, scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); - object_set_animation(&local->bigportrait1, ani); - object_select_sprite(&local->bigportrait1, 0); + // Load HAR and Pilot face portraits and har sprites for the selection grid + load_pilot_portraits(scene, local); + load_har_portraits(scene, local); + load_hars(scene, local, player2->selectable); + // Load the big faces on the top corners + animation *pilot_big_portraits = &bk_get_info(&scene->bk_data, 4)->ani; + object_create_static(&local->big_portrait_1, scene->gs); + object_set_animation(&local->big_portrait_1, pilot_big_portraits); + object_select_sprite(&local->big_portrait_1, 0); if(player2->selectable) { - object_create(&local->bigportrait2, scene->gs, vec2i_create(320, 0), vec2f_create(0, 0)); - object_set_animation(&local->bigportrait2, ani); - object_select_sprite(&local->bigportrait2, 4); - object_set_direction(&local->bigportrait2, OBJECT_FACE_LEFT); + object_create(&local->big_portrait_2, scene->gs, vec2i_create(320, 0), vec2f_create(0, 0)); + object_set_animation(&local->big_portrait_2, pilot_big_portraits); + object_select_sprite(&local->big_portrait_2, 4); + object_set_direction(&local->big_portrait_2, OBJECT_FACE_LEFT); } - ani = &bk_get_info(&scene->bk_data, 5)->ani; - object_create(&local->player2_placeholder, scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); - object_set_animation(&local->player2_placeholder, ani); + // This contains the big logo and the frames + animation *misc_stuff = &bk_get_info(&scene->bk_data, 5)->ani; + object_create_static(&local->player2_placeholder, scene->gs); + object_set_animation(&local->player2_placeholder, misc_stuff); if(player2->selectable) { object_select_sprite(&local->player2_placeholder, 0); } else { object_select_sprite(&local->player2_placeholder, 1); } - spr = sprite_copy(animation_get_sprite(&bk_get_info(&scene->bk_data, 1)->ani, 0)); - surface_convert_to_rgba(spr->data, video_get_pal_ref(), 0); - ani = create_animation_from_single(spr, spr->pos); - object_create(&local->unselected_har_portraits, scene->gs, vec2i_create(0, 0), vec2f_create(0, 0)); - object_set_animation(&local->unselected_har_portraits, ani); - object_select_sprite(&local->unselected_har_portraits, 0); - object_set_animation_owner(&local->unselected_har_portraits, OWNER_OBJECT); - for(int i = 0; i < 2; i++) { local->bar_power[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50); local->bar_agility[i] = progressbar_create(PROGRESSBAR_THEME_MELEE, PROGRESSBAR_LEFT, 50); @@ -679,11 +711,12 @@ int melee_create(scene *scene) { component_layout(local->bar_power[0], 74, 12, 20 * 4, 8); component_layout(local->bar_agility[0], 74, 30, 20 * 4, 8); component_layout(local->bar_endurance[0], 74, 48, 20 * 4, 8); - component_layout(local->bar_power[1], 320 - 66 - local->feh.w, 12, 20 * 4, 8); - component_layout(local->bar_agility[1], 320 - 66 - local->feh.w, 30, 20 * 4, 8); - component_layout(local->bar_endurance[1], 320 - 66 - local->feh.w, 48, 20 * 4, 8); + component_layout(local->bar_power[1], 320 - 66 - local->bg_player_stats.w, 12, 20 * 4, 8); + component_layout(local->bar_agility[1], 320 - 66 - local->bg_player_stats.w, 30, 20 * 4, 8); + component_layout(local->bar_endurance[1], 320 - 66 - local->bg_player_stats.w, 48, 20 * 4, 8); refresh_pilot_stats(local); + set_cursor_colors(0); // initialize nova selection cheat memset(local->har_selected, 0, sizeof(local->har_selected)); @@ -698,10 +731,6 @@ int melee_create(scene *scene) { // Play correct music audio_play_music(PSM_MENU); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - // All done return 0; } diff --git a/src/game/scenes/newsroom.c b/src/game/scenes/newsroom.c index 660cbe9b1..596188f9d 100644 --- a/src/game/scenes/newsroom.c +++ b/src/game/scenes/newsroom.c @@ -126,19 +126,19 @@ void newsroom_static_tick(scene *scene, int paused) { void newsroom_overlay_render(scene *scene) { newsroom_local *local = scene_get_userdata(scene); - // Render screencapture + // Render screen capture har_screencaps *caps = &(game_state_get_player(scene->gs, (local->won ? 0 : 1))->screencaps); if(local->screen == 0) { if(caps->ok[SCREENCAP_POSE]) - video_render_sprite_size(&caps->cap[SCREENCAP_POSE], 165, 15, SCREENCAP_W, SCREENCAP_H); + video_draw_size(&caps->cap[SCREENCAP_POSE], 165, 15, SCREENCAP_W, SCREENCAP_H); } else { if(caps->ok[SCREENCAP_BLOW]) - video_render_sprite_size(&caps->cap[SCREENCAP_BLOW], 165, 15, SCREENCAP_W, SCREENCAP_H); + video_draw_size(&caps->cap[SCREENCAP_BLOW], 165, 15, SCREENCAP_W, SCREENCAP_H); } // Render text if(str_size(&local->news_str) > 0) { - video_render_sprite(&local->news_bg, 20, 140, BLEND_ALPHA, 0); + video_draw(&local->news_bg, 20, 140); font_render_wrapped(&font_small, str_c(&local->news_str), 30, 150, 250, COLOR_YELLOW); } @@ -363,9 +363,5 @@ int newsroom_create(scene *scene) { // Start correct music audio_play_music(PSM_MENU); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - return 0; } diff --git a/src/game/scenes/openomf.c b/src/game/scenes/openomf.c index 1b07b80c8..f2a64aa08 100644 --- a/src/game/scenes/openomf.c +++ b/src/game/scenes/openomf.c @@ -54,9 +54,5 @@ int openomf_create(scene *scene) { scene_set_input_poll_cb(scene, openomf_input_tick); scene_set_free_cb(scene, openomf_free); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - return 0; } diff --git a/src/game/scenes/scoreboard.c b/src/game/scenes/scoreboard.c index 51dd7ec60..23749bb38 100644 --- a/src/game/scenes/scoreboard.c +++ b/src/game/scenes/scoreboard.c @@ -13,8 +13,8 @@ #include "video/video.h" #define MAX_PAGES (NUMBER_OF_ROUND_TYPES - 1) -#define TEXT_COLOR_HEADER color_create(80, 220, 80, 0xFF) -#define TEXT_COLOR_SCORES color_create(0xFF, 0xFF, 0xFF, 0xFF) +#define TEXT_COLOR_HEADER TEXT_BLINKY_GREEN +#define TEXT_COLOR_SCORES 0x7F #define CURSOR_STR "\x7f" typedef struct scoreboard_local_t { @@ -123,7 +123,7 @@ void scoreboard_input_tick(scene *scene) { void scoreboard_render_overlay(scene *scene) { scoreboard_local *local = scene_get_userdata(scene); - video_render_sprite_size(&local->black_surface, 0, 0, 320, 200); + video_draw_size(&local->black_surface, 0, 0, 320, 200); char row[128]; char score_text[15]; char temp_name[17]; @@ -219,9 +219,14 @@ int scoreboard_create(scene *scene) { chr_score_reset(game_player_get_score(player), 1); } - // Create a surface that has an appropriate alpha for darkening the screen a bit - surface_create(&local->black_surface, SURFACE_TYPE_RGBA, 32, 32); - surface_fill(&local->black_surface, color_create(0, 0, 0, 200)); + // Darken the colors for the background a bit. + palette *pal = video_get_base_palette(); + for(int i = 0; i < 0xEF; i++) { + pal->data[i][0] *= 0.6; + pal->data[i][1] *= 0.6; + pal->data[i][2] *= 0.6; + } + video_force_pal_refresh(); // Set callbacks scene_set_userdata(scene, local); @@ -230,10 +235,6 @@ int scoreboard_create(scene *scene) { scene_set_render_overlay_cb(scene, scoreboard_render_overlay); scene_set_free_cb(scene, scoreboard_free); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - // All done return 0; } diff --git a/src/game/scenes/vs.c b/src/game/scenes/vs.c index cafc05ff3..a58adcb65 100644 --- a/src/game/scenes/vs.c +++ b/src/game/scenes/vs.c @@ -267,15 +267,15 @@ void vs_render(scene *scene) { if(player2->selectable) { // arena selection - video_render_sprite(&local->arena_select_bg, 55, 150, BLEND_ALPHA, 0); + video_draw(&local->arena_select_bg, 55, 150); object_render(&local->arena_select); // arena name - font_render_wrapped(&font_small, lang_get(56 + local->arena), 56 + 72, 153, (211 - 72) - 4, COLOR_GREEN); + font_render_wrapped(&font_small, lang_get(56 + local->arena), 56 + 72, 153, (211 - 72) - 4, TEXT_MEDIUM_GREEN); // arena description - font_render_wrapped(&font_small, lang_get(66 + local->arena), 56 + 72, 160, (211 - 72) - 4, COLOR_GREEN); + font_render_wrapped(&font_small, lang_get(66 + local->arena), 56 + 72, 160, (211 - 72) - 4, TEXT_MEDIUM_GREEN); } else if(player2->pilot && player2->pilot->pilot_id == PILOT_KREISSACK && settings_get()->gameplay.difficulty < 2) { // kreissack, but not on Veteran or higher @@ -403,6 +403,7 @@ int vs_create(scene *scene) { object_select_sprite(&local->player2_har, player2->pilot->har_id); object_set_direction(&local->player2_har, OBJECT_FACE_LEFT); object_set_pal_offset(&local->player2_har, 48); + object_set_pal_limit(&local->player2_har, 96); // PLAYER object_create(&local->player1_portrait, scene->gs, vec2i_create(-10, 150), vec2f_create(0, 0)); @@ -555,9 +556,5 @@ int vs_create(scene *scene) { scene_set_static_tick_cb(scene, vs_static_tick); scene_set_free_cb(scene, vs_free); - // Don't render background on its own layer - // Fix for some additive blending tricks. - video_render_bg_separately(false); - return 0; } diff --git a/src/game/utils/har_screencap.c b/src/game/utils/har_screencap.c index 577bb8229..6023b438a 100644 --- a/src/game/utils/har_screencap.c +++ b/src/game/utils/har_screencap.c @@ -1,9 +1,10 @@ #include "game/utils/har_screencap.h" +#include "utils/miscmath.h" #include "video/video.h" void har_screencaps_create(har_screencaps *caps) { for(int i = 0; i < 2; i++) { - caps->ok[i] = 0; + caps->ok[i] = false; } } @@ -11,7 +12,7 @@ void har_screencaps_free(har_screencaps *caps) { for(int i = 0; i < 2; i++) { if(caps->ok[i]) { surface_free(&caps->cap[i]); - caps->ok[i] = 0; + caps->ok[i] = false; } } } @@ -23,24 +24,21 @@ void har_screencaps_reset(har_screencaps *caps) { void har_screencaps_capture(har_screencaps *caps, object *obj, int id) { if(caps->ok[id]) { surface_free(&caps->cap[id]); - caps->ok[id] = 0; + caps->ok[id] = false; } // Position - int x = (object_px(obj) - object_w(obj) / 2) - (SCREENCAP_W - object_w(obj)) / 2; - int y = (object_py(obj) - object_h(obj)) - (SCREENCAP_H - object_h(obj)) / 2; - if(x < 0) - x = 0; - if(y < 0) - y = 0; - if(x + SCREENCAP_W >= NATIVE_W) - x = NATIVE_W - SCREENCAP_W; - if(y + SCREENCAP_H >= NATIVE_H) - y = NATIVE_H - SCREENCAP_H; + vec2i size = object_get_size(obj); + vec2i pos = object_get_pos(obj); + int x_margin = (SCREENCAP_W - size.x) / 2; + int y_margin = (SCREENCAP_H - size.y) / 2; + int x_center = pos.x - size.x / 2; + int y_center = (NATIVE_H - pos.y); + int x = clamp(x_center - x_margin, 0, NATIVE_W - SCREENCAP_W); + int y = clamp(y_center + y_margin, 0, NATIVE_H); // Capture - int ret = video_area_capture(&caps->cap[id], x, y, SCREENCAP_W, SCREENCAP_H); - if(ret == 0) { - caps->ok[id] = 1; - } + video_area_capture(&caps->cap[id], x, y, SCREENCAP_W, SCREENCAP_H); + surface_convert_to_grayscale(&caps->cap[id], video_get_pal_ref(), 0xD0, 0xDF); + caps->ok[id] = true; } diff --git a/src/game/utils/har_screencap.h b/src/game/utils/har_screencap.h index 6e1e9b732..a03022dc4 100644 --- a/src/game/utils/har_screencap.h +++ b/src/game/utils/har_screencap.h @@ -13,7 +13,7 @@ // There should be screencaps for each HAR/player typedef struct { surface cap[2]; - int ok[2]; + bool ok[2]; } har_screencaps; void har_screencaps_create(har_screencaps *caps); diff --git a/src/game/utils/score.c b/src/game/utils/score.c index 8afd028bb..f366adda5 100644 --- a/src/game/utils/score.c +++ b/src/game/utils/score.c @@ -6,14 +6,14 @@ #include #include -#define TEXT_COLOR color_create(186, 250, 250, 255) +#define TEXT_COLOR 0xC7 #define SLIDER_DISTANCE 50 #define SLIDER_HANG_TIME 25 #define SCRAP 100000 #define DESTRUCTION 200000 -typedef struct score_text_t { +typedef struct score_text { char *text; float position; // Position of text between middle of screen and (x,y). 1.0 at middle, 0.0 at end vec2i start; diff --git a/src/resources/bk.c b/src/resources/bk.c index 169fcc407..812f62b8e 100644 --- a/src/resources/bk.c +++ b/src/resources/bk.c @@ -1,6 +1,5 @@ #include "formats/bk.h" #include "resources/bk.h" -#include void bk_create(bk *b, void *src) { sd_bk_file *sdbk = (sd_bk_file *)src; @@ -9,8 +8,8 @@ void bk_create(bk *b, void *src) { b->file_id = sdbk->file_id; // Copy VGA image - surface_create_from_data(&b->background, SURFACE_TYPE_PALETTE, sdbk->background->w, sdbk->background->h, - sdbk->background->data); + surface_create_from_data(&b->background, sdbk->background->w, sdbk->background->h, + (unsigned char *)sdbk->background->data); // Copy sound translation table memcpy(b->sound_translation_table, sdbk->soundtable, 30); @@ -21,6 +20,13 @@ void bk_create(bk *b, void *src) { vector_append(&b->palettes, (palette *)sdbk->palettes[i]); } + // All scenes always have the menu colors set for palette 0. + palette *pal = vector_get(&b->palettes, 0); + palette_set_menu_colors(pal); + + // Index 0 is always black. + pal->data[0][0] = pal->data[0][1] = pal->data[0][2] = 0; + // Copy info structs hashmap_create(&b->infos, 7); bk_info tmp_bk_info; diff --git a/src/resources/fonts.c b/src/resources/fonts.c index 3b9ca6813..6c992dd06 100644 --- a/src/resources/fonts.c +++ b/src/resources/fonts.c @@ -29,7 +29,7 @@ void font_free(font *font) { } int font_load(font *font, const char *filename, unsigned int size) { - sd_rgba_image img; + sd_vga_image img; sd_font sdfont; int pixsize; surface *sur; @@ -56,11 +56,11 @@ int font_load(font *font, const char *filename, unsigned int size) { } // Load into textures - sd_rgba_image_create(&img, pixsize, pixsize); + sd_vga_image_create(&img, pixsize, pixsize); for(int i = 0; i < 224; i++) { sur = omf_calloc(1, sizeof(surface)); - sd_font_decode(&sdfont, &img, i, 0xFF, 0xFF, 0xFF); - surface_create_from_data(sur, SURFACE_TYPE_RGBA, img.w, img.h, img.data); + sd_font_decode(&sdfont, &img, i, 0); + surface_create_from_vga(sur, &img); vector_append(&font->surfaces, &sur); } @@ -70,7 +70,7 @@ int font_load(font *font, const char *filename, unsigned int size) { font->size = size; // Free resources - sd_rgba_image_free(&img); + sd_vga_image_free(&img); sd_font_free(&sdfont); return 0; } diff --git a/src/resources/sprite.c b/src/resources/sprite.c index 4a8d56a13..5a94843b4 100644 --- a/src/resources/sprite.c +++ b/src/resources/sprite.c @@ -19,7 +19,7 @@ void sprite_create(sprite *sp, void *src, int id) { // Load data sd_vga_image raw; sd_sprite_vga_decode(&raw, sdsprite); - surface_create_from_data(sp->data, SURFACE_TYPE_PALETTE, raw.w, raw.h, raw.data); + surface_create_from_data(sp->data, raw.w, raw.h, (unsigned char *)raw.data); memcpy(sp->data->stencil, raw.stencil, raw.w * raw.h); sd_vga_image_free(&raw); } @@ -46,6 +46,6 @@ sprite *sprite_copy(sprite *src) { // Copy surface new->data = omf_calloc(1, sizeof(surface)); - surface_copy(new->data, src->data); + surface_create_from(new->data, src->data); return new; }