Bounce

\displaystyle \frac{\vec{\Delta s}}{\Delta t} = \vec{v}\vec{\Delta s} = \vec{v}\cdot \Delta t\vec{s} \ \ += \ \ \vec{\Delta s}

Una pallina bianca al centro della scena

from vpython import *

sphere()

Una pallina azzurra e una parete verde a destra

from vpython import *
   
ball = sphere(color  = color.cyan      , 
              pos    = vector(-5, 0, 0), 
              radius = 0.5             )
 
wallR = box(color = color.green        , 
            pos   = vector(6, 0, 0)    , 
            size  = vector(0.2, 12, 12))

La posizione della palla dipende dal tempo:

  • ball.pos = ball.pos + ball.velocità * dt
from vpython import *

ball = sphere(color = color.cyan, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(6, 0, 0), size = vector(0.2, 12, 12))

ball.velocità = vector(25, 0, 0)
dt = 0.005
t = 0
ball.pos += ball.velocità * dt

Il tempo scorre per alcuni secondi

  • t = t + dt
from vpython import *

ball = sphere(color = color.cyan, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(6, 0, 0), size = vector(0.2, 12, 12))

ball.velocità = vector(25, 0, 0)
dt = 0.005
t = 0
while(t < 3):
    rate(100) 
    ball.pos += ball.velocità * dt
    t += dt

Se la posizione della palla supera quella del muro a destra allora si inverte il segno della velocità

from vpython import *

ball  = sphere(color = color.cyan, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(6, 0, 0), size = vector(0.2, 12, 12))

ball.velocità = vector(25, 0, 0)
dt = 0.005
t = 0
while(t < 3):
    rate(100)
 
    if(ball.pos.x > wallR.pos.x): 
        ball.velocità.x = -ball.velocità.x
    ball.pos += ball.velocità * dt
    t += dt

La palla rimbalza sul lato destro ma si perde sul lato sinistro…
Un’altra parete e un’altra condizione per rimbalzare

from vpython import *

ball = sphere(color = color.cyan, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(6, 0, 0), size = vector(0.2, 12, 12))

ball.velocità = vector(25, 0, 0)
dt = 0.005
t = 0
while(t < 3):
    rate(100) 

    if(ball.pos.x > wallR.pos.x): ball.velocità.x = -ball.velocità.x 
    if(ball.pos.x < wallL.pos.x): ball.velocità.x = -ball.velocità.x 

    ball.pos += ball.velocità * dt
    t += dt

La palla annega parzialmente nelle pareti, è necessario migliorare il controllo

from vpython import *

ball = sphere(color=color.cyan, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(+6, 0, 0), size = vector(0.2, 12, 12))
wallL = box(color = color.green, pos = vector(-6, 0, 0), size = vector(0.2, 12, 12))

ball.velocità = vector(25, 0, 0)
dt = 0.005
t = 0
while(t < 3):
    rate(100) 

    if(ball.pos.x + ball.radius > wallR.pos.x): ball.velocità.x = -ball.velocità.x
    if(ball.pos.x - ball.radius < wallL.pos.x): ball.velocità.x = -ball.velocità.x      

    ball.pos += ball.velocità * dt
    t += dt

Un vettore di colore giallo segue la palla e indica direzione e verso del movimento

from vpython import *

ball = sphere(color = color.cyan, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(+6, 0, 0), size = vector(0.2, 12, 12))
wallL = box(color = color.green, pos = vector(-6, 0, 0), size = vector(0.2, 12, 12))

ball.velocità = vector(25, 0, 0)

varr = attach_arrow(ball,
                    "velocità",
                    color=color.yellow,
                    scale=0.1,
                    shaftwidth=0.2)

dt = 0.005
t = 0
while(t < 3):
    rate(100)

    if(ball.pos.x + ball.radius > wallR.pos.x): ball.velocità.x = -ball.velocità.x
    if(ball.pos.x - ball.radius < wallL.pos.x): ball.velocità.x = -ball.velocità.x      

    ball.pos += ball.velocità * dt
    t += dt

Per seguire la traiettoria della palla aggiungi automaticamente una traccia grafica: make_trail=True

...
ball = sphere(color = color.cyan, make_trail = True, pos = vector(-5, 0, 0), radius = 0.5)
...

La traiettoria completamente orizzontale è prevedibile, aggiungi

  1. il movimento in verticale
  2. le pareti in alto e in basso
  3. i controlli corrispondenti
from vpython import *

ball = sphere(color = color.cyan, make_trail = True, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(+6, 0, 0), size = vector(.2, 12, 12))
wallL = box(color = color.green, pos = vector(-6, 0, 0), size = vector(.2, 12, 12))
wallU = box(color = color.green, pos = vector(0, +6, 0), size = vector(12, .2, 12))
wallD = box(color = color.green, pos = vector(0, -6, 0), size = vector(12, .2, 12))

ball.velocità = vector(25,7,0)

varr = attach_arrow(ball,  "velocità",  color=color.yellow, scale=0.1, shaftwidth=0.2)

dt = 0.005
t = 0
while(t < 3):
    rate(100) 

    if(ball.pos.x + ball.radius > wallR.pos.x): ball.velocità.x = -ball.velocità.x
    if(ball.pos.x - ball.radius < wallL.pos.x): ball.velocità.x = -ball.velocità.x 
    if(ball.pos.y + ball.radius > wallU.pos.y): ball.velocità.y = -ball.velocità.y
    if(ball.pos.y - ball.radius < wallD.pos.y): ball.velocità.y = -ball.velocità.y 

    ball.pos += ball.velocità * dt
    t += dt

La palla si muove su un piano xy piuttosto che nello spazio 3d, aggiungi

  • il movimento in profondità
  • una parete di fondo
  • la parete frontale è solo immaginata…
  • i controlli corrispondenti

L’animazione può continuare all’infinito modificando la condizione del ciclo

...
while(True):
    ...

Si può aggiungere una seconda palla con colore e vettore velocità diversi

from vpython import *
 
ball1 = sphere(color = color.cyan   , make_trail = True, pos = vector(-5, 0, 0), radius = 0.5)
ball2 = sphere(color = color.magenta, make_trail = True, pos = vector(-5, 0, 0), radius = 0.5)

wallR = box(color = color.green, pos = vector(+6, 0, 0), size = vector(.2, 12, 12))
wallL = box(color = color.green, pos = vector(-6, 0, 0), size = vector(.2, 12, 12))
wallU = box(color = color.green, pos = vector( 0,+6, 0), size = vector(12, .2, 12))
wallD = box(color = color.green, pos = vector( 0,-6, 0), size = vector(12, .2, 12))
wallB = box(color = color.green, pos = vector( 0, 0,-6), size = vector(12, 12, .2))
 
ball1.velocità = vector(25, 7, 13)
ball2.velocità = vector(23, 5, 7)

varr1 = attach_arrow(ball1, "velocità",  scale=0.1, shaftwidth=0.2)
varr2 = attach_arrow(ball2, "velocità",  scale=0.1, shaftwidth=0.2)
 
dt = 0.005
t = 0
while(True):
    rate(100)
 
    if(ball1.pos.x + ball1.radius > wallR.pos.x): ball1.velocità.x = -ball1.velocità.x
    if(ball1.pos.x - ball1.radius < wallL.pos.x): ball1.velocità.x = -ball1.velocità.x 
    if(ball1.pos.y + ball1.radius > wallU.pos.y): ball1.velocità.y = -ball1.velocità.y
    if(ball1.pos.y - ball1.radius < wallD.pos.y): ball1.velocità.y = -ball1.velocità.y 
    if(ball1.pos.z + ball1.radius > +6         ): ball1.velocità.z = -ball1.velocità.z
    if(ball1.pos.z - ball1.radius < wallB.pos.z): ball1.velocità.z = -ball1.velocità.z 
    
    ball1.pos += ball1.velocità*dt 
    
    if(ball2.pos.x + ball2.radius > wallR.pos.x): ball2.velocità.x = -ball2.velocità.x
    if(ball2.pos.x - ball2.radius < wallL.pos.x): ball2.velocità.x = -ball2.velocità.x 
    if(ball2.pos.y + ball2.radius > wallU.pos.y): ball2.velocità.y = -ball2.velocità.y
    if(ball2.pos.y - ball2.radius < wallD.pos.y): ball2.velocità.y = -ball2.velocità.y 
    if(ball2.pos.z + ball2.radius > +6         ): ball2.velocità.z = -ball2.velocità.z
    if(ball2.pos.z - ball2.radius < wallB.pos.z): ball2.velocità.z = -ball2.velocità.z 

    ball2.pos += ball2.velocità*dt

    t += dt

Ancora…

  1. Più palline
  2. Posizione iniziale, velocità, colore a piacere
  3. Colori delle palline, o delle pareti, che cambiano quando c’è un rimbalzo
  4. Pareti mobili…

Per evitare che la finestra si adatti a ogni intervento dell’utente escludi autoscale prima del ciclo while

...
scene.autoscale = False
...

Tutorial ufficiale