Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - Tracking di oggetti
Forum - C# / VB.NET - Tracking di oggetti

Avatar
Thejuster (Member)
Guru^2


Messaggi: 1704
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 16:12
Mercoledì, 15/10/2014
Salve ragazzi.

Oggi espongo un mio piccolo dilemma al quale sto ancora pensando a come risolvere.
Ma non riesco a trovare un indizio o un qualche esempio su cui affidarmi.

Vi spiego semplicemente cosa voglio fare.

prendete esempio questa immagine.

http://www.gdunlimited.net/forums/uploads/gallery/category ...

sono tanti elementi grafici disposti su una griglia, ed ogni singolo oggetto ha come dimensione 32x32 px.

Ma ci sono alcuni oggetti che hanno dimensioni superiori esempio  32x64  o 64x64

quello che volevo fare era un tracking degli oggetti.

Ho pensato di usare il Bitmap.GetPixel  per sapere se l'oggetto continua o si ferma li a 32 pixel.

L'algoritmo che voglio scrivere è questo.


parto da 0 ed arrivo a 32.
se l'ultimo pixel 32 ha come colore trasparente, ferma e disegna un rettangolo 32x32
se invece non è di colore trasparente continua il traking fino a 64 ed esegui una nuova verifica.

Provando a fare ciò, sbaglio sicuramente qualche passaggio.
su alcune parti funziona ed alcune no.

Codice sorgente - presumibilmente C# / VB.NET

  1. Bitmap b = new Bitmap(Tileset); //Prendo la grafica
  2.  
  3.             Graphics g = Graphics.FromImage(b);
  4.  
  5.  for (int i = 0; i < b.Width; i += 32)
  6.                 {
  7.                     for (int j = 0; j < b.Height; j += 32)
  8.                     {
  9.                         Color c = b.GetPixel(i, j);
  10.  
  11. if (c.Name == "0")  //Se il colore è trasparente
  12. {
  13. g.DrawRectangle(Pens.Red, new Rectangle(i, j, 32, 32));
  14. }
  15.                             else
  16.                             {
  17.                                 g.FillRectangle(Brushes.Yellow, new Rectangle(i, j, 32, 32));
  18.                             }
  19.  
  20.  
  21.      }
  22.                 }





A sinistra l'immagine normale su griglia
a destra con il tracking

Dove sbaglio? o ancora meglio sapete un modo migliore per fare ciò?


Thejuster ha allegato un file: 2.JPG (95291 bytes)
Clicca qui per guardare l'immagine


PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6116
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 16:55
Mercoledì, 15/10/2014
Personalmente userei una mappa per collegare le immagini nella spritesheet a una lista di nomi --> cordinate.

In pratica un file secondario (di testo, puoi usare XML, JSON, quello che ti pare) dove per ogni immagine specifichi le coordinate X,Y e altezza e larghezza (width, height). Questo ovviamente dovrebbe essere generato automaticamente dal programma che crea la spritesheet.

Il bonus è che oltre ad avere le coordinate giuste, ora puoi anche inserire metadata come i nomi delle immagini. Ad esempio puoi scrivere codice del tipo:

Codice sorgente - presumibilmente Plain Text

  1. spritesheet.get("tree-1");



Dove "tree-1" è il nome di un'immagine.

La libreria libgdx utilizza quest'approccio.


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
Thejuster (Member)
Guru^2


Messaggi: 1704
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 17:37
Mercoledì, 15/10/2014
Si, a questo ci avevo pensato.
Però c'è un solo problema.

Questa funzione mi serviva per L'editor.
Ovvero per velocizzare il pick delle sprite.

del tipo cliccando sulla punta punta dell'albero che si troverebbe in 64 x 0 esempio
L'algoritmo verifica se la sprite e continua anche sotto, ed invece di prendere un solo pezzo
li prende entrambi in automatico. Quindi prenderebbe  64 x 0 e 64 x 32
non sò se mi sono spiegato bene.

Mentre per il lato Client ho fatto proprio come dici tu piero.

Ho creato una libreria che mi và a serializzare l'intero set di elementi. (Nome,W,H,IMG) in una lista
Ed anziché portarmi tutte le immagini nel file delle risorse, mi porto dietro l'immagine convertita in stringa ( base64 )

un pò come fà libgdx.

Con un unica differenza ovviamente. Il file serializzato è firmato dall'assembly.
Questo evita di poter leggere il file anche da altri programmi.

Così posso ricrearla dove e quando voglio. velocizzando anche il caricamento delle risorse.

PS:
Forse posso sbagliarmi sulla velocità. Ma sembra il metodo migliore per evitare fuga di risorse
o di manomissione dei soliti archivi rar o zip facilmente accessibili.


PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6116
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 17:52
Mercoledì, 15/10/2014
Mm, non sono sicuro di aver capito. Prova ad includere ulteriori dettagli o spiegazioni.


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
Thejuster (Member)
Guru^2


Messaggi: 1704
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 9:24
Giovedì, 16/10/2014
Ok provo a spiegare meglio.

Normalmente nel mio editor di livelli che ho creato apposta per un progetto.
Con una semplicissima funzione riesco a prendere una sprite di 32x32 dove il mouse và a cliccare

esempio

http://s9.postimg.org/oqbyq0mcf/image.jpg


Quello che volevo fare io, Utilizzando una sorta di algoritmo di tracking,
verificava se il blocco sottostante, o quello a destro o a sinistra continua, allora prende gli altri blocchi di sprite in auto

esempio:

http://s14.postimg.org/t5tbo9kw1/image.jpg

per fare ciò avevo pensato di controllare l'ultimo pixel alla fine del blocco


Codice sorgente - presumibilmente C# / VB.NET

  1. Color c = b.GetPixe(32,32);
  2.  
  3. if(c.Name == "0" || c.Name == "Transparent") { //Ferma, il blocco non è continua }
  4. else
  5. {
  6. //Il blocco continua quindi devo recuperare anche il pezzo in basso.
  7. }



Più o meno intendo far questo.
Ma come puoi notare dalla prima screen. ho problemi nel farlo.
alcuni elementi me li prende ed altri no.
Serve un metodo più affidabile


PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6116
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 14:46
Giovedì, 16/10/2014
Purtroppo non penso ci sia un metodo affidabile. Ci sono diversi algoritmi (lenti) che possono analizzare i contorni delle figure dell'immagine (vedi AForge), ma non sarà corretto il 100% delle volte. Ad esempio nela tua immagine la scatola piena di spade è messa vicino alla scatola di legno. Come fa il programma a distinguere le due?


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
Thejuster (Member)
Guru^2


Messaggi: 1704
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 17:41
Giovedì, 16/10/2014
A questo non avevo pensato.
(Sia alla lentezza che ad un tracking abbastanza efficiente. )

Piero, ultimo consiglio.
L'unica cosa che rimane da fare sarebbe quella di dare la possibilità all'utente di selezionare anche l'area sottostante.

Se vorrei fare che tenendo premuto il mouse e scendendo sotto all'altro blocco ( 32 x 32 ) mi seleziona entrambi i pezzi come potrei fare?

come in questa figura

http://s24.postimg.org/aqa87371x/image.jpg

( ovviamente partendo dall'alto e scendendo verso il basso. )

attualmente sulla griglia per recuperare un blocco uso

mouse_x / blocco_w * blocco_h

come faccio a fare in modo che l'utente scendendo il mouse sotto al 32 standard mi và a selezionare anche l'altra porzione
sottostante di 32?

ovviamente la stessa cosa poi deve accadere sull'asse X


PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6116
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 16:37
Venerdì, 17/10/2014
Con l'evento mousedown imposti una flag boolean a true (default false) e resetti i parametri usati qui sotto.

Con l'evento mousemove se la flag e' impostata a true, devi tener traccia di quali parti hai selezionato (magari un array bidimensionale di boolean). Per gestire gli incrementi, semplicemente controlla che mouse_x e mouse_y siano incrementi di 32 (int)(mouse_x / 32) --> [0, 1, 2, 3, ...] per la casella 0, 1, 2, 3, ... stessa cosa per mouse_y.

Dopodiche' controlla l'array per selezionare i blocchi.

Con l'evento mouseup imposti la flag boolean a false.


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote