pygame langsam und ruckelt?

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

ich habe mal nen kleines programm geschrieben, das einen sternenhimmel simuliert. allerdings habe ich das gefühl, das es nicht so recht smooth ist, und irgendwie auch ruckelt. auf meinem 700Mhz rechner, ist es dann kaum noch zumutbar, obwohl alle rechner 3D beschleunigung haben ( nutze linux debian lenny ).

Code: Alles auswählen

import pygame, random
from pygame.locals import *

xsize=800
ysize=600

pygame.init()
screen = pygame.display.set_mode([xsize,ysize],pygame.DOUBLEBUF | pygame.HWSURFACE | pygame.FULLSCREEN,32)
screen.fill([0,0,0])

mainloop, x,y, color, fontsize, delta, fps =  True, 25 , 0, (16,16,16), 35, 1, 30
clock = pygame.time.Clock()
x=range(xsize)
for i in range(1, xsize):
	x[i]=random.randrange(1,xsize)


while mainloop:
	y=0
	tick_time = clock.tick(fps) # milliseconds since last frame
	pygame.display.set_caption("press Esc to quit. FPS: %.2f" % (clock.get_fps()))
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			mainloop = False
		elif event.type == pygame.KEYDOWN:
			if event.key == pygame.K_ESCAPE:
				mainloop = False
	screen.fill([0,0,0])
	for i in range(1, xsize):
		screen.set_at((x[i], y), (255,255,255))
		y=y+1
	for i in range(1, xsize):
		x[i]=x[i]+1
	for i in range(1, xsize, 2):
		x[i]=x[i]+1
	for i in range(1, xsize, 3):
		x[i]=x[i]+1
	for i in range(1, xsize):
		if x[i]>xsize:
			x[i]=0
	pygame.display.update()
weiß da jemand rat?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich kenne mich mit PyGame nicht aus, aber vielleicht ist Clock.tick etwas für dich.

Die letzten vier for-Schleifen kann man übrigens gut zu einer zusammenfassen. Für die letzte Schleife Empfehle ich einen Blick auf den Modulo-Operator (%).

Nur kurz nachgefragt: Zeilen 30 bis 32 sollen nicht den Bildschirm löschen, oder?
Das Leben ist wie ein Tennisball.
BlackJack

@EyDu: Die Zeilen sollen die Sterne (Punkte) zeichnen, aber damit ist definitiv etwas nicht in Ordnung, weil `y` von 1 bis 799 läuft, aber so viele Zeilen gibt es auf dem Surface ja gar nicht.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

@BlackJack
richtig, löschen mache ich mit fill.

ja, suche schon nach einem timer, sprich clock, tick. aber ich habe mal gehört, das das gar nicht so einfach sein soll, da jeder bildschirm eine andere frequenz haben könnte.

EDIT:
nur hier sehe ich gerade, das der clock timer nur dafür da ist, eine bestimmte zeit einzuhalten
http://jonasbsb.jo.funpic.de/hendrix/py ... ample.html

beim c64er war das irgendwie einfacher. da konnte ich den rasterstrahl einfach abfragen. je nach dem, wo er stand, konnte man einen weichen scroller programmieren. ich frage mich nur, wie soll so etwas auf dem PC bzw. SDL gehen?
BlackJack

@The Hit-Man: Zuverlässig geht das auf dem PC im Grunde (heute) gar nicht (mehr). TFTs haben ja nicht einmal einen Rasterstrahl, dessen Position man abfragen könnte.

Bei VGA-Karten kann man den Zeitpunkt abfragen, bei dem der Rasterstahl wieder vom unteren Bildrand zum oberen Bildrand hochbewegt wird, ich weiss aber nicht, ob SDL das benutzt oder irgendwie zur Verfügung stellt. Ausserdem würde man die Geschwindigkeit dann von der Bildwiederholzahl des Monitors bzw. Grafikmodus abhängig machen. Etwas, dass man eigentlich auch nicht wirklich möchte.

Andererseits kann ich bei meinem Starscroller und einem TFT kein besonderes ruckeln feststellen: http://paste.pocoo.org/show/137336/
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

@BlackJack

habs mir angesehen, und deines sieht genau so aus wie meins. bei den sternen fällt das auch nicht ganz so auf, aber laß mal nen logo drüber fliegen in einem tic tac effekt. also nen logo, was sich von links nach rechts bewegt, per sinus bewegung ( sinus deshalb, das es sanft hin und her schwingt ). ich glaube, dann sieht man das ruckeln. des weiteren weiß ich nicht, warum meine framerate so in den keller geht und der prozessor so ausgelastet ist :(

EDIT: es spielt auch keine rolle, welche programmiersprache. habs in python, C und C# programmiert. überall der gleiche effekt. irgendwie muß es aber möglich sein, da es ja auch gute spiele unter SDL gibt. des weiteren hatte ich irgendwo nen smooth-scroller gesehen, der eine landschaft scrollt. war unter C geschrieben, aber was der da für timerberechnungen genommen hatte, war nen wahnsinn. das wollte ich eigentlich vermeiden, irgendwie.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Um irgendwelche Timerberechnungen wirst Du wohl nicht herumkommen. Die wahrgenommene Geschwindigkeit sollte natuerlich unabhaengig von den FPS sein. Die Geschwindigkeit in Pixeln sollte in Abhaengigkeit von der Dauer eines Frames berechnet werden. Habe mit Deinem Code mal etwas herumgespielt, weiss aber nicht, ob das hier Dir 'smooth' genug ist:

Code: Alles auswählen

import pygame, random
from pygame.locals import *

xsize = 800
ysize = 600

pygame.init()
screen = pygame.display.set_mode([xsize,ysize],pygame.DOUBLEBUF |
                                 pygame.HWSURFACE #| pygame.FULLSCREEN,
                                 ,32)
screen.fill([0,0,0])

mainloop, x,y, color, fontsize, delta =  True, 25 , 0, (16,16,16), 35, 1
clock = pygame.time.Clock()
x=range(xsize)
for i in range(1, ysize):
    x[i]=random.randrange(1, xsize)

## !
FPS = 500
SPEED = 0.07
dx = 0

while mainloop:

    y=0
    tick_time = clock.tick_busy_loop(FPS) # milliseconds since last frame
    pygame.display.set_caption("press Esc to quit. FPS: %.2f" % (clock.get_fps()))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            mainloop = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                mainloop = False
    screen.fill([0,0,0])
    for i in xrange(1, ysize):
        screen.set_at((int(x[i] + 0.5), y), (255,255,255))
        y=y+1
    for i in range(1, xsize):
        x[i]=x[i] + dx #!
    for i in range(1, xsize, 2):
        x[i]=x[i] + dx #!
    for i in range(1, xsize, 3):
        x[i]=x[i] + dx #!
    for i in range(1, xsize):
        if x[i]>xsize:
            x[i]=0

    pygame.display.update()

    ## !
    ms = clock.get_time() # ms per frame
    dx = SPEED * ms
Die Prozessorauslastung betraegt ca. 66%.

:wink:
yipyip
Antworten