Nex_Lite Nex_Lite - 1 month ago 11
Python Question

velocity reassignment for collision detection is none-responsive when collision is triggered through a function

import pygame as pg
import sys





def main():
pg.init()
clock = pg.time.Clock()
fps = 60
bg = (255, 255, 255)

size = [400, 400]

this = pg.display.set_mode(size)

ay = .5
vy = 2
vx = 4


player = pg.Rect(100, 50, 20, 20)
platform = pg.Rect(0, size[1]-20, size[0], 20)

objs = [player, platform]

colors = [[255, 0, 0], [0, 255, 0]]

move = [pg.K_LEFT, pg.K_RIGHT]

def collide(player, platform, vy):
hit = player.colliderect(platform)

if hit:
if player.bottom >= platform.top:
player.bottom = platform.top
vy = 0

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

if event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
vy -= 10

key = pg.key.get_pressed()

for i in range(2):
if key[move[i]]:
player.x += vx * [-1, 1][i]


this.fill(bg)

vy += ay
player.y += vy


collide(player, platform, vy)


for i, obj in enumerate(objs):
pg.draw.rect(this, colors[i], obj)

pg.display.update()
clock.tick(fps)

pg.quit()
sys.exit


if __name__ == '__main__':
main()


As you can see from the above code i am attempting to create a landing procedure through the "rectcollide" method but for some unknown reason whenever the function is called although the collision is detected and the player's position is re-assigned, the player's velocity however is not altered in anyway. The strange thing is, if i don't use a function and directly implement the conditional in the main game update loop, it works just fine. So the problem is with the function's behavior i presume. Any help in solving this will be much appreciated. Thanks in advance.

Answer

In your inner function, vy is a local variable (an argument to the function). Changing its value doesn't change the value of the vy variable in the outer function. You either need to return the new velocity (and change the code calling the function to vy = collide(player, platform, vy)), or change your design around so that the velocity is an attribute of some other object (maybe player if you changed it to be an instance of a custom class).

If you were directly accessing vy in the outer namespace (without it being an argument), you could use a nonlocal statement in the inner function to let it write to the outer function's local variable. However, letting things scribble on other namespaces like this is often considered poor design. Using objects or return values is generally easier to reason about and much simpler to debug when things go wrong.