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.ew...@canterbury.ac.nz>
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

Reply via email to