danjperron wrote:I practically always use a thread for serial communication. This way is not on the main loop and it could be asynchronous.
I made a small "pong" game to test my analog input using a separate thread for reading the input. It works fine so I will continue down that path.
Code: Select all
#!/usr/bin/env python
import serial, threading, time
import pygame, sys, os
from pygame.locals import *
# INTIALISATION
BAT_WIDTH=20
BAT_HEIGHT=50
BAT_RIM = 20
BALL_WIDTH=20
BASE_SPEED=4
speed=BASE_SPEED
input1 = 300-BAT_WIDTH/2
input2 = 300-BAT_WIDTH/2
ball_v_x = -speed
ball_v_y = 0
bat1_pos_x =100-BAT_WIDTH
bat1_pos_y =300-BAT_HEIGHT/2
bat2_pos_x =1100
bat2_pos_y =300-BAT_HEIGHT/2
ball_pos_x = bat2_pos_x-BALL_WIDTH-5
ball_pos_y = 300-BALL_WIDTH/2
player1_scr = 0
player2_scr = 0
#Bounce function for the bats
def bounce(bat_y) :
global ball_v_x, ball_v_y
if ball_pos_y + BALL_WIDTH >= bat_y and ball_pos_y + BALL_WIDTH < bat_y + BAT_RIM :
ball_v_x = -ball_v_x
ball_v_y = max(-speed, ball_v_y-speed)
elif ball_pos_y > bat_y + BAT_HEIGHT - BAT_RIM and ball_pos_y <= bat_y + BAT_HEIGHT :
ball_v_x = -ball_v_x
ball_v_y = min(speed, ball_v_y+speed)
elif ball_pos_y >= bat_y and ball_pos_y <= bat_y + BAT_HEIGHT :
ball_v_x = -ball_v_x
#Serial reader run in a separate daemon thread
def serial_reader() :
global input1, input2
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
while 1:
x=(ser.readline()).rstrip()
numbers=x.split(',')
oi1=input1
oi2=input2
try:
input1=int(int(numbers[0])*(600-BAT_HEIGHT)/1023)
input2=int(int(numbers[1])*(600-BAT_HEIGHT)/1023)
except :
input1=oi1
input2=oi2
print sys.exc_info()[0]
time.sleep(0)
#Start of main program
#Start serial reader thread
if __name__ == '__main__':
sr = threading.Thread(name='serial-reader', target=serial_reader)
sr.setDaemon(True)
sr.start()
#Init pygame stuff
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((1200, 600))
pygame.display.set_caption("Pong", 'Pong')
pygame.font.init()
font = pygame.font.SysFont('monospace', 48)
#Main loop
while 1:
clock.tick(120) #Update screen every 1/120 s
# User input events
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit();
if not hasattr(event, 'key'): continue
if event.key == K_ESCAPE: sys.exit(0) # quit the game
elif event.key == K_UP: speed=min(BAT_WIDTH-2,speed+1)
elif event.key == K_DOWN: speed=max(1,speed-1)
elif event.key == K_r:
ball_pos_x = bat2_pos_x-BALL_WIDTH-5
ball_pos_y = 300-BALL_WIDTH/2
speed=BASE_SPEED
ball_v_x = -speed
ball_v_y = 0
player1_scr = 0
player2_scr = 0
#Updating bat position from serial input
bat1_pos_y=input1
bat2_pos_y=input2
#Checking bounce or miss
if ball_pos_y < 0 or ball_pos_y+BALL_WIDTH > 600:
ball_v_y = -ball_v_y
if ball_pos_x+BALL_WIDTH > 1200:
ball_v_x = speed
ball_v_y = 0
ball_pos_y = 300-BAT_HEIGHT/2
ball_pos_x= bat1_pos_x + BAT_WIDTH+5
player1_scr +=1
if ball_pos_x < 0:
ball_v_x = -speed
ball_v_y = 0
ball_pos_y = 300-BAT_HEIGHT/2
ball_pos_x= bat2_pos_x-BALL_WIDTH-5
player2_scr +=1
if ball_pos_x < bat1_pos_x + BAT_WIDTH and ball_pos_x > bat1_pos_x :
bounce(bat1_pos_y)
if ball_pos_x + BALL_WIDTH > bat2_pos_x and ball_pos_x < bat2_pos_x + BAT_WIDTH :
bounce(bat2_pos_y)
#Updating position of ball
ball_pos_x +=ball_v_x
ball_pos_y +=ball_v_y
# Rendering
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (bat1_pos_x,bat1_pos_y,BAT_WIDTH,BAT_HEIGHT), 0)
pygame.draw.rect(screen, (255,255,255), (bat2_pos_x,bat2_pos_y,BAT_WIDTH,BAT_HEIGHT), 0)
pygame.draw.rect(screen, (255,255,255), (ball_pos_x,ball_pos_y,BALL_WIDTH,BALL_WIDTH), 0)
text = font.render(str(player1_scr) + " - " + str(player2_scr), 0, (255,255,255))
textrect = text.get_rect()
textrect.centerx = screen.get_rect().centerx
textrect.centery = 25
screen.blit(text, textrect)
pygame.display.flip()
#print pygame.time.get_ticks()
The serial input receives new position data approx 60 times/second from an ATTiny85 with two potentiometers attached to analogue input pins.