erstmal ein Lob: tolles Forum und tolle Leute!
Ich habe mich jetzt mal registriert, nachdem mir das Forum schon unzählige Male weiter geholfen hat, und auch gleich mal eine Frage:
Ich möchte ein Spiel mit PyGame programmieren bei dem es um folgendes geht:
Man wird in einem zufällig generierten Labyrinth ausgesetzt und muss den Weg nach draußen finden. Blöd ist nur, es ist dunkel, man sieht also nichts.
Also läuft man mit dem Spieler (Im Moment mal ein roter Punkt) in eine Richtung, wenn jedoch eine Wand im Weg ist, so kommt man nicht weiter und diese wird im Spielfeld eingezeichnet.
Man macht also Wände sichtbar, in dem man dagegen läuft.
Das Spielfeld ist in Zellen eingeteilt, das kommt daher, dass das ursprünglich ein Spiel war, welches wir auf Karopapier gespielt haben
Später sind einige Dinge geplant, auf die Man im Labyrinth stoßen kann (Beispiele: Fällt man in einen Brunnen, so kommt man irgendwo anders im Labyrinth wieder heraus, man weiß aber nicht wo, oder: Es gibt einen Minotaurus,
dieser jagt einen und kommt einem jedes Mal, wenn Man gegen eine Wand läuft eine Zelle näher.)
Nun ist ja bekannt, dass PyGame Programme eine Hauptschleife besitzen, die unablässig durchlaufen wird. Die Idee war also, alle Wände von Anfang an zeichnen zu lassen, allerdings schwarze Wände auf schwarzem Hintergrund.
Jedes Mal, wenn Man gegen eine Wand läuft, wird diese in eine Liste (bzw. Dictionary) hineingeschrieben, welche beim erneuten Zeichnen der Wände abgefragt und die darin eingetragenen (entdeckten) Wände sichtbar gezeichnet werden.
Unsichtbar werden alle Wände gezeichnet (das sieht Man, wenn man die Farbe dieser ändert), bei den sichtbare (entdeckten) Wänden gibt es aber ein Problem:
Läuft der Spieler von rechts nach links gegen eine Wand, so wird diese sichtbar eingezeichnet, genau so von unten nach oben.
Läuft er jedoch von links nach rechts oder von oben nach unten gegen eine Wand, so wird diese gar nicht eingezeichnet. Dabei ist das die ein und die selbe Funktion !? Wieso?
Ich habe überprüft, ob die Funktion aufgerufen wird und ja: das Skript wird vollständig ausgeführt, nur der Befehl pygame.draw.line() wird für die oben beschriebenen Fälle "übergangen"?!
Ich habe die betreffende Funktion Mal mit ####### PROBLEM ####### gekennzeichnet, ich habe auch versucht, das Programm verständlich zu machen. Hier der Code:
Code: Alles auswählen
import pygame as pg
import random
BREITE = HÖHE = 1000 #
SPALTEN = ZEILEN = 30 # quadratische Sielfläche; quadratische Zellen
ZE_BH = BREITE // SPALTEN #
quellposition = (-(ZE_BH // 2), -(ZE_BH // 2)) # Koordinaten, um von der Quellposition (links oben in z.B. einer Zelle)
# zur Mitte z.B. einer Zelle zu gelangen (wo der Spieler hin soll)
# QUELLPOSITION:
# Dies bezeichnet immer die "rechnerische" Position, welche auch der Zeichen-Algorythmus verwendet (am Anfang z.B. (0,0))
# pos/ NORMALE POSITION:
# Bezeichnet die "graphische" Position (in der Mitte einer Zelle), der spieler soll ja nicht immer links oben in einer Zelle kleben
delta_linien = {'l': [(0,0), (0,ZE_BH)], 'r': [(ZE_BH,0), (ZE_BH,ZE_BH)], 'o': [(0,0), (ZE_BH,0)], 'u': [(0,ZE_BH), (ZE_BH,ZE_BH)]}
delta_nachbarn = {'l': (-ZE_BH, 0), 'r': (ZE_BH, 0), 'o': (0, -ZE_BH), 'u': (0, ZE_BH)}
richtung_invers = {'l': 'r', 'r': 'l', 'o': 'u', 'u': 'o'}
wandverzeichnis = {}
entdeckte_wände = {'l':[], 'r':[], 'o':[], 'u':[]} # verzeichnet Wände, gegen die man bereits gelaufen ist
# (diese sollen später farblich markiert werden)
pg.init()
screen = pg.display.set_mode([BREITE, HÖHE])
farbe_hintergrund = pg.Color('Black') #
farbe_linie_sichtbar = pg.Color('White') # Wand erst sichtbar, wenn man sie entdeckt hat (s.o.)
farbe_linie_unsichtbar = pg.Color('Black') #
farbe_spieler = pg.Color('Red')
raster = {}
for i in range(SPALTEN*ZEILEN):
pos = i % SPALTEN * ZE_BH, i // SPALTEN * ZE_BH
raster[pos] = {'l', 'r', 'o', 'u'}
def add_pos(pos1, pos2): # um eine Positionen (Tupel) zu addieren
return pos1[0] + pos2[0], pos1[1] + pos2[1]
def zeichne_zelle(pos, wände):
for wand in wände: # wände enthält alle Wende, die eine Zelle hat (z.B.: 'l','r','u')
delta_von, delta_bis = delta_linien[wand] # wand = z.B.: 'l' oder 'r' oder 'u'
von = add_pos(pos, delta_von)
bis = add_pos(pos, delta_bis)
if pos in entdeckte_wände[wand]: # linie soll sichtbar gezeichnet werden, wenn man sie schon entdeckt hat
pg.draw.line(screen, farbe_linie_sichtbar, von, bis, 2) ############ PROBLEM ############
else: # ansonsten unsichtbar (schwarz auf schwarz)
pg.draw.line(screen, farbe_linie_unsichtbar, von, bis, 2)
wandverzeichnis[pos] = wände # erstellt ein Wandverzeichnis für jede Zelle (Position)
# ist wichtig für check_wall() (siehe unten)
def nachbarn_ermitteln(pos): # ermittelt alle (möglichen) Nachbarzellen von der aktuellen Position
nachb = []
for richtung, delta in delta_nachbarn.items():
neue_pos = add_pos(pos, delta)
if neue_pos not in raster:
continue
else:
nachb.append((richtung, neue_pos))
random.shuffle(nachb)
return nachb
besucht = set() # set für bereits besuchte Zellen
def labyrinth_erstellen(pos_aktuell, richtung_von):
besucht.add(pos_aktuell)
raster[pos_aktuell].remove(richtung_von)
nachb = nachbarn_ermitteln(pos_aktuell)
for richtung_nach, pos_neu in nachb:
if pos_neu in besucht:
continue
else:
raster[pos_aktuell].remove(richtung_nach)
labyrinth_erstellen(pos_neu, richtung_invers[richtung_nach]) # ruft sich selbst auf und generiert so das Labyrinth
def check_wall(gewünschte_richtung, pos): # überprüft auf im Weg stehende Wände
if gewünschte_richtung in wandverzeichnis[pos]: # (wenn Bewegungsrichtung klar ist)
return True
else:
return False
startx = random.randint(1,29) #
starty = random.randint(1,29) # setzt Startkoordinaten für Spieler per Zufall
labyrinth_erstellen((0,0), 'l') # fängt immer links oben mit dem Erstellen an
alte_pos_spieler = (startx,starty)
neue_pos_spieler = (startx*ZE_BH + ZE_BH // 2, starty*ZE_BH + ZE_BH // 2) # setzt Spieler in die Welt ZE_BEH // 2 garantiert,
# dass er in der Mitte einer Zelle auftaucht
# (nicht im linken oberen Eck (= quellposition))
pg_quit = False
############### HAUPTSCHLEIFE ###############
while not pg_quit:
screen.fill(farbe_hintergrund)
for pos, wände in raster.items(): # zeichnet sowohl entdeckte als auch unentdeckte Wände immer neu
zeichne_zelle(pos, wände) # entdeckte Wände werden so laufend aktualisiert
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE): # QUIT event
pg_quit = True
if event.type == pg.KEYDOWN and event.key == pg.K_LEFT: # Kommando für linke Pfeiltaste
pg.time.delay(100)
gewünschte_richtung = 'l'
quellposition_aktuell = add_pos(alte_pos_spieler, quellposition) # errechnet Quellposition (s.o.)
if check_wall(gewünschte_richtung, quellposition_aktuell) == True:
entdeckte_wände[gewünschte_richtung].append(quellposition_aktuell) # markiert entdeckte Wand
# verschiebt Sieler nicht
else:
neue_pos_spieler = add_pos(alte_pos_spieler, delta_nachbarn['l']) # verschiebt Spieler
if event.type == pg.KEYDOWN and event.key == pg.K_RIGHT: # Kommando für rechte Pfeiltaste
pg.time.delay(100)
gewünschte_richtung = 'r'
quellposition_aktuell = add_pos(alte_pos_spieler, quellposition) # ...
if check_wall(gewünschte_richtung, quellposition_aktuell) == True:
entdeckte_wände[gewünschte_richtung].append(quellposition_aktuell)
else:
neue_pos_spieler = add_pos(alte_pos_spieler, delta_nachbarn['r'])
if event.type == pg.KEYDOWN and event.key == pg.K_UP: # Kommando für Pfeiltaste hoch
pg.time.delay(100)
gewünschte_richtung = 'o'
quellposition_aktuell = add_pos(alte_pos_spieler, quellposition)
if check_wall(gewünschte_richtung, quellposition_aktuell) == True:
entdeckte_wände[gewünschte_richtung].append(quellposition_aktuell)
else:
neue_pos_spieler = add_pos(alte_pos_spieler, delta_nachbarn['o'])
if event.type == pg.KEYDOWN and event.key == pg.K_DOWN: # Kommando für Pfeiltaste runter
pg.time.delay(100)
gewünschte_richtung = 'u'
quellposition_aktuell = add_pos(alte_pos_spieler, quellposition)
if check_wall(gewünschte_richtung, quellposition_aktuell) == True:
entdeckte_wände[gewünschte_richtung].append(quellposition_aktuell)
else:
neue_pos_spieler = add_pos(alte_pos_spieler, delta_nachbarn['u'])
pg.draw.circle(screen, farbe_spieler, neue_pos_spieler, 7) # zeichnet Spieler
alte_pos_spieler = neue_pos_spieler # speichert aktuelle Position des Spielers
pg.display.flip()
pg.quit()
Mit freundlichen Grüßen, MOIN.