momente şi schiţe de informatică şi matematică
To attain knowledge, write. To attain wisdom, rewrite.

Modelarea tablei şi jocului de şah (VI)

Bash | CSS | Linux | background-position | sprite
2012 jun

Am considerat până acum un singur "set de piese" de şah şi am poziţionat câmpurile tablei şi imaginile pieselor prin valori determinate în pixeli, corespunzând exact acestui set.

Să spunem acum de unde putem obţine mai multe seturi şi să vedem cum realizăm printr-un program, sprite-urile corespunzătoare. Apoi, cum am putea face pentru ca poziţionările câmpurilor şi imaginilor să nu depindă totuşi, de setul curent folosit. Ulterior, vom vedea cum am putea minimiza acele definiţii CSS care depind inevitabil de setul curent.

Seturi de piese de şah în format PNG pot fi obţinute de la jin-piece-sets (Eric De Mund, sub licenţă Creative Commons Attribution-Share Alike 3.0 Unported). Am download-at "alpha.ead-02.zip" şi am dezarhivat în $HOME/Resources/alpha2; subdirectoare apărute astfel sunt '/20', '/21', etc. - numite după dimensiunea piesei - şi fiecare conţine fişierele ".png" corespunzătoare pieselor, astfel:

vb@vb:~/Resources/alpha2$ ls 20
bb.png  bn.png  bq.png  wb.png  wn.png  wq.png
bk.png  bp.png  br.png  wk.png  wp.png  wr.png

Prima literă ('b' sau 'w') din numele acestor fişiere reprezintă culoarea ('black' sau 'white'), iar a doua - numele piesei (conform standardului FEN).

Montarea în sprite-uri

Am văzut în (V), cum putem folosi comanda montage pentru a obţine un sprite corespunzător unui set de piese; acum ar trebui să iterăm "montage" pentru fiecare set şi este firesc să scriem un program Bash pentru aceasta.

Directorul în care lucrăm asupra widget-ului nostru este $HOME/brw-sah şi are structura:

vb@vb:~$ ls brw-sah/
brw-sah.html  css  images  js

Să adăugăm un fişier executabil (pentru programul Bash anunţat):

vb@vb:~/brw-sah$ touch  chessmen-sprite.sh ; chmod  +x  chessmen-sprite.sh 

şi să-l edităm apoi, cu următorul conţinut:

#!/bin/bash

mkdir -p chessmen  # creează $HOME/brw-sah/chessmen

cd chessmen  # copiază seturile 20..32 în /chessmen
cp -r $HOME/Resources/alpha2/{20..32} . 

for sz in $(ls)  # pentru fiecare set din /chessmen
do
    cd $sz  # montează sprite-ul corespunzător
    montage -adjoin -tile 12x1 -geometry +0+0 -background none \
        wp.png wk.png wq.png wr.png wb.png wn.png \
        bn.png bb.png br.png bq.png bk.png bp.png \
        men$sz.png
    
    cp men$sz.png ../../images/  # copiază sprite-ul în /images

    cd ..  # revine în /chessmen, pentru următorul set
done

Executând programul, obţinem în subdirectorul /images sprite-urile dorite ("men20.png", ş.a.m.d.); am optat numai pentru seturile 20..32 (nu mai mari) pentru că lucrăm la un widget pentru pagini Web (de montat alături de alte conţinuturi), nu la o aplicaţie independentă pentru desktop.

Poziţionarea independentă de set, a câmpurilor şi imaginilor

Definiţiile CSS din brw-sah/css/brw-sah.css (vezi (I) şi (V)) au avut în vedere numai piesele de 20 pixeli, încât ele corespund acum numai pentru "men20.png".

Am putea imagina iarăşi, un program Bash (sau în alt limbaj) care să furnizeze fişierul CSS necesar unui set dat - urmând să concatenăm fişierele respective (grupând CSS selectorii corespunzători unui set, pentru fiecare set)… Dar aceasta ar trebui să fie "ultima soluţie"; întâi ar fi de văzut cât de favorabil am putea specula faptul că proprietăţile CSS de poziţionare (top, left, background-position) pot avea ca valori nu numai pixeli, ci şi procente.

Dacă reuşim să indicăm valori procentuale adecvate, atunci vom putea imagina definiţii CSS comune pentru toate seturile (plus un număr minimal de definiţii particulare setului).

Pentru poziţionarea celor 8 coloane şi 8 linii ale tablei, trebuie să setăm left şi respectiv top; împărţind dimensiunea 100% a tablei la 8 obţinem (exact) 12.5% şi putem considera că lucrurile sunt simple: avansăm la următoarea coloană adunând 12.5% la left-ul celei precedente (la fel, pentru linii). Adică putem redefini selectorii CSS .Col-n şi .Row-n astfel:

.Col-1 { left: 0%; }        .Row-1 { top: 0%; }
.Col-2 { left: 12.5%; }     .Row-2 { top: 12.5%; }
.Col-3 { left: 25%; }       .Row-3 { top: 25%; }
.Col-4 { left: 37.5%; }     .Row-4 { top: 37.5%; }
.Col-5 { left: 50%; }       .Row-5 { top: 50%; }
.Col-6 { left: 62.5%; }     .Row-6 { top: 62.5%; }
.Col-7 { left: 75%; }       .Row-7 { top: 75%; }
.Col-8 { left: 87.5%; }     .Row-8 { top: 87.5%; }

Acum - cu aceste definiţii procentuale de poziţionare - construcţia tablei de şah este independentă de dimensiunea câmpului.

În schimb, pentru piese avem de folosit background-position şi lucrurile se complică. Am investigat deja chestiunea în Poziţionarea procentuală a unei piese:

rezultând că următoarele definiţii asigură poziţionarea independent de mărimea pieselor:

.white-pawn   { background-position: 0; }      
.white-king   { background-position: -100%; }
.white-queen  { background-position: -200%; }
.white-rook   { background-position: -300%; }
.white-bishop { background-position: -400%; }
.white-knight { background-position: -500%; }
.black-knight { background-position: -600%; }
.black-bishop { background-position: -700%; }
.black-rook   { background-position: -800%; }
.black-queen  { background-position: -900%; }
.black-king   { background-position: -1000%; }
.black-pawn   { background-position: 100%; }

Privitor la "independenţă", ar mai fi un aspect de luat în seamă…

Asigurarea independenţei faţă de direcţia tablei

În poziţia normală, tabla de şah apare cu piesele albe în partea de jos şi cu cele negre în partea de sus a tablei. Este firesc să creem posibilitatea inversării tablei şi aceasta se face de obicei printr-o funcţie javaScript care inversează ordinea celor 64 de <div>-uri corespunzătoare câmpurilor tablei şi deasemenea, inversează notaţia liniilor şi respectiv, a coloanelor tablei.

În programul său de şah din 2008, dynarch a introdus o metodă mult mai simplă: se grupează selectorii de coloane şi de linii într-un nou selector CSS, dar inversând ordinea; funcţia javaScript necesară pentru inversarea tablei se poate astfel rezuma la adăugarea / ştergerea acestei noi proprietăţi în definiţia iniţială a tablei (într-un singur loc - nu este necesar pe fiecare câmp!).

Prin inversare, "Col-1" trebuie să devină (sub noul selector) "Col-8", "Row-8" trebuie să devină "Row-1", ş.a.m.d. iar această transformare asigură de la sine şi "inversarea" pieselor de pe tablă. Să rescriem deci definiţiile anterioare pentru poziţionarea liniilor şi coloanelor, astfel:

.Col-1, .revBoard .Col-8 { left: 0% }     .Row-8, .revBoard .Row-1 {  top: 0% }
.Col-2, .revBoard .Col-7 { left: 12.5% }  .Row-7, .revBoard .Row-2 {  top: 12.5% }
.Col-3, .revBoard .Col-6 { left: 25% }    .Row-6, .revBoard .Row-3 {  top: 25% }
.Col-4, .revBoard .Col-5 { left: 37.5% }  .Row-5, .revBoard .Row-4 {  top: 37.5% }
.Col-5, .revBoard .Col-4 { left: 50% }    .Row-4, .revBoard .Row-5 {  top: 50% }
.Col-6, .revBoard .Col-3 { left: 62.5% }  .Row-3, .revBoard .Row-6 {  top: 62.5% }
.Col-7, .revBoard .Col-2 { left: 75% }    .Row-2, .revBoard .Row-7 {  top: 75% }
.Col-8, .revBoard .Col-1 { left: 87.5% }  .Row-1, .revBoard .Row-8 {  top: 87.5% }

Modificând astfel "brw-sah.css", va fi suficient să se adauge în <script>-ul final din fişierul HTML (vezi eventual (IV)): $('div.container').addClass('revBoard'); pentru ca (la reîncărcarea HTML) tabla să-şi schimbe orientarea (piesele albe - sus, iar cele negre - jos).

vezi Cărţile mele (de programare)

docerpro | Prev | Next