Skip to content

Instantly share code, notes, and snippets.

@villares
Last active June 19, 2022 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save villares/3c1831e2b149bd443285f1fbe19a9ce2 to your computer and use it in GitHub Desktop.
Save villares/3c1831e2b149bd443285f1fbe19a9ce2 to your computer and use it in GitHub Desktop.
Made with @Introscopia and 2D simulations course at participants at Sesc Av. Paulista [WIP at https://github.com/villares/pymunk-pinball-paulista/]
# Check out further developments at: https://github.com/villares/pymunk-pinball-paulista/
# Pymunk PINBALL experiments at Sesc Av. Paulista
# Needs py5.ixora.io and pymunk.org
# You'll need to learn about py5 imported mode (sketch_runner)
import pymunk as pm # importa lib de simulação
from random import choice
space = pm.Space() # objeto espaço de simulação
shapes = []
constraints = []
LEFT_CONTROL = 'a'
RIGHT_CONTROL = 'l'
PLUNGER_CONTROL = ' '
keys = {
LEFT_CONTROL: False,
RIGHT_CONTROL: False,
PLUNGER_CONTROL: False,
} # key: state (held)
def settings():
size(800, 750) # área de desenho (width, height)
def setup(): # configs iniciais (para o py5)
space.gravity = (0, 600) # (x, y) tupla vetor da acel.
assemble_ring( 300, 200, 300, -PI, 0, 100 )
build_box( 0, 200, 100, 850, True )
build_box( 500, 200, 100, 850, True )
build_box( 100, 850, 400, 100, True )
shapes[-1].collision_type = 99
build_line( 467, 300, 467, 850, 1 )
build_line( 155, 570, 101, 546, 1 )
build_line( 410, 572, 465, 553, 1 )
#build_ball( 280, 400, 16, static=True )
obst_pos = ( ( 280, 400 ), )
obst_verts = ( ( 0, -20 ), ( 10, 0 ), ( 0, 20 ), ( -10, 0 ) )
for pos in obst_pos:
body = pm.Body(0, 0)
body.position = pos
shp = pm.Poly( body, obst_verts )
shp.density = 1.2
shp.friction = 0.75
shp.elasticity = 0.66
shp.cor = color(255, 0, 0)
shapes.append(shp)
pvj = pm.PivotJoint( space.static_body, body, pos )
space.add( body, shp, pvj )
global plunger
build_box(468, 620, 32, 30, static=False)
plunger = shapes[-1].body
shapes[-1].friction = 0
shapes[-1].elasticity = 0
plunger_spring = pm.DampedSpring(plunger, space.static_body, (0, 0), (484, 635),
0, stiffness=90000, damping=5000)
space.add(plunger_spring)
#build_ball(484, 735, 8, static=True) # plunger stopper
global ball
build_ball( 486, 610, 15 )
shapes[-1].density = 0.02
shapes[-1].collision_type = 1
ball = shapes[-1].body #.apply_impulse_at_local_point( (0, -117000), (0,0) )
handler = space.add_collision_handler( 99, 1 )
handler.post_solve = lose_ball
#Paddle Comprimentos e Grossuras
PC = 80
Pc = 20
PG = 20
Pg = 10
#Left Paddle shape & body
global LPb, RPb
LPpts = ( (-Pc, -PG), (-Pc, PG), (PC, Pg), (PC, -Pg) )
LPb = pm.Body()
LPb.position = ( 180, 600 )
LPs = pm.Poly(LPb, LPpts)
space.add(LPb, LPs)
LPs.density = 0.1
LPs.friction = 0.3
LPs.elasticity = 0.5
LPs.cor = color(127)
shapes.append(LPs)
LPp = pm.PivotJoint( space.static_body, LPb, (180, 600) )
LPrl = pm.RotaryLimitJoint( space.static_body, LPb,
-PI / 12, PI / 10)
constraints.append( LPp )
space.add( LPp, LPrl )
#Right Paddle shape & body
RPpts = ( (-PC, -Pg), (-PC, Pg), (Pc, PG), (Pc, -PG) )
RPb = pm.Body()
RPb.position = ( 467-80, 600 )
RPs = pm.Poly(RPb, RPpts)
space.add(RPb, RPs)
RPs.density = 0.1
RPs.friction = 0.3
RPs.elasticity = 0.5
RPs.cor = color(127)
shapes.append(RPs)
RPp = pm.PivotJoint( space.static_body, RPb, (467-80, 600) )
RPrl = pm.RotaryLimitJoint( space.static_body, RPb,
-PI / 12, PI / 10)
constraints.append( RPp ) # only for drawing
space.add( RPp, RPrl )
def draw(): # loop de animação
background(222) # fundo cinza, limpa frame
#print(f"esquerda: {keys['a']}\ndireita: {keys['l']}") # "a: " + str(keys['a'])
#rect( 100, 0, 400, 650 );
# desenhar os shapes
for shp in shapes:
if isinstance(shp, pm.Segment): # se for um segmento
stroke_weight(shp.radius * 2) # espessura do traço
line(shp.a.x, shp.a.y, shp.b.x, shp.b.y)
elif isinstance(shp, pm.Circle):
stroke_weight(1)
fill(255)
x, y = shp.body.position + shp.offset
circle(x, y, shp.radius * 2)
elif isinstance(shp, pm.Poly):
stroke_weight(1)
fill(shp.cor)
begin_shape()
for v in shp.get_vertices():
a = shp.body.angle
xt, yt = v.rotated(a) + shp.body.position
vertex(xt, yt)
end_shape(CLOSE)
# paddle control
if keys[LEFT_CONTROL]:
LPb.torque = -150_000_000
if keys[RIGHT_CONTROL]:
RPb.torque = 150_000_000
if keys[PLUNGER_CONTROL]:
plunger.position = ( plunger.position.x, lerp( plunger.position.y, 775, 0.25 ) ) #apply_force_at_local_point( (0, 50000000), (0,0) )
ball.position = ( ball.position.x, plunger.position.y-30 )
for _ in range(3):
# avançar a simulação
space.step(0.01) # passo da simulação
def lose_ball(arbiter, space, data):
# perde pontos
# arbiter.shapes[0]
ball.position = (486, 610)
def build_ball( x, y, r, static = False ):
if static:
shp = pm.Circle(space.static_body, r, (x, y)) # corpo, raio, coordenadas relativas ao body (offset)
else:
mass = 0.2 * PI * r ** 2
moi = pm.moment_for_circle(mass, 0, r, (0, 0)) # massa, raio interno, raio, centro
body = pm.Body(mass, moi)
body.position = (x, y)
shp = pm.Circle(body, r, (0, 0)) # corpo, raio, coordenadas relativas ao body (offset)
shp.friction = 0.3
shp.elasticity = 0.5
shapes.append(shp)
shp.cor = color(127)
if static:
space.add(shp)
else:
space.add(body, shp)
def build_line(x1, y1, x2, y2, thickness, static = True ):
shp = pm.Segment(space.static_body, (x1, y1), (x2, y2), thickness )
space.add(shp)
shapes.append(shp)
def build_box(x, y, w, h, static = False): # x, y do canto superior esquerdo; larg, e alt
if static:
pts = ( (x, y), (x, y + h), (x + w, y + h), (x + w, y) )
shp = pm.Poly(space.static_body, pts)
space.add(shp)
else:
mass = 0.2 * w * h
moi = pm.moment_for_box(mass, (w, h)) # massa, (larg, altura)
body = pm.Body(mass, moi)
body.position = (x + w / 2, y + h / 2)
shp = pm.Poly.create_box(body, (w, h)) # corpo, (larg, altura)
space.add(body, shp)
shp.friction = 0.3
shp.elasticity = 0.5
shp.cor = color(127)
shapes.append(shp)
def assemble_ring( cx, cy, rad, start, stop, E ):
res = 32
s = (stop-start) / res;
A = pm.Vec2d(cx, cy)
for r in range(res):
verts = [];
t1 = pm.Vec2d( cos(start + r*s), sin(start + r*s) );
t2 = pm.Vec2d( cos(start + (r+1)*s), sin(start + (r+1)*s) );
verts.append( A + (t1 * rad) )
verts.append( A + (t1 * (rad - E)) )
verts.append( A + (t2 * (rad - E)) )
verts.append( A + (t2 * rad) )
shp = pm.Poly(space.static_body, verts)
space.add(shp)
shp.cor = color(127)
shapes.append(shp)
def mouse_clicked():
print(mouse_x, mouse_y)
def key_pressed():
keys[key] = True
def key_released():
keys[key] = False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment