summaryrefslogtreecommitdiff
path: root/src/engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine.c')
-rw-r--r--src/engine.c493
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();
+}
+