Nex_Lite - 7 months ago 36
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.

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.