---
# System prepended metadata

title: Grupo de estudos em Python - Simulações físicas 2D

---

### Sesc Av. Paulista
## Grupo de estudos em Python
#### `hackmd.io/@sesc-av-paulista/estudos-em-python-24-abril`


# Simulações físicas 2D (com [PyMunk](https://pymunk.org))

Primeiro exemplo (bolinhas e uma parede fixa)

![image](https://hackmd.io/_uploads/S13AS-uJeg.png)


```python=
import pymunk

bolinhas = []  # lista vazia
paredes = []

space = pymunk.Space()
space.gravity = 0, 900

def setup():
    size(600, 600)
    acrescenta_parede(100, 500, 500, 500)
    
def acrescenta_bola(x, y):
    corpo = pymunk.Body(10, 100)
    corpo.position = x, y
    forma = pymunk.Circle(corpo, 10, (0, 0))
    forma.friction = 0.99
    space.add(corpo, forma)
    bolinhas.append(forma)

def acrescenta_parede(xa, ya, xb, yb):
    forma = pymunk.Segment(space.static_body,
                           (xa, ya), (xb, yb),
                           radius=1.5)
    forma.friction = 100.99
    space.add(forma)
    paredes.append(forma)
    
    
def draw():  # fica repetindo
    background(0, 0, 200)  # R, G, B
    for bola in bolinhas:
        r = bola.radius
        pos = bola.body.position
        no_stroke()
        fill(0)
        circle(pos.x, pos.y, r * 2)
    for parede in paredes:
        stroke(128)
        stroke_weight(3)
        corpo = parede.body
        angulo = corpo.angle
        inicio = corpo.position + parede.a.rotated(angulo)
        final = corpo.position + parede.b.rotated(angulo)
        line(inicio.x, inicio.y, final.x, final.y)
    
    if is_key_pressed and key_code == SHIFT:     
        acrescenta_bola(mouse_x + random(-1, 1), mouse_y)

    print(len(space.shapes))
    
    space.step(1 / 60)
    
def mouse_pressed():
    acrescenta_bola(mouse_x + random(-1, 1), mouse_y)
   
def key_pressed():
    if key == DELETE and paredes:
        ultima_parede = paredes.pop()
        space.shapes.remove(ultima_parede)


```

Final

![image](https://hackmd.io/_uploads/rJZnabu1ex.png)


```python=
# Código para py5 "imported mode" precisa de um "sketch runner"
# Saiba mais em: https://abav.lugaralgum.com/como-instalar-py5/

import pymunk

space = pymunk.Space()
space.gravity = 0, 900

bolinhas = []  
paredes = []
inicio_nova_parede = None

def setup():
    size(600, 600)
    acrescenta_parede(100, 500, 500, 500)
    
def acrescenta_bola(x, y):
    corpo = pymunk.Body(10, 100)
    corpo.position = x, y
    forma = pymunk.Circle(corpo, 10, (0, 0))
    forma.friction = 0.99
    space.add(corpo, forma)
    bolinhas.append(forma)

def acrescenta_parede(xa, ya, xb, yb):
    forma = pymunk.Segment(space.static_body,
                           (xa, ya), (xb, yb),
                           radius=1.5)
    forma.friction = 100.99
    space.add(forma)
    paredes.append(forma)

def draw():  # fica repetindo
    background(0, 0, 200)  # R, G, B
    for bola in bolinhas.copy():
        r = bola.radius
        pos = bola.body.position
        no_stroke()
        fill(0)
        circle(pos.x, pos.y, r * 2)
        # remover bolas que cairam pra baixo da tela
        if pos.y > height + 50:
            bolinhas.remove(bola)
            space.remove(bola)
    # desenhar linhas-parede (simplifiquei!)
    for parede in paredes:
        stroke(128)
        stroke_weight(3)
        line(parede.a.x, parede.a.y,
             parede.b.x, parede.b.y)
    # muitas bolas novas
    if is_key_pressed and key_code == SHIFT:     
        acrescenta_bola(mouse_x + random(-1, 1), mouse_y)
    # mostra preview da parede sendo desenhada
    if inicio_nova_parede:
        stroke(255, 0, 0) # linha vermelha
        line(*inicio_nova_parede, mouse_x, mouse_y)
    # avança um passo da simulação
    space.step(1 / 60)
    
def mouse_pressed():
    global inicio_nova_parede
    if key_code == CONTROL:
        acrescenta_bola(mouse_x + random(-1, 1), mouse_y)
    else:
        inicio_nova_parede = (mouse_x, mouse_y)
        
def mouse_released():
    global inicio_nova_parede
    if (inicio_nova_parede and
        dist(*inicio_nova_parede, mouse_x, mouse_y) > 5):
        inicio_x, inicio_y = inicio_nova_parede
        acrescenta_parede(inicio_x, inicio_y,
                          mouse_x, mouse_y)
        inicio_nova_parede = None
   
def key_pressed():
    global inicio_nova_parede, space, bolinhas, paredes
    # tecla DELETE apaga paredes
    if key == DELETE and inicio_nova_parede:
        inicio_nova_parede = None
    elif key == DELETE and paredes:
        ultima_parede = paredes.pop()
        space.remove(ultima_parede)
    # "c" limpa bolas
    elif key == 'c' or key == 'C':
        for bola in bolinhas.copy():
            bolinhas.remove(bola)
            space.remove(bola)
    # "s" salva estado da simulação
    elif key == 's':
        save_pickle((space, bolinhas, paredes), 'space.data')
        print('salvo')
    # "l" (de "load") recarrega estado salvo
    elif key == 'l':
        if Path('space.data').is_file():
            space, bolinhas, paredes = load_pickle('space.data')

    print(f'objetos simulados: {len(space.shapes)}')
```