[EMAIL PROTECTED] wrote: > All, > Hello and welcome to Python. > Apologies in advance: I'm new to Python and OO, and I'm sure this is a > really simple question, but I just can't seem to crack it on my own, or > through looking at examples. I'm playing around with VPython > (http://www.vypthon.org) to try and teach myself about objects: I've > got a box that I've put some balls in, and I'm trying to get said balls > to move around and bounce off the walls of the box -- that's literally > it. I can put multiple balls in the box, but I can't get them to update > their position -- it works when I have one ball, but now that I have a > list of balls, I can't get them to move. > > I've copied in the code I'm using below, as it's not very long -- can > anyone help me? > Below is your code with the many impovements (including other suggestions in this thread). I've used double (``##``) comments to indicate all changes.
Stylistic improvements aside, the biggest issue was that your code didn't bounce the balls off the walls but just wrapped them to the opposite wall. The simplest example of bouncing appears in http://vpython.org/vpythonprog.htm Bouncing requires a separate velocity per ball (when one bounces, the others keep direction). Note that `b.velocity` has no signifacance to the sphere object -- in Python you can add attributes to most objects whenever you want. OOP purists would say this is dirty but "practicality beats purity". You could also use a separate `velocities[b]` dictionary if you prefer. # <--START--> ## Say this at the top if you use division. This fixes 3/2 to equal 1.5. ## (3//2 == 1 if you really want the floor of the ratio.) from __future__ import division from visual import * from random import uniform ## why limit to integral [a,b) values? # set up a box to collide with side_length = 100 minx = side_length * -10 maxx = side_length * 10 miny = side_length * -4 maxy = side_length * 4 numballs = 5 # number of balls ## List comprehensions simplify the ``b=[]; for...: b.append(...)`` idiom balls = [sphere(pos=(uniform(minx, maxx), uniform(miny, maxy)), radius=50, color=color.red) for i in range(numballs)] # create a wireframe of space ## Common spacing conventions: space after commas and around = in ## assignements but not = in keyword arguments left = curve(pos=[(minx, miny), (minx, maxy)], color=color.white) top = curve(pos=[(minx, maxy), (maxx, maxy)], color=color.white) right = curve(pos=[(maxx, maxy), (maxx, miny)], color=color.white) bottom = curve(pos=[(maxx, miny), (minx,miny)], color=color.white) ## Note that your `dt` was not equal to 1/rate, so you were not simulating ## in real time. I'll assume your velocity is correct but will increase ## the simulation speedup to make it less boring. fps = 50 ## this should not be touched once you match it to your computer speedup = 40.0 ## tune this to watch the process at different speeds dt = speedup/fps ## note that a big `dt` will increase simulation errors ## bouncing requires separate velocity per ball for b in balls: ## removed z component since you want a 2D simulation (right?) b.velocity = vector(2, 0.2) while True: ## the idiomatic way to say forever ... rate(fps) ## see comment above for b in balls: ## usually you don't need the indexes, only the items ## First update, then bounce - this way you never display ## a ball outside the box. b.pos += (b.velocity * dt) ## += avoids repeating yourself # check it hasn't overrun a boundary ## if it has, reflect velocity, not wrap around the position if b.x - b.radius < minx: b.velocity.x *= -1 if b.x + b.radius > maxx: b.velocity.x *= -1 if b.y - b.radius < miny: b.velocity.y *= -1 if b.y + b.radius > maxy: b.velocity.y *= -1 # <--END--> The above is an approximation: when the ball has already penetrated the wall to some depth, it only reverses the speed but leaves the ball in the wall. We are simulating a continious process by discrete steps. If the ball is inside the wall it means the collision occured earlier and the ball has already moved away for that distance. (I'm ingnoring ball and wall deformation here. This penetration depends randomly on `dt` so it's not the proper way to simulate deformation anyway.) So we shoud do:: if b.x - b.radius < minx: b.velocity.x *= -1 #b.x = minx - (b.x - b.radius - minx) + b.radius b.x = (minx + b.radius)*2 - b.x and similarly for other cases... -- http://mail.python.org/mailman/listinfo/python-list