From de1fb3881a75a95c3933038d6e595fb8ef8459ed Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Mar 09 2025 06:09:57 +0000 Subject: x11: shisen: improve --- diff --git a/simple/x11/shisen/data/buttons.xcf b/simple/x11/shisen/data/buttons.xcf index d331477..3872c6d 100644 Binary files a/simple/x11/shisen/data/buttons.xcf and b/simple/x11/shisen/data/buttons.xcf differ diff --git a/simple/x11/shisen/data/import.sh b/simple/x11/shisen/data/import.sh index 1751d73..5038534 100755 --- a/simple/x11/shisen/data/import.sh +++ b/simple/x11/shisen/data/import.sh @@ -13,11 +13,12 @@ function echodo() { SRC="../../../../onefile/data/shisen/" #echodo convert "$SRC/letters-gen.png" ./letters.tga #echodo convert "$SRC/minas.png" ./minas.tga +echodo cp "$SRC/shisen.png" "$SRC/shisen.desktop" ./ echodo mkdir -p sounds for file in "$SRC/sounds/"*.ogg; do f="$(basename "$file")" - echodo ffmpeg -i "$file" -f s16le -acodec pcm_s16le "sounds/${f:0:-4}.raw" + echodo ffmpeg -y -i "$file" -f s16le -acodec pcm_s16le "sounds/${f:0:-4}.raw" done echo "success" diff --git a/simple/x11/shisen/data/letters-sel.tga b/simple/x11/shisen/data/letters-sel.tga new file mode 100644 index 0000000..bf95a48 Binary files /dev/null and b/simple/x11/shisen/data/letters-sel.tga differ diff --git a/simple/x11/shisen/data/letters.xcf b/simple/x11/shisen/data/letters.xcf new file mode 100644 index 0000000..8ebd3dc Binary files /dev/null and b/simple/x11/shisen/data/letters.xcf differ diff --git a/simple/x11/shisen/data/shisen.desktop b/simple/x11/shisen/data/shisen.desktop new file mode 100644 index 0000000..6a7e9dd --- /dev/null +++ b/simple/x11/shisen/data/shisen.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Name=Shisen-Sho Armenian +GenericName=Shisen-Sho Armenian Alphabet +Path=/some/path +Exec=/some/path/shisen +Icon=/some/path/data/shisen/shisen.png +Terminal=false +Type=Application +Categories=Game;BoardGame; diff --git a/simple/x11/shisen/data/shisen.png b/simple/x11/shisen/data/shisen.png new file mode 100644 index 0000000..cb9a17f Binary files /dev/null and b/simple/x11/shisen/data/shisen.png differ diff --git a/simple/x11/shisen/data/silence.tga b/simple/x11/shisen/data/silence.tga new file mode 100644 index 0000000..39e8d75 Binary files /dev/null and b/simple/x11/shisen/data/silence.tga differ diff --git a/simple/x11/shisen/data/sound.tga b/simple/x11/shisen/data/sound.tga new file mode 100644 index 0000000..23df82f Binary files /dev/null and b/simple/x11/shisen/data/sound.tga differ diff --git a/simple/x11/shisen/data/sound2.tga b/simple/x11/shisen/data/sound2.tga new file mode 100644 index 0000000..6fa2830 Binary files /dev/null and b/simple/x11/shisen/data/sound2.tga differ diff --git a/simple/x11/shisen/shisen.c b/simple/x11/shisen/shisen.c index b27a3d5..a7605d7 100644 --- a/simple/x11/shisen/shisen.c +++ b/simple/x11/shisen/shisen.c @@ -24,11 +24,15 @@ typedef struct { } ImageEx; typedef struct { - ImageEx glyphs[4]; + ImageEx a, b; +} ImagePair; + +typedef struct { + ImagePair glyphs[4]; int glyphsCount; Sound sounds[MAXSOUNDS]; int soundsCount; - ImageEx *g[4]; + ImagePair *g[4]; } Letter; typedef struct { @@ -42,7 +46,7 @@ typedef struct { typedef struct { Letter *l; - ImageEx *g; + ImagePair *g; } Cell; @@ -61,22 +65,25 @@ int glyphsMask = 0; int mode; int showhint; int back; +int mute; int ox, oy, cw, ch; ImageEx bgtex; ImageEx starttex; ImageEx hinttex; ImageEx backtex[3]; +ImageEx sndtex[3]; void imgExFree(ImageEx *img) { + if (!img) return; if (img->x) XDestroyImage(img->x); imgFree(&img->src); *img = (ImageEx){}; } -void imgExDraw(ImageEx *img, int x, int y, int w, int h) { +void imgExResample(ImageEx *img, int w, int h) { if (!imgValid(img->src) || w <= 0 || h <= 0) return; if (img->x && (img->x->width != w || img->x->height != h)) { XDestroyImage(img->x); img->x = NULL; } @@ -85,6 +92,11 @@ void imgExDraw(ImageEx *img, int x, int y, int w, int h) { imgDivA(tmp); img->x = imgToX(&tmp); } +} + + +void imgExDraw(ImageEx *img, int x, int y, int w, int h) { + imgExResample(img, w, h); if (img->x) XPutImage(dpy, drw, gc, img->x, 0, 0, x, y, img->x->width, img->x->height); } @@ -98,7 +110,21 @@ int imgExLoadTga(ImageEx *img, const char *filename) { } +void imgPairFree(ImagePair *img) { + if (!img) return; + imgExFree(&img->a); + imgExFree(&img->b); +} + + +void imgPairDraw(ImagePair *img, int mode, int x, int y, int w, int h) { + imgExResample(mode ? &img->a : &img->b, w, h); + imgExDraw(mode ? &img->b : &img->a, x, y, w, h); +} + + void clearBoard() { + if (mute != 1) mute = 0; mode = 0; back = 0; memset(tracks, 0, sizeof(tracks)); @@ -120,7 +146,7 @@ void clearLetters() { clearSounds(); for(int i = 0; i < lettersCount; ++i) for(int j = 0; j < letters[i].glyphsCount; ++j) - imgExFree(&letters[i].glyphs[j]); + imgPairFree(&letters[i].glyphs[j]); memset(letters, 0, sizeof(letters)); memset(&menuLetter, 0, sizeof(menuLetter)); lettersCount = 0; @@ -128,7 +154,7 @@ void clearLetters() { } -int loadLetters(const char *filename, int rows, int cols) { +int loadLetters(const char *filename, const char *filesel, int rows, int cols) { clearLetters(); Image img = imgLoadTga(filename); @@ -139,6 +165,14 @@ int loadLetters(const char *filename, int rows, int cols) { if (!ww || !hh) return LOGERR("loadLetters: image too small (%dx%d): %s", img.w, img.h, filename), imgFree(&img), 0; + Image imgsel = imgLoadTga(filesel); + if (!imgValid(imgsel)) + return imgFree(&img), 0; + int wws = imgsel.w/cols/2; + int hhs = imgsel.h/rows/2; + if (!wws || !hhs) + return LOGERR("loadLetters: image too small (%dx%d): %s", imgsel.w, imgsel.h, filesel), imgFree(&img), imgFree(&imgsel), 0; + imgMultA(img); Letter *letter = letters; for(int r = 0; r < rows; ++r) @@ -149,7 +183,9 @@ int loadLetters(const char *filename, int rows, int cols) { Image sub = imgSub(img, (c*2 + cc)*ww, (r*2 + rr)*hh, ww, hh); if (!imgHasPicture(sub)) { imgFree(&sub); continue; } - letter->glyphs[ letter->glyphsCount++ ].src = sub; + letter->glyphs[ letter->glyphsCount ].a.src = sub; + letter->glyphs[ letter->glyphsCount ].b.src = imgSub(imgsel, (c*2 + cc)*wws, (r*2 + rr)*hhs, wws, hhs); + ++letter->glyphsCount; } if (letter->glyphsCount > menuLetter.glyphsCount) menuLetter = *letter; if (letter->glyphsCount > 0) ++letter; @@ -205,14 +241,14 @@ void shuffleLetters(int glyps) { assert(l->glyphsCount > 0); int gc = 0; - ImageEx *g[4] = {}; + ImagePair *g[4] = {}; for(int j = 0; j < l->glyphsCount; ++j) if (glyps & (1 << j)) g[gc++] = &l->glyphs[j]; if (!gc) g[gc++] = &l->glyphs[0]; for(int j = 0; j < gc; ++j) { int k = rand()%(gc - j) + j; - if (k != j) { ImageEx *a = g[j]; g[j] = g[k]; g[k] = a; } + if (k != j) { ImagePair *a = g[j]; g[j] = g[k]; g[k] = a; } } for(int j = 0; j < 4; ++j) @@ -220,7 +256,7 @@ void shuffleLetters(int glyps) { for(int j = 0; j < 4; ++j) { int k = rand()%(4 - j) + j; - if (k != j) { ImageEx *g = l->g[j]; l->g[j] = l->g[k]; l->g[k] = g; } + if (k != j) { ImagePair *g = l->g[j]; l->g[j] = l->g[k]; l->g[k] = g; } assert(l->g[j]); } } @@ -374,7 +410,10 @@ int init() { imgExLoadTga(&backtex[0], "data/back.tga"); imgExLoadTga(&backtex[1], "data/back1.tga"); imgExLoadTga(&backtex[2], "data/back2.tga"); - if (!loadLetters("data/letters.tga", 5, 8)) + imgExLoadTga(&sndtex[0], "data/sound.tga"); + imgExLoadTga(&sndtex[1], "data/silence.tga"); + imgExLoadTga(&sndtex[2], "data/sound2.tga"); + if (!loadLetters("data/letters.tga", "data/letters-sel.tga", 5, 8)) return LOGERR("init: cannot load letters"), 0; loadSounds("data/sounds"); //simpleBoard(); @@ -390,6 +429,9 @@ void deinit() { imgExFree(&backtex[0]); imgExFree(&backtex[1]); imgExFree(&backtex[2]); + imgExFree(&sndtex[0]); + imgExFree(&sndtex[1]); + imgExFree(&sndtex[2]); sndDeinit(); } @@ -420,11 +462,14 @@ void mouseDown(int x, int y) { if (get(selected)) showhint = 1; else hint(); } else + if (mc >= COLS && mr < 0) { + mute = mute == 1 ? 2 : 1; + } else if (mc >= 0 && mr >= 0 && mc < COLS && mr < COLS) { hover.r = mr; hover.c = mc; Letter *l = get(hover); - if (l && l->soundsCount > 0) + if (l && l->soundsCount > 0 && mute != 1) sndPlay(l->sounds[rand() % l->soundsCount]); if (!l || (mr == selected.r && mc == selected.c)) { selected.r = selected.c = hover.r = hover.c = -1; @@ -482,18 +527,10 @@ void draw() { ox = (winW - cw*4)/2; oy = (winH - ch)/2; - int lw = cw/6; - if (lw < 1) lw = 1; - XSetForeground(dpy, gc, 0x0000ff); - XSetLineAttributes(dpy, gc, lw, LineSolid, CapRound, JoinRound); - for(int i = 0; i < 4; ++i) - imgExDraw(&menuLetter.glyphs[i], ox + i*cw, oy, cw, ch); + imgPairDraw(&menuLetter.glyphs[i], !(glyphsMask & (1 << i)), ox + i*cw, oy, cw, ch); if (glyphsMask) imgExDraw(&starttex, ox + cw, oy + ch, 2*cw, ch); - for(int i = 0; i < 4; ++i) - if (glyphsMask & (1 << i)) - XDrawRectangle(dpy, drw, gc, ox + i*cw, oy, cw, ch); } else { if (winW*cellHeight*(ROWS + 2) < winH*cellWidth*(COLS + 4)) { cw = winW/(COLS + 4); @@ -505,14 +542,11 @@ void draw() { ox = (winW - cw*COLS)/2; oy = (winH - ch*ROWS)/2; - int lw = cw/6; - if (lw < 1) lw = 1; - XSetForeground(dpy, gc, 0x0000ff); - XSetLineAttributes(dpy, gc, lw, LineSolid, CapRound, JoinRound); - // draw buttons imgExDraw(&backtex[back], ox - 2*cw, oy - ch, 2*cw, ch); imgExDraw(&hinttex, ox + COLS*cw, oy + ROWS*ch, 2*cw, ch); + imgExDraw(&sndtex[mute], ox + COLS*cw, oy - ch, 2*cw, ch); + for(int i = 0; i < 3; ++i) imgExResample(&sndtex[i], cw, ch); // draw cells Letter *hl = showhint ? get(selected) : NULL; @@ -520,22 +554,17 @@ void draw() { for(int c = 0; c < COLS; ++c) { Cell *cell = &board[r][c]; if (!cell->g) continue; - imgExDraw(cell->g, ox + c*cw, oy + r*ch, cw, ch); - } - - // draw selection - for(int r = 0; r < ROWS; ++r) - for(int c = 0; c < COLS; ++c) { - Cell *cell = &board[r][c]; - if (!cell->g) continue; - if ( (r == hover.r && c == hover.c) - || (r == selected.r && c == selected.c) - || (hl && hl == cell->l) ) - XDrawRectangle(dpy, drw, gc, ox + c*cw, oy + r*ch, cw, ch); + int hilight = (r == hover.r && c == hover.c) + || (r == selected.r && c == selected.c) + || (hl && hl == cell->l); + imgPairDraw(cell->g, hilight, ox + c*cw, oy + r*ch, cw, ch); } // draw tracks + int lw = cw/6; + if (lw < 1) lw = 1; XSetForeground(dpy, gc, 0xff0000); + XSetLineAttributes(dpy, gc, lw, LineSolid, CapRound, JoinRound); for(int i = 0; i < tracksCount; ++i) { Track *t = &tracks[i]; XPoint p[4];