diff --git a/overlay/rootfs/usr/bin/snake b/overlay/rootfs/usr/bin/snake index 6b11ff9..a77184b 100755 Binary files a/overlay/rootfs/usr/bin/snake and b/overlay/rootfs/usr/bin/snake differ diff --git a/overlay/rootfs/usr/bin/tetris b/overlay/rootfs/usr/bin/tetris index b703e0b..76d4023 100755 Binary files a/overlay/rootfs/usr/bin/tetris and b/overlay/rootfs/usr/bin/tetris differ diff --git a/prebuilt/games/usr/bin/snake b/prebuilt/games/usr/bin/snake index 6b11ff9..a77184b 100755 Binary files a/prebuilt/games/usr/bin/snake and b/prebuilt/games/usr/bin/snake differ diff --git a/prebuilt/games/usr/bin/tetris b/prebuilt/games/usr/bin/tetris index b703e0b..76d4023 100755 Binary files a/prebuilt/games/usr/bin/tetris and b/prebuilt/games/usr/bin/tetris differ diff --git a/src/games/snake.cpp b/src/games/snake.cpp index e4fa960..0fe1128 100644 --- a/src/games/snake.cpp +++ b/src/games/snake.cpp @@ -101,7 +101,8 @@ static int ndirx = 1, ndiry = 0; // buffered next direction static int foodx, foody; static int score = 0; static int best = 0; -static int speed = 130; // ms per step (speeds up with score) +static int speed = 130; // ms per step (derived from pps below) +static int pps = 70; // base speed px/sec; +1 px/sec per 5 food eaten static unsigned long nextTick = 0; static bool running = true; static unsigned long now_ms() { @@ -110,6 +111,14 @@ static unsigned long now_ms() { return (unsigned long)(tv.tv_sec * 1000 + tv.tv_usec / 1000); } +// Derive the per-step delay (ms) from the target pixels/second. The snake +// advances one cell (cell pixels) per step, so step time = cell / pps. +static void update_speed() { + int ms = (cell * 1000) / pps; + if (ms < 40) ms = 40; // cap so the snake never becomes uncontrollable + speed = ms; +} + static void compute_grid() { int m = 2; int topH = 14; // reserved status strip for SCORE/BEST @@ -151,7 +160,8 @@ static void reset_game() { dirx = 1; diry = 0; ndirx = 1; ndiry = 0; score = 0; - speed = 130; + pps = 70; + update_speed(); place_food(); state = PLAYING; nextTick = now_ms() + speed; @@ -184,9 +194,9 @@ static void step() { if (ate) { score += 10; if (score > best) best = score; - int ns = 130 - (score / 50) * 8; - if (ns < 60) ns = 60; - speed = ns; + int food = score / 10; // food items eaten so far + pps = 70 + food / 5; // +1 px/sec per 5 food eaten (progressive difficulty) + update_speed(); place_food(); } nextTick = now_ms() + speed; diff --git a/src/games/tetris.cpp b/src/games/tetris.cpp index 9648231..bc6be0c 100644 --- a/src/games/tetris.cpp +++ b/src/games/tetris.cpp @@ -109,7 +109,8 @@ static int board[PCOLS][PROWS]; // 0 empty, else type+1 static int curType = 0, curRot = 0, curX = 3, curY = 0; static int nextType = 0; static int score = 0, best = 0, lines = 0, level = 1; -static int speed = 1000; // ms per gravity step +static int speed = 600; // ms per gravity step (derived from pps below) +static int pps = 23; // base speed px/sec; +1 px/sec per 10 lines cleared static unsigned long nextTick = 0; static bool running = true; @@ -137,6 +138,15 @@ static unsigned long now_ms() { return (unsigned long)(tv.tv_sec * 1000 + tv.tv_usec / 1000); } +// Derive the gravity delay (ms) from the target pixels/second. A piece drops +// one cell (CELL pixels) per gravity step, so step time = CELL / pps. +static void update_speed() { + pps = 23 + lines / 10; // +1 px/sec per 10 cleared lines (progressive difficulty) + int ms = (CELL * 1000) / pps; + if (ms < 40) ms = 40; // floor on gravity so it stays playable + speed = ms; +} + static void spawn() { curType = nextType; nextType = rand() % 7; @@ -176,11 +186,11 @@ static void lock_piece() { } if (cleared > 0) { lines += cleared; + level = 1 + lines / 10; int pts[5] = {0, 100, 300, 500, 800}; score += pts[cleared] * level; if (score > best) best = score; - int nl = 1 + lines / 10; - if (nl != level) { level = nl; speed = 1000 - (level - 1) * 40; if (speed < 300) speed = 300; } + update_speed(); // +1 px/sec per 10 cleared lines } spawn(); } @@ -227,7 +237,7 @@ static void try_rotate() { static void reset_game() { for (int x = 0; x < PCOLS; x++) for (int y = 0; y < PROWS; y++) board[x][y] = 0; - score = 0; lines = 0; level = 1; speed = 600; + score = 0; lines = 0; level = 1; update_speed(); nextType = rand() % 7; spawn(); state = PLAYING; @@ -319,6 +329,16 @@ static void render() { snprintf(buf, sizeof(buf), "LEVEL %d", level); draw_text(sx, ty + 18, 1, C_DIM, buf); if (best > 0) { snprintf(buf, sizeof(buf), "BEST %d", best); draw_text(sx, ty + 27, 1, C_DIM, buf); } + // concise controls in the free space below the stats + int ky = ty + 27 + 12; + draw_text(sx, ky, 1, C_DIM, "KEYS"); + draw_text(sx, ky + 9, 1, C_DIM, "4/6 MOVE"); + draw_text(sx, ky + 18, 1, C_DIM, "2 ROTATE"); + draw_text(sx, ky + 27, 1, C_DIM, "8 SOFT"); + draw_text(sx, ky + 36, 1, C_DIM, "0 DROP"); + draw_text(sx, ky + 45, 1, C_DIM, "# PAUSE"); + draw_text(sx, ky + 54, 1, C_DIM, "5 OK"); + if (state == PAUSED || state == GAMEOVER) { XSetForeground(dpy, gc, C_BG); XFillRectangle(dpy, back, gc, 0, 0, winW, winH); @@ -352,7 +372,7 @@ static void setup_window() { if (winW < 96) winW = 96; if (winH < 96) winH = 96; win = XCreateWindow(dpy, RootWindow(dpy, screen), bw, TOPBAR + bw, winW, winH, 0, - CopyFromParent, InputOutput, CopyFromParent, 0, nullptr); + CopyFromParent, InputOutput, CopyFromParent, 0, nullptr); XStoreName(dpy, win, "Tetris"); XClassHint* ch = XAllocClassHint(); if (ch) { ch->res_name = (char*)"tetris"; ch->res_class = (char*)"tetris"; XSetClassHint(dpy, win, ch); XFree(ch); }