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

Re: [pygame] Rect borders



On Tue, 2005-11-29 at 10:23 +0100, Lionel barret De Nazaris wrote:
> I have a question for the community, I am a bit puzzled  :
> The last element of a list is the length of the list minus one :
> 
> >>> a = range(4)
> >>>  a[len(a)-1] == 3
> True
> 
> But for a rect, the last element of a line is length of the line :
> 
> >>> import pygame
> >>> a = pygame.Rect(0,0,5,5)
> >>> a.right != a.width-1
> True 
> >>> a.right
> 5

Yes, what you are describing is that the Rect does not include its
"upper bounds" (the left and bottom edges). This is a common concept for
2D graphics, although the logic behind it is not immediately obvious.

Your example with range brings up a good example.

>>> r = range(10, 20)
>>> print len(r), 10 in r, 20 in r
10 True False

>>> r = pygame.Rect(10, 10, 20, 20)
>>> print r.width, r.collidepoint(10, 10), r.collidepoint(20, 20)
10 1 0


The reasons for the outer edges do not include its area are similar to
the reasons python ranges and arrays do not include their upper bound.
Although the benefits are not scientific, a system where "right = left +
width" and "left = right - width" works out better for a lot of the
rectangular math and looping. You could do "range(rect.top,
rect.bottom)" and be sure you'll loop over every row.

This is generally the way regions are defined in graphical toolkits. If
you've done any drawing or widget positioning under Windows, GTK, etc,
they all use this same system. 

As a side effect, this allows you to easily align rectangles next to
each other without overlap. I can assign "rect2.left = rect1.right" and
be sure there is no overlap.

When just starting out, it can be a surprise. Hopefully now that you
know it won't bite you again. All I can really say is just go with it,
it ends up working better. :]