PDA

View Full Version : Oltre ogni mia comprensione!


visual_b
20-07-2005, 15:53
Sono uno studente autodidatta privatista di in formatica delle superiori e sto facendo un programma in vb 6 per potermi allenare con le tecniche studiate.

Il progetto in questione è una versione e-emhhh.. come dire.... "personalizata", di campo minato, ultimata al 90%.

Ma il programma (tralasciando alcune funzionalità extra che devo ancora implementare) presenta due gravi bug e comportamenti inspiegabile che vanno molto oltre le mie capacità:


1°) Se il campo di gioco è quadrato tutto ok, ma se ha un numero di righe diverso da quello delle colonne mi scopre caselle diverse da quelle premute con il mouse.

P.S. Nessun progresso :( :(


2°)La tabella con i punteggi viene cancellata tutte le volte che chiudo il form FrmClassifica, senza un motivo apparente!

P.S. Risolto!

Nell' evento queryUnload disattivo la chiusura del form e lo rendo invisibile.
Nel pulsante che mostra la classifica nel form principale ho modificato il codice in modo che usi il comando Show la prima volta che viene aperta la tabella, e setti la propietà visible a true tutte le altre volte.

In questo modo si consuma un pò più di memoria ram ma si risparmia tempo di CPU.


Se poi trovate altri errori o parti migliorabili avvisatemi.

Avviso che ho la bruttisima tendenza a dare NOMI STUPIDI a variabili e funzioni e spesso il codice risulta un pò oscuro,ma HO COMMENTATO TUTTE LE PARTI INNERENTI AL PROBLEMA per cui non dovrebbero esserci difficoltà.

Spedisco l'intero progetto in formato Zip. Ri-aggiornato

BigBug
20-07-2005, 16:41
2°)La tabella con i punteggi viene cancellata tutte le volte che chiudo il form FrmClassifica, senza un motivo apparente!

le variabili nascono e muoiono all'interno del form,
ma cmq dovresti imparare la lettura e scrittura sul file, così la classifica rimane sempre in memoria...
ciao

visual_b
20-07-2005, 16:53
E' gia memorizzato in un file.

Non volevo rieditare la tabella inutilmente.

E se faccio semplicemete diventare invisibile il form?

La tabella rimane? E le prestazioni migliorano?

visual_b
20-07-2005, 20:37
3°) Le caselle "catturano" l' evento move del mouse quando vengono premute, quindi anche spostandosi da una casella, se la si tiene premuta, gli eventi mouse move delle altre caselle non si attivano.

Lo stesso accade se si esce con il mouse fuori dall' area di gioco, (per esempio sul dekstop), si tiene premuto il 1° pulsante del mouse e si rietra sul campo di gioco.

Sembrerebbe cosa da poco se cio non bastasse a neutralizzare l' effetto dei soldati nemici. (tutti tranne il cecchino :D )

4°) Tutti i soldati nemici non "ti vedono" se stai fermo con il mouse su una casella senza premere un bottone. Infatti lo "sparo" dei soldati è attivato da un evento MouseMove sulla casella, e questo evento non si verifica se tu sei fermo, ma solo se passi su una casella su cui c'è un soldato.

Nel caso del cecchino non è un problema, in quanto se non "ti vede" (attivi un evento MouseMove su una casella) per più di 2 Sec. muori lo stesso, e muori anche se rimani fermo per più di 0,2 Sec. per poi muoverti.

Ma con gli altri due tipi di nemici basta "stare fermi" per esserne immuni.

Spero di essere stato chiaro.

visual_b
21-07-2005, 10:10
Per comodità vostra inserisco una parte del codice qui:

Codice (parziale) del form principale


Option Explicit
Public fi As Campo

'Questa sub crea il campo da gioco
Sub AAA(ByVal rig As Byte, ByVal col As Byte)
If metag > 0 Then Call reset 'cancella il vecchio campo da gioco se neccesario
Set fi = New Campo 'ricrea la sua controparte oggetto
Dim o As Integer
metag = (CLng(rig) * col) - 1 'qui conservo il numero totale di caselle
Call fi.dime(rig, col) 'imposto le dimensioni: vedi l'oggetto campo
Call ini(0) 'imposto i valori iniziali delle caselle: vedi sub Ini
For o = 1 To metag 'in questo for posiziono le nuove caselle create
Load Imgcas(o)
If o Mod col = 0 Then
Imgcas(o).Move 0, Imgcas(o - 1).Top + 240, 255, 255
Else
Imgcas(o).Move Imgcas(o - 1).Left + 255, Imgcas(o - 1).Top, 255, 255
End If
Call ini(o) 'imposto il valore iniziale della casella: vedi sub Ini
Next
Me.Height = Imgcas(metag).Top + 945 'ridimensiono opportunamente il form
Me.Width = Imgcas(metag).Left + 365
If imgstpd.Tag = 2 Then Call pi2(0) 'guardo che la faccina sia giusta e la posiziono
imgstpd.Left = Imgcas(Fix(fi.cmax / 2)).Left - 165 + (fi.cmax Mod 2) * 123
lbltempo.Left = imgstpd.Left + 830 'imposto l' etichette con il tempo e con le bandiere e el posiziono
fi.unti = metag * Fix(15 + metag / 250) / 100
lblmine = fi.unti ' Se per test volete vincere sostituire la precedente istruzione con ==> lblmine =1
fi.unti = fi.unti * 10 'imposto il punteggio
Call fi.mine ' posiziono le mine: vedi oggetto Campo
End Sub

'Possibile (Molto Probabile!!!) fonte del 1° problema: La sub che risponde alla pressione della casella
Private Sub Imgcas_MouseUp(Index As Integer, Button As Integer, Shift As Integer, x As Single, y As Single)
ReDim te(2) As Byte 'qui ci saranno le coordinate della casella
If Button = 1 Then
If Imgcas(Index).Tag = 1 Then ' Equivale a: "Se la casella è coperta..""
te(0) = Fix(Index / fi.cmax) 'RIGHE SOSPETTE! scrivo le coordinate della matrice bidimensionale ricavandole da quella monodimensionale
te(1) = Index Mod fi.rmax
Call fi.poli(te(), 1) ' Il resto del codice di questa sub è sicuro (credo!)
Call fi.uin
If fi.p = 0 Then If Not TmrZoc.Enabled Then TmrZoc.Enabled = True
End If
End If
If Not xxx Is Nothing Then
With xxx
.ntag = Imgcas(Index).Tag
End With
End If
End Sub

Private Sub ini(ByVal o As Integer)
Call pi(o, 0)
Imgcas(o).Visible = True
Call fi.im(Imgcas(o), o) 'collego la casella con il suo corrispondente nell' oggetto Campo: Controllare in Campo la sub Im!
End Sub

visual_b
21-07-2005, 10:15
Codice (sempre parziale) dell' oggetto Campo:


Option Explicit
Private g() As Casella
Public cmax, rmax As Byte
Public pt As Byte
Private time As Long


' sub che gollega la cassella al suo corrispondente
Sub im(imm As Image, o As Integer)
Dim r As Byte
r = Fix(o / cmax)
o = o Mod cmax
Set g(r, o).A = imm
End Sub

' sub per il dimensionamento del campo di gioco
Sub dime(ByVal rig As Byte, ByVal col As Byte)
If rig > 3 And col > 3 Then
cmax = col
rmax = rig
ReDim g(rmax, cmax) As Casella
End If
time = rmax * cmax / 2.4
End Sub


Definizione di casella in un modulo Bas standar


Type Casella
A As Image
m As Byte
t As Integer
End Type

visual_b
21-07-2005, 17:32
Niente? Nessun commento, nessuna risposta?

Nemmeno tu, cionci, dici qualcosa?

sirus
21-07-2005, 19:12
io e il VB siamo due cose opposte ma qualche cosuccia la so ;) tuttavia mi sembra che gli errori che hai identificato siano più che altro errori di progetto...
ora ho scaricato il progetto ;) domani installo il VB6 e provo a vedere se ci capisco qualche cosa ;) anche se non garantisco nulla :p

visual_b
21-07-2005, 19:16
ora ho scaricato il progetto domani installo il VB6 e provo a vedere se ci capisco qualche cosa anche se non garantisco nulla

Sono commosso! Non ci speravo più!

Grazie

sirus
21-07-2005, 19:43
Sono commosso! Non ci speravo più!

Grazie
ma ti pare...
comunque una mano me la daresti se scrivi due righe di come hai implementato il programma...una specie di analisi ;)

visual_b
21-07-2005, 21:33
Ci sono tre form:

Il principale con il campo da gioco, uno con i punteggi, uno con le opzioni per personalizare la partita.

Ai form secondari ci si accede selezionando la relativa voce nel menu, e per tornare in dietro basta chiuderli.

Ci sono quatro difficoltà, (l' ultima è nascosta) e inizialmente solo la più facile è sbloccata, poi completando un livello si accede a quello successivo.

In ogni livello del gioco ci sono ingredienti extra che non sono presenti nel prato fiorito di windows, evoluti a seconda della difficoltà:

- Le caselle si ricoprono dopo un tot di secondi. Più il livello di difficoltà è alto, più tempo ti viene concesso prima che ciò accada

- Ogni tanto degli aerei aggiungono mine. Attualmente in fase di programmazione.

- Soldati. Graficamente sono rapresentati da un mirino che si muove per il campo. Se ci passi sopra con il mouse muori. ce ne sono di tre tipi:

Il 1° si mouve lento sollo parallelamente agli assi e solo sulle caselle coperte.
Se non ha un attorno a lui una casella dove spostarsi sparisce.

Il 2° va in diagonale e sempre solo su caselle coperte, è veloce, e se rimane bloccato non sparisce, ma aspetta che le caselle si ricoprano e torna a muoversi.

il 3° e' l'unico che può muoversi dappertutto, è sempre a una casella di distanza dalla freccia del tuo mouse, e se ti fermi in una casella per più di tre decimi ti raggiunge. Muori anche se abbandoni il terreno di gioco.

I punteggi si basano sul numero di mine presenti nel campo, sul numero di soldati nemici, (+ un extra per quelli "uccisi"), e sul tempo impiegato, e vengono memorizati su un file (malamente) criptato per impedire che venga editato.

visual_b
21-07-2005, 22:01
prima ho spiegato com' è il gioco. Ora invece faccio uno schema generale del codice.

Le caselle compongono una matrice monodimensionale (ImgCas()) di controlli image creati dinamicamente, che durante il gioco prendo le immagini da un secondo array fisso che contiene tutte le figure (imgcrlt()).

Per poter lavorare più semplicemente ho creato una matrice bidimensionale di immagini (più altri dati che mi servivano) nell oggetto campo (fi.g()), e l' ho associata a quella sul form.

Esempio:

Ho un campo di 10 X 10 e le istruzioni imgcas(20) sul Form e g(2,0) in Campo puntano alla stessa casella.

Per evitare di fare controlli fra immagini, uso il tag delle caselle per contenere in numero di indice del relativo controllo image nel arrey imgcrtl().

Esempio:

Voglio controllare se una casella è coperta. L'immagine della casella copertà è contenuta nella posizione 0 dell' arrey imgcrtl().

al posto di usare questo controllo

if imgcas(index).picture=imgcrtl.picture(1) then

che è un controllo pixel per pixel dell 'intera bipman, all inizio assegno il numero dell immagine insieme all immagine stessa e poi faccio un confronto sui tag

imgcas(index).picture=imgcrtl(1).picture
imgcas(index).tag=1

.....

if imgcas(index).tag=1 then

visual_b
21-07-2005, 22:19
Ogni soldato (tranne il cecchino), è contenuto in un array dinamico di oggetti che viene ridimensionato a seconda del numero di caselle,e in base alle impostazioni della partita i soldati vengono divisi fra i 2 tipi, e viene assegnata loro una posizione casuale (controllando di non sovrapporli).


Nella sub Sol (che è quella dove vengono istanziati i soldati), viene creato un soldato ogni 100 caselle (se l'opzone è stata attivata) +1 (per arrotondamento), e se una sola tipologia è attiva, diventano tutti dello stasso tipo, mentre se sono presenti soldati di tutte e due i tipi, due terzi diventano del primo tipo (più semplici), e i restanti diventano del secondo

Esempi:

campo da 200 caselle, tutt' e due i tipi attivati ==> 2 del 1° tipo e 1 del 2°

campo da 780 solo primo tipo ==> 8 del 1°

campo da 50 solo 2°tipo ==> 1 del 2°

Il cecchino invece è sempre e solo uno, e viene semplicemente attivato con

set xxx= new cosone

(xxx è il nome della variabile e Cosone della classe oggetto)
(avevo già setto che ho usato nomi stupidi !!!!)

ho disattivato

set xxx= nothing

ha seconda della partita.

visual_b
21-07-2005, 22:41
Gli aerei e il "fattore sorpresa" sono in lavorazione.

Le impostazioni degli extra sono memorizati nella variabile globale di un byte GTO nel modulo bas standar settando a 0 o 1 il bit relativo all impostazione.

Ordine dei bit:

1°- soldati semplici (bit a 0 disattivato/bit a uno attivato)

2°- soldati plus "" ""

3°-cecchino "" ""

dal 4° al 6° Aerei "" ""

7°-fattore sorpresa "" ""

8°-vuoto

Esempio:

gto=3 (00000011 in binario) ==>i primi 2 tipi di soldato sono attivati

gto=68 (01000100 "" ) ==>fattore sorpresa e cecchino attivati

gto=127 (01111111 "" ) ==>attivato tutto

gto=0 (00000000 "" ) ==>niente di attivato


L' unico extra non disattivabile e sempre presente nel gioco è la ricopertura delle caselle.

Il numero di secondi prima che una casella si ricopra è uguale a il numero totale di caselle diviso 2,4

Esempio

campo 12*12==>144 caselle==> Le caselle rimangono scoperte 1 minuto

campo 20*30==>600 caselle==> Le caselle rimangono scoperte 4 min. e 10

Le mine sono presenti in percentuale variabile in dipendenza alle dimensioni del campo con una funzione matematica e che và dal 15% del livello più facile, al 20% del più duro.

visual_b
21-07-2005, 23:50
Schema Logico Generale


1) il programma si parte con il formV (il principale) vuoto.
2) si legge sul file "classifica.mine" il livello più difficile completato e si parte con quello successivo, altrimenti si parte con quello base
3)si controlla se c'e gia un campo sul form==> SI-prosegui / No-vai al 5)
4)distruggi il vecchio campo
5)le caselle nuove vengono create, impostate con l'immagine della casella chiusa
e associate al corrispondente nell' oggetto campo
6)in LblMine viene scritto il numero di bandiere a disposizione
7)la faccina e le caselle con il tempo e le bendiere vengono piazzati
8)nell 'ogg. Campo la sub Mine() aggiunge le mine in posizione casuale nelle caselle voute, scrive in un arrey le loro coordinate e passa l'arrey alla funzione Poli() (nota- il numero di mine è uguale a quello delle bandiere scritto in LblMine)
9)La funzione Poli nella classe ogg. Campo somma 1 alla variabile m di ogni casella addiacente alle coordinate dell' arrey
10)vengono creati e soldati e aerei
11)se si preme sulla faccina si comporta come un pulsante (cambio di "espressione") ==> SI- va al punto 3)/ NO- prosegui
12)quando la prima casella viene premuta si attiva il timer
13)i cicli del timer gestiscono il muovimento dei soldati, gli attachhi aerei e la ricopertura delle caselle. - vedi 18)
14)gli eventi del mouse sulle caselle gestiscono le bandiere, lo "sparo dei soldati", la scoppritura del terreno, la simulazione grafica di "pressione pulsante" e il "cambio di pressione" della faccina. - vedi 17)
15)se si scopre una casella vuota si passano le sue coordinate all' arrey della funzione Poli nell' ogg. Campo che svuota tutte le casselle addiacenti, e se fra loro scopre altri spazzi vuoti, li aggiunge all' arrey e ricomincia
16)controlla se si scopre una mina==>SI- vai a 26) / NO-prosegui
17)controlla se si passa su un soldato==>SI- vai a 26) / NO-prosegui
18)controlla se il tempo di una casella scoperta scade ricoprila
19)controlla se tutte le caselle coperte hanno sotto una mina o sono coperte da un soldato ==> SI- prosegui / NO- vai a 28)
20)faccina con occhiali da sole (vittoria)
21)controlla se ci si è classificati==> SI- Prosegui / No vai a 24)
22)Aggiungi il punteggio alla classifica nel file
23)Esegui 35) poi prosegui qui
24)blocca il timer e la possibilità di premere le caselle
25) Vai alla 2)
26)faccina da morto (sconfitta)
27)vai a 2)
28)scelta nel menù di una nuova partita con il livello di difficolta n°Tot==>vai a 3)
29)scelta nel menù di una nuova partita con il livello di difficolta personalizzato
30)nascodi FrmV
31)mostra FrmZ (form partita personalizata)
32)abilità le opzioni in base alle modalità di gioco sbloccate
33)imposta le scelte del giocatore sulla varaiabile globale GTO
34)alla chiusura di FrmZ nascondi FrmZ e mostra FrmV
35)Disabilità i punti
36)vai a 3)
37)scelta nel menù di mostrare la classifica
38)mostra il form FrmU

visual_b
22-07-2005, 00:11
Se voui sapere qualcosa di più specifico chiedi pure.

Se le mie spiegazioni (fatte da cane) non le capisci puoi sempre piazzare break point in massa per il gioco e provare.

Comunque oltre agli errori citati non DOVREBBERO essercene altri.

Grazie ancora.

visual_b
22-07-2005, 16:27
up

sirus
23-07-2005, 13:06
OK grazie per le INFO adesso le leggo e do un'occhiata al sorgente e faccio qualche prova di debug per capire dove sbaglia ;)

visual_b
27-07-2005, 18:28
sirus come và?

sirus
27-07-2005, 20:07
sirus come và?
non ho ancora capito l'intoppo dove sta :muro: comunque sto provando :D vedrai che qualche cosa la tiriamo fuori :mc:

visual_b
27-07-2005, 21:04
Grazie dell' aiuto. tiemmi aggiornato.

visual_b
25-08-2005, 21:02
up