Seite 1 von 1

werte zur laufzeit ändern

Verfasst: Samstag 5. April 2008, 13:23
von sechsrad
hallo,ich habe ein problem mit der steuerung mit x und y. dieses programm habe ich aus dem forum.
diese werte self.rect.topleft = 230, 70 in der class Starte möchte ich aus der main mit variablen ändern. die werte sollen also nicht fest auf 230,70 stehen. bekomme das nicht hin.
starte wird ja nur einmal aufgerufen, wie komme ich dann an die werte ran mit dauernder änderung (x,y)von mir?

wenn ich eine zusätzliche routine in die class reinsetze:
def gehe(self,x,y):
self.rect.topleft = x,y

und in der main "sprites1.gehe(100,100)" aufrufe ,kommt eine fehlermeldung das diese routine unbekannt ist.

Code: Alles auswählen

import os, pygame
from pygame.locals import *

def load_image(name, colorkey=None):
    neuname = name
    try:
        image = pygame.image.load(neuname)
    except pygame.error, message:
        print 'kann bild nicht laden:', fullname
        raise SystemExit, message
    image = image.convert()
    return image, image.get_rect()

class Starte(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image, self.rect = load_image("test1.png", -1)
        self.original = self.image
        screen = pygame.display.get_surface()
        self.rect.topleft = 230, 70
        self.spin=0

    def update(self,wert): 
        self.spinSpeed = wert
        center = self.rect.center
        self.spin += wert
        if self.spin >= 360:
            self.spin -= 360
        if self.spin <0:
            self.spin += 360
        self.image = pygame.transform.rotate(self.original, self.spin)
        self.rect = self.image.get_rect()
        self.rect.center = center

   def gehe(self,x,y):
       self.rect.topleft = x,y    

def main():
    pygame.init()
    screen = pygame.display.set_mode((320,240))

    clock = pygame.time.Clock()
    starte = Starte()
    sprites1 = pygame.sprite.RenderPlain((starte))

    while 1:
        clock.tick(60)

        for event in pygame.event.get():
            if event.type in (QUIT, KEYDOWN, K_ESCAPE):
                return
        sprites1.update(5)
        sprites1.gehe(100,100)
        sprites1.draw(screen)
        pygame.display.flip()

main()


Verfasst: Samstag 5. April 2008, 13:34
von Hyperion
Naja, Du übergibst eben dem Konstruktor der Starte Klasse die benötigten Parameter ...

Code: Alles auswählen

class Starte(pygame.sprite.Sprite):
    def __init__(self, rect=(230, 70)):
        pygame.sprite.Sprite.__init__(self)
        self.rect.topleft = rect

...

starte = Starte(rect=(100,50))
Wobei rect als Bezeichner hier nicht unbedingt gut ist!

Verfasst: Samstag 5. April 2008, 13:48
von sechsrad
jetzt geht es. danke.

wird die ladefunktion für das bild "test.png" nicht durch den aufruf "starte" immer neu aufgerufen?

mit den befehl "class" klappt es bei mir noch nicht in der denkweise.
ich begreife die funktion nicht ganz mit den parametern und den def-routinen da drin. mit der hilfe über diese "class" tue ich mich schwer.

mfg

Verfasst: Samstag 5. April 2008, 14:29
von BlackJack
Die Ladefunktion wird durch einen Aufruf von `Starte()` aufgerufen, falls Du das meintest.

Verfasst: Samstag 5. April 2008, 14:41
von sechsrad
sag mal, wie kann ich hier die 3 funktionen ohne class machen?

würde gerne zur übersicht einzelne funktionen haben.
bekomme das nicht hin, wegen diesem "self".

Code: Alles auswählen

class Starte(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image, self.rect = load_image("test1.png", -1)
        self.original = self.image
        screen = pygame.display.get_surface()
        self.rect.topleft = 230, 70
        self.spin=0 

def update(self,wert):
        self.spinSpeed = wert
        center = self.rect.center
        self.spin += wert
        if self.spin >= 360:
            self.spin -= 360
        if self.spin <0:
            self.spin += 360
        self.image = pygame.transform.rotate(self.original, self.spin)
        self.rect = self.image.get_rect()
        self.rect.center = center

   def gehe(self,x,y):
       self.rect.topleft = x,y    


Verfasst: Samstag 5. April 2008, 14:45
von sechsrad
ja, wird jetzt die ladefunktion hiermit immer neu aufgerufen "starte = Starte(rect=(100,50))", weil ich ja jetzt in der "while" dauernd die werte ändere?
....
b=b+1
starte = Starte(rect=(b,b))
sprites1 = pygame.sprite.RenderPlain((starte))
.......

Verfasst: Samstag 5. April 2008, 14:48
von Leonidas
sechsrad hat geschrieben:sag mal, wie kann ich hier die 3 funktionen ohne class machen?
Stop. Bevor du hier weitermachst, lerne OOP. Ist alles gut dokumentiert, aber so ist es nur Programming-by-accident, das verschwendet deine Zeit.

Verfasst: Samstag 5. April 2008, 15:48
von sechsrad
dann brauchen wir ja hier auch nicht das forum.

ich sehe in verschiedenen sparten hier, das gecodet wird.

es fehlt manchmal nur ein kleiner texthinweis, dann klappt es auch mit der nachbarin.

Verfasst: Samstag 5. April 2008, 15:49
von sechsrad
Ist alles gut dokumentiert,
wo gibt es eine einweisung, wie man eine class in normale funktionen überführen kann?

Verfasst: Samstag 5. April 2008, 16:08
von Hyperion
sechsrad hat geschrieben:dann brauchen wir ja hier auch nicht das forum.
Doch, denn hier bekommst du eben Hilfe - und im Moment brauchst Du eben Grundlagen! Daher der Hinweis von Leonidas!
ich sehe in verschiedenen sparten hier, das gecodet wird.
Naja, klar wird hier auch mal was gepostet, bei kleineren Sachen auch mal gerne ne Lösung. Aber meist nur, wenn der Fragesteller auch Ideen / Kenntnisse hat.
es fehlt manchmal nur ein kleiner texthinweis, dann klappt es auch mit der nachbarin.
Deine Frage mit dem "self" hat ja genau gezeigt, dass es bei Dir an Grundlagen fehlt! Du verstehst OO nicht und hast extrem wenig Ahnung i.A. von Python. Daher investiere die Zeit und fange einfach mal von vorne an, das Tutorial durchzuarbeiten. Danach hättest Du für diese Fragen keine Verwendung mehr, glaub mir ;-)

Verfasst: Samstag 5. April 2008, 16:35
von Leonidas
sechsrad hat geschrieben:
Ist alles gut dokumentiert,
wo gibt es eine einweisung, wie man eine class in normale funktionen überführen kann?
Gibt es nicht, weil Klassen und Funktionen was ganz anderes sind. Du kannst aber eine Klasse ausführbar machen, so dass sie sich wie eine normale Funktion verhält, indem du ``__call__`` implementierst.
Du kannst ja auch nicht erwarten, dass du einen Kreis in eine Orange umwandeln kannst, nur weil sie sich ähnlich sehen.
sachsrad hat geschrieben:es fehlt manchmal nur ein kleiner texthinweis, dann klappt es auch mit der nachbarin.
Aber natürlich, gerne. Wenn du dich mit OOP auseinandergesetzt hättest, hätte sich das Problem von selbst gelöst. Wenn nicht, dann wirst du die Hinweise nicht verstehen.

Und du siehst, dass ich nicht der einzige bin, der dir zum Lernen von Grundlagen rät - da musst du mir keine beleidigten PMs schicken. Du musst zwar die Tipps nicht annehmen, aber sie machen dir (ja, dir) das Leben einfacher.

Verfasst: Samstag 5. April 2008, 16:54
von audax

Code: Alles auswählen

global self
*kicher*

hab ich übrigens schonmal in freier Wildbahn gesehen :o

Verfasst: Samstag 5. April 2008, 17:06
von BlackJack
@sechsrad: Grundsätzlich kann man die Methoden in Klassen schon in einzelne Funktionen umwandeln, man muss dann die benötigten Attribute halt immer als Argumente herum reichen. Aber damit wird das alles komplizierter und nicht einfacher.

Ausserdem erbst Du ja von der `Sprite`-Klasse, dass heisst Du willst ja schon ein `Sprite`-Objekt mit der entsprechenden Funktionalität haben.

Verfasst: Samstag 5. April 2008, 17:37
von sechsrad
oder besser , dieses ist der grund:
im programm hier wird über einen roten kreis ein bild test1.png gedreht, 64x64pixel.
komischerweise wandert das bild während der 360graddrehung ca 12pixel nach rechts unten und wieder 12 pixel nach links oben.
dieses gleiche bild wird aber oben im programm mit der class genau im zentrum gedreht wie ich es erwartet habe.
darum möchte ich diesen fehler suchen durch zerlegen der class.
aber vielleicht kann bitte das mal ein anderer testen.

Code: Alles auswählen

import pygame
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode([320, 240], 0, 16)

bild=pygame.image.load("test1.png").convert_alpha()
 
b=0
clock = pygame.time.Clock()

bild1=bild
while b < 360:
    clock.tick(60)
    bild1=pygame.transform.rotate(bild,b)
    screen.blit(bild1,(100,100))
    
    pygame.display.flip()
    pygame.draw.circle(screen, (255,0 ,0), (150,130),80,0)
    b=b+2

while pygame.event.poll().type != KEYDOWN: pygame.time.delay(10)
pygame.quit() 

Verfasst: Samstag 5. April 2008, 19:21
von BlackJack
Das Problem ist, dass das Bild durch's rotieren zwangsläufig grösser werden muss (Höhe und Breite), Du beim "blitten" aber die obere linke Ecke immer nach (100, 100) auf den Hintergrund abbildest.

Du wirst ein wenig Rechnen müssen, bzw. `rect`-Objekte verwenden und da über den Mittelpunkt die richtige obere linke Ecke ermitteln.

Code: Alles auswählen

import pygame

def main():
    pygame.init()
    screen = pygame.display.set_mode((320, 240), 0, 16)
    
    red = (255, 0, 0)
    circle_center = (150, 130)
    
    bild = pygame.image.load('test.png').convert_alpha()
    clock = pygame.time.Clock()
    
    for angle in xrange(0, 360, 2):
        clock.tick(60)
        pygame.draw.circle(screen, red, circle_center, 80, 0)
        rotated = pygame.transform.rotate(bild, angle)
        screen.blit(rotated, rotated.get_rect(center=circle_center))
        pygame.display.flip()
    
    while pygame.event.poll().type != pygame.KEYDOWN:
        pygame.time.delay(10)
    pygame.quit()

Verfasst: Samstag 5. April 2008, 19:37
von BlackJack
Na im Grunde wie im Beispiel: vom gedrehten Objekt ein `Rect` anfordern was als Mittelpunkt den Mittelpunkt des `Rect`\s des anderen Objekts hat.

Verfasst: Samstag 5. April 2008, 19:41
von sechsrad
danke erstmal für die hilfe.

es läuft wunderbar.

mfg

Verfasst: Samstag 5. April 2008, 20:08
von sechsrad
hmmm. das verstehe ich nicht ganz.
Na im Grunde wie im Beispiel: vom gedrehten Objekt ein `Rect` anfordern was als Mittelpunkt den Mittelpunkt des `Rect`\s des anderen Objekts hat.

werde mich nach dieser erklärung mal dran machen das umzusetzen.
dieses mit dem rect anfordern kapier ich nicht!

mfg

Verfasst: Samstag 5. April 2008, 21:00
von BlackJack
`Surface`\s haben eine `get_rect()`-Methode, die ein Rechteck mit der Grösse des `Surface`-Exemplars zurück geben und wie man in der Doku zu Pygame und meinem Beispiel weiter oben sehen kann, kann man für dieses Rechteck einen Bezugspunkt bei der `get_rect()`-Methode geben.

Verfasst: Samstag 5. April 2008, 21:51
von sechsrad
jup, danke. jetzt habe ich es kapiert.
es hat lange gedauert.

kann jetzt sprites flimmerfrei , drehen und bewegen bzw während des programmablaufes manipulieren.

die beispiele laufen jetzt wunderbar auf dem gp2x mit pygame.

so hatte ich es mir vorgestellt.

mfg