diff options
-rw-r--r-- | README.txt | 28 | ||||
-rw-r--r-- | joystick/disable.wav | bin | 0 -> 419318 bytes | |||
-rw-r--r-- | joystick/enable.wav | bin | 0 -> 418996 bytes | |||
-rwxr-xr-x | joystick/joystick-input.py | 69 | ||||
-rwxr-xr-x | joystick/test-joystick.py | 22 | ||||
-rw-r--r-- | pong/Pong.wav | bin | 0 -> 23292 bytes | |||
-rw-r--r-- | pong/ball.py | 33 | ||||
-rw-r--r-- | pong/paddle.py | 33 | ||||
-rwxr-xr-x | pong/pong.py | 227 | ||||
-rwxr-xr-x | tetris/tetris.py | 612 | ||||
-rw-r--r-- | tetris/tetrisb.mid | bin | 0 -> 8612 bytes | |||
-rw-r--r-- | tetris/tetrisc.mid | bin | 0 -> 14661 bytes |
12 files changed, 1024 insertions, 0 deletions
diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..951a49c --- /dev/null +++ b/README.txt @@ -0,0 +1,28 @@ += some games for palladiumpi with gamepad input = + +pong and tetris from pygames and https://www.101computing.net/pong-tutorial-using-pygame-getting-started/ adapted +to a palladium-pi game device (Palladium TV 500 with black and white screen and Raspbian Raspbery Pi 1 with composite output) + +joystick-input.py used for starting games from the menu and in-game controller +only the first gamepad is used by python inputs library (https://inputs.readthedocs.io/en/latest/user/intro.html) + +select -> ALT+F4 +start -> WIN key +A -> Return +B -> Escape +A+B -> toggle gamepad as OS input (for using the gamepad inside games or toggling the lxdmenu) + +the script is started using this joystick-input.desktop file in /etc/xdg/autostart +the Path variable is important for python scripts + +""" +[Desktop Entry] +Type=Application +Name=joystick-input +Comment=Joystick input +NoDisplay=true +Exec=/home/pi/src/joystick/joystick-input.py +Path=/home/pi/src/joystick +Terminal=false +Categories=Application; +""" diff --git a/joystick/disable.wav b/joystick/disable.wav Binary files differnew file mode 100644 index 0000000..ef2ddff --- /dev/null +++ b/joystick/disable.wav diff --git a/joystick/enable.wav b/joystick/enable.wav Binary files differnew file mode 100644 index 0000000..2e726b8 --- /dev/null +++ b/joystick/enable.wav diff --git a/joystick/joystick-input.py b/joystick/joystick-input.py new file mode 100755 index 0000000..fb49765 --- /dev/null +++ b/joystick/joystick-input.py @@ -0,0 +1,69 @@ +#!/usr/bin/python3 + +import inputs,os,pygame + +print(inputs.devices.gamepads) + +pads = inputs.devices.gamepads +select=0 +start=0 +disable_pad=False + +pygame.init() +enable=pygame.mixer.Sound('enable.wav') +disable=pygame.mixer.Sound('disable.wav') + +while True: + events = inputs.get_gamepad() + for event in events: + #print(event.ev_type, event.code, event.state) + if event.code == 'ABS_Y' and event.state == 255: + #print("down") + if not disable_pad: + os.system("xte 'key Down'") + elif event.code == 'ABS_Y' and event.state == 0: + #print("up") + if not disable_pad: + os.system("xte 'key Up'") + elif event.code == 'ABS_X' and event.state == 255: + #print("right") + if not disable_pad: + os.system("xte 'key Right'") + elif event.code == 'ABS_X' and event.state == 0: + #print("left") + if not disable_pad: + os.system("xte 'key Left'") + elif event.code == 'BTN_TRIGGER' and event.state == 1: + #print("B") + if not disable_pad: + os.system("xte 'key Escape'") + start=1 + elif event.code == 'BTN_TRIGGER' and event.state == 0: + #print("B") + start=0 + elif event.code == 'BTN_THUMB' and event.state == 1: + #print("A") + if not disable_pad: + os.system("xte 'key Return'") + select=1 + elif event.code == 'BTN_THUMB' and event.state == 0: + #print("select") + select=0 + elif event.code == 'BTN_BASE3' and event.state == 1: + #print("select") + if not disable_pad: + os.system("xte 'keydown Meta_L' 'key F4' 'keyup Meta_L'") + elif event.code == 'BTN_BASE4' and event.state == 1: + #print("start") + if not disable_pad: + os.system("xte 'key Super_L'") + if start == 1 and select == 1: + print("toggle disable pad") + disable_pad=not disable_pad + if disable_pad: + disable.play() + else: + enable.play() + select=0 + start=0 + diff --git a/joystick/test-joystick.py b/joystick/test-joystick.py new file mode 100755 index 0000000..a8ed6f1 --- /dev/null +++ b/joystick/test-joystick.py @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +import pygame + +pygame.display.init() +pygame.joystick.init() + +print ("Joystics: ", pygame.joystick.get_count()) +my_joystick = pygame.joystick.Joystick(0) +my_joystick.init() +clock = pygame.time.Clock() + +print (my_joystick.get_numbuttons()) +print (my_joystick.get_numhats()) +while 1: + for event in pygame.event.get(): + print (my_joystick.get_axis(0), my_joystick.get_axis(1)) + for i in range(my_joystick.get_numbuttons()): + print(i, my_joystick.get_button(i)) + clock.tick(40) + +pygame.quit () diff --git a/pong/Pong.wav b/pong/Pong.wav Binary files differnew file mode 100644 index 0000000..fc00db8 --- /dev/null +++ b/pong/Pong.wav diff --git a/pong/ball.py b/pong/ball.py new file mode 100644 index 0000000..f4e0168 --- /dev/null +++ b/pong/ball.py @@ -0,0 +1,33 @@ +import pygame +from random import randint + +BLACK = (0, 0, 0) + +class Ball(pygame.sprite.Sprite): + #This class represents a car. It derives from the "Sprite" class in Pygame. + + def __init__(self, color, width, height): + # Call the parent class (Sprite) constructor + super().__init__() + + # Pass in the color of the car, and its x and y position, width and height. + # Set the background color and set it to be transparent + self.image = pygame.Surface([width, height]) + self.image.fill(BLACK) + self.image.set_colorkey(BLACK) + + # Draw the ball (a rectangle!) + pygame.draw.rect(self.image, color, [0, 0, width, height]) + + self.velocity = [randint(4,8),randint(-8,8)] + + # Fetch the rectangle object that has the dimensions of the image. + self.rect = self.image.get_rect() + + def update(self): + self.rect.x += self.velocity[0] + self.rect.y += self.velocity[1] + + def bounce(self): + self.velocity[0] = -self.velocity[0] + self.velocity[1] = randint(-8,8) diff --git a/pong/paddle.py b/pong/paddle.py new file mode 100644 index 0000000..25dbcbb --- /dev/null +++ b/pong/paddle.py @@ -0,0 +1,33 @@ +import pygame +BLACK = (0,0,0) + +class Paddle(pygame.sprite.Sprite): + #This class represents a car. It derives from the "Sprite" class in Pygame. + + def __init__(self, color, width, height): + # Call the parent class (Sprite) constructor + super().__init__() + + # Pass in the color of the car, and its x and y position, width and height. + # Set the background color and set it to be transparent + self.image = pygame.Surface([width, height]) + self.image.fill(BLACK) + self.image.set_colorkey(BLACK) + + # Draw the paddle (a rectangle!) + pygame.draw.rect(self.image, color, [0, 0, width, height]) + + # Fetch the rectangle object that has the dimensions of the image. + self.rect = self.image.get_rect() + + def moveUp(self, pixels): + self.rect.y -= pixels + #Check that you are not going too far (off the screen) + if self.rect.y < 0: + self.rect.y = 0 + + def moveDown(self, pixels): + self.rect.y += pixels + #Check that you are not going too far (off the screen) + if self.rect.y > 480-100: + self.rect.y = 480-100 diff --git a/pong/pong.py b/pong/pong.py new file mode 100755 index 0000000..0363f3c --- /dev/null +++ b/pong/pong.py @@ -0,0 +1,227 @@ +#!/usr/bin/python3 +# Import the pygame library and initialise the game engine +import pygame, sys +from paddle import Paddle +from ball import Ball +from pygame.locals import * + +# Open a new window was 700x500 +WIDTH=640 +HEIGHT=480 + +# R G B +WHITE = (255, 255, 255) +GRAY = (185, 185, 185) +BLACK = ( 0, 0, 0) +RED = (155, 0, 0) +LIGHTRED = (175, 20, 20) +GREEN = ( 0, 155, 0) +LIGHTGREEN = ( 20, 175, 20) +BLUE = ( 0, 0, 155) +LIGHTBLUE = ( 20, 20, 175) +YELLOW = (155, 155, 0) +LIGHTYELLOW = (175, 175, 20) + +BORDERCOLOR = BLUE +BGCOLOR = BLACK +TEXTCOLOR = WHITE +TEXTSHADOWCOLOR = GRAY +COLORS = ( BLUE, GREEN, RED, YELLOW) +LIGHTCOLORS = (LIGHTBLUE, LIGHTGREEN, LIGHTRED, LIGHTYELLOW) +assert len(COLORS) == len(LIGHTCOLORS) # each color must have light color + + +def makeTextObjs(text, font, color): + surf = font.render(text, True, color) + return surf, surf.get_rect() + +def terminate(): + pygame.quit() + sys.exit() + +def showTextScreen(text): + # This function displays large text in the + # center of the screen until a key is pressed. + # Draw the text drop shadow + titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTSHADOWCOLOR) + titleRect.center = (int(WIDTH / 2), int(HEIGHT / 2)) + screen.blit(titleSurf, titleRect) + + # Draw the text + titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTCOLOR) + titleRect.center = (int(WIDTH / 2) - 3, int(HEIGHT / 2) - 3) + screen.blit(titleSurf, titleRect) + + # Draw the additional "Press a key to play." text. + pressKeySurf, pressKeyRect = makeTextObjs('Press a key to play. \'Select\' to quit. \'B\' to reset.', BASICFONT, TEXTCOLOR) + pressKeyRect.center = (int(WIDTH / 2), int(HEIGHT / 2) + 100) + screen.blit(pressKeySurf, pressKeyRect) + + while checkForKeyPress() == None: + pygame.display.update() + clock.tick() + +def checkForKeyPress(): + global scoreA, scoreB + for event in pygame.event.get(): + if event.type == QUIT: #event is quit + terminate() + elif event.type == KEYDOWN: + if event.key == K_ESCAPE: #event is escape key + terminate() + else: + return event.key #key found return with it + elif event.type == JOYBUTTONDOWN or event.type == JOYAXISMOTION: + if (js1.get_button(8) == 1 or js2.get_button(8) == 1): + terminate() + elif (js1.get_button(0) == 1 or js2.get_button(0) == 1): + scoreA=0 + scoreB=0 + return 1 + # no quit or key events in queue so return None + return None + +def main(): + global clock, screen, BASICFONT, BIGFONT, js1, js2 + pygame.init() + pygame.mouse.set_visible(False) + + # Define some colors + BLACK = (0,0,0) + WHITE = (255,255,255) + + BASICFONT = pygame.font.Font('freesansbold.ttf', 18) + BIGFONT = pygame.font.Font('freesansbold.ttf', 100) + + size = (WIDTH, HEIGHT) + screen = pygame.display.set_mode(size, FULLSCREEN) + pygame.display.set_caption("Pong") + effect=pygame.mixer.Sound('Pong.wav') + + #joystick or gamepad init + pygame.joystick.init() + print ("Joystics: ", pygame.joystick.get_count()) + js1 = pygame.joystick.Joystick(0) + js1.init() + js2 = pygame.joystick.Joystick(1) + js2.init() + + paddleA = Paddle(WHITE, 10, 100) + paddleA.rect.x = 20 + paddleA.rect.y = 200 + + paddleB = Paddle(WHITE, 10, 100) + paddleB.rect.x = WIDTH-30 + paddleB.rect.y = 200 + + ball = Ball(WHITE,10,10) + ball.rect.x = int(WIDTH/2-5) + ball.rect.y = 195 + + #This will be a list that will contain all the sprites we intend to use in our game. + all_sprites_list = pygame.sprite.Group() + + # Add the car to the list of objects + all_sprites_list.add(paddleA) + all_sprites_list.add(paddleB) + all_sprites_list.add(ball) + + # The loop will carry on until the user exit the game (e.g. clicks the close button). + carryOn = True + + # The clock will be used to control how fast the screen updates + clock = pygame.time.Clock() + + #Initialise player scores + global scoreA, scoreB + scoreA = 0 + scoreB = 0 + + showTextScreen('Pong') + # -------- Main Program Loop ----------- + while carryOn: + # --- Main event loop + for event in pygame.event.get(): # User did something + if event.type == pygame.QUIT: # If user clicked close + carryOn = False # Flag that we are done so we exit this loop + elif event.type==pygame.KEYDOWN: + if event.key==pygame.K_x: #Pressing the x Key will quit the game + carryOn=False + + #Moving the paddles when the use uses the arrow keys (player A) or "W/S" keys (player B) + """keys = pygame.key.get_pressed() + if keys[pygame.K_w]: + paddleA.moveUp(5) + if keys[pygame.K_s]: + paddleA.moveDown(5) + if keys[pygame.K_UP]: + paddleB.moveUp(5) + if keys[pygame.K_DOWN]: + paddleB.moveDown(5) + """ + + if js1.get_axis(1) < 0: + paddleA.moveUp(5) + if js1.get_axis(1) > 0: + paddleA.moveDown(5) + if js2.get_axis(1) < 0: + paddleB.moveUp(5) + if js2.get_axis(1) > 0: + paddleB.moveDown(5) + if (js1.get_button(8) == 1 or js2.get_button(8) == 1): + terminate() + if (js1.get_button(9) == 1 or js2.get_button(9) == 1): + showTextScreen('-Pause-') + + # --- Game logic should go here + all_sprites_list.update() + + #Check if the ball is bouncing against any of the 4 walls: + if ball.rect.x>=WIDTH-10: + scoreA+=1 + ball.velocity[0] = -ball.velocity[0] + effect.play() + if ball.rect.x<=0: + scoreB+=1 + ball.velocity[0] = -ball.velocity[0] + effect.play() + if ball.rect.y>HEIGHT-10: + ball.velocity[1] = -ball.velocity[1] + effect.play() + if ball.rect.y<0: + ball.velocity[1] = -ball.velocity[1] + effect.play() + + #Detect collisions between the ball and the paddles + if pygame.sprite.collide_mask(ball, paddleA) or pygame.sprite.collide_mask(ball, paddleB): + ball.bounce() + effect.play() + + # --- Drawing code should go here + # First, clear the screen to black. + screen.fill(BLACK) + #Draw the net + pygame.draw.line(screen, WHITE, [int(WIDTH/2), 0], [int(WIDTH/2), HEIGHT], 5) + + #Now let's draw all the sprites in one go. (For now we only have 2 sprites!) + all_sprites_list.draw(screen) + + #Display scores: + font = pygame.font.Font(None, 74) + text = font.render(str(scoreA), 1, WHITE) + screen.blit(text, (int(WIDTH/2-WIDTH/4),10)) + text = font.render(str(scoreB), 1, WHITE) + screen.blit(text, (int(WIDTH/2+WIDTH/4),10)) + + # --- Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + # --- Limit to 60 frames per second + clock.tick(60) + + #Once we have exited the main program loop we can stop the game engine: + pygame.quit() + +if __name__ == '__main__': + main() + diff --git a/tetris/tetris.py b/tetris/tetris.py new file mode 100755 index 0000000..b03689e --- /dev/null +++ b/tetris/tetris.py @@ -0,0 +1,612 @@ +#!/usr/bin/python3 +# Tetromino (a Tetris clone) +# By Al Sweigart al@inventwithpython.com +# http://inventwithpython.com/pygame +# Released under a "Simplified BSD" license + +# KRT 17/06/2012 rewrite event detection to deal with mouse use +# mods for joystick use by Robert Scheibe 18.06.2020 + +import random, time, pygame, sys +from pygame.locals import * + +#joystick or gamepad init +pygame.joystick.init() +print ("Joystics: ", pygame.joystick.get_count()) +js = pygame.joystick.Joystick(0) +js.init() + + +FPS = 25 +WINDOWWIDTH = 640 +WINDOWHEIGHT = 480 +BOXSIZE = 20 +BOARDWIDTH = 10 +BOARDHEIGHT = 20 +BLANK = '.' + +MOVESIDEWAYSFREQ = 0.15 +MOVEDOWNFREQ = 0.1 + +XMARGIN = int((WINDOWWIDTH - BOARDWIDTH * BOXSIZE) / 2) +TOPMARGIN = WINDOWHEIGHT - (BOARDHEIGHT * BOXSIZE) - 5 + +# R G B +WHITE = (255, 255, 255) +GRAY = (185, 185, 185) +GRAY1 = (240, 240, 240) +GRAY2 = (200, 200, 200) +GRAY3 = (160, 160, 160) +GRAY4 = (120, 120, 120) +BLACK = ( 0, 0, 0) +RED = (155, 0, 0) +LIGHTRED = (175, 20, 20) +GREEN = ( 0, 155, 0) +LIGHTGREEN = ( 20, 175, 20) +BLUE = ( 0, 0, 155) +LIGHTBLUE = ( 20, 20, 175) +YELLOW = (155, 155, 0) +LIGHTYELLOW = (175, 175, 20) + +BORDERCOLOR = BLUE +BGCOLOR = BLACK +TEXTCOLOR = WHITE +TEXTSHADOWCOLOR = GRAY +#COLORS = ( BLUE, GREEN, RED, YELLOW) +COLORS = ( GRAY1, GRAY2, GRAY3, GRAY4) +#LIGHTCOLORS = (LIGHTBLUE, LIGHTGREEN, LIGHTRED, LIGHTYELLOW) +LIGHTCOLORS = ( GRAY1, GRAY2, GRAY3, GRAY4) +assert len(COLORS) == len(LIGHTCOLORS) # each color must have light color + +#TEMPLATEWIDTH = i, 5 +TEMPLATEWIDTH = 5 +TEMPLATEHEIGHT = 5 + +S_SHAPE_TEMPLATE = [['.....', + '.....', + '..OO.', + '.OO..', + '.....'], + ['.....', + '..O..', + '..OO.', + '...O.', + '.....']] + +Z_SHAPE_TEMPLATE = [['.....', + '.....', + '.OO..', + '..OO.', + '.....'], + ['.....', + '..O..', + '.OO..', + '.O...', + '.....']] + +I_SHAPE_TEMPLATE = [['..O..', + '..O..', + '..O..', + '..O..', + '.....'], + ['.....', + '.....', + 'OOOO.', + '.....', + '.....']] + +O_SHAPE_TEMPLATE = [['.....', + '.....', + '.OO..', + '.OO..', + '.....']] + +J_SHAPE_TEMPLATE = [['.....', + '.O...', + '.OOO.', + '.....', + '.....'], + ['.....', + '..OO.', + '..O..', + '..O..', + '.....'], + ['.....', + '.....', + '.OOO.', + '...O.', + '.....'], + ['.....', + '..O..', + '..O..', + '.OO..', + '.....']] + +L_SHAPE_TEMPLATE = [['.....', + '...O.', + '.OOO.', + '.....', + '.....'], + ['.....', + '..O..', + '..O..', + '..OO.', + '.....'], + ['.....', + '.....', + '.OOO.', + '.O...', + '.....'], + ['.....', + '.OO..', + '..O..', + '..O..', + '.....']] + +T_SHAPE_TEMPLATE = [['.....', + '..O..', + '.OOO.', + '.....', + '.....'], + ['.....', + '..O..', + '..OO.', + '..O..', + '.....'], + ['.....', + '.....', + '.OOO.', + '..O..', + '.....'], + ['.....', + '..O..', + '.OO..', + '..O..', + '.....']] + +PIECES = {'S': S_SHAPE_TEMPLATE, + 'Z': Z_SHAPE_TEMPLATE, + 'J': J_SHAPE_TEMPLATE, + 'L': L_SHAPE_TEMPLATE, + 'I': I_SHAPE_TEMPLATE, + 'O': O_SHAPE_TEMPLATE, + 'T': T_SHAPE_TEMPLATE} + + +def main(): + global FPSCLOCK, DISPLAYSURF, BASICFONT, BIGFONT + pygame.init() + pygame.mouse.set_visible(False) + + FPSCLOCK = pygame.time.Clock() + #DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) + DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT),FULLSCREEN) + BASICFONT = pygame.font.Font('freesansbold.ttf', 18) + BIGFONT = pygame.font.Font('freesansbold.ttf', 100) + pygame.display.set_caption('Tetromino') + + showTextScreen('-=TETЯIS=-') + while True: # game loop + if random.randint(0, 1) == 0: + pygame.mixer.music.load('tetrisb.mid') + else: + pygame.mixer.music.load('tetrisc.mid') + pygame.mixer.music.play(-1, 0.0) + runGame() + pygame.mixer.music.stop() + showTextScreen('Game Over') + + +def runGame(): + # setup variables for the start of the game + board = getBlankBoard() + lastMoveDownTime = time.time() + lastMoveSidewaysTime = time.time() + lastFallTime = time.time() + movingDown = False # note: there is no movingUp variable + movingLeft = False + movingRight = False + score = 0 + level, fallFreq = calculateLevelAndFallFreq(score) + + fallingPiece = getNewPiece() + nextPiece = getNewPiece() + + while True: # game loop + if fallingPiece == None: + # No falling piece in play, so start a new piece at the top + fallingPiece = nextPiece + nextPiece = getNewPiece() + lastFallTime = time.time() # reset lastFallTime + + if not isValidPosition(board, fallingPiece): + return # can't fit a new piece on the board, so game over + + checkForQuit() + for event in pygame.event.get(): # event handling loop + #key events + if (event.type == KEYUP ): + if (event.key == K_p): + # Pausing the game + DISPLAYSURF.fill(BGCOLOR) + pygame.mixer.music.stop() + showTextScreen('Paused') # pause until a key press + pygame.mixer.music.play(-1, 0.0) + lastFallTime = time.time() + lastMoveDownTime = time.time() + lastMoveSidewaysTime = time.time() + elif (event.key == K_LEFT or event.key == K_a): + movingLeft = False + elif (event.key == K_RIGHT or event.key == K_d): + movingRight = False + elif (event.key == K_DOWN or event.key == K_s): + movingDown = False + + elif (event.type == KEYDOWN ): + # moving the piece sideways + if (event.key == K_LEFT or event.key == K_a and isValidPosition(board, fallingPiece, adjX=-1)): + fallingPiece['x'] -= 1 + movingLeft = True + movingRight = False + lastMoveSidewaysTime = time.time() + + elif (event.key == K_RIGHT or event.key == K_d and isValidPosition(board, fallingPiece, adjX=1)): + fallingPiece['x'] += 1 + movingRight = True + movingLeft = False + lastMoveSidewaysTime = time.time() + + # rotating the piece (if there is room to rotate) + elif (event.key == K_UP or event.key == K_w ): + fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']]) + if not isValidPosition(board, fallingPiece): + fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) + elif (event.key == K_q): # rotate the other direction + fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) + if not isValidPosition(board, fallingPiece): + fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']]) + + # making the piece fall faster with the down key + elif (event.key == K_DOWN or event.key == K_s): + movingDown = True + if isValidPosition(board, fallingPiece, adjY=1): + fallingPiece['y'] += 1 + lastMoveDownTime = time.time() + + # move the current piece all the way down + elif event.key == K_SPACE: + movingDown = False + movingLeft = False + movingRight = False + for i in range(1, BOARDHEIGHT): + if not isValidPosition(board, fallingPiece, adjY=i): + break + fallingPiece['y'] += i - 1 + + #joystick events + elif (event.type == JOYBUTTONDOWN): + if (js.get_button(9) == 1): + # Pausing the game + DISPLAYSURF.fill(BGCOLOR) + pygame.mixer.music.stop() + showTextScreen('Paused') # pause until a key press + pygame.mixer.music.play(-1, 0.0) + lastFallTime = time.time() + lastMoveDownTime = time.time() + lastMoveSidewaysTime = time.time() + + # move the current piece all the way down with Button A + elif (js.get_button(1) == 1): + movingDown = False + movingLeft = False + movingRight = False + for i in range(1, BOARDHEIGHT): + if not isValidPosition(board, fallingPiece, adjY=i): + break + fallingPiece['y'] += i - 1 + + #rotate with button B + elif (js.get_button(0) == 1): + fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) + if not isValidPosition(board, fallingPiece): + fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']]) + + + elif (event.type == JOYAXISMOTION): + # moving the piece sideways + if (js.get_axis(0) < 0 and isValidPosition(board, fallingPiece, adjX=-1)): + fallingPiece['x'] -= 1 + movingLeft = True + movingRight = False + lastMoveSidewaysTime = time.time() + + elif ((js.get_axis(0) > 0) and isValidPosition(board, fallingPiece, adjX=1)): + fallingPiece['x'] += 1 + movingRight = True + movingLeft = False + lastMoveSidewaysTime = time.time() + + # rotating the piece (if there is room to rotate) + elif (js.get_axis(1) < 0): + fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']]) + if not isValidPosition(board, fallingPiece): + fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) + #elif (js.get_axis(1) > 0): # rotate the other direction + # fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) + # if not isValidPosition(board, fallingPiece): + # fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']]) + + # making the piece fall faster with the down key + elif (js.get_axis(1) > 0): + movingDown = True + if isValidPosition(board, fallingPiece, adjY=1): + fallingPiece['y'] += 1 + lastMoveDownTime = time.time() + + elif (js.get_axis(0)== 0.0): + movingLeft = False + movingRight = False + movingDown = False + + # handle moving the piece because of user input + if (movingLeft or movingRight) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ: + if movingLeft and isValidPosition(board, fallingPiece, adjX=-1): + fallingPiece['x'] -= 1 + elif movingRight and isValidPosition(board, fallingPiece, adjX=1): + fallingPiece['x'] += 1 + lastMoveSidewaysTime = time.time() + + if movingDown and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition(board, fallingPiece, adjY=1): + fallingPiece['y'] += 1 + lastMoveDownTime = time.time() + + # let the piece fall if it is time to fall + if time.time() - lastFallTime > fallFreq: + # see if the piece has landed + if not isValidPosition(board, fallingPiece, adjY=1): + # falling piece has landed, set it on the board + addToBoard(board, fallingPiece) + score += removeCompleteLines(board) + level, fallFreq = calculateLevelAndFallFreq(score) + fallingPiece = None + else: + # piece did not land, just move the piece down + fallingPiece['y'] += 1 + lastFallTime = time.time() + + # drawing everything on the screen + DISPLAYSURF.fill(BGCOLOR) + drawBoard(board) + drawStatus(score, level) + drawNextPiece(nextPiece) + if fallingPiece != None: + drawPiece(fallingPiece) + + pygame.display.update() + FPSCLOCK.tick(FPS) + + +def makeTextObjs(text, font, color): + surf = font.render(text, True, color) + return surf, surf.get_rect() + + +def terminate(): + pygame.quit() + sys.exit() + + +# KRT 17/06/2012 rewrite event detection to deal with mouse use +def checkForKeyPress(): + for event in pygame.event.get(): + if event.type == QUIT: #event is quit + terminate() + elif event.type == KEYDOWN: + if event.key == K_ESCAPE: #event is escape key + terminate() + else: + return event.key #key found return with it + elif event.type == JOYBUTTONDOWN or event.type == JOYAXISMOTION: + if (js.get_button(8) == 1): + terminate() + return 1 + # no quit or key events in queue so return None + return None + + + +##def checkForKeyPress(): +## # Go through event queue looking for a KEYUP event. +## # Grab KEYDOWN events to remove them from the event queue. +## checkForQuit() +## +## for event in pygame.event.get([KEYDOWN, KEYUP]): +## if event.type == KEYDOWN: +## continue +## return event.key +## return None + + +def showTextScreen(text): + # This function displays large text in the + # center of the screen until a key is pressed. + # Draw the text drop shadow + titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTSHADOWCOLOR) + titleRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2)) + DISPLAYSURF.blit(titleSurf, titleRect) + + # Draw the text + titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTCOLOR) + titleRect.center = (int(WINDOWWIDTH / 2) - 3, int(WINDOWHEIGHT / 2) - 3) + DISPLAYSURF.blit(titleSurf, titleRect) + + # Draw the additional "Press a key to play." text. + pressKeySurf, pressKeyRect = makeTextObjs('Press a key to play. \'Select\' to quit.', BASICFONT, TEXTCOLOR) + pressKeyRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2) + 100) + DISPLAYSURF.blit(pressKeySurf, pressKeyRect) + + while checkForKeyPress() == None: + pygame.display.update() + FPSCLOCK.tick() + + +def checkForQuit(): + for event in pygame.event.get(QUIT): # get all the QUIT events + terminate() # terminate if any QUIT events are present + for event in pygame.event.get(KEYUP): # get all the KEYUP events + if event.key == K_ESCAPE: + terminate() # terminate if the KEYUP event was for the Esc key + pygame.event.post(event) # put the other KEYUP event objects back + + +def calculateLevelAndFallFreq(score): + # Based on the score, return the level the player is on and + # how many seconds pass until a falling piece falls one space. + level = int(score / 10) + 1 + fallFreq = 0.27 - (level * 0.02) + return level, fallFreq + +def getNewPiece(): + # return a random new piece in a random rotation and color + shape = random.choice(list(PIECES.keys())) + newPiece = {'shape': shape, + 'rotation': random.randint(0, len(PIECES[shape]) - 1), + 'x': int(BOARDWIDTH / 2) - int(TEMPLATEWIDTH / 2), + 'y': -2, # start it above the board (i.e. less than 0) + 'color': random.randint(0, len(COLORS)-1)} + return newPiece + + +def addToBoard(board, piece): + # fill in the board based on piece's location, shape, and rotation + for x in range(TEMPLATEWIDTH): + for y in range(TEMPLATEHEIGHT): + if PIECES[piece['shape']][piece['rotation']][y][x] != BLANK: + board[x + piece['x']][y + piece['y']] = piece['color'] + + +def getBlankBoard(): + # create and return a new blank board data structure + board = [] + for i in range(BOARDWIDTH): + board.append([BLANK] * BOARDHEIGHT) + return board + + +def isOnBoard(x, y): + return x >= 0 and x < BOARDWIDTH and y < BOARDHEIGHT + + +def isValidPosition(board, piece, adjX=0, adjY=0): + # Return True if the piece is within the board and not colliding + for x in range(TEMPLATEWIDTH): + for y in range(TEMPLATEHEIGHT): + isAboveBoard = y + piece['y'] + adjY < 0 + if isAboveBoard or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK: + continue + if not isOnBoard(x + piece['x'] + adjX, y + piece['y'] + adjY): + return False + if board[x + piece['x'] + adjX][y + piece['y'] + adjY] != BLANK: + return False + return True + +def isCompleteLine(board, y): + # Return True if the line filled with boxes with no gaps. + for x in range(BOARDWIDTH): + if board[x][y] == BLANK: + return False + return True + + +def removeCompleteLines(board): + # Remove any completed lines on the board, move everything above them down, and return the number of complete lines. + numLinesRemoved = 0 + y = BOARDHEIGHT - 1 # start y at the bottom of the board + while y >= 0: + if isCompleteLine(board, y): + # Remove the line and pull boxes down by one line. + for pullDownY in range(y, 0, -1): + for x in range(BOARDWIDTH): + board[x][pullDownY] = board[x][pullDownY-1] + # Set very top line to blank. + for x in range(BOARDWIDTH): + board[x][0] = BLANK + numLinesRemoved += 1 + # Note on the next iteration of the loop, y is the same. + # This is so that if the line that was pulled down is also + # complete, it will be removed. + else: + y -= 1 # move on to check next row up + return numLinesRemoved + + +def convertToPixelCoords(boxx, boxy): + # Convert the given xy coordinates of the board to xy + # coordinates of the location on the screen. + return (XMARGIN + (boxx * BOXSIZE)), (TOPMARGIN + (boxy * BOXSIZE)) + + +def drawBox(boxx, boxy, color, pixelx=None, pixely=None): + # draw a single box (each tetromino piece has four boxes) + # at xy coordinates on the board. Or, if pixelx & pixely + # are specified, draw to the pixel coordinates stored in + # pixelx & pixely (this is used for the "Next" piece). + if color == BLANK: + return + if pixelx == None and pixely == None: + pixelx, pixely = convertToPixelCoords(boxx, boxy) + pygame.draw.rect(DISPLAYSURF, COLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 1, BOXSIZE - 1)) + pygame.draw.rect(DISPLAYSURF, LIGHTCOLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 4, BOXSIZE - 4)) + + +def drawBoard(board): + # draw the border around the board + pygame.draw.rect(DISPLAYSURF, BORDERCOLOR, (XMARGIN - 3, TOPMARGIN - 7, (BOARDWIDTH * BOXSIZE) + 8, (BOARDHEIGHT * BOXSIZE) + 8), 5) + + # fill the background of the board + pygame.draw.rect(DISPLAYSURF, BGCOLOR, (XMARGIN, TOPMARGIN, BOXSIZE * BOARDWIDTH, BOXSIZE * BOARDHEIGHT)) + # draw the individual boxes on the board + for x in range(BOARDWIDTH): + for y in range(BOARDHEIGHT): + drawBox(x, y, board[x][y]) + + +def drawStatus(score, level): + # draw the score text + scoreSurf = BASICFONT.render('Score: %s' % score, True, TEXTCOLOR) + scoreRect = scoreSurf.get_rect() + scoreRect.topleft = (WINDOWWIDTH - 150, 20) + DISPLAYSURF.blit(scoreSurf, scoreRect) + + # draw the level text + levelSurf = BASICFONT.render('Level: %s' % level, True, TEXTCOLOR) + levelRect = levelSurf.get_rect() + levelRect.topleft = (WINDOWWIDTH - 150, 50) + DISPLAYSURF.blit(levelSurf, levelRect) + + +def drawPiece(piece, pixelx=None, pixely=None): + shapeToDraw = PIECES[piece['shape']][piece['rotation']] + if pixelx == None and pixely == None: + # if pixelx & pixely hasn't been specified, use the location stored in the piece data structure + pixelx, pixely = convertToPixelCoords(piece['x'], piece['y']) + + # draw each of the boxes that make up the piece + for x in range(TEMPLATEWIDTH): + for y in range(TEMPLATEHEIGHT): + if shapeToDraw[y][x] != BLANK: + drawBox(None, None, piece['color'], pixelx + (x * BOXSIZE), pixely + (y * BOXSIZE)) + + +def drawNextPiece(piece): + # draw the "next" text + nextSurf = BASICFONT.render('Next:', True, TEXTCOLOR) + nextRect = nextSurf.get_rect() + nextRect.topleft = (WINDOWWIDTH - 120, 80) + DISPLAYSURF.blit(nextSurf, nextRect) + # draw the "next" piece + drawPiece(piece, pixelx=WINDOWWIDTH-120, pixely=100) + + +if __name__ == '__main__': + main() diff --git a/tetris/tetrisb.mid b/tetris/tetrisb.mid Binary files differnew file mode 100644 index 0000000..04a78d9 --- /dev/null +++ b/tetris/tetrisb.mid diff --git a/tetris/tetrisc.mid b/tetris/tetrisc.mid Binary files differnew file mode 100644 index 0000000..24a57bd --- /dev/null +++ b/tetris/tetrisc.mid |