Gestione del cursore in una finestra console e matrix effect

di il
50 risposte

50 Risposte - Pagina 2

  • Re: Gestione del cursore in una finestra console e matrix effect

    Certamente che il comando if e' la stessa cosa, ma la struttura e' completamente diversa.

    Appunto:

    Pascal: if... then... else...

    C++: if... else...

    Si tratta sempre dello stesso comando decisionale, ma nel C++ essendo strutturato in maniera meno completa bisogna utilizzare piu' if nidificati uno dentro l'altro, mentre nel Pascal questo non accade.

    Che poi si inseriscono diversi if all'interno di {... } parentesi, questo non significa niente.
    Alla fine nel C++ devi comunque utilizzare un if in piu'.
  • Re: Gestione del cursore in una finestra console e matrix effect

    Beh comunque non ho solo risolto, ma qualcosa ho imparato ovvero che per gestire il cursore, a meno di spostamenti di base, per i quali si possono utilizzare alcuni caratteri di escape, si possono utilizzare funzioni che utilizzano le API, molto più comode (se mi troverò in altri problemi di gestione della finestra console, me le guarderò bene, e non dovrò aprire una nuova discussione).
    Sinceramente un conto era impararsele nel caso le usassi spesso, ma credo che questa sia la prima e ultima volta che le userò... era per uno sfizio mio, volevo creare una "pioggia" di caratteri che veniva giù dallo schermo come in matrix, ma mi sono reso conto che è molto più difficile di quanto pensassi farla uguale (a meno dei simboli usati) a quello vera.
  • Re: Gestione del cursore in una finestra console e matrix effect

    OK...

    Se posso esserti d'aiuto, per quanto mi ricordi... la pioggia di caratteri stile Matrix puo' essere fatta in diversi modi, ma teoricamente la modalita' migliore e' quella di riempire a priori lo schermo di caratteri fissi, e a questi associare poi dei colori diversi che sfumano verso lo stesso colore di fondo che decidi di creare.

    Mi spiego meglio:

    - Colore di fondo dello schermo nero. OK.
    - Riempire lo schermo di caratteri una solo volta senza effetti particolari, dando a tutti un colore uguale a quello del fondo dello schermo, quindi continuerai a vedere sempre nero.
    - con diversi cicli di for nidificati cambiare il colore di ogni singolo carattere dello schermo che ciclicamente sfumano dall'alto verso il basso da un colore particolare fino al nero del fondo dello schermo.

    in tal modo otterrai l'effetto di caratteri che sembrano cadere verso il basso e nello stesso tempo cambiare colore mano a mano che cadono.

    Piu' o meno e' cosi, poi naturalmente puoi migliorare l'algoritmo come piu' ti aggrada dando anche un effetto di caduta reale con l'utilizzo delle API.

    cmq. non e' una cosa banale... in genere credo che nessun algoritmo sia mai banale quando lo si vuole fare a dovere.
  • Re: Gestione del cursore in una finestra console e matrix effect

    Spero di non andare OT, comunque al massimo modifico il titolo in "gestione del cursore nella finestra console e effetto matrix"

    Guardando attentamente l'animazione:
    http://www.youtube.com/watch?v=i9k2OCJk81

    Si nota che:
    -per ogni colonna, il flusso di caratteri inizia da un punto casuale (anche se la probabilità che inizi dalla prima riga sembra essere più alta) e finisce in un punto casuale (anche qui la probabilità che finisca alla fine del riquadro sembra maggiore);
    -man mano che i flussi delle varie colonne scorrono in giù, i simboli all'interno del flusso cambiano con frequenza diversa (casuale) per ogni simbolo.

    Ora io volevo realizzare ciò senza fare l'effetto sfumato (tu dici di cambiare gradualmente il colore, ma bisognerebbe cambiare gradualmente l'intensità del colore, e non credo sia possibile) e senza usare i simboli usati lì, ma sceglierne un tot dai caratteri ASCII.

    Avevo pensato, come dici tu, di riempire un determinato riquadro di caratteri neri (corrispondenti al carattere ASCII 1 mi pare) e poi ad esempio, per una determinata colonna, partendo da un punto casuale in giù, riempirla con altri caratteri diversi da quello nero (fasandoli correttamente con Sleep() in modo da dare l'effetto discesa) fino ad un altro punto casuale, e a quel punto, dopo un certo tot di tempo partendo dal primo carattere non nero della colonna, trasformare gradualmente tutti quelli sotto in caratteri neri.
    E questo, fatto per una colonna l'ho fatto, il problema è che devo farlo per più colonne contemporaneamente, e contemporaneamente fare variare i simboli non neri di ogni colonna con una certa frequenza.

    Il problema è che non so come fargli fare più cose contemporaneamente...
  • Re: Gestione del cursore in una finestra console e matrix effect

    Bhè banale no ma semplice si.
    Lo schermo della console è generalmente 80x24 o qualcosa di simile.
    Detto ciò pare logico usare una matrice 80x24.
    ogni colonna avrà un suo tempo per la creazione del sucessivo carattere,basta quindi creare un algoritmo che "swappy" dalla posizione 24 alla posizione 0 indicizzata dalla colonna.
    
    #define SZ_W 81
    #define SZ_H 24
    
    void swapbuffer(char b[][SZ_W], int index)
    {
        int i;
        for (i = SZ_H; i > 0 ; i--)
            b[i][index] = b[i-1][index];
    }
    
    char newchar()
    {
        static char alpha[] = "abcdefg hijklmnopqrstuvwxyz ";
        return alpha[mth_random(27)];
    }
    
    void zeromap(char b[][SZ_W])
    {
        int ix,iy;
        for (iy = 0; iy < SZ_H; iy++)
        {
            for(ix = 0; ix < SZ_W - 1; ix++)
                b[iy][ix] = ' ';
            b[iy][ix] = '\0';
        }
    
    }
    
    void draw(char b[][SZ_W])
    {
        con_cls();
        int iy;
        for (iy = 0; iy < SZ_H; iy++)
            printf("%s",b[iy]);
        fflush(stdout);
    }
    
    int main()
    {
        con_cls();
        con_setcolor(CON_COLOR_BK_BLACK,CON_COLOR_GREEN);
    
        mth_initrandom();
    
        char map[SZ_H][SZ_W];
        zeromap(map);
    
        int ic;
        while(1234)
        {
            while ( (ic = mth_random(79)) % 2 );//righe alterne piu carino
            swapbuffer(map,ic);
            map[0][ic] = newchar();
            ic = mth_randomrange(10,50);
            draw(map);
            thr_sleep(ic);
        }
    
    
        return 0;
    }
    
    Naturalmente poi puoi modificare a seconda del tuo gradimento.
  • Re: Gestione del cursore in una finestra console e matrix effect

    Io avrei qualche idea e dopo quando torno a casa possiamo provare. ci sn verso sera

    Ma prima di tutto... conosci gli array/le matrici? Una qualsiasi funzione che genera numeri casuali?
    Potrei vedere cos'hai fatto fino ad adesso?
  • Re: Gestione del cursore in una finestra console e matrix effect

    Ho visto solo ora gli altri messaggi d'aiuto inviati. Comunque avevo gia' scritto il mio messaggio quindi lo invio lo stesso, magari puo' servire.

    OK ho visto il video, ora mi e' un po' piu' chiaro l'effetto che avevo dimenticato.

    Osservando bene tutto, tre cose accadono contemporaneamente:

    1) I caratteri sfumano - la cosa ottimale e' che cmq. usano sfumature di verde e basta.
    2) I caratteri cambiano tra di loro velocemente.
    3) Il carattere della testa della scia parte con il bianco da un punto alto dello schermo e scende in un punto basso.

    Per quanto riguarda la partenza e l'arrivo delle varie scie, sicuramente ci sara' un effetto RANDOM, mentre per quanto riguarda la sfumatura del verde verso il nero e anche per quanto riguarda il fatto che i caratteri cambiano velocemente tra di loro, non mi pare ci sia un effetto random, ma piuttosto un effetto controllato.

    Cioe' quando parte la scia da un punto casuale dello schermo, il carattere e' bianco e tutta la scia che crea dall'alto verso il basso segue la regola che dal bianco sfuma in verde per sfumare pian piano verso il nero, quando la scia termina. (Quindi il colore e' controllato e non random).

    I caratteri che si scambiano tra loro velocemente a rotazione sembrano sempre uguali, quindi immagino che anche questo non sia random ma controllato.

    Infine l'algoritmo che viene utilizzato per dare l'impressione che tutto si svolga contemporaneamente e' abbastanza semplice. In effetti non fa' niente in contemporanea, ma esegue le varie operazioni cosi velocemente che sembra faccia tutto insieme.

    Per essere piu' chiaro... prova a creare una funzione che comando dopo comando:
    PRIMO alterna due caratteri.
    SECONDO varia il colore dei due caratteri.
    TERZO li fa scendere incolonnati dall'alto verso il basso dello schermo.
    Tutto questo naturalmente istruzione dopo istruzione e non prima la sola rotazione dei caratteri, poi l'alternaza dei colori e poi la discesa dall'alto in basso della colonna, Altrimenti invece che ottenere un effetto ottico stile matrix, otterrai le tre operazioni separate e non fatte contemporaneamente.

    Questa prova puoi farla inizialmente non per tutto lo schermo ma per una solo colonna, giusto per avere le idee piu' chiare e vedere anche se potrebbe essere meglio l'utilizzo di un ciclo di for... piuttosto che un while... o viceversa.

    Se riesci naturalmente, evita a priori chiamate di salto tipo GOTO. Non fanno propriamente un buon programmatore chi utilizza tali chiamate.
  • Re: Gestione del cursore in una finestra console e matrix effect

    Intanto grazie mille a tutti per gli spunti

    @vbextreme: ho visto il tuo algoritmo, devo ancora capire bene alcune parti ma ci sono spunti interessanti (comunque non mi funziona perchè non so quali librerie includere all'inizio).

    @ale99: le matrici e i vettori li conosco e li so gestire in C, il codice che avevo scritto io era proprio un'inizio ma inizio:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <windows.h>
    #include <unistd.h>
    
    
    void gotoxy(int xpos, int ypos)
    {
        HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO cinfo;
        GetConsoleScreenBufferInfo(out, &cinfo);
        cinfo.dwCursorPosition.X = xpos;
        cinfo.dwCursorPosition.Y = ypos;
        SetConsoleCursorPosition(out, cinfo.dwCursorPosition);
    }
    
    
    int main()
    {
        int a,i,n=20;
        char b;
        system("COLOR 0A");
        for (i=0; i<n; i++)
        {
            srand(rand() + clock() + time(NULL));  //inizializzazione rand
            a=rand()%13+224;
            b=a;
            printf("%c\n",b);
            Sleep(100);       //150 millisecondi di pausa
        }
        gotoxy(0,0);
        for(i=0; i<n+1; i++)
        {
            printf("%c",(char)0);
            gotoxy(0,i);
            Sleep(100);
        }                                   //r va all'inizio della riga, \b indietro di un carattere
        return 0;
    }
    
    @ramrack: per quanto riguarda la sfumatura si, l'effetto è controllato come dici tu, per quanto riguarda il fatto che i singoli caratteri cambiano tra di loro, io intendo che ogni carattere diverso dal nero associato ad un punto della matrice cambia ad una frequenza random diversa ( fissa finchè il carattere non diventa nero) per ogni punto della matrice...
  • Re: Gestione del cursore in una finestra console e matrix effect

    Il codice postato richiede un set di librerie propriearie non obbligatorie.
    Per non utilizzare tale librerie dovrai implementare te le funzioni:
    queste sono le classiche funzioni per console:
    
    void con_gotoxy (short x,short y)
    {
        HANDLE hconsole  = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD coord = {x, y};
        SetConsoleCursorPosition (hconsole,coord );
    }
    
    void con_cls()
    {
        HANDLE hconsole  = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        const COORD startCoords = {0,0};
        DWORD dummy;
        GetConsoleScreenBufferInfo(hconsole,&csbi);
        FillConsoleOutputAttribute(hconsole,0,csbi.dwSize.X * csbi.dwSize.Y,startCoords,&dummy);
        FillConsoleOutputCharacter(hconsole,' ',csbi.dwSize.X * csbi.dwSize.Y,startCoords,&dummy);
        con_gotoxy(0,0);
    }
    
    void con_colorset(unsigned short color)
    {
        SetConsoleTextAttribute(hconsole,color);
    }
    
    L'unica cosa da modificare nel mio codice oltre l'inserimento delle suddette funzioni è che ti ho postato la colorset specifica per window,quindi invece che due parametri ne hai uno solo,non mi ricordo a memoria il colore del verde ma avendo a disposizione 16 colori non farai fatica a trovarlo,parti dal 7 che è quello di default della console.

    per finire thr_sleep() non è altro che la classica Sleep() di windows.
    
    void mth_initrandom()
    {
        srand((unsigned)time(NULL));
    }
    
    int mth_random(int n)
    {
        return rand() % (n+1);
    }
    
    int mth_randomrange(int min,int max)
    {
        return min + (rand() % (max-min+1));
    }
    
    eccoti le random.
    
    #include <windows.h>
    #include <unistd.h>
    
    ???includi uni sotto win???



    Tornando al progetto inizia con le cose semplici e dimenticati troppi effetti sui colori perchè la console non te ne permette troppi.
    Un accrocchio carino sarà piu che sufficiente.
  • Re: Gestione del cursore in una finestra console e matrix effect

    ...
    Allegati:
    Eccoti un'anteprima
    Eccoti un'anteprima
  • Re: Gestione del cursore in una finestra console e matrix effect

    Ho sistemato aggiungendo le funzioni che hai messo sopra, ho proprio levato quella per il colore in modo da lasciare i caratteri bianchi (per vedere se andava così intanto) e cambiato thr_sleep con Sleep. Così si compila senza errori solo che dopo un tot di secondi (che variano di volta in volta ma di solito sono pochi) il programma si blocca e appare la finestrella che dice "il programma ha smesso di funzionare".

    Per quanto riguarda i progressi con la mia versione, io infatti come ho scritto in un post sopra avevo messo come ipotesi iniziali di non fare le sfumature e di usare caratteri diversi da quelli del video dell'animazione...

    Poi chiaramente certo che parto da cose semplificate: sono partito con una versione di una sola colonna che scorre in giù, se fai girare il mio codice, che ho messo sopra, lo vedi...

    Una cosa: perchè non va bene includere uni sotto win? Scusa la mia inesperienza
  • Re: Gestione del cursore in una finestra console e matrix effect

    Ho provato a fare questo.
    é pieno di bug ma può darti un'idea alternativa.
    Non ha funzioni particolari di windows e compagnia bella

    Funziona per un po' ma poi non crea più linee... vedi tu
    #include <stdio.h>
    #include <windows.h>
    #include <stdlib.h>
    #include <time.h>
    #include <unistd.h>
    
    #define X 79
    #define Y 56
    
    #define N_SYM sizeof(symbol)
    
    char symbol[] = {" abcdefghilmnopqrstuvzABCDEFGHILMNOPQRSTVZ0123456789£$%&§@#"};
    
    typedef struct __matrice
    {
        char c;
        // unsigned short color;
        char pos;
    } _matrice;
    
    _matrice matrice[X][Y];
    _matrice matrice2[X][Y];
    
    int i,j;
    
    
    void colorset(unsigned short color)
    {
        HANDLE hconsole  = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hconsole,color);
    }
    
    void gotoxy(int xpos, int ypos)
    {
        HANDLE hconsole  = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD coord = {xpos, ypos};
        SetConsoleCursorPosition (hconsole,coord );
    }
    
    void initMatrice()
    {
        for(i=0; i<X; i++)
            for(j=0; j<Y; j++)
            {
                matrice[i][j].c=symbol[0];
                matrice[i][j].pos=0;
            }
    
        return;
    }
    
    void initMatrice2()
    {
        for(i=0; i<X; i++)
        {
            for(j=0; j<Y; j++)
            {
                matrice2[i][j].c=matrice[i][j].c;
                matrice2[i][j].pos=matrice[i][j].pos;
            }
        }
    }
    
    char newSymbol()
    {
        return symbol[(rand()%N_SYM)];
    }
    
    void copyMatrice()
    {
        for(i=0; i<X; i++)
        {
            for(j=0; j<Y; j++)
            {
                matrice[i][j].c=matrice2[i][j].c;
                matrice[i][j].pos=matrice2[i][j].pos;
            }
        }
    }
    
    void spawnLine()
    {
        for(i=0; i<X; i++)
        {
            for(j=0; j<Y-4; j++)
            {
                if(matrice[j][i].c==symbol[0] && matrice[j][i+1].c==symbol[0] && matrice[j][i+2].c==symbol[0]
                        && matrice[j][i+3].c==symbol[0])
                {
                    if(rand() % 5000 == 0)
                    {
                        matrice[i][j].c=newSymbol();
                        matrice[i][j].pos=1;
                    }
                }
            }
        }
    
        return;
    }
    
    
    void changeSymbol()
    {
        for(i=0; i<X; i++)
            for(j=0; j<Y; j++)
                if(matrice[i][j].c!=symbol[0] && matrice[i][j].pos!=0)
                    if(rand() % 5 == 0)
                        matrice[i][j].c=newSymbol();
    
        return;
    }
    
    void markLine()
    {
        for(i=0; i<X; i++)
        {
            for(j=0; j<Y; j++)
            {
                if(matrice[i][j].c==symbol[0] && matrice[i][j+1].c!=symbol[0] && matrice[i][j+1].pos!=0)
                {
                    matrice[i][j+1].pos=rand()%30;
                }
            }
        }
    
        for(j=0; j<X; j++)
        {
            if(matrice[i][0].c!=symbol[0] && matrice[i][0].pos!=0)
            {
                matrice[i][j+1].pos=rand()%30;
            }
        }
    
        return;
    }
    
    void deleteLine()
    {
        initMatrice2();
    
        for(i=0; i<X-1; i++)
        {
            for(j=0; j<Y; j++)
            {
                if(matrice[i][j].pos==0 && matrice[i][j].c!=symbol[0])
                {
                    matrice2[i][j+1].pos=0;
                    matrice2[i][j].c=0;
                }
            }
        }
    
        copyMatrice();
    
        return;
    }
    
    void continueLine()
    {
        initMatrice2();
    
        for(i=0; i<X; i++)
        {
            for(j=0; j<Y-1; j++)
            {
                if(matrice[i][j].c!=symbol[0] && matrice[i][j+1].c==symbol[0])
                {
                    matrice2[i][j+1].c=newSymbol();
                    matrice2[i][j+1].pos=1;
                }
            }
        }
    
        copyMatrice();
    
        return;
    }
    
    void printMatrice()
    {
        gotoxy(0,0);
        colorset(10);
        for(j=0; j<Y; j++)
        {
            for(i=0; i<X; i++)
            {
                printf("%c", matrice[i][j].c);
            }
            printf("\n");
        }
    
        return;
    }
    
    /*
    void printMatrice_2()
    {
        gotoxy(0,0);
        for(j=0;j<Y;j++){
            for(i=0;i<X;i++){
                printf("%c", matrice[i][j]);
            }
            printf("\n");
        }
    
        return;
    }
    
    void spawnLine_2()
    {
        for(i=0;i<X;i++){
            for(j=0;j<Y;j++){
                if(matrice[j][i]!=symbol[0] && matrice[j][i+1]!=symbol[0] && matrice[j][i+2]!=symbol[0]
                   && matrice[j][i-1]!=symbol[0] && matrice[j][i-2]!=symbol[0]){
                        if(rand() % 5000 == 0)    matrice[i][j]=symbol[0];
                   }
            }
        }
    
        return;
    }
    
    void continueLine_2()
    {
        for(i=0;i<X;i++){
            for(j=0;j<Y;j++){
                if(matrice[i][j]==symbol[0] && matrice[i][j+1]!=symbol[0]){
                        matrice2[i][j+1]=symbol[0];
                   }
            }
        }
    
        copyMatrice();
    
        return;
    }*/
    
    
    
    
    int main(int args, char **argv)
    {
        srand((unsigned int)time(NULL));
    
        initMatrice();
    
    //   printMatrice();
    
        while(1)
        {
            spawnLine();
            continueLine();
    
            markLine();
            deleteLine();
    
            changeSymbol();
    
            printMatrice();
        }
    
        /*int k;
    
        while(1){
            for(k=0;k<200;k++){
                spawnLine();
                continueLine();
    
                printMatrice();
            }
    
            for(k=0;k<200;k++){
                spawnLine_2();
                continueLine_2();
    
                printMatrice_2();
            }
        }*/
    
    
        return 0;
    }
  • Re: Gestione del cursore in una finestra console e matrix effect

    La tua versione non è male... Ho provato e gira, i problemi sono che va un pò troppo veloce e a scatti, e le colonne si dovrebbero muovere come ho fatto io nell'abbozzo con una colonna. Il fatto però che i caratteri cambino ognuno con una frequenza quello si, vedo che l'hai fatto

    Ti messo una cosa che ho fatto prima, è fatta coi comandi di base perchè il mio livello è quello, non è neanche minimamente vicina a come dovrebbe venire veramente. C'è giusto il fatto che le colonne si creano in un punto casuale e finiscono in un punto casuale. Inoltre una volta che si è creato un carattere non nero in una colonna, è alta la probabilità che anche il carattere dopo sia non nero, mentre una volta che se ne crea uno nero, è alta la probabilità che anche quello dopo sia nero.
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <windows.h>
    #include <unistd.h>
    
    #define Rmax 100
    #define Cmax 80
    
    
    void gotoxy(int xpos, int ypos)
    {
        HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO cinfo;
        GetConsoleScreenBufferInfo(out, &cinfo);
        cinfo.dwCursorPosition.X = xpos;
        cinfo.dwCursorPosition.Y = ypos;
        SetConsoleCursorPosition(out, cinfo.dwCursorPosition);
    }
    
    
    int main()
    {
        char M[Rmax][Cmax];
        int a,i,j;
        char vet[20],vet2[20];
        system("COLOR 0A");
        vet[0]=(char)0;
        vet[1]=(char)0;
        for (i=2; i<20; i++)
            vet[i]=(char)(224+i);
        vet2[19]=(char)224;
        for(i=0; i<19; i++)
            vet2[i]=(char)0;
    
        for (i=0; i<Rmax; i++)
        {
            for(j=0; j<Cmax; j++)
            {
                srand(rand() + clock() + time(NULL));
                a=rand()%20;
                if(M[i-1][j]==(char)0)
                    M[i][j]=vet2[a];
                else
                    M[i][j]=vet[a];
                gotoxy(j,i);
                printf("%c",M[i][j]);
            }
            Sleep(50);
        }
        return 0;
    }
    
    
  • Re: Gestione del cursore in una finestra console e matrix effect

    Devi eseguire il mio codice con la finestra a schermo intero o cambiare i due valori #define.
    Io ho provato solo a schermo intero.

    Altrimenti viene un obrobrio spaventoso!
  • Re: Gestione del cursore in una finestra console e matrix effect

    Ah è vero, ora si che ci siamo! Beh così è quasi perfetto
Devi accedere o registrarti per scrivere nel forum
50 risposte