- 论坛徽章:
- 0
|
python实现的“打砖块”游戏。根据摩托罗拉C289手机上的同名游戏写成。- #!/usr/bin/python
- #
- # Brick & Ball in Python
- # by Jerry Fleming
- #
- # This is a small game adapted from that in Motorola Mobile C289, and my first game in python :)
- #
- # This progrma is best run under linux. Since Windows port of Python has poor curses support,
- # play it under Windows is not recommended. If you have no linux box available, try Cygwin,
- # though it too has poor curses support.
- #
- # As I am a newbie to python, please tell me if you have a better implementation or any suggestions.
- #
- # TODO:
- # re-implemente it with wxPython, so one does not have to rely on the ugly curses.
- # session support.
- # pausing, especially when confirming
- # resize terminal at run time
- #
- # HISTORY
- # 2006-04-19: first version
- #
- #
- import curses
- import _curses
- import thread
- from time import sleep
- from string import split
- from random import randint
- # parameters: adjust them to fit you terminal
- brick_width = 7
- brick_gap_x = 1
- brick_gap_y = 1
- speed = 0.1 # sleep time to control moving speed of the ball
- # terminal initialization
- stdscr = curses.initscr()
- curses.noecho()
- curses.cbreak()
- curses.curs_set(0)
- stdscr.keypad(1)
- screen_height, screen_width = stdscr.getmaxyx()
- screen_height = screen_height - 1
- screen_width = screen_width - 1
- brick_rows = screen_height / 4
- if brick_rows > 7: brick_rows = 7
- brick_cols = (screen_width + brick_gap_x) / (brick_width + brick_gap_x)
- brick_margin = (screen_width - brick_cols * (brick_width + brick_gap_x) + brick_gap_x)/2
- pad_position = randint(0, screen_width - brick_width)
- ball_position = [screen_height - 3, randint(0, screen_width - brick_width)]
- ball_direction = [-1, 1] # abs(tan(a)) must be 1
- pad_direction = ''
- bricks = []
- game_score = 0
- tStart = '''
- ______ _ _ ___ ______ _ _ _ ______ _
- (____ \ (_) | | / _ \ (____ \ | | | (_) (_____ \ _ | |
- ____) ) ____ _ ____| | _ ( (_) ) ____) )_____| | | _ ____ _____) ) _ _| |_| |__ ___ ____
- | __ ( / ___) |/ ___) |_/ ) ) _ ( | __ ((____ | | | | | _ \ | ____/ | | (_ _) _ \ / _ \| _ \
- | |__) ) | | ( (___| _ ( ( (/ \ | |__) ) ___ | | | | | | | | | | | |_| | | |_| | | | |_| | | | |
- |______/|_| |_|\____)_| \_) \__/\_) |______/\_____|\_)_) |_|_| |_| |_| \__ | \__)_| |_|\___/|_| |_|
- (____/
- by Jerry Fleming
- GAME STARTING ...
- (this assumes that your terminal be larger that 130x40)
- '''
- tExit = '''
- 88888 88888
- 88888888888 88 ad88888ba 88 8b d8 d8 88
- 88 "" ,d d8" "8b 88 Y8, ,8P ,8P' 88
- 88 88 "" a8P 88 Y8, ,8P d8" 88
- 88aaaaa 8b, ,d8 88 MM88MMM ,a8P" 88 "8aa8" ,8P' 8b,dPPYba, 88
- 88""""" `Y8, ,8P' 88 88 d8" 88 `88' d8" 88P' `"8a 88
- 88 )888( 88 88 "" 88 88 ,8P' 88 88 88
- 88 ,d8" "8b, 88 88, aa 88 88 d8" 88 88 88
- 88888888888 8P' `Y8 88 "Y888 88 88 88 8P' 88 88 88
- 88888 88888
- '''
- tOver = '''
- ,ad8888ba, 88
- d8"' `"8b 88
- d8' 88
- 88 ,adPPYYba, 88,dPYba,,adPYba, ,adPPYba, ,adPPYba, 8b d8 ,adPPYba, 8b,dPPYba, 88
- 88 88888 "" `Y8 88P' "88" "8a a8P_____88 a8" "8a `8b d8' a8P_____88 88P' "Y8 88
- Y8, 88 ,adPPPPP88 88 88 88 8PP""""""" 8b d8 `8b d8' 8PP""""""" 88 ""
- Y8a. .a88 88, ,88 88 88 88 "8b, ,aa "8a, ,a8" `8b,d8' "8b, ,aa 88 aa
- `"Y88888P" `"8bbdP"Y8 88 88 88 `"Ybbd8"' `"YbbdP"' "8" `"Ybbd8"' 88 88
- '''
- tGoon = '''
- 88888 88888
- ,ad8888ba, ad88888ba 88 8b d8 d8 88
- d8"' `"8b d8" "8b 88 Y8, ,8P ,8P' 88
- d8' "" a8P 88 Y8, ,8P d8" 88
- 88 ,adPPYba, ,adPPYba, 8b,dPPYba, ,a8P" 88 "8aa8" ,8P' 8b,dPPYba, 88
- 88 88888 a8" "8a a8" "8a 88P' `"8a d8" 88 `88' d8" 88P' `"8a 88
- Y8, 88 8b d8 8b d8 88 88 "" 88 88 ,8P' 88 88 88
- Y8a. .a88 "8a, ,a8" "8a, ,a8" 88 88 aa 88 88 d8" 88 88 88
- `"Y88888P" `"YbbdP"' `"YbbdP"' 88 88 88 88 88 8P' 88 88 88
- 88888 88888
- '''
- def init_game():
- global bricks
- # display the bricks
- for row in range(brick_rows):
- y = row * (1 + brick_gap_y)
- for col in range(brick_cols):
- x = col * (brick_gap_x + brick_width) + brick_margin
- stdscr.addstr(y, x, ' ' * brick_width, curses.A_REVERSE)
- bricks.append([y, x])
- # move the pad to center of bottom at starting up
- stdscr.addstr(screen_height - 1, pad_position, ' ' * brick_width, curses.A_REVERSE)
- # move the ball to left bottom side at starting up
- stdscr.addstr(ball_position[0], ball_position[1], ' ', curses.A_REVERSE)
- # display score board
- stdscr.addstr(screen_height, 0, ' SCORE: '+ ('%03d' % game_score) + ' '* 4, curses.A_REVERSE)
- stdscr.addstr(screen_height, 15, 'USE q to quit' + ' '* (screen_width - 28), curses.A_REVERSE)
- # final step to init display
- stdscr.refresh()
- # move the pad to catch the ball
- def move_pad(lock):
- global pad_position
- char = stdscr.getch()
- if char == ord('q'):
- quit_game(lock)
- else:
- if char == curses.KEY_LEFT: pad_position = pad_position - 1; pad_direction = 'left'
- if char == curses.KEY_RIGHT: pad_position = pad_position + 1; pad_direction = 'right'
- if pad_position = screen_width - brick_width: pad_position = screen_width - brick_width
- stdscr.addstr(screen_height - 1, 0, ' ' * screen_width)
- stdscr.addstr(screen_height - 1, pad_position, ' ' * brick_width, curses.A_REVERSE)
- stdscr.refresh()
- move_pad(lock)
- # move the ball to a direction
- def move_ball(lock):
- global ball_position, ball_direction
- # clear the old position, do not if in pad
- if ball_position[0] != screen_height - 1:
- stdscr.addstr(ball_position[0], ball_position[1], ' ')
- ball_position[0] = ball_position[0] + ball_direction[0]
- ball_position[1] = ball_position[1] + ball_direction[1]
- stdscr.addstr(ball_position[0], ball_position[1], ' ', curses.A_REVERSE)
- detect_collision(lock)
- stdscr.refresh()
- sleep(speed)
- move_ball(lock)
- # detect whether the ball has hit something, change direction if yes
- def detect_collision(lock):
- global bricks, ball_direction, game_score
- # hit upper wall
- if ball_position[0] == 0 :
- ball_direction = [- ball_direction[0], ball_direction[1]]
- # hit left and right wall
- if ball_position[1] == 0 or ball_position[1] == screen_width:
- ball_direction = [ball_direction[0], - ball_direction[1]]
- # hit brick
- for brick in bricks:
- # hit from bottom or upper direction
- if brick[1] <= ball_position[1] + ball_direction[1] <= brick[1] + brick_width \
- and ball_position[0] + ball_direction[0] == brick[0]:
- ball_direction[0] = - ball_direction[0]
- stdscr.addstr(brick[0], brick[1], ' '* brick_width)
- game_score = game_score + 10
- stdscr.addstr(screen_height, 8, '%03d' % game_score, curses.A_REVERSE)
- bricks.remove(brick)
- # another level to continue the game
- if not len(bricks): another_level()
- # hit body of pad
- if ball_position[0] == screen_height - 2 and pad_position <= ball_position[1] <= pad_position + brick_width:
- ball_direction[0] = - ball_direction[0]
- # hit bottom
- elif ball_position[0] == screen_height - 1:
- ball_direction[0] = - ball_direction[0]
- # hit left side of pad (hit bottom already)
- if ball_position[1] == pad_position and pad_direction == 'left' and ball_direction[1]:
- ball_direction[1] = - ball_direction[1]
- # hit right side of pad (hit bottom already)
- if ball_position[1] == pad_position + brick_width and pad_direction == 'right' and not ball_direction[1]:
- ball_direction[1] = - ball_direction[1]
- # hit bottom wall, game over
- if ball_position[0] == screen_height - 1 and not pad_position <= ball_position[1] <= pad_position + brick_width:
- line_num = 0
- for line in split(tOver, "\n"):
- stdscr.addstr(screen_height / 2 + line_num, 10, line)
- line_num = line_num + 1
- stdscr.refresh()
- curses.flash()
- sleep(1)
- curses.flash()
- sleep(1)
- lock.release()
- # confirm quit the game
- def quit_game(lock):
- line_num = 0
- for line in split(tExit, "\n"):
- stdscr.addstr(screen_height / 2 + line_num, 10, line)
- line_num = line_num + 1
- stdscr.refresh()
- char = stdscr.getch()
- if char == ord('N') or char == ord('n'):
- line_num = 0
- for line in split(tExit, "\n"):
- stdscr.addstr(screen_height / 2 + line_num, 10, ' ' * len(line) )
- line_num = line_num + 1
- stdscr.refresh()
- else:
- lock.release()
- # confirm another level of the game
- def another_level():
- line_num = 0
- for line in split(tGoon, "\n"):
- stdscr.addstr(screen_height / 2 + line_num, 10, line)
- line_num = line_num + 1
- stdscr.refresh()
- char = stdscr.getch()
- if char == ord('N') or char == ord('n'):
- lock.release()
- else:
- line_num = 0
- for line in split(tGoon, "\n"):
- stdscr.addstr(screen_height / 2 + line_num, 10, ' ' * len(line) )
- line_num = line_num + 1
- stdscr.refresh()
- init_game()
- # main loop starts here
- if __name__ == "__main__":
- try:
- line_num = 0
- for line in split(tStart, "\n"):
- stdscr.addstr(screen_height /4 + line_num, 10, line)
- line_num = line_num + 1
- stdscr.refresh()
- sleep(1)
- stdscr.erase()
- running = 1
- init_game()
- locks = []
- for i in range(2):
- lock = thread.allocate_lock()
- lock.acquire()
- locks.append(lock)
- thread.start_new_thread(move_ball, (locks[0],))
- thread.start_new_thread(move_pad, (locks[1],))
- except _curses.error, diag:
- msg = 'Your terminal is too small: ' + str(diag)
- running = 0
- except:
- msg = 'An unknown error occured.'
- running = 0
- else:
- msg = 'Game stopped.'
- while running:
- for i in range(len(locks)):
- if locks[i].locked()==False: running = 0
- if running == 0:
- for i in range(len(locks)):
- if locks[i].locked(): locks[i].release()
- curses.curs_set(1)
- stdscr.keypad(0)
- curses.nocbreak()
- curses.echo()
- curses.endwin()
- print msg
复制代码
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/8484/showart_102109.html |
|