Pygame Tutorial Reihe

Gute Links und Tutorials könnt ihr hier posten.
raecher-der-enterbten
User
Beiträge: 4
Registriert: Freitag 1. August 2008, 20:00

schon passiert, hatte vergessen es hier reinzuschreiben. danke :)

mfg

raecher-der-enterbten
sea-live
User
Beiträge: 440
Registriert: Montag 18. Februar 2008, 12:24
Wohnort: RP

ja und geht es jetzt
um images zu laden verwende ich funktionen

Code: Alles auswählen

def load_image(file):
    file = os.path.join('data', 'images', file)
    try:
        surface = pygame.image.load(file)
    except pygame.error:
        raise SystemExit, '"%s" %s not found'%(file, pygame.get_error())
    return surface.convert_alpha()

def load_images(*files):
    imgs = []
    for file in files:
        imgs.append(load_image(file))
    return imgs   

def load_image_alpha(file, colorkey=None):
    file = os.path.join('data', 'images', file)
    try:
        surface = pygame.image.load(file)
    except pygame.error:
        raise SystemExit, '"%s" %s not found'%(file, pygame.get_error())
    if colorkey is not None:
        if colorkey is -1:
            colorkey = surface.get_at((0,0))
        surface.set_colorkey(colorkey, RLEACCEL)
    return surface.convert_alpha()
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das Built-in ``file`` zu überschreiben gilt gemeinhin als eher schlechte Idee.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Das simple Hilfsfunktionen einfach so das Programm abbrechen halte ich auch für etwas unglücklich.

Die `load_images()` ist vielleicht übertrieben, weil die Implementierung ein wirklich einfacher Einzeiler sein könnte: ``return map(load_image, filenames)``.
Benutzeravatar
Basti91
User
Beiträge: 53
Registriert: Samstag 15. Dezember 2007, 11:50
Wohnort: Saarland

Hab ne frage zu Tileset.

Also ich hab jetzt ein Grundprogramm (Jump and Run). Wollte die Figur jetzt animieren aber weiss nicht genua wie ich beide Elemente zusammenführen kann. Kann mir jemand helfen?

Hier die Codes:

Grundprogramm

Code: Alles auswählen

import pygame
import random

breite=800
hoehe=800
screen = pygame.display.set_mode((breite,hoehe))

clock = pygame.time.Clock()

boden1=pygame.image.load("Boden1.png")
Hintergrund=pygame.image.load("Hintergrund.png")
Hintergrund2=pygame.image.load("hintergrund2.png")
Mariorechts=pygame.image.load("mario.gif")
Mariolinks=pygame.image.load("mario2links.png")

Mario=Mariorechts
MarioX=100
MarioY=602
Hintergrundx=0
Bodenx=0
JumpNichtmoeglich=True
Jump=False
Bewegung=False
rechts=False
links=False
running=True
JumpAktiv=False
Fallen=False
while running:
    hintergrund=screen.blit(Hintergrund,(Hintergrundx,0))
    hintergrund2=screen.blit(Hintergrund2,(900,0))
    boden=screen.blit(boden1,(Bodenx,hoehe-100))
    mario=screen.blit(Mario,(MarioX,MarioY))
    
    pygame.display.flip()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key==pygame.K_RIGHT:
                if JumpAktiv == False:
                    Bewegung=True
                    rechts=True
            elif event.key==pygame.K_LEFT:
                if JumpAktiv == False:
                    Bewegung=True
                    links=True
            elif event.key==pygame.K_SPACE:
                if MarioY==602:
                    Jump=True
                    JumpAktiv=True

                
        elif event.type == pygame.KEYUP:
            if event.key==pygame.K_RIGHT:
                Bewegung=False
                rechts=False
            elif event.key==pygame.K_LEFT:
                Bewegung=False
                rechts=False
    if Jump:
        MarioY-=20
        if MarioY < 300:
            Jump=False
    if Bewegung:
        if rechts:
            MarioX+=20
            Mario=Mariorechts
        elif links:
            if MarioX != 0:
                MarioX+=-20
            Mario=Mariolinks

    if MarioY < 300: #Fallen
        Fallen=True
    else:
        JumpAktiv=False
    if Fallen:
        MarioY+=20
        if MarioY>600:
            Fallen=False



So nun hier meine Tileset Klasse, bei der ich nicht genau weiss wie ich sie einbauen kann:

Code: Alles auswählen

def loadImage(filename, colorkey = None):
    image = pygame.image.load(filename)

    if image.get_alpha() == None:
        image = image.convert()
    else:
        image = image.convert_alpha()

    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))

        image.set_colorkey(colorkey, RLEACCEL)

    return image

class Tileset(object):
    def __init__(self, image ,colorkey ,tileWidth, tileHeight):
        self.__image = loadImage(image,colorkey)
        self.__tileWidth = tileWidth
        self.__tileHeight = tileHeight

        self.__tileTypes = dict()

    def getImage(self):
        return self.__image

    def setImage(self, image, colorkey):
        self.__image = loadImage(image,colorkey )
        
    def getTileWidth(self):
        return self.__tileWidth

    def getTileHeight(self):
        return self.__tileHeight

    def getTileSize(self):
        return (self.__tileWidth, self.__tileHeight)
    
    def addTile(self, Mario, tileWidth,tileHeight ):
        self.__tileTypes[Mario] = TileType(Mario, 0, 0, self.__tileWidth, self.__tileHeight)

    def getTile(self, Mario):
        try:
            return self.__tileTypes[Mario]
        except KeyError:
            return None



Hab mir noch überlegt anstatt diesem ganen Quellcode mit animierten .gifs zu arbeiten, aber anscheined unterstützt python diese nicht, da immer nur der erste Frame angezeigt wird. Ist mir da ein Fehler unterlaufen oder gehts das wirklich nicht?
BlackJack

@Basti91: Animieren bedeutet, dass über die Zeit immer andere Bilder angezeigt werden müssen. Das musst Du von Hand implementieren. Bei jedem Update ein anderes Bild zu blitten, wäre wahrscheinlich zu schnell, also könnte man eine Verzögerung einbauen, zum Beispiel einen Zähler benutzen um nur alle x Frames ein anderes Bild zu nehmen.

Die `Tileset`-Klasse sieht übrigens extrem unpythonisch aus. Lass da mal die ganzen doppelten Unterstriche und die Getter/Setter weg. Ungetestet:

Code: Alles auswählen

class Tileset(object):
    def __init__(self, image_filename, colorkey, tile_width, tile_height):
        self._image = None
        self.image = (image_filename, colorkey)
        self.tile_width = tile_width
        self.tile_height = tile_height

        self.tile_types = dict()

    def _get_image(self):
        return self._image

    def _set_image(self, filename_and_colorkey):
        self._image = load_image(*filename_and_colorkey)

    image = property(_get_image, _set_image)

    @property
    def tile_size(self):
        return (self.tile_width, self.tile_height)
    
    def add_tile(self, tile_content):
        self.tile_types[tile_content] = TileType(tile_content,
                                                 0,
                                                 0,
                                                 self.tile_width,
                                                 self.tile_height)

    def get_tile(self, tile):
        return self.tile_types.get(tile)
Die Asymmetrie bei den Typen bei den letzten beiden Methoden ist unschön.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

load_image() nutzt einmal is zum Prüfen auf einen Integer, -> [wiki]FAQ[/wiki]. Auf None immer mit is prüfen. Schau dir mal PEP8 (im Wiki suchen) an. Den ganzen Code des "Grundprogramms" am besten in eine Funktion packen (bis auf importe und Konstanten wie breite / hoehe (die man grossschreiben sollte)).

EDIT: Falsche FAQ verlinkt.
Benutzeravatar
Basti91
User
Beiträge: 53
Registriert: Samstag 15. Dezember 2007, 11:50
Wohnort: Saarland

Und wie bekomme ich jetzt so ne Ani hin? Hab jetzt schon mehrere Versuche gestartet die Bilder nacheinander laufen zu lassen aber nichts funzt -.-

Hab versucht ne Fuktion zu schreiben mit der ich es hinbekomme aber das wird iwie nichts:

Code: Alles auswählen

import pygame
import random

breite=800
hoehe=800
screen = pygame.display.set_mode((breite,hoehe))

clock = pygame.time.Clock()


def Mario_rechts():
    Mariorechts1= pygame.image.load("mario1.gif")
    Mariorechts2= pygame.image.load("mario2.gif")
    Mariorechts3= pygame.image.load("mario3.gif")
    Mariorechts4= pygame.image.load("mario4.gif")
    Mariorechts5= pygame.image.load("mario5.gif")
    Mariorechts6= pygame.image.load("mario6.gif")
    MarioX=68
    MarioY=602
    mario=screen.blit(Mariorechts1,(MarioX,MarioY))
    mario=screen.blit(Mariorechts2,(MarioX,MarioY))
    mario=screen.blit(Mariorechts3,(MarioX,MarioY))
    mario=screen.blit(Mariorechts4,(MarioX,MarioY))
    mario=screen.blit(Mariorechts5,(MarioX,MarioY))
    mario=screen.blit(Mariorechts6,(MarioX,MarioY))

Mario_rechts()
 
BlackJack

@Basti91: Du darfst nicht einfach alle Bilder *sofort* nacheinander "blitten", das sieht man natürlich nicht. Du musst halt in regelmässigen Abständen ein anderes Bild nehmen.

Das kapselt man am besten in ein Objekt, dass die Zeit berücksichtigt um zu entscheiden welches Bild gezeichnet werden soll.
Benutzeravatar
Basti91
User
Beiträge: 53
Registriert: Samstag 15. Dezember 2007, 11:50
Wohnort: Saarland

thx schonmal für die schnelle Antwort, wie bekomm ich denn diese Zeitabstände hin?
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

rogge
User
Beiträge: 1
Registriert: Dienstag 18. August 2009, 13:18

hi

im teil 2 wird ja in der Funktion handleInput die variable key benutzt (in Map.py). und im "richtigen" programm dann wird geschrieben:

Code: Alles auswählen

map.handleInput (key)
.
bei mir wird beim ausführen dann allerdings angezeigt:

Code: Alles auswählen

global name "key" is not defined
könnt ihr mir da weiterhelfen?

gruß
rogge
waldmeister xD
User
Beiträge: 2
Registriert: Sonntag 18. April 2010, 15:09

Hallo,

danke für das Tutorial, ich arbeite seit einigen Stunden zum ersten mal Python und habe auch gleich ein Problem.

Wenn ich das besagte Tutorial ausführe und das Script starte, dann öffnet sich zwar ein Fenster, aber es schließt sich sofort wieder.

Was mache ich falsch? Wie kann ich das Script/ Fenster länger offen lassen, sprich mit einer Wait/Sleep Funktion versehen?

Könnte mir das bitte jemand mal erklären, wäre echt lieb =)

Lieben Gruß xD
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

Starte doch das Script nicht durch Doppelklick, sondern indem du es auf der Konsole via "python scriptname.py" aufrufst. Dann siehts du auch die Fehlermeldungen.
Gruß!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

waldmeister xD hat geschrieben: Wenn ich das besagte Tutorial ausführe und das Script starte, dann öffnet sich zwar ein Fenster, aber es schließt sich sofort wieder.

Was mache ich falsch? Wie kann ich das Script/ Fenster länger offen lassen, sprich mit einer Wait/Sleep Funktion versehen?
Ich will jetzt nicht zu zynisch klingen, aber: Du fängst falsch an!

Imho solltest Du vergessen, dass es pygame gibt und Dich zunächst auf die Grundlagen ohne GUI Schnick Schnack konzentrieren. Natürlich ist das eine sehr persönliche Meinung, aber im Grunde hat es sich schon häufig gezeigt, dass es wichtig ist die Grundlagen verstanden zu haben. Und diese lernt man besser, ohne zu viel Overhead- und Boilerplate-Code.

Wir hatten dazu schon einige Threads, ich verlinke einfach mal den.
Pyanfänger
User
Beiträge: 99
Registriert: Mittwoch 28. Dezember 2011, 12:50

Kann irgendwer den ausgelagerten Code wo anders auslagern .. :roll: ? Is nämlich nich mehr vorhanden :/ Bzw wie kann man bei einer TileMap eine Perspektivischen Blick ahbe n, also so leiht seitlich? ohne 3d zu programmieren... Und wie geht das "ranzoomen" der tylemap?
-
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Redest du rein zufällig von Isometrie oder was? Und bei Kamera-Operationen wie Zoomen wird einfach der dementsprechende Faktor in der Rendering-Funktion angepasst.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Pyanfänger hat geschrieben:Kann irgendwer den ausgelagerten Code wo anders auslagern .. :roll: ? Is nämlich nich mehr vorhanden :/
Du erkennst das Problem bei Deinem Vorschlag? ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Pyanfänger
User
Beiträge: 99
Registriert: Mittwoch 28. Dezember 2011, 12:50

Achso ja :mrgreen:

@webspider wahrscheinlich =S
-
Antworten