Seite 1 von 2

pygame.ransform.rotate

Verfasst: Sonntag 20. April 2008, 12:12
von Imperator
Hallo Community,

bei der im Titel genannten Funktion trat bei mir ein Bug auf, der darin resultierte, dass das Bild das ichrotieren lassen wollte verschwand und ein schwarzer (je nach Bild auch anderstfarbig) Fleck immer weiter ausbreitete und immer mehr RAM frass. Also las ich mir den Abschnitt um rotate in der Doku nochmal genau durch und stellte fest, dass das kein Bug ist sonder ganz normal: http://www.pygame.org/docs/ref/transfor ... orm.rotate
Weiß jemand wie ich das umgehen kann?

Re: pygame.ransform.rotate

Verfasst: Sonntag 20. April 2008, 14:10
von Leonidas
Imperator hat geschrieben:Weiß jemand wie ich das umgehen kann?
Ja, das habe ich in meinem Pygame-Talk mal angesprochen. Du darfst ein Bild nicht mehrmals rotieren. Du musst das Ursprungsbild mit immer anderem Winkel jeweils neu rotieren.

Verfasst: Sonntag 20. April 2008, 14:35
von Imperator
Äh, meinst du damit, ich soll das Bild immer bevor es gedreht wird nochmal reseten?

Verfasst: Sonntag 20. April 2008, 14:43
von Leonidas
Imperator hat geschrieben:Äh, meinst du damit, ich soll das Bild immer bevor es gedreht wird nochmal reseten?
Du speichers immer ein mal das Ursprungsbild. Dieses rotierst du dann um sagen wie mal 1°. Dann willst du noch ein mal rotieren, wieder 1°. Statt jetzt das rotierte Bild nochmal zu rotieren, nimmst du das Ursprungsbild und rotierst es um 2°. In ``screensaw.py`` habe ich sowas in der ``AXE`` Demo implementiert.

Verfasst: Sonntag 20. April 2008, 15:05
von Imperator
Danke, war mir zuerst nur nicht sicher ob ich es auch richtig verstanden habe.
Jetzt gehts dem Spieler mit einem tollen roteirenden Geschützturm an den Kragen :twisted:

Verfasst: Montag 21. April 2008, 11:58
von C4S3
Heureka!
Habe selbiges Problemchen. Wenn das so ist, weiß man ja nun bescheid. Nur, um ehrlich zu sein: so ganz klar ist es mir noch nicht!
Ich meine: wie kann ich ein Bild rotieren und wenn ich es noch mals rotieren will, vom ursprünglichen Punkt wieder rotieren?
Brauche ich dazu eine Art "Hilfsrect"?

Köntte mir das jemand noch ein wenig "ausdeutschen"? Danke.

Verfasst: Montag 21. April 2008, 13:05
von fred.reichbier
Hallo,

erstelle doch einfach einmal die Surface 'image' und eine Surface 'image_backup' (mit image.copy()).
Nun rotierst du immer mit image = pygame.transform.rotate(image_backup, winkel). image_backup ist also immer das Bild in Originalausrichtung, nur image änderst du.
Ich hoffe, das ist verständlich ;)

Gruß Fred

Verfasst: Montag 21. April 2008, 13:07
von Leonidas
C4S3 hat geschrieben:Ich meine: wie kann ich ein Bild rotieren und wenn ich es noch mals rotieren will, vom ursprünglichen Punkt wieder rotieren?
Brauche ich dazu eine Art "Hilfsrect"?
Nein. Du hast einfach zwei Bilder. Das Ursprüngliche, das speicherst du ab. Wenn du etwas rotieren willst, dann nimmst du das unrotierte Ursprungsbild und rotierste es. Wenn du nun aber noch einmal rotieren willst, nimmst du statt dem bereits rotierten einfach das ursprüngliche, unrotierte und rotierst das.

Kurz zusammengefasst: du darfst ein Bild nicht mehr als ein mal rotieren. Sonst kommt Müll raus.

Verfasst: Montag 21. April 2008, 20:29
von C4S3
OK, soweit habe ich das ja nun durch rumprobieren hinbekommen, denke ich. Was jetzt noch fehlt, ist folgendes (das hatte ich anfangs gar nicht bedacht):
Zum Testen hatt ich ein Bild mit 128x128px gemacht.
Wenn ich das Bild jetzt aber Rotiere, ändert sich ja die Bildgröße, bzw. das Rect-Objekt, wenn ich richtig liege.
Wenn ich aber beim Blitten, die X/Y-Koordinaten angebe, kommt wieder Müll dabei raus, weil der Mittelpunkt meines Objektes nicht mehr stimmt.

Gibt es da noch eine nette Möglichkeit, bzw. kann mir bitte jemand einen Denkanstoß geben? Irgendwie muss ich den Mittelpunkt meines Objekts immer an die gleiche Stelle bekommen, egal welche Größe es hat.

Danke.

Code: Alles auswählen

import pygame
from pygame.locals import *
import sys

img = "cross.png"

pygame.init()

screen = pygame.display.set_mode((320,240), 0, 32)
pygame.display.set_caption("transform.rotate - Test")

cross = pygame.image.load(img).convert_alpha()
toRotate = pygame.Surface((128,128))
toRotate = cross.copy()
angle = 0

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        elif event.type == pygame.KEYUP and event.key == pygame.K_q:
            sys.exit()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
            angle += 1
            toRotate = pygame.transform.rotate(cross, angle)

    x,y = 50,50
    screen.fill((0,0,255))
    screen.blit(toRotate,(x,y))
    pygame.display.update()

Verfasst: Montag 21. April 2008, 21:06
von Leonidas
Dafür hat ja auch jedes Rect eine ``center``-Koordinate, die du verwenden kannst um das Rect wieder an die richtige Stelle zu positionieren.

Verfasst: Dienstag 22. April 2008, 08:51
von C4S3
Mein Bild ist ja ein Surface und kein Rect! Wie bekomme ich die zur Kooperation? Ich habe es versucht, komme aber auf keinen grünen Zweig. :(

Verfasst: Dienstag 22. April 2008, 10:15
von Leonidas
``Surfaces`` haben ``get_rect()``, wo du auch etwa ``center`` definieren kannst.

Verfasst: Dienstag 22. April 2008, 10:44
von C4S3
:roll:

Pfff...
Kennt ihr das Gefühl, wenn ihr euch absolut nicht sicher seid, und raten müsst, wie denn etwas gehen könnte!? So ist es mir gegangen, weil mir einige Zusammenhänge unklar waren. Teile der Doku lesen, probieren, ärgern. Nächsten Teil der Doku lesen, probieren, ... usw.
Naja, macht nix.

Danke Leonidas, dass du mir nur die Denkanstöße gegeben hast und keine fertige Lösung. Ich habe mich zwar geärgert, aber im Endeffekt war das der bessere Weg. Danke nochmal.

Sollte doch noch mal jemand danach suchen, hier mal mein erster funktionierender Versuch:

Code: Alles auswählen

import pygame
from pygame.locals import *
import sys

img = "cross.png"

pygame.init()

screen = pygame.display.set_mode((320,240), 0, 32)
pygame.display.set_caption("transform.rotate - Test")

cross = pygame.image.load(img).convert_alpha()
toRotate = pygame.Surface((128,128))
toRotate = cross.copy()
angle = 0

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        elif event.type == pygame.KEYUP and event.key == pygame.K_q:
            sys.exit()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
            angle += 1
            toRotate = pygame.transform.rotate(cross, angle)

    rect = toRotate.get_rect(center=(100,100))
    screen.fill((0,0,255))
    screen.blit(toRotate,rect)
    pygame.display.update()

Verfasst: Donnerstag 24. April 2008, 20:16
von sechsrad
hier ein drehendes rechteck, welches nach rechts wandert:

Code: Alles auswählen

import pygame
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode([320, 240], 0, 16)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill([255,255,0])

bild_rect = pygame.Surface([50,50])
bild_rect.fill([255,0,255])
bild_rect.set_colorkey((255,0,255), RLEACCEL)
pygame.draw.rect(bild_rect, (255,0,0), (10,0,30,50),1)

clock = pygame.time.Clock()
b=10  

for angle in xrange(0, 600, 2):
    clock.tick(60)
    
    b=b+1
    
    screen.blit(background, (0, 0))
    
    bild = pygame.transform.rotate(bild_rect, angle)
    bild1=bild.get_rect(center=(b,120))  
    screen.blit(bild,bild1 )  
    
    pygame.display.flip()
    
#while pygame.event.poll().type != pygame.KEYDOWN:
 #       pygame.time.delay(10)
        
pygame.quit()

Verfasst: Donnerstag 8. Mai 2008, 21:49
von sea-live
müsste das surface beim drehen eines quadrates nicht grösser werden

PYTHAGORAS

Code: Alles auswählen

class Rechteck(pygame.sprite.Sprite):
    speed = 5
    angle = 90
    def __init__(self):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.images = pygame.Surface([50,50])
        self.images.fill([255,0,255])
        self.image = self.images
        self.rect = self.image.get_rect(center=(160,120))
        
    def move(self,moving_vertical,moving_horizontal,rotate_left,rotate_right):
        if moving_vertical and rotate_left != 2 and rotate_right != 2:
            self.rect[1] += moving_vertical*self.speed
            self.rect = self.rect.clamp(SCREENRECT)
        if moving_horizontal and rotate_left != 2 and rotate_right != 2:
            self.rect[0] += moving_horizontal*self.speed
            self.rect = self.rect.clamp(SCREENRECT)
        if rotate_left == 2:
            oldCenter = self.rect.center
            self.angle += 2
            self.image = pygame.transform.rotate(self.images, self.angle)
            self.rect = self.image.get_rect()
            self.rect.center = oldCenter
        if rotate_right == 2:
            oldCenter = self.rect.center
            self.angle -= 2
            self.image = pygame.transform.rotate(self.images, self.angle)
            self.rect = self.image.get_rect()
            self.rect.center = oldCenter


Verfasst: Freitag 9. Mai 2008, 05:52
von BlackJack
Was ist denn das für eine haarsträubende API!? Man kann nur um zwei Grad drehen, aber nicht bewegen wenn gedreht wird, wobei die "keine Drehung" durch alles ausser dem Wert 2 für die beiden "Drehargumente" angezeigt wird? Und je ein Argument für links und rechts drehen statt *einem* was dann halt auch negativ sein kann!?

Verfasst: Freitag 9. Mai 2008, 10:42
von sechsrad
müsste das surface beim drehen eines quadrates nicht grösser werden
ist bei pygame total überflüssig, weil es intern von pygame durchgeführt wird. wenn du mein viereck drehst und vorher die transparens ausgeschaltest, ist es beim drehen gut sichtbar, wie die hintergrundfläche angepasst wird.

pygame nimmt hier einem die arbeit ab.

Verfasst: Freitag 9. Mai 2008, 16:05
von fred.reichbier
bzw. erzeugt pygame.transform.rotate ein neues Surface-Objekt.

Übrigens, sicher, dass dein Code funktioniert?
self.image = self.images
bedeutet nämlich, dass self.image und self.images dasselbe Objekt sind.

Verfasst: Freitag 9. Mai 2008, 19:03
von sea-live
es läuft einfach nicht move left right top bottem geht aber rotieren nicht

Code: Alles auswählen

import pygame
from pygame.locals import *

SCREENRECT = Rect(0, 0, 320, 240)

class Rechteck(pygame.sprite.Sprite):
    speed = 5
    angle = 90
    def __init__(self):
        pygame.sprite.Sprite.__init__(self,self.containers)
        self.image = pygame.Surface([50,50])
        self.image.fill([255,0,255])
        self.original = pygame.Surface([50,50])
        self.original.fill([255,0,255])
        self.rect = self.image.get_rect(center=(160,120))
        self.speed = 5
        self.angle = 90
        
    def update(self):
        keystate = pygame.key.get_pressed()  

        moving_vertical = keystate[K_DOWN] - keystate[K_UP]
        moving_horizontal = keystate[K_RIGHT] - keystate[K_LEFT] 
        rotate_left = keystate[K_DOWN] + keystate[K_LEFT]
        rotate_right = keystate[K_DOWN] + keystate[K_RIGHT]

        if moving_vertical and rotate_left != 2 and rotate_right != 2:
            self.rect[1] += moving_vertical*self.speed
            self.rect = self.rect.clamp(SCREENRECT)
        if moving_horizontal and rotate_left != 2 and rotate_right != 2:
            self.rect[0] += moving_horizontal*self.speed
            self.rect = self.rect.clamp(SCREENRECT)
        if rotate_left == 2:
            self.oldCenter = self.rect.center
            self.angle += 5
            if self.angle == 180:
                self.angle = 90
            self.image = pygame.transform.rotate(self.original, self.angle)
            self.rect = self.image.get_rect()
            self.rect.center = self.oldCenter
        if rotate_right == 2:
            self.oldCenter = self.rect.center
            self.angle -= 5
            if self.angle == 0:
                self.angle = 90
            self.image = pygame.transform.rotate(self.original, self.angle)
            self.rect = self.image.get_rect()
            self.rect.center = self.oldCenter
        
def main():
        
    pygame.init()
    try:
        os.environ['SDL_VIDEO_CENTERED'] = '1'
    except:
        pass

    #pygame.display.set_icon(pygame.image.load(os.path.join('data', 'icones1.gif')))

    pygame.display.set_caption('RECHTECK move')
    pygame.mouse.set_visible(0)
    screen = pygame.display.set_mode(SCREENRECT.size)

    background = pygame.Surface(screen.get_size())
    background.fill([255,255,0])
     
    clock = pygame.time.Clock()

    all = pygame.sprite.RenderUpdates()
    Rechteck.containers = all

    rechteck = Rechteck()

    weiter = True

    while weiter:
        clock.tick(60)
        
        event = pygame.event.poll()
        if event.type == QUIT or \
           (event.type == KEYDOWN and event.key == K_q):
            break
        if event.type == KEYDOWN and event.key == K_ESCAPE:
            break

        screen.blit(background, (0, 0))
        all.draw(screen)
        all.update()
        pygame.display.flip()
        pygame.time.wait(50)
    pygame.quit()

if __name__ == '__main__': main()

Verfasst: Freitag 9. Mai 2008, 20:47
von sechsrad
wenn du dieses änderst: "if rotate_left == 2"
in : "if rotate_left " dann geht es und du siehst deutlich wie der hintergrund sich dem drehenden viereck anpasst bzw grösser und kleiner wird.
du musst dem surface noch einen andere farbe geben , damit sich dein viereck und das surface unterscheiden , du siehst ja nicht die drehung.