diff options
Diffstat (limited to 'src/engine.c')
-rw-r--r-- | src/engine.c | 493 |
1 files changed, 301 insertions, 192 deletions
diff --git a/src/engine.c b/src/engine.c index 9840b34..c218105 100644 --- a/src/engine.c +++ b/src/engine.c @@ -7,41 +7,97 @@ #include <SFML/Graphics/Text.h> #include "common.h" +#include "idlist.h" #include "tet_conf.h" +#include "vector.h" #include "text.h" #include "field.h" -#include "draw.h" +#include "painter.h" #include "engine.h" +#define RIGHT (1 << 0) +#define UP (1 << 1) +#define DOWN (1 << 2) +#define LEFT (1 << 3) +#define RIGHTHOLD (1 << 4) +#define LEFTHOLD (1 << 7) + +int level_move_latency[] = { + L00LATENCY, + L01LATENCY, + L02LATENCY, + L03LATENCY, + L04LATENCY, + L05LATENCY, + L06LATENCY, + L07LATENCY, + L08LATENCY, + L09LATENCY, + L10LATENCY, + L11LATENCY, + L12LATENCY, + L13LATENCY, + L14LATENCY, + L15LATENCY, + L16LATENCY, + L17LATENCY, + L18LATENCY, + L19LATENCY, + L20LATENCY, + L21LATENCY, + L22LATENCY, + L23LATENCY, + L24LATENCY, + L25LATENCY, + L26LATENCY, + L27LATENCY, + L28LATENCY, + L29LATENCY +}; + +int rmlines_score[] = { + 0, + RM_1LINES_SCORE, + RM_2LINES_SCORE, + RM_3LINES_SCORE, + RM_4LINES_SCORE +}; + /* Externs from main.c */ -extern struct game game; -extern struct field fld, nxt; - -extern char arrKeys; // Arrow keys states byte container - -void valueAfterTextDisplay(int value, List *texts, char *type) -{ - List *l = texts; - while (l) { - Text *text = (Text *)l->obj; - if (text->type) - if (!strcmp(text->type, type)) { - char a[64]; - if (text->text) { - if (strlen(text->text) > 52) { - memset(text->text+52, '\0', 1); - strcpy(a, text->text); - } - sprintf(a, "%s%d", text->text, value); - sfText_setString(text->sfText, (char *)&a); - break; - } - } - l = l->next; +extern struct game game; +extern struct field fld, nxt; +extern struct idlist *texts; +extern char arrKeys; + +static void render_score_value(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->type, "score.value")) { + if (!text->text) + text->text = malloc(sizeof(char) * BUFSIZ); + sprintf(text->text, "%d", game.scoreCurrent); } } -void checkLevelUp(struct game *game) +static void render_level_value(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->type, "level.value")) { + if (!text->text) + text->text = malloc(sizeof(char) * BUFSIZ); + sprintf(text->text, "%d", game.level); + } +} + +static int getMoveLatencyOfLevel(unsigned int level) +{ + if (level > 29) + return level_move_latency[29]; + else + return level_move_latency[level]; +} + +static void level_up(struct game *game) { while (game->lines >= LEVELUP_LINES) { game->level++; @@ -50,206 +106,259 @@ void checkLevelUp(struct game *game) } } -int getMoveLatencyOfLevel(unsigned int level) -{ - if (level >= 29) - return L29LATENCY; - else if (level >= 19) - return L19LATENCY; - else if (level >= 16) - return L16LATENCY; - else if (level >= 13) - return L13LATENCY; - else if (level >= 10) - return L10LATENCY; - else if (level == 9) - return L09LATENCY; - else if (level == 8) - return L08LATENCY; - else if (level == 7) - return L07LATENCY; - else if (level == 6) - return L06LATENCY; - else if (level == 5) - return L05LATENCY; - else if (level == 4) - return L04LATENCY; - else if (level == 3) - return L03LATENCY; - else if (level == 2) - return L02LATENCY; - else if (level == 1) - return L01LATENCY; - else if (level == 0) - return L00LATENCY; - return L00LATENCY; -} - - -/* - * Game tick - * - */ -void tTick() -{ // If tick exceeds current level tick latency - if (sfClock_getElapsedTime(game.gameTick).microseconds >= game.moveLatency) { - sfClock_restart(game.gameTick); - fld.shape[0].y--; // try - if (field_shape_collision(&fld, &fld.shape[0])) - fld.shape[0].y++; // fallback +static void hide_menu_text(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->scene, "menu")) + text->attr |= TXT_ATTR_INVISIBLE; +} + +static void show_menu_text(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->scene, "menu")) + text->attr &= ~TXT_ATTR_INVISIBLE; +} + +static void hide_game_text(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->scene, "game")) + text->attr |= TXT_ATTR_INVISIBLE; +} + +static void show_game_text(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->scene, "game")) + text->attr &= ~TXT_ATTR_INVISIBLE; +} + +static void update_menu_text(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->scene, "menu")) + painter_update_text(text->id, text); +} + +static void update_game_text(void *obj) +{ + struct text *text = obj; + if (!strcmp(text->scene, "game")) + painter_update_text(text->id, text); +} + +static void transition_game_over() +{ + game.isStarted = 0; + game.scoreCurrent = 0; + game.level = 0; + game.moveLatency = L00LATENCY; + game.lines = 0; + + nxt.attr |= FLD_ATTR_INVISIBLE; + painter_update_field(nxt.id, &nxt); + + fld.shape[0].y = fld.size.y; + field_fill_random(&fld); + painter_update_field(fld.id, &fld); + + list_foreach(texts, show_menu_text); + list_foreach(texts, hide_game_text); + list_foreach(texts, update_menu_text); + list_foreach(texts, update_game_text); +} + +static void transition_put_shape() +{ + field_put_shape(&fld, &fld.shape[0]); + int removedLines = field_rm_lines(&fld); + game.lines += removedLines; + game.scoreCurrent += rmlines_score[removedLines] * game.level; + fld.shape[0].t = nxt.shape[0].t; + field_reset_walking_shape(&fld, 0); + for (unsigned int s = 0; s < nxt.shape_cnt - 1; ++s) { + nxt.shape[s] = nxt.shape[s + 1]; + nxt.shape[s].y = 4 - s * 3; + } + shape_gen_random(&nxt.shape[nxt.shape_cnt - 1]); + level_up(&game); +} + +static void game_tick() +{ + sfClock_restart(game.gameTick); + fld.shape[0].y--; // try + if (field_shape_collision(&fld, &fld.shape[0])) + fld.shape[0].y++; // fallback + else + sfClock_restart(game.putTick); + if (sfClock_getElapsedTime(game.putTick).microseconds >= PUT_LATENCY) { + if (field_shape_out_of_bounds(&fld, &fld.shape[0])) + transition_game_over(); else - sfClock_restart(game.putTick); - if (sfClock_getElapsedTime(game.putTick).microseconds >= PUT_LATENCY) { - if (field_shape_out_of_bounds(&fld, &fld.shape[0])) { - gameover(&game); - fld.shape[0].y = fld.size.y; - field_fill_random(&fld); - nxt.attr |= FLD_ATTR_INVISIBLE; - painter_update_field(nxt.id, &nxt); - return; - } else { - field_put_shape(&fld, &fld.shape[0]); - int removedLines = field_rm_lines(&fld); - game.lines += removedLines; - switch (removedLines) { - case 1: - game.scoreCurrent += RM_1LINES_SCORE * game.level; - break; - case 2: - game.scoreCurrent += RM_2LINES_SCORE * game.level; - break; - case 3: - game.scoreCurrent += RM_3LINES_SCORE * game.level; - break; - case 4: - game.scoreCurrent += RM_4LINES_SCORE * game.level; - break; - } - fld.shape[0].t = nxt.shape[0].t; - field_reset_walking_shape(&fld, 0); - for (unsigned int s = 0; s < nxt.shape_cnt - 1; ++s) { - nxt.shape[s] = nxt.shape[s + 1]; - nxt.shape[s].y = 4 - s * 3; - } - shape_gen_random(&nxt.shape[nxt.shape_cnt - 1]); - checkLevelUp(&game); - } - sfClock_restart(game.putTick); - } + transition_put_shape(); + sfClock_restart(game.putTick); } } -/* - * Keys hold handler - * - */ -void tKeyCtrl() +static void signal_up() +{ + field_rotate_shape(&fld, 0); +} + +static void signal_down() { - /* Up arrow key 'hold' handler */ + fld.shape[0].y--; + if (field_shape_collision(&fld, &fld.shape[0])) { + fld.shape[0].y++; + } else { + sfClock_restart(game.gameTick); + game.scoreCurrent++; + } + sfClock_restart(game.repPushDown); +} + +static void signal_left() +{ + fld.shape[0].x--; + if (field_shape_collision(&fld, &fld.shape[0])) + fld.shape[0].x++; + else + sfClock_restart(game.putTick); + sfClock_restart(game.repKeyLeft); +} + +static void signal_right() +{ + fld.shape[0].x++; + if (field_shape_collision(&fld, &fld.shape[0])) + fld.shape[0].x--; + else + sfClock_restart(game.putTick); + sfClock_restart(game.repKeyRight); +} + +static void game_keys() +{ + /* UP */ if (sfKeyboard_isKeyPressed(sfKeyUp)) { if (!(arrKeys & UP)) { arrKeys = arrKeys | UP; - field_rotate_shape(&fld, 0); + signal_up(); } } else { - if ((arrKeys & UP)) { - arrKeys = arrKeys & ~UP; - } + arrKeys = arrKeys & ~UP; } - /* Down Arrow Key 'hold' handler */ + /* DOWN */ if (sfKeyboard_isKeyPressed(sfKeyDown)) { if (!(arrKeys & DOWN)) { arrKeys = arrKeys | DOWN; - fld.shape[0].y--; - if (field_shape_collision(&fld, &fld.shape[0])) - fld.shape[0].y++; - else { - // Avoid excess move down by gameTick - sfClock_restart(game.putTick); - sfClock_restart(game.gameTick); - game.scoreCurrent++; - } - sfClock_restart(game.repPushDown); + signal_down(); } else { - if (sfClock_getElapsedTime(game.repPushDown).microseconds - >= moveRepeatLatency2) + if (sfClock_getElapsedTime(game.repPushDown).microseconds >= moveRepeatLatency2) arrKeys = arrKeys & ~DOWN; } } else { - if ((arrKeys & DOWN)) { - arrKeys = arrKeys & ~DOWN; - } + arrKeys = arrKeys & ~DOWN; } - /* Left Arrow Key 'hold' handler */ - if (sfKeyboard_isKeyPressed(sfKeyLeft) - && !sfKeyboard_isKeyPressed(sfKeyRight)) { + /* LEFT */ + if (sfKeyboard_isKeyPressed(sfKeyLeft) && !sfKeyboard_isKeyPressed(sfKeyRight)) { if (!(arrKeys & LEFT)) { arrKeys = arrKeys | LEFT; - fld.shape[0].x--; - if (field_shape_collision(&fld, &fld.shape[0])) - fld.shape[0].x++; - else - sfClock_restart(game.putTick); - sfClock_restart(game.repKeyLeft); - } else { - if (!(arrKeys & LEFTHOLD)) { - if (sfClock_getElapsedTime(game.repKeyLeft).microseconds - >= moveRepeatLatency1) { - arrKeys = arrKeys | LEFTHOLD; - arrKeys = arrKeys & ~LEFT; - } - } else { - if (sfClock_getElapsedTime(game.repKeyLeft).microseconds - >= moveRepeatLatency2) - arrKeys = arrKeys & ~LEFT; + signal_left(); + } else if (!(arrKeys & LEFTHOLD)) { + if (sfClock_getElapsedTime(game.repKeyLeft).microseconds >= moveRepeatLatency1) { + arrKeys = arrKeys | LEFTHOLD; + arrKeys = arrKeys & ~LEFT; } + } else { + if (sfClock_getElapsedTime(game.repKeyLeft).microseconds >= moveRepeatLatency2) + arrKeys = arrKeys & ~LEFT; } - } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) { - if ((arrKeys & LEFT)) { - arrKeys = arrKeys & ~LEFT; - arrKeys = arrKeys & ~LEFTHOLD; - } + } else { + arrKeys = arrKeys & ~LEFT; + arrKeys = arrKeys & ~LEFTHOLD; } - /* Right Arrow Key 'hold' handler */ - if (sfKeyboard_isKeyPressed(sfKeyRight) - && !sfKeyboard_isKeyPressed(sfKeyLeft)) { + /* RIGHT */ + if (sfKeyboard_isKeyPressed(sfKeyRight) && !sfKeyboard_isKeyPressed(sfKeyLeft)) { if (!(arrKeys & RIGHT)) { arrKeys = arrKeys | RIGHT; - fld.shape[0].x++; - if (field_shape_collision(&fld, &fld.shape[0])) - fld.shape[0].x--; - else - sfClock_restart(game.putTick); - sfClock_restart(game.repKeyRight); - } else { - if (!(arrKeys & RIGHTHOLD)) { - if (sfClock_getElapsedTime(game.repKeyRight).microseconds - >= moveRepeatLatency1) { - arrKeys = arrKeys | RIGHTHOLD; - arrKeys = arrKeys & ~RIGHT; - } - } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) { - if (sfClock_getElapsedTime(game.repKeyRight).microseconds - >= moveRepeatLatency2) // Wait short time - arrKeys = arrKeys & ~RIGHT; + signal_right(); + } else if (!(arrKeys & RIGHTHOLD)) { + if (sfClock_getElapsedTime(game.repKeyRight).microseconds >= moveRepeatLatency1) { + arrKeys = arrKeys | RIGHTHOLD; + arrKeys = arrKeys & ~RIGHT; } + } else { + if (sfClock_getElapsedTime(game.repKeyRight).microseconds >= moveRepeatLatency2) + arrKeys = arrKeys & ~RIGHT; } } else { - if ((arrKeys & RIGHT)) { - arrKeys = arrKeys & ~RIGHT; - arrKeys = arrKeys & ~RIGHTHOLD; - } + arrKeys = arrKeys & ~RIGHT; + arrKeys = arrKeys & ~RIGHTHOLD; } } -void gameover(struct game *game) +static void menuTick() { - game->isStarted = 0; - game->scoreCurrent = 0; - game->level = 0; - game->moveLatency = L00LATENCY; - game->lines = 0; + sfClock_restart(game.mTick); + field_fill_random(&fld); + painter_update_field(fld.id, &fld); } + +void transition_init(void) +{ + list_foreach(texts, show_menu_text); + list_foreach(texts, hide_game_text); + list_foreach(texts, update_menu_text); + list_foreach(texts, update_game_text); +} + +static void transition_game_start() +{ + game.isStarted = 1; + field_clear(&fld); + shape_gen_random(&fld.shape[0]); + field_reset_walking_shape(&fld, 0); + for (unsigned int i = 0; i < nxt.shape_cnt; ++i) + shape_gen_random(&nxt.shape[i]); + nxt.attr &= ~FLD_ATTR_INVISIBLE; + list_foreach(texts, hide_menu_text); + list_foreach(texts, show_game_text); + list_foreach(texts, update_menu_text); + list_foreach(texts, update_game_text); + sfClock_restart(game.gameTick); +} + +static void menu_loop() { + if (sfClock_getElapsedTime(game.mTick).microseconds >= basicLatency) + menuTick(); + if (sfKeyboard_isKeyPressed(sfKeyS) == 1) + transition_game_start(); + painter_draw(); +} + +static void game_loop() { + game_keys(); + if (sfClock_getElapsedTime(game.gameTick).microseconds >= game.moveLatency) + game_tick(); + list_foreach(texts, render_score_value); + list_foreach(texts, render_level_value); + painter_update_field(fld.id, &fld); + painter_update_field(nxt.id, &nxt); + list_foreach(texts, update_game_text); + painter_draw(); +} + +void main_loop() +{ + if (game.isStarted) + game_loop(); + else + menu_loop(); +} + |