Last active
June 19, 2022 14:17
-
-
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/]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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