Laser Pinball

From Tmplab
"""A very basic flipper game.
"""
__version__ = "$Id:$"
__docformat__ = "reStructuredText"

import random

import pygame
from pygame.locals import *
from pygame.color import *
import os
import pymunk
from pymunk import Vec2d

def to_pygame(p):
    """Small hack to convert pymunk to pygame coordinates"""
    return int(p.x), int(-p.y+600)


# Sound
pygame.mixer.pre_init(44100, -16, 2, 2048)

pygame.init()
screen = pygame.display.set_mode((600, 600))
clock = pygame.time.Clock()
running = True
print(os.path.join('snd','bumper.ogg'))
try:
#    pygame.mixer.music.load(os.path.join('data', 'music.ogg'))#load music
    snd_bump = pygame.mixer.Sound(os.path.join('snd','bumper.ogg'))  #load sound
except:
    raise UserWarning, "could not load or play soundfiles in 'data' folder :-("


### Physics stuff
# To be tinkered with :)
space = pymunk.Space(50)
# To be tinkered with (second only):)
space.gravity = (0.0, -1850.0)

# Define collision callback function, will be called when X touches Y 
def bumper_collision(space, arbiter):
    snd_bump = pygame.mixer.Sound(os.path.join('snd','bumper.ogg'))  #load sound
    snd_bump.play()
    return True

COLLTYPE_BALL = 1
COLLTYPE_BUMPER = 2

# Setup the collision callback function
space.add_collision_handler(COLLTYPE_BALL, COLLTYPE_BUMPER, bumper_collision, None, None, None)   



## Balls
balls = []
   
### walls
static_body = pymunk.Body()
static_lines = [
                # Main Box
                pymunk.Segment(static_body, (50, 50.0), (0.0, 600.0), 1.0)
                ,pymunk.Segment(static_body, (550.0, 50.0), (600.0, 600.0), 1.0)
                ,pymunk.Segment(static_body, (0.0, 600.0), (300.0, 580.0), 1.0)
                ,pymunk.Segment(static_body, (300.0, 580.0), (600.0, 600.0), 1.0)
                ,pymunk.Segment(static_body, (50.0, 50.0), (300.0, 0.0), 1.0)
                ,pymunk.Segment(static_body, (300.0, 0.0), (550.0, 50.0), 1.0)
                # Upper triangle
                ,pymunk.Segment(static_body, (300.0, 400.0), (220.0, 500.0), 1.0)
                ,pymunk.Segment(static_body, (300.0, 400.0), (380.0, 500.0), 1.0)
                # Lower triangle
                ,pymunk.Segment(static_body, (300.0, 300.0), (240.0, 360.0), 1.0)
                ,pymunk.Segment(static_body, (300.0, 300.0), (360.0, 360.0), 1.0)
                ]  

for line in static_lines:
    line.elasticity = 0.05
    line.group = 1
space.add(static_lines)

# "bumpers"
for p in [
    (300,10), # Central
    (50,50),(550,50), # Lower
    (15,300),(585,300), # Middle
    (300,440), # Upper triangle 
    (300,340), # Lower triangle
    ]:
    body = pymunk.Body()
    body.position = p
    shape = pymunk.Circle(body, 20)
    shape.elasticity = 2
    shape.collision_type = COLLTYPE_BUMPER
    space.add(shape)
    balls.append(shape)

while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        elif event.type == KEYDOWN and event.key == K_ESCAPE:
            running = False
        elif event.type == KEYDOWN and event.key == K_p:
            pygame.image.save(screen, "flipper.png")
                
        elif event.type == KEYDOWN and event.key == K_b:
            # The ball physics
            mass = 500
            radius = 10
            inertia = pymunk.moment_for_circle(mass, 0, radius, (0,0))
            body = pymunk.Body(mass, inertia)
            # The ball initial position
            rand_x = random.randint(1,5)
            if (rand_x % 2) :
                x = 300 - rand_x  
            else : 
                x = 300 + rand_x;
            body.position = x, 550
            # Draw ball
            shape = pymunk.Circle(body, radius, (0,0))
            shape.elasticity = 1
            shape.collision_type = COLLTYPE_BALL
            space.add(body, shape)
            balls.append(shape)
    
    ### Clear screen
    screen.fill(THECOLORS["white"])
    
    ### Draw stuff
    for ball in balls:
        p = to_pygame(ball.body.position)
        pygame.draw.circle(screen, THECOLORS["blue"], p, int(ball.radius), 2)


    for line in static_lines:
        body = line.body
        pv1 = body.position + line.a.rotated(body.angle)
        pv2 = body.position + line.b.rotated(body.angle)
        p1 = to_pygame(pv1)
        p2 = to_pygame(pv2)
        pygame.draw.lines(screen, THECOLORS["lightgray"], False, [p1,p2])
    
    
    ### Update physics
    dt = 1.0/60.0/5.
    for x in range(5):
        space.step(dt)
    
    ### Flip screen
    pygame.display.flip()
    clock.tick(50)
    pygame.display.set_caption("fps: " + str(clock.get_fps()))