Mr.Python Mr.Python - 4 months ago 7
Python Question

If/else statement in for loop causes variable to have strange behavior

I have a list of rectangles coordinates, that I'm iterating over to test for collisions with each one. The list is Like so:

self.rectangle_list = [(200, 30, 100, 10), (200, 60, 100, 10), (200, 90, 100, 10), (200, 120, 100, 10), (200, 150, 100, 10)]
. My code for the for loop is below.

mouse_x, mouse_y = event_obj.pos
for rects in self.rectangle_list:
x, y, w, h = rects
if x <= mouse_x <= x + w and y <= mouse_y <= y + h:
self.hovering = True
else:
self.hovering = False
print(self.hovering)


Now when I print out self.hovering, The only time It changes to
True
is when The mouse cursor is in the coordinates of the very last rectangle in the list.

I'm stumped as to why this, I thought I Was iterating over the entire list not just the last part of the list.

The thing is though, when I move
self.hovering
under the
if
statement it works, but never sets
self.hovering
back to False while the
if
condition is not meet.

example code to reproduce the problem is bellow:

import pygame as pg


class RenderRects:
def __init__(self, surface, rects_to_render=0):
self.surface = surface
self.rects_to_render = rects_to_render
self.rectangle_list = []
self.hovering = False

def render_rects(self):
y_padding = 0
for rects in range(self.rects_to_render):
y_padding += 30
menu_items_rect = (200, y_padding, 100, 10)
pg.draw.rect(self.surface, (255, 0, 0), menu_items_rect)
if len(self.rectangle_list) > 5:
del self.rectangle_list[4:]
self.rectangle_list.append(menu_items_rect)

def check_for_rect_collision(self, event_obj):
#-----------------Where problem is-----------#
mx, my = event_obj.pos
for rects in self.rectangle_list:
x, y, w, h = rects
if x <= mx <= x + w and y <= my <= y + h:
self.hovering = True
else:
self.hovering = False
print(self.hovering)
#-----------------Where problem is-----------#

def update_rects(self, event_obj):
if event_obj.type == pg.MOUSEMOTION:
self.check_for_rect_collision(event_obj)

def main():
WIDTH = 800
HEIGHT = 600
display = pg.display.set_mode((WIDTH, HEIGHT))

R = RenderRects(display, rects_to_render=5)

running = True
while running:
for e in pg.event.get():
if e.type == pg.QUIT:
running = False
pg.quit()
quit()

R.update_rects(e)

display.fill((255, 255, 255))
R.render_rects()
pg.display.flip()

if __name__ == '__main__':
main()


Try hovering over each red rectangle and you'll see that the only time
True
is printed is when the mouse is over the very bottom red rectangle.

Thanks for any answers.

~Mr.Python

Answer

Your if statement has a problem:

if x <= mouse_x <= x + w and y <= mouse_y <= y + h:
                self.hovering = True

You can't chain less than/greater than as you do in: x <= mouse_x <= x + w. This really gets translated to:

if x <= (mouse_x <= x + w) ....

And since True == 1 and False == 0, this means that if mouse_x <= x + w is True, x <= (mouse_x <= x + w) really becomes x <= 1

Comments