#!/usr/bin/env python import pygame import sys import time from touch import MultitouchServer, screen_size from math import degrees, cos, sin from events import Rotate pygame.init() FULLSCREEN = '-f' in sys.argv[1:] # Config FINGER_RADIUS = 20 CENTROID_RADIUS = 15 W, H = screen_size if FULLSCREEN else (640, 480) BG_COLOR = 0, 0, 0 LINE_COLOR = 128, 128, 128 CIRCLE_COLOR = 255, 255, 255 RECT_COLOR = 0, 200, 0 RECT_POS = W / 2, H / 2 RECT_SIZE = W / 6., H / 6. TAP_RADIUS = 65 TAP_INCREMENT = .3 BEAM_COLOR = 255, 50, 50 BEAM_LENGTH = 50 BEAM_WIDTH = 3 BEAM_INCREMENT = .8 MAX_SCALE = 10 # Create canvas GUI flags = pygame.FULLSCREEN if FULLSCREEN else 0 screen = pygame.display.set_mode((W, H), flags) def rotate_point(point, axis, angle): px, py = point ax, ay = axis x, y = px - ax, py - ay radius = (x * x + y * y) ** .5 return ax + radius * cos(angle), ay + radius * sin(angle) def coord(x, y): return int(round(W * x)), int(round(H * y)) # Global state angle = 0 scale = 1 taps = [] dtaps = [] def update(): global taps, dtaps # Clear previous frame screen.fill(BG_COLOR) # Apply scale and rotation to a fixed-size rectangle canvas canvas = pygame.Surface(RECT_SIZE) canvas.fill(RECT_COLOR) transformed = pygame.transform.rotozoom(canvas, degrees(angle), scale) rect = transformed.get_rect() rect.center = W / 2, H / 2 screen.blit(transformed, rect) # Draw touch points c = coord(*server.centroid) for p in server.points: xy = coord(p.x, p.y) # Draw line to centroid pygame.draw.line(screen, LINE_COLOR, xy, c, 1) # Draw outlined circle around touch point pygame.draw.circle(screen, CIRCLE_COLOR, xy, FINGER_RADIUS, 1) # Fill filled circle with background color within the outline pygame.draw.circle(screen, BG_COLOR, xy, FINGER_RADIUS - 1, 0) # Draw filled circle around centroid pygame.draw.circle(screen, CIRCLE_COLOR, c, CENTROID_RADIUS) # Draw an expanding circle around each tap event taps = filter(lambda (xy, r): r <= TAP_RADIUS, taps) for tap in taps: xy, radius = tap pygame.draw.circle(screen, CIRCLE_COLOR, xy, int(radius), 2) # Increment radius tap[1] += TAP_INCREMENT # Shoot a beam from each double tap event to the left dtaps = filter(lambda (x, y, s): 0 <= x <= W, dtaps) for dtap in dtaps: x, y, single = dtap if single: start_x = x end_x = x + BEAM_LENGTH dtap[0] += BEAM_INCREMENT else: start_x = x - BEAM_LENGTH end_x = x dtap[0] -= BEAM_INCREMENT pygame.draw.line(screen, BEAM_COLOR, (start_x, y), (end_x, y), BEAM_WIDTH) # Update canvas pygame.display.flip() def rotate(event): global angle angle += event.angle def pinch(event): global scale scale = min(scale * event.amount, MAX_SCALE) # Start touch event server in separate thread server = MultitouchServer(verbose=1, tuio_verbose=0) server.bind('rotate', rotate) server.bind('pinch', pinch) server.bind('tap', lambda e: taps.append([coord(*e.xy), FINGER_RADIUS])) server.bind('single_tap', lambda e: dtaps.append(list(coord(*e.xy)) + [1])) server.bind('double_tap', lambda e: dtaps.append(list(coord(*e.xy)) + [0])) server.start(threaded=True) def is_quit_event(e): return e.type == pygame.QUIT \ or (e.type == pygame.KEYDOWN and e.key == ord('q')) try: # Start GUI event loop while not any(filter(is_quit_event, pygame.event.get())): update() except KeyboardInterrupt: pass finally: server.stop()