Frage zu Pygame (Zielkoordianten)

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Schildi
User
Beiträge: 30
Registriert: Freitag 19. Mai 2006, 22:23
Kontaktdaten:

Hallo!

Ich hab mal eine Fragen zu Pygame. Sagen wir ich habe ein Bild, das die Koordinaten x = 100, y = 100 hat. Was muss ich anstellen, dass sich das Bild z.B. zu x = 200, y = 200 bewegt? Damit meine ich jetzt nicht sowas hier:

Code: Alles auswählen

bildrect.move_ip(200, 200)
sondern ich möchte das in der While-Schleife drin haben, sodass man die Bewegung praktisch sieht. Ich hab's zwar hinbekommen, dass sich das Bild z.B. von rechts nach links bewegt, mit speed = [-1, 0] beispielsweise. Aber das ist ja nicht direkt das, was ich suche.

Man muss ja auch beachten, das das Beispiel jetzt recht einfach ist. Also ich meine x = 100, y = 100 -> x = 200, y = 200. Aber es müsste nachher auch gehn, dass sich das Bild von 100, 100 nach 531, 344 bewegt, nur so als Beispiel. Hättet ihr ne Idee, wie man das lösen könnte?

Danke im Voraus :)

MfG, Schildi
by: Schildi
BlackJack

Wenn es eine Bewegung auf einer Linie sein soll, dann ist das ganz einfach. Du musst vorher nur noch festlegen in wievielen Schritten die Bewegung passieren soll. Dann lässt sich einfach ausrechnen, wieviele Pixel Du pro Schritt verschieben musst. Einfach die Differenz von alter und neuer X-Koordinate durch die Anzahl der Schritte teilen. Mit der Y-Koordinate machst Du das gleiche. Also von 100,100 nach 200,200 in 10 Schritten musst Du in jedem Schritt um 10,10 verschieben.
Schildi
User
Beiträge: 30
Registriert: Freitag 19. Mai 2006, 22:23
Kontaktdaten:

also erstmal: klingt logisch :wink:
aber so flüssig läuft das leider nicht...hier mal der gesamte code:

Code: Alles auswählen

import sys, pygame
from pygame.locals import *

pygame.init()

size = width, height = 640, 480
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Test')
black = 0, 0, 0

surface = pygame.Surface((100, 100))
farbe = 255, 0, 0
surface.fill(farbe)

x = 100
y = 100

x1 = 345
y1 = 233

j = 0

schritte = 100

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == KEYDOWN:
             if event.key == K_ESCAPE:
                 sys.exit()
             elif event.key == K_SPACE:
                 j = 1

    if j == 1:
        y += (y1-y)/schritte
        x += (x1-x)/schritte
    
    screen.fill(black)
    screen.blit(surface, (x, y))
    pygame.display.flip()
hab das jetzt mal so gemacht, wie du gesagt hast. Und ich will nicht bestreiten, dass es das macht, was es soll, aber wie gesagt, es läuft nicht direkt flüssig. denn: bei mir erreicht das bild die y-koordiante (y1) eher als die x-koordinate (x1), d.h. es läuft erst auf einer linie diagonal nach unten rechts und wenn y dann mit y1 übereinstimmt, läuft es nur noch nach rechts, solange bis auch beide x-werte übereinstimmen. verstehst du wie ich das meine? woran liegt das? weißt du da auch eine Lösung für?

danke, schildi
by: Schildi
BlackJack

Du teilst die Distanz immer wieder durch die Gesamtzahl der Schritte. Die Distanz wird aber nach jedem Schritt kleiner. Wenn Du z.B. schon 75 Schritte gemacht hast, dann teilst Du die Reststrecke immer noch in 100 Teile auf statt 25.
Schildi
User
Beiträge: 30
Registriert: Freitag 19. Mai 2006, 22:23
Kontaktdaten:

...und was muss ich ändern? Sry, das ich so doof frage, aber ich kapier das iwie net, wie ich das machen muss :wink:

MfG, Schildi
by: Schildi
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Code: Alles auswählen

stepx = (x1-x)/schritte
stepy = (y1-y)/schritte
vor die Schleife schreiben, und dann

Code: Alles auswählen

y += stepy
x += stepx
Schildi
User
Beiträge: 30
Registriert: Freitag 19. Mai 2006, 22:23
Kontaktdaten:

etwas verpätet, sry, aber DANKE! hat mich sehr viel weiter gebracht.

Und weil ich jetzt keinen neuen Thread öffnen will, schreib ich meine nächste frage gleich mal hierhin. :lol:

und zwar geht es um

Code: Alles auswählen

bild = pygame.transform.rotate(bild, 45)
(als Beispiel)

wenn ich also ein bild drehen möchte. bei mir kommt da dann was ganz komisches raus. also auf jeden fall kein bild, was um 45° gedreht wurde... :? also ich könnte mir gut vorstellen, das es irgendwas mit

Code: Alles auswählen

screen.blit(bild, (x, y))
am ende zu tun haben könnte, also das da irgendwas falsch 'geblittet' wird. weiß aber nicht, ob das stimmt, oder gar, wie ich das lösen kann. könnt ihr mir da auch wieterhelfen? danke im voraus schon mal :wink:

MfG, Schildi
by: Schildi
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Die Frage würde doch hervorragend ins PyGame-Forum passen, oder? ;-)
http://www.python-forum.de/topic-6769.html?highlight=

Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hi Schildi,

ich habe mal eben das Chimp-Tutorial beim Abschreiben angepasst und das läuft eigentlich einwandfrei:

Code: Alles auswählen

import os, pygame
from pygame.locals import *

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

class Smile(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image, self.rect = load_image("borg.jpg", -1)
        self.original = self.image
        screen = pygame.display.get_surface()
        self.area = screen.get_rect()
        self.rect.topleft = 70, 70
        self.spin = 230
        self.spinSpeed = 0
        self.increment = 1

    def update(self):
        if self.spinSpeed > 15 or self.spinSpeed < -15:
            self.increment = -self.increment
        self.spinSpeed += self.increment
        self._spin()

    def _spin(self):
        center = self.rect.center
        self.spin += self.spinSpeed
        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 main():
    ##  Initialize Everything
    pygame.init()
    screen = pygame.display.set_mode((200, 200))
    pygame.display.set_caption("Borgsmile Twist")

    ##  prepare game objects
    clock = pygame.time.Clock()
    smile = Smile()
    allsprites = pygame.sprite.RenderPlain((smile))
    pygame.display.flip()

    ##  main loop
    while 1:
        clock.tick(60)

        ##  handle input events
        for event in pygame.event.get():
            if event.type in (QUIT, KEYDOWN, K_ESCAPE):
                return
        allsprites.update()

        ##  draw next smile
        allsprites.draw(screen)
        pygame.display.flip()

main()
Wenn mir noch jemand sagen könnte, wie ich meinen Borg-Smiley irgendwo hochladen kann... :D

[EDIT] Man ist ja erfinderisch und für einen Ingenieur ist nichts zu schwör. ;-)
BildDas Bild bitte als borg.jpg im Verzeichnis mit dem Code speichern.[/EDIT]

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Also bei mir funktioniert das problemlos...

Code: Alles auswählen

import os, pygame
from pygame.locals import *

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

##  Initialize Everything
pygame.init()
screen = pygame.display.set_mode((200, 200))
image, rect = load_image("borg.jpg", -1)
rect.topleft = 70, 70
image = pygame.transform.rotate(image, 45)
screen.blit(image, rect)

pygame.display.flip()

while 1:
    ##  handle input events
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN, K_ESCAPE):
            raise SystemExit()
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Michael Schneider hat geschrieben:Die Frage würde doch hervorragend ins PyGame-Forum passen, oder? ;-)
Absolut! Deswegen habe ich den Thread ins passende Forum verschoben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Schildi
User
Beiträge: 30
Registriert: Freitag 19. Mai 2006, 22:23
Kontaktdaten:

Morgen!

Na gut, ich hab jetzt herausgefunden, woran das die ganze zeit lag, das es nicht funktioniert hat, bevor du das beispiel gepostet hast. und zwar hab ich herausgefunden, dass mein problem nur bei bilden "ohne rand" auftreten, also dein smiley ist ja auf weißem grund, aber ich hatte immer bilder (rechtecke bzw. quadrate zum testen), die das ganze bild ausfüllten. das gleiche würde also mit "surface" passieren. auf jeden fall noch mal DANKE! :wink:

naja, und weils so schön ist gleich noch eine andere frage:

gibt es eine möglichkeit, 2 oder mehr rects zusammen zu fassen? also es geht mir darum, das ich z.b. ein "hintergrundrect" habe (welches dann mit der bg-farbe gefüllt wird und halt den hintergrund darstellt) und eine anzahl von anderen rects, die irgendwo gezeichnet werden. diese möchte ich dann mit dem hintergrundrect zusammenfassen, weil wenn ich nachher 40-50 rects habe, lahmt das ganze verständlicher weise. so bräuchte ich dann gar nicht alle 40 oder 50 rects zeichnen, sondern die einfach dem hintergrundrect "hinzufügen" und nur das zeichnen.

versteht ihr was ich meine?

mfg schildi

ps:

Code: Alles auswählen

bgRect = bgRect.union(aRect)
hab ich schon ausprobiert, aber damit bin ich iwie nich klar gekommen :?: :oops:
by: Schildi
BlackJack

Du verwechselst `Rect` und `Surface`. `Rect` sind nur die "Masse" von einem Rechteck, ein `Rect` enthält keine Grafik.

Was Du wahrscheinlich möchtest ist eine Kopie von Deinem Hintergrund (`Surface.copy()`) und dann die kleinen `Surface` Objekte auf diese Kopie "blitten".
Schildi
User
Beiträge: 30
Registriert: Freitag 19. Mai 2006, 22:23
Kontaktdaten:

hm..also ich kann am besten mal ein theoretisches beispiel nennen zur verdeutlichung:

ich hab ein hintergrund bild, welches ich weiss mache:

Code: Alles auswählen

bg = pygame.Surface((800, 600))
bg.fill((255, 255, 255))
dann hab ich mehere quadrate, die ich rot mache:

Code: Alles auswählen

q1 = pygame.Surface((20, 20))
q1.fill((255, 0, 0))
so, ich möchte jetz nich immer

Code: Alles auswählen

screen.blit(bg, (0, 0))
screen.blit(q1, (x1, y1))
screen.blit(q2, (x2, y2))
screen.blit(q3, (x3, y3))
...
schreiben, sondern die quadrate jeweils dem hintergrund "hinzufügen", so, dass ich zum schluss nur

Code: Alles auswählen

screen.blit(bg, (0, 0))
schreiben muss, und trotzdem die roten quadrate mit geblittet werden, weil sie ja praktisch dann zum hintergrund gehören.

mfg schildi
by: Schildi
BlackJack

Naja, dann machst Du genau das was ich geschrieben habe: Du machst vom weissen Hintergrund eine Kopie, blittest da die roten Quadrate drauf und benutzt das als neuen Hintergrund den Du auf den Bildschirm blittest. Die `blit()` Methode ist nicht nur auf dem sichtbaren `Surface` definiert sondern auf jedem `Surface`.
KC25m
User
Beiträge: 65
Registriert: Freitag 14. Juli 2006, 12:11
Wohnort: Kassel
Kontaktdaten:

sorry wenn ich mich einmisch aber habe da nich einen Tip ...
Langsamme system werden stark beansprucht durch dem befehl pygame.display.flip() !
Pygame.display.flip() sollte in der regel nur dann genommen werden wenn es dadrum geht ein DoubleBuffer nach vorne zu bringen .

Wenn ihr für ein System speed braucht nutzt die möglichkeit der Dirtyrects ....

Code: Alles auswählen

Dirtyrect=screen.blit(img,(x,y))
pygame.display.update(dirtyrects)
Es beschleunigt die grafikausgabe ungemein .

Programmiere gerade auf einen Via EPia board mit 600MHz und es macht riesen unterschiede ob der ganze bildschirm geupdatet wird oder nur einzelnde bereiche.
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Hm, wo hier grade die Rede von performance ist:

Hat jermand eine Idee warum mein (ziemlich) einfaches Übungsprogramm ca viermal so schnell läuft, wenn sich etwas anderes (Skype oder Thunderbird benachrichtigung) in den Vordergrund drängt?

Ich hab zum Üben aus den PyGame-Tutorials ein Progrämmchen gebastelt, bei dem ein paar Kugeln durch die Gegend fliegen und wenn man auf so eine Kugel klickt, verschwindet sie. Das ganze habe ich als Fullscreen, den genauen Code habe ich auf dem anderen Rechner, kann ich momentan leider nicht posten. Vielleicht hat ja auch so jemand eine Idee.

Das ganze läuft grademal bei ca 35 fps (für so ein kleines Programm ziemlich wenig, wie ich finde). Aber wenn sich ein Kontakt bei Skype einloggt und so ein Benachrichtigungsfenster von Skype davorschiebt, fliegen die Kugeln plötzlich mit 140 fps über den Bildschirm. Sobald sich das Benachrichtigungsfenster wieder zurückzieht geht auch die Performance nach unten. Ich versteh irgendwie nicht, warum es schneller wird, wenn sich was anderes davor schiebt. Wäre echt dankbar wenn mir jemand helfen kann... Code leifere ich wie gesagt gerne nach.
KC25m
User
Beiträge: 65
Registriert: Freitag 14. Juli 2006, 12:11
Wohnort: Kassel
Kontaktdaten:

Performance hat auch viel mit dem Bildschirmmodus zutun ,
Es gibt ja Software , hardware unterstützung.
Bei mir auf mein WindowsSystem habe ich festgestellt wenn etwas alpha hat ist es besser einen software screen zu nutzen.
Unter Linux auf dem Via EPIA ist es besser ein hardware screen zu benutzen.
Vieleicht soltest du einfach mal den Bildschidm umstellen...
Voreingestellt unter pygame.FULLSCREEN ist ein Software Screen.
Heist alles wird durch die Software geblittet...
pygame.HWSURFACE , pygame.DOUBLEBUF sind noch zwei weiter modies ...

FULLSCREEN ist bei mir auf dem windows system am schnellste da win kein Alphablitting hardware mässig unterstützt und die software dann schneller arbeitet.

Wenn ich ich recht entsinne ist HWSURFACE und DOUBLEBUF auch mit dem VSync syncron..
Nirven
User
Beiträge: 130
Registriert: Mittwoch 10. Mai 2006, 08:18
Wohnort: Bremerhaven

Danke, das hat schonmal etwas geholfen. :)

Mit DOUBLEBUF komme ich jetzt auf 75 fps. Mit HWSURFACE alleine sogar auf 90fps, aber dann flackert das Bild total.

Aber mit SWSURFACE (dem "Standard") komme ich halt auf 120 fps, wenn sich ein anderes Fenster davor schiebt. Die Software gibt es also her, nur igrendwas funktioniert anscheinend nicht ganz richtig. Mal weiter probieren.
KC25m
User
Beiträge: 65
Registriert: Freitag 14. Juli 2006, 12:11
Wohnort: Kassel
Kontaktdaten:

guck mal in PyGames nach get_fps , get_ticks und so da gab es eine funktion die das ganze auf eine Maximale FPS beschränken läst...

Ich habe inmo keine erklärung wieso es so ist das wenn ein externes event passiert deine grafikkarte auf einmal rennt wie sonstwas.
Kann das ganze leider auch nicht nachvolziehen.
Antworten