Oppure

Loading
19/11/15 15:21
3E8b12
Salve a tutti, dopo aver posto la domanda sulle matrici in c++ (e aver ottenuto validissime solzioni che però ho applicato solo su scacchiere) ho deciso di riprodurre l'intero gioco di PacMan (ma in python), e ci sono (quasi) riuscito, il gioco funziona perfettamente, ma odio con anima e corpo quei dannati muri :grr:.
Mi spiego, e spero di essere il più chiaro possibile:
Premetto di aver utilizzato le classi astratte.
All'interno del metodo __init__ del ghost ho dichiarato le seguenti variabili:
(chiaramente non posto ora TUTTO il codice completo del gioco, ma solo le porzioni interessate, spero comunque di poterlo fare nei prossimi giorni proprio su questo sito)
    
        self._x, self._y = x, y
        self._dx, self._dy = 0, 0#delta x e y
  

        self._costante_x, self._costante_y = 110, 88#punto dove devo arrivare
        self._attuale_x, self._attuale_y, self._w, self._h = self.rect()#il metodo rect mi restituisce sempre "x,y,w,h", ma a noi interessano solo x e y in questo caso


        self._COmAT_x = self._costante_x - self._attuale_x#COSTANTE meno ATTUALE X
        self._COmAT_y = self._costante_y - self._attuale_y#COSTANTE meno ATTUALE Y

Io quindi ho una classe Ghost, con il proprio metodo collide, rect, movimento ecc..
Il metodo movimento è sempre in funzione, quindi bisognerebbe immaginarlo COME SE FOSSE un ciclo, e questo è un codice FUNZIONANTE solo se non si tengono in considerazione i muri al momento della "morte" dei fantasmi (ma io voglio una copia fedele del gioco :heehee: )
    def movimento(self):
            self._attuale_x, self._attuale_y, self._w, self._h = self.rect()
            self._COmAT_x = self._costante_x - self._attuale_x
            self._COmAT_y = self._costante_y - self._attuale_y
            
            if self._COmAT_x < 0:
                self._x = self._x - 2
                        
            elif self._COmAT_x > 0:
                self._x = self._x + 2
                        
            if self._COmAT_y < 0:
                self._y = self._y - 2
                        
            elif self._COmAT_y > 0:
                self._y = self._y + 2
        

premessa, ovviamente ho già un metodo di nome GTW(GoingToWall) che mi dice se sto andando o meno su un muro.
Ad esempio:
 if not (GTW(ClasseAstratta,self,[b]self._DX[/b], [b]self._DY[/b])):

che si traduce in "SE NON TI SCONTRI CONTRO UN MURO.
Scrivo questo post di fretta, quindi nell'eventualità di aver omesso un dettaglio importante, o di non essere stato abbastanza chiaro, fatemelo sapere.
Ultima modifica effettuata da 3E8b12 19/11/15 15:23
aaa
20/11/15 8:59
HeDo
mi dispiace ma non si è capito molto, aggiungi dei dettagli altrimenti non possiamo aiutarti
aaa
20/11/15 16:47
3E8b12
Postato originariamente da HeDo:

mi dispiace ma non si è capito molto, aggiungi dei dettagli altrimenti non possiamo aiutarti

Sì, scusami ;).
In sostanza, tenendo conto di avere un punto A e un punto B, come faccio a tracciare il percorso che il Ghost deve seguire al momento della morte, tenendo conto dei muri proprio della mappa di pacman?
Io nella versione attuale riesco a farli tornare in base solamente facendogli seguire un percorso retto, e rendendo i muri "incosistenti" fino alla "rigenerazione".
Proprio non mi viene semplice fargli seguire il percorso più breve della mappa...
aaa
20/11/15 17:16
HeDo
Semplicemente perchè ti manca un po di teoria di base.
Qui c'è la formalizzazione del tuo problema e anche alcuni algoritmi che lo risolvono

en.wikipedia.org/wiki/…
aaa
20/11/15 20:42
lumo
Senza scomodare troppo grafi eccetera (anche se ti consiglio di studiarli bene, prima o poi servono), un modo semplice potrebbe essere quello di determinare prima che inizi la partita il percorso che da una casella porta al centro.

WARNING: mi è balenata in testa ora, non garantisco nulla

per ogni casella definisci due cose:
1) distanza minima dall'ingresso del box in centro (numero intero >= 0)
2) direzione di percorrenza (le quattro direzioni oppure fermo, capirai poi perché;)

(di fatto mi sto definendo un potenziale e un gradiente discreto, si vede che qualcosa di analisi 2 mi sta entrando in testa :| )

L'algoritmo è una cosa simile (pseudocodice):
def calcola_matrice_movimento(griglia_gioco, nodi, (x_safe, y_safe, w_safe, h_safe)):
    dist = array bidimensionale con le stesse dimensioni di griglia_gioco # all'inizio tutti -1 
    dir = array bidimensionale con le stesse dimensioni di griglia_gioco

    # inizializzazione: marcare la zona safe dove i fantasmini staranno fermi
    for x in range(x_safe, x_safe+w_safe):
        for y in range(y_safe, y_safe+h):
            dir[x][y] = fermo
            dist[x][y] = 0

    while len(nodi) > 0:
        nodo = nodi.pop() # sarebbe meglio estrarre il primo nodo, ma le liste python fanno schifo
        best_dir = None
        min_dist = float('inf')
        for x, y, direzione in nodi_adiacenti(griglia_gioco, x, y): # nodi
            if not muro(x, y):
                if dist[x][y] != -1: #nodo già processato
                    if dist[x][y] < min_dist:
                        min_dist = dist[x][y]
                        best_dir = direzione # nota: direzione è la direzione da 'nodo' al nodo (x,y)
                    else:
                        nodi.append(nodo) # il nodo verrà processato dopo
        dir[x_nodo][y_nodo] = best_dir
        dist[x_nodo][y_nodo] = min_dist + 1

    return dir

Devi chiamare la funzioni usando come argomento 'nodi' il nodo (o i nodi) che si affacciano sulla zona safe (la porta in pratica).
A questo punto ti basta usare la matrice risultante per muoverti (ogni volta devi seguire la "freccia" indicata).
L'unica difficoltà sono le funzioni che prendono i nodi adiacenti considerando bordi & so on

Ultima modifica effettuata da lumo 20/11/15 20:45
aaa
26/11/15 17:46
3E8b12
Semplicemente perchè ti manca un po di teoria di base.
Qui c'è la formalizzazione del tuo problema e anche alcuni algoritmi che lo risolvono

en.wikipedia.org/wiki/…

Grazie per il suggerimento ;)
Postato originariamente da lumo:

Senza scomodare troppo grafi eccetera (anche se ti consiglio di studiarli bene, prima o poi servono), un modo semplice potrebbe essere quello di determinare prima che inizi la partita il percorso che da una casella porta al centro.

WARNING: mi è balenata in testa ora, non garantisco nulla

per ogni casella definisci due cose:
1) distanza minima dall'ingresso del box in centro (numero intero >= 0)
2) direzione di percorrenza (le quattro direzioni oppure fermo, capirai poi perché;)

(di fatto mi sto definendo un potenziale e un gradiente discreto, si vede che qualcosa di analisi 2 mi sta entrando in testa :| )

L'algoritmo è una cosa simile (pseudocodice):
def calcola_matrice_movimento(griglia_gioco, nodi, (x_safe, y_safe, w_safe, h_safe)):
    dist = array bidimensionale con le stesse dimensioni di griglia_gioco # all'inizio tutti -1 
    dir = array bidimensionale con le stesse dimensioni di griglia_gioco

    # inizializzazione: marcare la zona safe dove i fantasmini staranno fermi
    for x in range(x_safe, x_safe+w_safe):
        for y in range(y_safe, y_safe+h):
            dir[x][y] = fermo
            dist[x][y] = 0

    while len(nodi) > 0:
        nodo = nodi.pop() # sarebbe meglio estrarre il primo nodo, ma le liste python fanno schifo
        best_dir = None
        min_dist = float('inf')
        for x, y, direzione in nodi_adiacenti(griglia_gioco, x, y): # nodi
            if not muro(x, y):
                if dist[x][y] != -1: #nodo già processato
                    if dist[x][y] < min_dist:
                        min_dist = dist[x][y]
                        best_dir = direzione # nota: direzione è la direzione da 'nodo' al nodo (x,y)
                    else:
                        nodi.append(nodo) # il nodo verrà processato dopo
        dir[x_nodo][y_nodo] = best_dir
        dist[x_nodo][y_nodo] = min_dist + 1

    return dir

Devi chiamare la funzioni usando come argomento 'nodi' il nodo (o i nodi) che si affacciano sulla zona safe (la porta in pratica).
A questo punto ti basta usare la matrice risultante per muoverti (ogni volta devi seguire la "freccia" indicata).
L'unica difficoltà sono le funzioni che prendono i nodi adiacenti considerando bordi & so on


Scusami se rispondo solo ora, ma il tempo mi è avverso...
Ottimo, grazie mille :k:
Proverò questa soluzione più avanti, sicuramente potrà essermi utile anche per altro (oltre quelle "scartoffie" che sto già studiando).
Rifinisco alcuni semplici dettagli e carico qui il progetto, (anche se ho avuto problemi a caricare sorgenti:-?)
si vede che qualcosa di analisi 2 mi sta entrando in testa :|

Io sono alle prese con analisi 1...:pat:
aaa