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(); +} + | 
