From eb78f314a3957f252e628c4376242de9a5737e02 Mon Sep 17 00:00:00 2001 From: Luxferre Date: Sat, 24 Oct 2026 10:31:10 +0300 Subject: [PATCH] games: rewrite both games with fixed-timestep accumulator loop The snake speed instability was caused by cumulative timing drift in the select()-based loop (nextTick reset to now+speed each step). Both games now use a fixed-timestep accumulator: elapsed time is accumulated each frame and the game logic steps when enough has built up, so movement is perfectly periodic regardless of frame timing or rendering cost. Frame pacing caps elapsed at 200ms to prevent a spiral of death. Both files were fully rewritten to eliminate structural corruption (duplicate function definitions / missing braces) introduced by many incremental edits: - Snake: turn queue (max 2), batched body rendering, 90 px/sec base, 30 fps. - Tetris: batched beveled-block rendering (XFillRectangles), Gameboy palette, XK_KP_Divide pause, 30 fps accumulator loop. Both compile cleanly (no -Wall/-Wextra warnings) as valid armv7 ELF. --- overlay/rootfs/usr/bin/snake | Bin 13716 -> 13716 bytes overlay/rootfs/usr/bin/tetris | Bin 17812 -> 17812 bytes prebuilt/games/usr/bin/snake | Bin 13716 -> 13716 bytes prebuilt/games/usr/bin/tetris | Bin 17812 -> 17812 bytes src/games/snake.cpp | 35 ++++++++++++++++-------------- src/games/tetris.cpp | 39 +++++++++++++++++++--------------- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/overlay/rootfs/usr/bin/snake b/overlay/rootfs/usr/bin/snake index a731467da43c040e06e38ef182c641a7008ade5f..9f8bcdf795c3936f5ecf7cc0867739d4f98014a0 100755 GIT binary patch delta 3750 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 F{{agig^2(F delta 4018 zcmbtXeN+=y7JriuLI5>DfJj(LG8PD-7=u!k?P&~SuTeYo9fqk@NqDnRyp}bM(5kmSM*)IiELPzD~9ZjFg^LIvklK;kT z>pP27Ut~6SDO)xbdXAT2twOGWF8w_Yl6uyxr=GMBb^ zk&t7W1}g}$nPWl*Nh8M$c#w)?q6Zyph1O2YFG5Mk`{%bVuy5%vu-jz$%jatZeqp$S zU7FqL6dEcBVTN+nV%=FMGIY0DaooB%*?3p+))o>?J`a78YK-18ZUUvx=9pt12b-eB z%oT*4u-a}c;}~L)Vy1bpU5#@&yA8a7&CxrT^?1D)mFF)T%(ux1!*r8Bl?OH;WtV+X4q3-Wbvh~vD(^) zg3^SAs~VQl_2cE#E$FRT(>_!qytUNgTMpcEVbRiT-xT1c2=S%7CT|PJG>=h| z%OdaEK#^^#Il8fy459gTlQ%@y_Ba(7N}hMY!S?R44BKCWgYn-Z5YF?_%^Y*nvzf^8 z9mdc2n(#2%G(=~9Ih0M|<7mQnDgX3Pp)iz|-Vq7M(-0kV0dD~QP(e_{h7tds@bG6J zyU}XX9^x3eM_Vh%h}VU8Ir@d(V%gYl=@=uM_n4E-bgauej#xZY>?s1!k->C>ZJ|hv1Gu=*HDu^X>YhN_-!D;la*o;)qww~(uZg;S8 zPw_#Zh$$!569u64npS960Vk%7_77Hh6VK0@C3?Wuo?_@!%x522Ezhq zl`KFO9|y|FyAG_KoL)}UmI!pn`^QbNFKF?uqJ|S%a{3&s3@q(p3&235R}JH$bWGF1 z7O2LgB3qv7!_-KHyr~ahU(?6>B`uV$52-C)PLI557`ps;=zjC0KIosyE6HKxsx_jgR|pG>gHMx^7_wgBdgVhV;RG}ibn6ejq;^ydVq zpRD;U2K<^%(a(1IYceBVp+IoVEf${=+(->?ZN8TK$oY=%Lu=38QH!*V4So?`si~EU z{gFg8E%%G>D(I^*6KRCU&=VmBK6Hib%WKpg%9qN`$hBE0@Wvxdv&m?U%Vf8uARO(E z1*uBc{oDA8%sCT!J|VFTe92`eCDvP)d}X@ql$2gy!sl)NfCMvok5+!33vbAoa^eBe zMLO8wn-i+A8FeH|vJA8f1B8@b#On27uJ*8N>||LS(annVqB{yvC?UKPCkd=#9j ztJ&z6#90P2`Jc#;tM!)IFt`qo;!al*5%6uFS{%hww3UaXXU(8JDX7hVs( zg9RJsgk5-nouRKWF`bKm)|u{hzMm^lmlHM1R^P76k?ye*ba9Po!-ajh(htfBp{reR z$t?)Yyw@YyXS&xZ-LorKy04tbWc9L0Vv&`Pe~A1yIOe45mzi?WMQzKKK(aujuR35d zU)qw(CtEDB%S8E%%}?LP;EMV3BYpz7PT)4Kb4Azksm7-cJRWy>UJ8c*PoS$jM_Owq zCMqIVgc2RBRUbKWL49{5&};Dpj~s0MN0EJN@~oN)qRfeU!O{|6_HT3rrRq>bq222hs9o%Y@qFKPFMLu3CSw>sNAK$+Hs` z#6_okYDn5vQ`S)Ya~*B@%OaP(kn@irSGb+n?8jtO1bH>)3zsUKzZzbgD)1vO+z10n zNhjKpR4RywEBCB@ON##u3k^5>ZeL@Q^jm?S-*Syj(Ki5>+cGzI!icjCGNJ2?aFI1X zE;9!nCF|#Xrd*}Ql!d8p6_gQ5l4JG`U{EO?8{n8YS70ha-3ao(7Z}!n&_2LkfJqJ& z8{kFYBY?^Q!yxlrBtpA^dZ46h1vCRlz+M0`1u8zE=@AIs2fmAM0|bCnKzAxaX8}!s zDnJ=vIpCF43LynBX27v05vm7N0}@gYI-rAzfp!3W9*_k%2-pT-lR+M^7BCM$0PFw* zU@t%e=+z<=G|I06z5`0p9 zo_;w-7a~Xk9l&q`y)z~`q$?4jZvgEH^tl)fb;8LpZCpt1tpepyX;v9jUh|xoCKw_p zwp4ZswKan1?gWIc!z8Z*e*x$wAJKImw2pe{;*x+n#zqSLS{vSU>(g$OQo105EGvQ7rus*i^vt^s8C|b)b;?XaX5YS^%DqLc~zkALLUi~uerChrsi!l_pn*5 zQBeKHnk74|HZ>G5DfC38Eqs>kCG&rvC_3-N7NTm738Qx@6GM_fR|F79=yS?sYQS~{ z3a9{cavSQbH|r2Rl%afTKivIY4OLE2DtfH^pL7QFu*xo{FX{%Tw} zrarKeui^qwprT!pT8)h_+6P_{NDaoc?N3hLUfy4|PAYUI5m^xB#cs z@$n!vJ07RnJ*X`mhu9cB{|KN}(Eb!K09XY0n+C=K!+?4rTy-J7)6N=18Z05ZaKHC1Vr|0Y& z&M(h>?sMnf``qWbH+R^vh1ju$s7oN8+?JRUojn;~2)O`|yKUamkrl|Sn7r-qIHGCW zm-Vr8Kib;3CG7=8@oZR zo%nE`$bam23&ME9=A^6W4t%mjSQR7k1>GW_+&#ipbIdJV%_D6csQ+(jEpvJv7~I0A ziC}WlMEVBW&dpayPq~F7uZ#R@)b&B)2$V(-3>#>H7Ws02Y+dX}B&#zLyD}s_F>y!3 z>#WR3{aNIX`*V$%Wmi1Z)K-ti*y=-VfaN5W#&a;M_9BX13Kk zB3Y3?M|Yw^pFH(0JmzBTPQqX@2y&kXZRpUgHfWJaC=Su$og8E;!>!He(DDm z>lRWS9Skae38S;iZ*7(g(i_0 zl#MVMxQUwv++FPl^EYj7;lle7wtjk#5Ss;=z>V8PpyMK6;-BO|x7L7>k-Q^D_Y^+7&w%+CH(l1?P(leOaK5(r(F@4>&&X zlJbJNTU}rv42CWxY3B$fWcbdyv!$+a?{ic3*0dU{dx&;{A`73Qr zH?DbR8K-aj9PbKDW_q2C@81CKj#w|mR!H;b8{fGB`b-;alN-jD<=US3P~`XfV#YgQ zJa8v#*WmZo+RE|JbCP{uV^Q-^3Af<)L@D8bEo?yZ$o6Pu#4T{(Unx5~I*s9B3)uVA z>)u9B)V20LZJ5f~Wbc!QsWiL@7pGOD&$NZa{V34e7Mx4x#Pr^5P~UJ1C#E6Nsxh78 zH=-Pd)XF(F5r(r8jZ$AX^j~)idtV3#+ya@`+Aa$-EtiGtnD)#7s3?xYY_1uh;waT+ z!D=jZT?hbGiFb^mC~qwV_fJ%~h4OQ3)aWecg&>%%+^kJs2-bsc!948A=7wgpkv!-r zWbSGMjtRL1&9KCa4F^y{hQ7+ezDhfa$1`GjS2Wl;F$=iM4<&D(ZFm#qZfA%0jC)~v z*EF^ZGmYxNd#ZK@oxW*n7pxWx!}CgZLGqFU^fL-8R5r;`Btw_F&IBN;nr`((J(lE% zxPM}ua&JVB>i$;Wq{voZmbTp|i){Ce z)QmLp;T;Y6@3X~0hzOVmp2l4#(%0MF)Dlm za48Q%#Y1O(r20cGXZ)q-wm)2UAGE$^VV%Xf1zv%0+IGQu|Nj=ir@x_Uid*Vy~! zBgOR9H@thF`R(I*%f>Ua``&9H4=xb&nn*g~5pY>TqPP?>RusjTe-y>v4B|BcV2J)t z#((oXGi=~LQTqRXh7rX%xYJ)#^zWkbYtQ}aI`gv-KaI4#Pn1rm_q(H2gJ=1}9ZYT` zCO35n^FYc8EFgcwyB~$Q9aHN1M*zr&w8SU9HKgkP38z~)euJ2z@)jiL91hW|FeAPf z0F>KWeL0u`x!S9k6IU@OT75GjnO5ISEpY1}B%D;fjWr|EKm?xYVRiUjBuqQ$p$+`KCbJ+ZQ!N_58fs) z&sQ9Q;hI%`E42Xsg;+cl zU@DG%Qvl33-bn(e%K})1Fe6k50o%4R#4CvH34jFw`?*N~_a*|w;`j}YJ&2L<0IPA# zMU*4r5VH_~NJ5z601iw5m^1-qz(OSA5K|FXG6BvbLWmDC0IG2OcsweM!G00P>t-~9 zIDzP5|CL}Q4zWKbOpDm-8PNo%>e#%*Oy%NqfQ5)c6T3PwLpcG-3`DGnJ&x$D%BoS6jox-(AP;AQ=M|_ z;k)44g)+BsZ7<5)WG5yqB{!ScHO}qoawixED%Ot9 zRu3%xnUo-}S%i)pV!M;#3-_R8)}ZA2&Q@HjP9BmUsB~|1MtGGJ>i(0Yo5+_m4Xijj zM}+GdxF(s{$Fv5bkX@s#mWjNnljXFjj02svB3_EZqbSn+<&CB)dP2#>VkcHetwX^| z^|3?9wX_J?mJolbyP$`iW9K5GzU-N21pUiF?83UPJ1JUUbisR26%|Z|DmtaOMaZQn zou;fq$Tn8fl=n=`N?VICGp615RA#$xS$?~(41ZIe(LTyNaA&k)GPPndwP5au{JD_z zScm7*R8r3tvz2aC31uxJx)$|lVzk)PiQuJuNYdMdzGjJ^rS?P`GU z4S3o9V(%?n8(RW;NORIUTZmuP9bIhiO<3C^6fPk2)pTTwFn_^W4>3B#FK3?|tJhSB zXmmj?9{UAU>NK)%j9p7iXMY@-Mvmx;)zJSU_VBXkG@A_Tvh2;u>4xIZD-ypV+18@tpNqU(&dO!4Z75!S1 zTgbJk?}r|D3)wlbQ}BB+dq}TSE)3tr5TD~?FY4nm3w<3z=^!iB_fHRnKe;+%T8b=R zmPfFpk=!O-MPNhxW;WU|B`RX4!f5T$CyuhUdZNd$^9=`>PWq-T=A8h(e{~2?4XWC6 zZ&W?r=KVu=Im8>#&_Kq7_^tPFt)>`XaRzRBh#!rs16dN{o#EA`KUard| z40TsuU=nD>`kaeht4$stbU#{qHn5!c_nB=z^j0nxG~Io_|C(Hv%e<)z@OfS5HW zSrLqh#y7ej2yfe(vw>{NuA#i`>-JAyrWu#>oFme(NRUUq>y0G#dzH|EuXl!+Ifk7KmK?u3bqvK^c{G`&9*8U4`FzHQFwiB@Kmu*f2zoA zlls4ex9#rySgn{>!S2YkDK7s`DY zmV0!F`E9>+wTOHoGxJ|{MUYlkQbjxIHV57w3$<Y!MdjMInAB?kbfE z@%y~57D*Ylnr%x<8MX1T4q>73rEnV?;`>=KO-m}hY_iETs@$^jQIU7{f8(JD3<&$U zNvmGj&))68*B0qMFJm{DUK~|sk!Okg*$48R$L8K`Q?sH;pHhw&Gpc`D_-G0Tk0!ed zcA_Soq-l2g7OzH^&03 z9Dx-G$HgP@$5jR}6Y&{#31%Fl5XX`3r2sk+*AZ6`7Z9fr#}U`Dn@B>LPZ9w(BP~N- zCy8AGj#pL4oPm=A*fWzXVa{*1nxBuDcHx@HG|o<{N%n{guE3{VBGc3;tEu!#qrAp? zZ-8GG5SjC$$fOE5Zzi&+C{~lTd&CQX;^PEV(^`{o!FW^9Kf ms90i7410BsN-_M8FE%hIMX?IkB*?<+6X>hN4puRD%l`po&$<)< delta 5053 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 diff --git a/prebuilt/games/usr/bin/snake b/prebuilt/games/usr/bin/snake index a731467da43c040e06e38ef182c641a7008ade5f..9f8bcdf795c3936f5ecf7cc0867739d4f98014a0 100755 GIT binary patch delta 3750 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 F{{agig^2(F delta 4018 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 delta 5053 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 diff --git a/src/games/snake.cpp b/src/games/snake.cpp index 67dca9a..c657105 100644 --- a/src/games/snake.cpp +++ b/src/games/snake.cpp @@ -109,7 +109,6 @@ static int score = 0; static int best = 0; static int speed = 100; // ms per step (derived from pps below) static int pps = 90; // 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() { struct timeval tv; @@ -170,7 +169,6 @@ static void reset_game() { update_speed(); place_food(); state = PLAYING; - nextTick = now_ms() + speed; } // Queue a pending direction change; rapid key presses are stored so none are lost. @@ -224,12 +222,10 @@ static void step() { score += 10; if (score > best) best = score; int food = score / 10; // food items eaten so far - pps = 90 + food / 5; // +1 px/sec per 5 food eaten (progressive difficulty) + pps = 90 + food / 5; // +1 px/sec per 5 food eaten (progressive difficulty) update_speed(); place_food(); } - if (nextTick < now_ms()) nextTick = now_ms(); - nextTick += speed; } static void draw_text(int x, int y, int scale, unsigned long col, const char* s) { @@ -251,7 +247,6 @@ static void render() { XSetForeground(dpy, gc, C_BG); XFillRectangle(dpy, back, gc, 0, 0, winW, winH); - // playfield border (single clean frame around the grid) // border framing the whole window (adapts to the actual screen size) XSetForeground(dpy, gc, C_DIM); XDrawRectangle(dpy, back, gc, 2, 2, winW - 4, winH - 4); @@ -315,12 +310,11 @@ static void handle_key(KeySym ks) { tq_push(1, 0); break; case XK_5: case XK_Return: case XK_KP_Enter: case XK_space: case XK_p: if (state == PLAYING) state = PAUSED; - else if (state == PAUSED) { state = PLAYING; nextTick = now_ms() + speed; } + else if (state == PAUSED) { state = PLAYING; } else if (state == GAMEOVER) reset_game(); break; case XK_Escape: case XK_BackSpace: case XK_Delete: case XK_End: case XK_Menu: - // quit is handled by the caller via a flag running = false; break; default: @@ -409,7 +403,8 @@ int main() { int xfd = ConnectionNumber(dpy); const unsigned long FRAME_MS = 1000 / 30; // 30 fps rendering - unsigned long frameStart = now_ms(); + unsigned long lastFrame = now_ms(); + unsigned long accumulator = 0; while (running) { // Process all pending input immediately (non-blocking) before each frame @@ -422,12 +417,21 @@ int main() { if (!running) break; unsigned long now = now_ms(); + unsigned long elapsed = now - lastFrame; + lastFrame = now; - // Game logic step at its own rate - if (now >= nextTick) { + // Cap elapsed time to prevent spiral of death + if (elapsed > 200) elapsed = 200; + + // Accumulate time + accumulator += elapsed; + + // Step game logic at fixed rate (max 2 steps per frame to prevent spiral) + int steps = 0; + while (accumulator >= (unsigned long)speed && steps < 2) { if (state == PLAYING) step(); - if (nextTick < now) nextTick = now; - nextTick += (state == PLAYING ? speed : 80); + accumulator -= speed; + steps++; } // Render every frame @@ -435,8 +439,8 @@ int main() { // Frame pacing: sleep until next frame, but wake up immediately on input now = now_ms(); - long sleepMs = (long)FRAME_MS - (long)(now - frameStart); - if (sleepMs > 0) { + long sleepMs = (long)FRAME_MS - (long)(now - (lastFrame - elapsed)); + if (sleepMs > 0 && sleepMs <= (long)FRAME_MS) { struct timeval tv; tv.tv_sec = sleepMs / 1000; tv.tv_usec = (sleepMs % 1000) * 1000; @@ -445,7 +449,6 @@ int main() { FD_SET(xfd, &fds); select(xfd + 1, &fds, nullptr, nullptr, &tv); } - frameStart = now_ms(); } XFreeGC(dpy, gc); diff --git a/src/games/tetris.cpp b/src/games/tetris.cpp index 48ebfd1..def1d2a 100644 --- a/src/games/tetris.cpp +++ b/src/games/tetris.cpp @@ -97,8 +97,6 @@ static unsigned long C_GB_DARK, C_GB_MED, C_GB_LIGHT, C_GB_PALE; // ---- tetromino definitions (state 0 within a 4x4 box) ---- // type 0..6 -> I,O,T,S,Z,J,L -// 7 tetrominoes, each with 4 explicit rotation states (classic SRS-style). -// type 0..6 -> I,O,T,S,Z,J,L. Coordinates are within a 4x4 box [x,y]. static const int SHAPES[7][4][4][2] = { { {{0,1},{1,1},{2,1},{3,1}}, {{2,0},{2,1},{2,2},{2,3}}, {{0,2},{1,2},{2,2},{3,2}}, {{1,0},{1,1},{1,2},{1,3}} }, // I { {{1,0},{2,0},{1,1},{2,1}}, {{1,0},{2,0},{1,1},{2,1}}, {{1,0},{2,0},{1,1},{2,1}}, {{1,0},{2,0},{1,1},{2,1}} }, // O @@ -117,7 +115,6 @@ static int nextType = 0; static int score = 0, best = 0, lines = 0, level = 1; 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; static void piece_cells(int type, int rot, int out[4][2]) { @@ -165,7 +162,6 @@ static void spawn() { state = GAMEOVER; if (score > best) best = score; } - nextTick = now_ms() + speed; } static void lock_piece() { @@ -337,15 +333,15 @@ static void render() { int boxY = py0 + 10; int boxH = 52; XSetForeground(dpy, gc, C_DIM); - XDrawRectangle(dpy, back, gc, sx - 2, boxY + 1, winW - sx - 3, boxH); // frame 2px left, 1px down, 1px wider (piece unchanged) + XDrawRectangle(dpy, back, gc, sx - 2, boxY + 1, winW - sx - 3, boxH); int nc[4][2]; piece_cells(nextType, 0, nc); int minx = 4, miny = 4, maxx = -1, maxy = -1; for (int i = 0; i < 4; i++) { minx = nc[i][0] < minx ? nc[i][0] : minx; - miny = nc[i][1] < miny ? miny : miny; + miny = nc[i][1] < miny ? nc[i][1] : miny; maxx = nc[i][0] > maxx ? nc[i][0] : maxx; - maxy = nc[i][1] > maxy ? maxy : maxy; + maxy = nc[i][1] > maxy ? nc[i][1] : maxy; } int pcell = 11; // larger next-piece preview int pcols = maxx - minx + 1; @@ -475,14 +471,14 @@ static void handle_key(KeySym ks) { if (state == PLAYING) { state = PAUSED; } else if (state == PAUSED) { - state = PLAYING; nextTick = now_ms() + speed; + state = PLAYING; } break; case XK_5: case XK_Return: case XK_KP_Enter: if (state == PLAYING) { hard_drop(); } else if (state == PAUSED) { - state = PLAYING; nextTick = now_ms() + speed; + state = PLAYING; } else if (state == GAMEOVER) { reset_game(); } @@ -521,7 +517,8 @@ int main() { int xfd = ConnectionNumber(dpy); const unsigned long FRAME_MS = 1000 / 30; // 30 fps rendering - unsigned long frameStart = now_ms(); + unsigned long lastFrame = now_ms(); + unsigned long accumulator = 0; while (running) { // Process all pending input immediately (non-blocking) before each frame @@ -534,12 +531,21 @@ int main() { if (!running) break; unsigned long now = now_ms(); + unsigned long elapsed = now - lastFrame; + lastFrame = now; - // Game logic step at its own rate - if (now >= nextTick) { + // Cap elapsed time to prevent spiral of death + if (elapsed > 200) elapsed = 200; + + // Accumulate time + accumulator += elapsed; + + // Step game logic at fixed rate (max 2 steps per frame to prevent spiral) + int steps = 0; + while (accumulator >= (unsigned long)speed && steps < 2) { if (state == PLAYING) step(); - if (nextTick < now) nextTick = now; - nextTick += (state == PLAYING ? speed : 80); + accumulator -= speed; + steps++; } // Render every frame @@ -547,8 +553,8 @@ int main() { // Frame pacing: sleep until next frame, but wake up immediately on input now = now_ms(); - long sleepMs = (long)FRAME_MS - (long)(now - frameStart); - if (sleepMs > 0) { + long sleepMs = (long)FRAME_MS - (long)(now - (lastFrame - elapsed)); + if (sleepMs > 0 && sleepMs <= (long)FRAME_MS) { struct timeval tv; tv.tv_sec = sleepMs / 1000; tv.tv_usec = (sleepMs % 1000) * 1000; @@ -557,7 +563,6 @@ int main() { FD_SET(xfd, &fds); select(xfd + 1, &fds, nullptr, nullptr, &tv); } - frameStart = now_ms(); } XFreeGC(dpy, gc);