werte zur laufzeit ändern

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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()

Zuletzt geändert von sechsrad am Samstag 5. April 2008, 13:39, insgesamt 2-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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!
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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
Zuletzt geändert von sechsrad am Samstag 5. April 2008, 14:46, insgesamt 1-mal geändert.
BlackJack

Die Ladefunktion wird durch einen Aufruf von `Starte()` aufgerufen, falls Du das meintest.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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    

sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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))
.......
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

Ist alles gut dokumentiert,
wo gibt es eine einweisung, wie man eine class in normale funktionen überführen kann?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 ;-)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

global self
*kicher*

hab ich übrigens schonmal in freier Wildbahn gesehen :o
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.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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() 
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()
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.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

danke erstmal für die hilfe.

es läuft wunderbar.

mfg
Zuletzt geändert von sechsrad am Samstag 5. April 2008, 20:09, insgesamt 1-mal geändert.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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
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.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

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
Antworten