[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [SPAM: 10.100] Re: [pygame] Circle cut off at 60+fps, fixed by display.flip





One thing I noticed about your code is you're making your own rectangle. The draw function returns a rect so you should pass that. It's useful because the rect it returns is constrained by the screen so there's less to update. Plus you don't have to make as many rects. But that doesn't fix your problem.

Here's just a list of observations I made while experimenting.

I'm not sure what's causing this issue. It's weird because it goes in all directions. It seems to be affected by the time it has to compute. Eg. if you change fps down to 20 it goes away. And if you change it to 120 it gets terrible. Also the amount of clipping is proportional to the speed at which you move. More speed = more clipping.

I'm not sure why flipping or increasing the size of the rect fixes the problem but it does. If you inflate your rect slightly it fixes it. But if you increase speed too much then it comes back.

The final observation that I made is that's it's not possible to stop on a clipped rect. This makes me think this is a vsync issue. I'm pretty sure that pygame does not vsync unless it's in hardware accelerated fullscreen. So maybe the reason that flipping and bigger rects stop the issue is because they give the system a slight delay. I also managed to get two circles to draw and the effect goes away entirely. This might also have to do with a longer processing time.

Here's modified code that allows you to try to "catch" the clipping in action (it's not observable). It also toggles from inflating to not if you uncomment the right part. This doesn't have two circles.

import pygame
w,h=500,500
fps=40
pygame.init()
screen = pygame.display.set_mode([w, h])
color=pygame.Color("white")
clock=pygame.time.Clock()
radius=20
x,y=w/2,h
dx = 10
r = pygame.Rect((0,0), (radius*2, radius*2))
r.center = (x, y)
inflate = False
def get_bbox(x,y):
ÂÂÂ left = x - radius
ÂÂÂ top = y - radius
ÂÂÂ width = radius * 2
ÂÂÂ height = radius * 2
ÂÂÂ return pygame.Rect((left, top), (width, height))

while True:
ÂÂÂ old_r=r
ÂÂÂ y-=dx
ÂÂÂ if y < 100:
ÂÂÂÂÂÂÂ y = w
ÂÂÂÂÂÂÂ #fps -= 5
ÂÂÂÂÂÂÂ #dx += 1
ÂÂÂÂÂÂÂ fps = 0
ÂÂÂÂÂÂÂ #inflate = not inflate
ÂÂÂ if fps <= 0:
ÂÂÂÂÂÂÂ fps = 40
ÂÂÂÂÂÂÂ pygame.time.wait(500)
ÂÂÂ screen.fill(pygame.Color("black"),old_r)
ÂÂÂ r = pygame.draw.circle(screen, color, (x, h-y), radius, 0)
ÂÂÂ if inflate: r.inflate_ip(20,20)
ÂÂÂ pygame.display.update([r,old_r])
ÂÂÂ clock.tick(fps)


I'm really at a loss as to what this actually is,
Jeffrey


On Fri, Jun 13, 2014 at 7:41 PM, Greg Ewing <greg.ewing@xxxxxxxxxxxxxxxx> wrote:
I just tried this on a Mac, and it works fine,
no flickering or tearing.

The only thing I can think of is that, on your system,
display.update() is not waiting for vertical sync,
whereas display.flip() is.

The pygame docs aren't very clear about whether it's
supposed to or not. They say that flip() does, and then
just say that update() is an "optimised version" of
flip().

This suggest to me that it should, and it does seem
to on my system, but maybe some implementations are
different.

Maybe you could try passing a single rect to update()
that's the union of the old an new rects. While that
won't eliminate all possibility of tearing, it may
make it less likely.

--
Greg




--

   Jeffrey Kleykamp