fix(games): correct Snake self-collision on spawn, enlarge Tetris, brighten labels

Snake: the snake was initialized with its head at the left end while
moving right, so the first gravity step walked the head into its own
body and the game started at Game Over. Initialize the head at the
right end (cx) so the initial direction is valid.

Tetris: enlarge the playfield cell (10 -> 12px) so pieces are not too
small, and slow gravity (800ms base, gentler per-level ramp, 250ms
floor) so pieces do not fall too fast.

Both: brighten the secondary/dim text colour (0x0a3a0a -> 0x2f9f2f)
so score/label/menu text is actually legible on the black background.

Also wire the Games section into the real main menu: the system menu
is hardcoded in the dwm-plugin dmenu (src/sxmo-dmenu/dmenu.c), not in
sxmo_appmenu.sh, so add a 'games' builtin menu that loads
sxmo_hook_games.sh and a Games entry after Apps in the sys menu, plus
scripts/build-dmenu.sh to cross-compile dmenu.so.
This commit is contained in:
Luxferre
2026-10-23 14:57:59 +03:00
parent 5f467b02fa
commit 3eb54e4306
10 changed files with 97 additions and 7 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+78
View File
@@ -0,0 +1,78 @@
#!/bin/sh
# Cross-compile the patched sxmo-dmenu plugin (dmenu.so) for armv7.
# Mirrors the dmenu section of scripts/build-sxmo-x11.sh.
set -eu
BASE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
ROOTFS_DIR="${ROOTFS_DIR:-$BASE_DIR/rootfs}"
if [ -e "$ROOTFS_DIR" ]; then
ROOTFS_DIR="$(realpath "$ROOTFS_DIR")"
fi
exec docker run --rm --network=host \
-e HOST_UID="$(id -u)" \
-e HOST_GID="$(id -g)" \
-v "$BASE_DIR:/bananarchy" \
-v "$ROOTFS_DIR:/target-rootfs" \
alpine:3.24 sh -eu -c '
cat > /etc/apk/repositories <<EOF
https://mirror.nura.eco/postmarketos/v26.06
https://dl-cdn.alpinelinux.org/alpine/edge/main
https://dl-cdn.alpinelinux.org/alpine/edge/community
https://dl-cdn.alpinelinux.org/alpine/edge/testing
EOF
cp /bananarchy/keys/* /etc/apk/keys/
echo "[1/3] Installing host cross-compilation toolchain..."
apk add --no-cache \
build-base \
gcc-armv7 \
g++-armv7 \
binutils-armv7 \
pkgconf >/dev/null
echo "[2/3] Preparing armv7 sysroot (X11 + xinerama/xft/fontconfig)..."
SYSROOT="/tmp/armv7-sysroot"
mkdir -p "$SYSROOT/etc/apk/keys"
cp /etc/apk/repositories "$SYSROOT/etc/apk/repositories"
cp /etc/apk/keys/* "$SYSROOT/etc/apk/keys/"
apk --root "$SYSROOT" --initdb --arch armv7 add --no-scripts \
alpine-baselayout \
musl-dev \
linux-headers \
libx11-dev \
libxinerama-dev \
libxft-dev \
fontconfig-dev \
freetype-dev >/dev/null
export PKG_CONFIG_SYSROOT_DIR="$SYSROOT"
export PKG_CONFIG_LIBDIR="$SYSROOT/usr/lib/pkgconfig:$SYSROOT/usr/share/pkgconfig"
CC="armv7-alpine-linux-musleabihf-gcc --sysroot=$SYSROOT"
STRIP="armv7-alpine-linux-musleabihf-strip"
OPT_CFLAGS="-O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -fno-plt -fomit-frame-pointer"
mkdir -p /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins
echo "[3/3] Compiling dmenu.so..."
cd /bananarchy/src/sxmo-dmenu
cp -f config.def.h config.h
DMENU_INCS="$(pkgconf --cflags x11 xinerama xft fontconfig freetype2)"
DMENU_LIBS="$(pkgconf --libs x11 xinerama xft fontconfig freetype2)"
$CC $OPT_CFLAGS -fPIC -shared -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"5.0.14-bananarchy\" -DXINERAMA $DMENU_INCS \
dmenu.c drw.c util.c $DMENU_LIBS -o /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dmenu.so
$STRIP --strip-unneeded /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dmenu.so
echo "Installing into overlay and (optional) target rootfs..."
mkdir -p /bananarchy/overlay/rootfs/usr/lib/dwm/plugins
cp -f /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dmenu.so /bananarchy/overlay/rootfs/usr/lib/dwm/plugins/dmenu.so
if [ -d /target-rootfs/usr/lib/dwm/plugins ]; then
cp -f /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dmenu.so /target-rootfs/usr/lib/dwm/plugins/dmenu.so
fi
chown -R "$HOST_UID:$HOST_GID" \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins \
/bananarchy/overlay/rootfs/usr/lib/dwm/plugins \
/bananarchy/src/sxmo-dmenu
ls -lh /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dmenu.so
'
+2 -2
View File
@@ -141,7 +141,7 @@ static void reset_game() {
snakelen = 4;
int cx = COLS / 2, cy = ROWS / 2;
for (int i = 0; i < snakelen; i++) {
snake[i][0] = cx - i; // tail to the left, head at cx
snake[i][0] = cx - (snakelen - 1 - i); // head at cx, tail to the left
snake[i][1] = cy;
}
dirx = 1; diry = 0;
@@ -306,7 +306,7 @@ static void setup_window() {
C_FG = 0x33ff33;
C_HEAD = 0x99ff99;
C_FOOD = 0x66ff66;
C_DIM = 0x0a3a0a;
C_DIM = 0x2f9f2f;
XSelectInput(dpy, win, KeyPressMask | StructureNotifyMask | ExposureMask);
XMapWindow(dpy, win);
+4 -4
View File
@@ -27,7 +27,7 @@ static const int WIN_W = 240;
static const int WIN_H = 296;
static const int PCOLS = 10;
static const int PROWS = 20;
static const int CELL = 10;
static const int CELL = 12;
// ---- 5x7 bitmap font ----
struct Glyph { char ch; unsigned char r[7]; };
@@ -101,7 +101,7 @@ 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 = 600; // ms per gravity step
static int speed = 800; // ms per gravity step
static unsigned long nextTick = 0;
static bool running = true;
@@ -176,7 +176,7 @@ static void lock_piece() {
score += pts[cleared] * level;
if (score > best) best = score;
int nl = 1 + lines / 10;
if (nl != level) { level = nl; speed = 600 - (level - 1) * 50; if (speed < 120) speed = 120; }
if (nl != level) { level = nl; speed = 800 - (level - 1) * 40; if (speed < 250) speed = 250; }
}
spawn();
}
@@ -341,7 +341,7 @@ static void setup_window() {
C_FG = 0x33ff33;
C_HEAD = 0x99ff99;
C_FOOD = 0x66ff66;
C_DIM = 0x0a3a0a;
C_DIM = 0x2f9f2f;
XSelectInput(dpy, win, KeyPressMask | StructureNotifyMask | ExposureMask);
XMapWindow(dpy, win);
+13 -1
View File
@@ -157,6 +157,7 @@ static const char *ICON_ZMO = "\xf3\xb0\x9b\xac";
static const char *ICON_A2X = "\xe2\x87\x84";
static const char *ICON_KBD = "\xef\x84\x9c";
static const char *ICON_THM = "\xf3\xb0\x8f\x98";
static const char *ICON_GAM = "\xf3\xb0\x8a\xb4";
static void drawmenu(void);
static void show_menu(void);
@@ -1682,6 +1683,9 @@ open_builtin_menu(const char *menu_name, int keep_idx)
snprintf(label, sizeof(label), "%s Apps", ICON_GRD);
add_menu_item(label, "@menu:applications", 1);
snprintf(label, sizeof(label), "%s Games", ICON_GAM);
add_menu_item(label, "@menu:games", 1);
snprintf(label, sizeof(label), "%s Scripts", ICON_GRD);
add_menu_item(label, "@menu:scripts", 1);
@@ -1764,7 +1768,15 @@ open_builtin_menu(const char *menu_name, int keep_idx)
add_menu_item(label, "@menu:sys", 1);
snprintf(label, sizeof(label), "%s Close Menu", ICON_CLS);
add_menu_item(label, "@close", 0);
} else if (strcmp(menu_name, "scripts") == 0) {
} else if (strcmp(menu_name, "games") == 0) {
reset_session_defaults(1, "Games");
append_active_call_entries();
load_cache_or_hook("sxmo_games.cache", "sxmo_hook_games.sh");
snprintf(label, sizeof(label), "%s System Menu", ICON_MNU);
add_menu_item(label, "@menu:sys", 1);
snprintf(label, sizeof(label), "%s Close Menu", ICON_CLS);
add_menu_item(label, "@close", 0);
} else if (strcmp(menu_name, "modem") == 0) {
reset_session_defaults(1, "Scripts");
append_active_call_entries();
load_cache_or_hook("sxmo_scripts.cache", "sxmo_hook_scripts.sh");