Transforming Raspberry Pi to a game console

by solusipse

Before yesterday I’ve never used Python. I was actually forced to do it because of the fact that it is now official language of Raspberry Pi. After spending one day with it I have to say that it’s amazing and I would recommend it for anyone who want to start programming (not advanced programmer here actually). Yesterday I modified already written Pong clone to use GPIO interface and move paddle when I push a button. Then I thought that it is rather senseless because keyboard can do it better. And then I come up with an idea that it would have sense if there were two players using custom controllers. I decided to write my own Pong clone which I called PiPong! At the end of that post you’ll find a source code. To run it you’ll need to images – for paddle and for ball. You can download package there: http://sourceforge.net/projects/pipong/files/. You can test it also on your computer. To do that, run keypong.py instead of pipong.py, which is made for Raspberry Pi. You’ll need also Pygame which can be downloaded there: http://www.pygame.org/download.shtml If you’re using a 64-bit version of Windows with Python 2.7 or 3.x, there is a binary for you: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame

This is how it looks:

# www.sudoxanthippe.wordpress.com
# PiPong!

import pygame, random
from pygame.locals import *
import RPi.GPIO as GPIO
pygame.init()

def menu():
	    
    pygame.init()
    display = True
    
    # Setting resolution
    screen = pygame.display.set_mode((800,600), 0, 24)
    # Hiding mouse
    pygame.mouse.set_visible(False)
    # Setting window's caption
    pygame.display.set_caption("PiPong!")
    # Displaying starting label 
    label = pygame.font.SysFont("Tahoma", 25).render("Press ENTER to start!", 1, (185,0,0))
    # Checking size of the Surface
    background = pygame.Surface(screen.get_size())
    # Returning converted size
    background = background.convert()
    # Filling background with colour
    background.fill((45,45,45))
    
    while display:
        
        for event in pygame.event.get():
        # Checking if RETURN key was pressed    
            if pygame.key.get_pressed()[pygame.locals.K_RETURN]:
		# Go further
                    display = False
        
        # Dealing with the colours of the menu
        color = (200, 200, 200)
        rectangle = pygame.Surface((265, 50))
        rectangle = rectangle.convert()
        rectangle.fill(color)
        # Refreshing menu elements
        screen.blit(background, (0,0))
        screen.blit(rectangle, (264, 280))
        screen.blit(label, (280, 290))
        
        # Update the full display Surface to the screen
        pygame.display.flip()
        
def game():
	pygame.init()
	display = True
	
	# Setting resolution
	screen = pygame.display.set_mode((800,600))
	# Hiding mouse
	pygame.mouse.set_visible(False)
	# Setting window's caption
	pygame.display.set_caption("PiPong!")
	

	# Checking size of the Surface
	background = pygame.Surface(screen.get_size())
	# Returning converted size
	background = background.convert()
	# Filling background with colour
	background.fill((45,45,45))
	
	# Loading images
	sprite_pad = pygame.image.load("pad.png")
	sprite_pad_mirror = pygame.transform.flip(sprite_pad, True, False)
	sprite_ball = pygame.image.load("ball.png")
	
	# Converting images to sprites
	rect_pad1 = sprite_pad.get_rect()
	rect_pad2 = sprite_pad_mirror.get_rect()
	rect_ball = sprite_ball.get_rect()
	
	
	# Ball movement speed
	hspeed = 0
	vspeed = 0
	while hspeed == 0:
		hspeed = random.choice([-4, 4])
	while vspeed == 0:
		vspeed = random.choice([-4, 4])
	slower = 1
	
	score1 = 0
	score2 = 0
	
	pad_y = 300
	pad_y_2 = 300
	
	while display:

		# Ball movement
		slower -= 1
		if slower == 0:
			slower = 5
			
		# Pads movement for keyboard
		if pygame.key.get_pressed()[pygame.locals.K_s]:
			if (pad_y <= 500):
				pad_y = pad_y + 4
		if pygame.key.get_pressed()[pygame.locals.K_w]:
			if (pad_y >= 10):
				pad_y = pad_y - 4
		if pygame.key.get_pressed()[pygame.locals.K_DOWN]:
			if (pad_y_2 <= 500):
				pad_y_2 = pad_y_2 + 4
		if pygame.key.get_pressed()[pygame.locals.K_UP]:
			if (pad_y_2 >= 10):
				pad_y_2 = pad_y_2 - 4
		
		# Pads movement for GPIO		
		if GPIO.input(22):
			if (pad_y <= 500):
				pad_y = pad_y + 4
		if GPIO.input(24):
			if (pad_y >= 10):
				pad_y = pad_y - 4
		if GPIO.input(21):
			if (pad_y_2 <= 500):
				pad_y_2 = pad_y_2 + 4
		if GPIO.input(19):
			if (pad_y_2 >= 10):
				pad_y_2 = pad_y_2 - 4			
								
		# Setting sprites position
		rect_pad1.left = 25
		rect_pad1.top = pad_y
		rect_pad2.left = 750
		rect_pad2.top = pad_y_2
		
		# Score refreshment
		score1_str = str(score1)
		score2_str = str(score2)
		score = pygame.font.SysFont("Tahoma", 18).render(score1_str + ":" + score2_str, 1, (155,122,222))
				
		# Ball movement
		if hspeed < 0:
			if (rect_ball.left + hspeed > 5):
				rect_ball.left += hspeed
				GPIO.output(23, False)
			else:
				rect_ball.left = 400
				rect_ball.top = 300
				score1 = score1 + 1
				GPIO.output(23, True)
		else:
			if (rect_ball.left + hspeed < 750):
				rect_ball.left += hspeed
				GPIO.output(23, False)
			else:
				rect_ball.left = 400
				rect_ball.top = 300
				score2 = score2 + 1
				GPIO.output(23, True)
		if vspeed < 0:
			if (rect_ball.top + vspeed > 5):
				rect_ball.top += vspeed
			else:
				vspeed = -vspeed
		else:
			if (rect_ball.top + vspeed < 550):
				rect_ball.top += vspeed
			else:	
				vspeed = -vspeed

		# Collision detection
		hit = False
		# Pad1
		if ((rect_ball.left >= rect_pad1.left) and \
		(rect_ball.left <= rect_pad1.left + rect_pad1.width) and \
		(rect_ball.top >= rect_pad1.top) and \
		(rect_ball.top <= rect_pad1.top + rect_pad1.height)):
			hit = True
		# Pad2
		if (rect_ball.left >= rect_pad2.left-27) and \
		(rect_ball.top >= rect_pad2.top) and \
		(rect_ball.top <= rect_pad2.top + rect_pad2.height):
			hit = True
			
		# When collision is detected
		if (hit == True):
			if (rect_ball.left > 400):
				rect_ball.left = rect_ball.left - 5
			else:
				rect_ball.left = rect_ball.left + 5
			hspeed = -hspeed

		if pygame.key.get_pressed()[pygame.locals.K_ESCAPE]:
			display = False
		# Killing process
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				display = False
			if pygame.key.get_pressed()[pygame.locals.K_RETURN]:
			# Go further
				menu()
		
		# Dealing with the colours
		screen.blit(background, (0,0))
		screen.blit(sprite_pad, rect_pad1)
		screen.blit(sprite_ball, rect_ball)
		screen.blit(sprite_pad_mirror, rect_pad2)
		screen.blit(score, (375, 555))
		
		# Update the full display Surface to the screen
		pygame.display.flip()
		
		
def main():
	#GPIO initialize
	GPIO.setmode(GPIO.BOARD)
	GPIO.setup(22, GPIO.IN)
	GPIO.setup(24, GPIO.IN)
	GPIO.setup(21, GPIO.IN)
	GPIO.setup(19, GPIO.IN)
	GPIO.setup(23, GPIO.OUT)
	menu()
	game()

main()
Advertisements