Created
March 30, 2020 14:46
-
-
Save channel2007/7c6e9466a4e8e79794d2e4d3c56bf9de to your computer and use it in GitHub Desktop.
那些年我們一起玩過的遊戲(二)-俄羅斯方塊 - play.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
import os, sys, random | |
import time | |
import pygame | |
from pygame.locals import * | |
from drew import * | |
# 常數-方塊快速下降速度. | |
BRICK_DROP_RAPIDLY = 0.01 | |
# 常數-方塊正常下降速度. | |
BRICK_DOWN_SPEED_MAX = 0.5 | |
# 視窗大小. | |
canvas_width = 800 | |
canvas_height = 600 | |
# 顏色. | |
color_block = (0,0,0) | |
color_white = (255, 255, 255) | |
color_red = (255, 0, 0) | |
color_gray = (107,130,114) | |
color_gray_block = (20,31,23) | |
color_gray_green = (0, 255, 0) | |
# 定義方塊. | |
brick_dict = { | |
"10": ( 4, 8, 9,13), "11": ( 9,10,12,13), # N1. | |
"20": ( 5, 8, 9,12), "21": ( 8, 9,13,14), # N2. | |
"30": ( 8,12,13,14), "31": ( 4, 5, 8,12), "32": (8, 9, 10, 14), "33": (5, 9, 12, 13), # L1. | |
"40": (10,12,13,14), "41": ( 4, 8,12,13), "42": (8, 9, 10, 12), "43": (4, 5, 9, 13), # L2. | |
"50": ( 9,12,13,14), "51": ( 4, 8, 9,12), "52": (8, 9, 10, 13), "53": (5, 8, 9, 13), # T. | |
"60": ( 8, 9,12,13), # O. | |
"70": (12,13,14,15), "71": ( 1, 5, 9,13) #I. | |
} | |
# 方塊陣列(10x20). | |
bricks_array = [] | |
for i in range(10): | |
bricks_array.append([0]*20) | |
# 方塊陣列(4x4). | |
bricks = [] | |
for i in range(4): | |
bricks.append([0]*4) | |
# 下一個方塊陣列(4x4). | |
bricks_next = [] | |
for i in range(4): | |
bricks_next.append([0]*4) | |
# 下一個方塊圖形陣列(4x4). | |
bricks_next_object = [] | |
for i in range(4): | |
bricks_next_object.append([0]*4) | |
# 方塊數量串列. | |
bricks_list = [] | |
for i in range(10): | |
bricks_list.append([0]*20) | |
# 方塊在容器的位置. | |
# (-2~6)( 為6的時候不能旋轉方塊). | |
container_x = 3 | |
# (-3~16)(-3表示在上邊界外慢慢往下掉). | |
container_y =-4 | |
# 除錯訊息. | |
debug_message = False | |
# 判斷遊戲結束. | |
game_over = False | |
# 方塊下降速度. | |
brick_down_speed = BRICK_DOWN_SPEED_MAX | |
# 方塊編號(1~7). | |
brick_id = 1 | |
# 方塊狀態(0~3). | |
brick_state = 0 | |
# 下一個方塊編號(1~7). | |
brick_next_id = 1 | |
# 最大連線數. | |
lines_number_max = 0 | |
# 本場連線數. | |
lines_number = 0 | |
# 遊戲狀態. | |
# 0:遊戲進行中. | |
# 1:清除方塊. | |
game_mode = 0 | |
#------------------------------------------------------------------------- | |
# 函數:秀字. | |
# 傳入: | |
# text : 字串. | |
# x, y : 坐標. | |
# color : 顏色. | |
#------------------------------------------------------------------------- | |
def showFont( text, x, y, color): | |
global canvas | |
text = font.render(text, True, color) | |
canvas.blit( text, (x,y)) | |
#------------------------------------------------------------------------- | |
# 函數:取得方塊索引陣列. | |
# 傳入: | |
# brickId : 方塊編號(1~7). | |
# state : 方塊狀態(0~3). | |
#------------------------------------------------------------------------- | |
def getBrickIndex( brickId, state): | |
global brick_dict | |
# 組合字串. | |
brickKey = str(brickId)+str(state) | |
# 回傳方塊陣列. | |
return brick_dict[brickKey] | |
#------------------------------------------------------------------------- | |
# 轉換定義方塊到方塊陣列. | |
# 傳入: | |
# brickId : 方塊編號(1~7). | |
# state : 方塊狀態(0~3). | |
#------------------------------------------------------------------------- | |
def transformToBricks( brickId, state): | |
global bricks | |
# 清除方塊陣列. | |
for x in range(4): | |
for y in range(4): | |
bricks[x][y] = 0 | |
# 取得方塊索引陣列. | |
p_brick = getBrickIndex(brickId, state) | |
# 轉換方塊到方塊陣列. | |
for i in range(4): | |
bx = int(p_brick[i] % 4) | |
by = int(p_brick[i] / 4) | |
bricks[bx][by] = brickId | |
""" | |
# 印出訊息. | |
for y in range(4): | |
s = "" | |
for x in range(4): | |
s = s + str(bricks[x][y]) + "," | |
print(s) | |
""" | |
#------------------------------------------------------------------------- | |
# 判斷是否可以複製到容器內. | |
# 傳出: | |
# true : 可以. | |
# false : 不可以. | |
#------------------------------------------------------------------------- | |
def ifCopyToBricksArray(): | |
global bricks, bricks_array | |
global container_x, container_y | |
posX = 0 | |
posY = 0 | |
for x in range(4): | |
for y in range(4): | |
if (bricks[x][y] != 0): | |
posX = container_x + x | |
posY = container_y + y | |
if (posX >= 0 and posY >= 0): | |
try: | |
if (bricks_array[posX][posY] != 0): | |
return False | |
except: | |
return False | |
return True | |
#------------------------------------------------------------------------- | |
# 複製方塊到容器內. | |
#------------------------------------------------------------------------- | |
def copyToBricksArray(): | |
global bricks, bricks_array | |
global container_x, container_y | |
posX = 0 | |
posY = 0 | |
for x in range(4): | |
for y in range(4): | |
if (bricks[x][y] != 0): | |
posX = container_x + x | |
posY = container_y + y | |
if (posX >= 0 and posY >= 0): | |
bricks_array[posX][posY] = bricks[x][y] | |
#------------------------------------------------------------------------- | |
# 初始遊戲. | |
#------------------------------------------------------------------------- | |
def resetGame(): | |
global BRICK_DOWN_SPEED_MAX | |
global bricks_array, bricks, lines_number, lines_number_max | |
# 清除方塊陣列. | |
for x in range(10): | |
for y in range(20): | |
bricks_array[x][y] = 0 | |
# 清除方塊陣列. | |
for x in range(4): | |
for y in range(4): | |
bricks[x][y] = 0 | |
# 初始方塊下降速度. | |
brick_down_speed = BRICK_DOWN_SPEED_MAX | |
# 最大連線數. | |
if(lines_number > lines_number_max): | |
lines_number_max = lines_number | |
# 連線數. | |
lines_number = 0 | |
#--------------------------------------------------------------------------- | |
# 判斷與設定要清除的方塊. | |
# 傳出: | |
# 連線數 | |
#--------------------------------------------------------------------------- | |
def ifClearBrick(): | |
pointNum = 0 | |
lineNum = 0 | |
for y in range(20): | |
for x in range(10): | |
if (bricks_array[x][y] > 0): | |
pointNum = pointNum + 1 | |
if (pointNum == 10): | |
for i in range(10): | |
lineNum = lineNum + 1 | |
bricks_array[i][y] = 9 | |
pointNum = 0 | |
return lineNum | |
#------------------------------------------------------------------------- | |
# 更新下一個方塊. | |
#------------------------------------------------------------------------- | |
def updateNextBricks(brickId): | |
global bricks_next | |
# 清除方塊陣列. | |
for y in range(4): | |
for x in range(4): | |
bricks_next[x][y] = 0 | |
# 取得方塊索引陣列. | |
pBrick = getBrickIndex(brickId, 0) | |
# 轉換方塊到方塊陣列. | |
for i in range(4): | |
bx = int(pBrick[i] % 4) | |
by = int(pBrick[i] / 4) | |
bricks_next[bx][by] = brickId | |
# 更新背景區塊. | |
background_bricks_next.update() | |
# 更新方塊圖. | |
pos_y = 52 | |
for y in range(4): | |
pos_x = 592 | |
for x in range(4): | |
if(bricks_next[x][y] != 0): | |
bricks_next_object[x][y].rect[0] = pos_x | |
bricks_next_object[x][y].rect[1] = pos_y | |
bricks_next_object[x][y].update() | |
pos_x = pos_x + 28 | |
pos_y = pos_y + 28 | |
#------------------------------------------------------------------------- | |
# 產生新方塊. | |
#------------------------------------------------------------------------- | |
def brickNew(): | |
global game_over, container_x, container_y, brick_id, brick_next_id, brick_state | |
global lines_number, game_mode | |
# 判斷遊戲結束. | |
game_over = False | |
if (container_y < 0): | |
game_over = True | |
# 複製方塊到容器內. | |
container_y = container_y - 1 | |
copyToBricksArray() | |
#------------------------------------------------ | |
# 判斷與設定要清除的方塊. | |
lines = ifClearBrick() / 10; | |
if (lines > 0): | |
# 消除連線數量累加. | |
lines_number = lines_number + lines | |
# 修改連線數量. | |
#modifyLabel(linesNumber, fontLinesNumber) | |
# 1:清除方塊. | |
game_mode = 1 | |
# 初始方塊位置. | |
container_x = 3 | |
container_y =-4 | |
# 現在出現方塊. | |
brick_id = brick_next_id | |
# 下個出現方塊. | |
# 方塊編號(1~7). | |
brick_next_id = random.randint( 1, 7) | |
# 初始方塊狀態. | |
brick_state = 0 | |
# GameOver. | |
if (game_over): | |
# 重新開始遊戲. | |
resetGame() | |
#------------------------------------------------------------------------- | |
# 清除的方塊. | |
#------------------------------------------------------------------------- | |
def clearBrick(): | |
global bricks_array | |
# 一列一列判斷清除方塊. | |
temp = 0 | |
for x in range(10): | |
for i in range(19): | |
for y in range(20): | |
if (bricks_array[x][y] == 9): | |
if (y > 0): | |
temp = bricks_array[x][y - 1] | |
bricks_array[x][y - 1] = bricks_array[x][y] | |
bricks_array[x][y] = temp | |
y = y - 1 | |
bricks_array[x][0] = 0 | |
#------------------------------------------------------------------------- | |
# 初始. | |
pygame.init() | |
# 顯示Title. | |
pygame.display.set_caption(u"俄羅斯方塊遊戲") | |
# 建立畫佈大小. | |
# 全螢幕模式. | |
#canvas = pygame.display.set_mode((canvas_width, canvas_height), pygame.DOUBLEBUF and pygame.FULLSCREEN ) | |
# 視窗模式. | |
canvas = pygame.display.set_mode((canvas_width, canvas_height)) | |
# 時脈. | |
clock = pygame.time.Clock() | |
# 查看系統支持那些字體 | |
#print(pygame.font.get_fonts()) | |
# 設定字型-黑體. | |
font = pygame.font.SysFont("simsunnsimsun", 24) | |
# 將繪圖方塊放入陣列. | |
for y in range(20): | |
for x in range(10): | |
bricks_list[x][y] = Box(pygame, canvas, "brick_x_" + str(x) + "_y_" + str(y), [ 0, 0, 26, 26], color_gray_block) | |
# 將繪圖方塊放入陣列. | |
for y in range(4): | |
for x in range(4): | |
bricks_next_object[x][y] = Box(pygame, canvas, "brick_next_x_" + str(x) + "_y_" + str(y), [ 0, 0, 26, 26], color_gray_block) | |
# 背景區塊. | |
background = Box(pygame, canvas, "background", [ 278, 18, 282, 562], color_gray) | |
# 背景區塊. | |
background_bricks_next = Box(pygame, canvas, "background_bricks_next", [ 590, 50, 114, 114], color_gray) | |
# 方塊編號(1~7). | |
brick_next_id = random.randint( 1, 7) | |
# 產生新方塊. | |
brickNew() | |
#------------------------------------------------------------------------- | |
# 主迴圈. | |
#------------------------------------------------------------------------- | |
running = True | |
time_temp = time.time() | |
time_now = 0 | |
while running: | |
# 計算時脈. | |
time_now = time_now + (time.time() - time_temp) | |
time_temp = time.time() | |
#--------------------------------------------------------------------- | |
# 判斷輸入. | |
#--------------------------------------------------------------------- | |
for event in pygame.event.get(): | |
# 離開遊戲. | |
if event.type == pygame.QUIT: | |
running = False | |
# 判斷按下按鈕 | |
if event.type == pygame.KEYDOWN: | |
#----------------------------------------------------------------- | |
# 判斷按下ESC按鈕 | |
if event.key == pygame.K_ESCAPE: | |
running = False | |
# 除錯訊息開關. | |
elif event.key == pygame.K_d: | |
debug_message = not debug_message | |
#----------------------------------------------------------------- | |
# 變換方塊-上. | |
elif event.key == pygame.K_UP and game_mode == 0: | |
# 在右邊界不能旋轉. | |
if (container_x == 8): | |
break | |
# 判斷方塊N1、N2、I. | |
if (brick_id == 1 or brick_id == 2 or brick_id == 7): | |
# 長條方塊旋轉例外處理. | |
if (brick_id == 7): | |
if (container_x < 0 or container_x == 7): | |
break | |
# 旋轉方塊. | |
brick_state = brick_state + 1 | |
if (brick_state > 1): | |
brick_state = 0 | |
# 轉換定義方塊到方塊陣列. | |
transformToBricks(brick_id, brick_state) | |
# 碰到方塊. | |
if (not ifCopyToBricksArray()): | |
brick_state = brick_state - 1 | |
if (brick_state < 0): | |
brick_state = 1 | |
# 判斷磚跨L1、L2、T. | |
elif (brick_id == 3 or brick_id == 4 or brick_id == 5): | |
# 旋轉方塊. | |
brick_state = brick_state + 1 | |
if (brick_state > 3): | |
brick_state = 0 | |
# 轉換定義方塊到方塊陣列. | |
transformToBricks(brick_id, brick_state) | |
# 碰到方塊. | |
if (not ifCopyToBricksArray()): | |
brick_state = brick_state - 1 | |
if (brick_state < 0): | |
brick_state = 3 | |
#----------------------------------------------------------------- | |
# 快速下降-下. | |
elif event.key == pygame.K_DOWN and game_mode == 0: | |
# 方塊快速下降. | |
brick_down_speed = BRICK_DROP_RAPIDLY | |
#----------------------------------------------------------------- | |
# 移動方塊-左. | |
elif event.key == pygame.K_LEFT and game_mode == 0: | |
container_x = container_x - 1 | |
if (container_x < 0): | |
if (container_x == -1): | |
if (bricks[0][0] != 0 or bricks[0][1] != 0 or bricks[0][2] != 0 or bricks[0][3] != 0): | |
container_x = container_x + 1 | |
elif (container_x == -2): | |
if (bricks[1][0] != 0 or bricks[1][1] != 0 or bricks[1][2] != 0 or bricks[1][3] != 0): | |
container_x = container_x + 1 | |
else: | |
container_x = container_x + 1 | |
# 碰到方塊. | |
if (not ifCopyToBricksArray()): | |
container_x = container_x + 1 | |
#----------------------------------------------------------------- | |
# 移動方塊-右. | |
elif event.key == pygame.K_RIGHT and game_mode == 0: | |
container_x = container_x + 1 | |
if (container_x > 6): | |
if (container_x == 7): | |
if (bricks[3][0] != 0 or bricks[3][1] != 0 or bricks[3][2] != 0 or bricks[3][3] != 0): | |
container_x = container_x - 1; | |
elif (container_x == 8): | |
if (bricks[2][0] != 0 or bricks[2][1] != 0 or bricks[2][2] != 0 or bricks[2][3] != 0): | |
container_x = container_x - 1 | |
else: | |
container_x = container_x - 1 | |
# 碰到方塊. | |
if (not ifCopyToBricksArray()): | |
container_x = container_x - 1 | |
#----------------------------------------------------------------- | |
# 判斷放開按鈕 | |
if event.type == pygame.KEYUP: | |
# 快速下降-下. | |
if event.key == pygame.K_DOWN: | |
# 恢復正常下降速度. | |
brick_down_speed = BRICK_DOWN_SPEED_MAX | |
#--------------------------------------------------------------------- | |
# 清除畫面. | |
canvas.fill(color_block) | |
# 遊戲中. | |
if (game_mode == 0): | |
# 處理方塊下降. | |
if(time_now >= brick_down_speed): | |
# 往下降. | |
container_y = container_y + 1; | |
# 碰到方塊. | |
if (not ifCopyToBricksArray()): | |
#產生新塊. | |
brickNew() | |
# 轉換定義方塊到方塊陣列(bricks). | |
transformToBricks( brick_id, brick_state) | |
# 清除時脈. | |
time_now = 0 | |
# 清除方塊. | |
elif (game_mode == 1): | |
# 清除的方塊. | |
clearBrick() | |
# 遊戲中. | |
game_mode = 0 | |
# 轉換定義方塊到方塊陣列. | |
transformToBricks(brick_id, brick_state) | |
#--------------------------------------------------------------------- | |
# 更新下一個方塊圖形. | |
updateNextBricks(brick_next_id) | |
# 更新繪圖. | |
pos_y = 20 | |
# 更新背景區塊. | |
background.update() | |
for y in range(20): | |
pos_x = 280 | |
for x in range(10): | |
if(bricks_array[x][y] != 0): | |
bricks_list[x][y].rect[0] = pos_x | |
bricks_list[x][y].rect[1] = pos_y | |
bricks_list[x][y].update() | |
pos_x = pos_x + 28 | |
pos_y = pos_y + 28 | |
# 更新方塊 | |
for y in range(4): | |
for x in range(4): | |
if (bricks[x][y] != 0): | |
posX = container_x + x | |
posY = container_y + y | |
if (posX >= 0 and posY >= 0): | |
bricks_list[posX][posY].rect[0] = (posX * 28) + 280 | |
bricks_list[posX][posY].rect[1] = (posY * 28) + 20 | |
bricks_list[posX][posY].update() | |
#--------------------------------------------------------------------- | |
# 除錯訊息. | |
if(debug_message): | |
# 更新容器. | |
str_x = "" | |
pos_x = 15 | |
pos_y = 20 | |
for y in range(20): | |
str_x = "" | |
for x in range(10): | |
str_x = str_x + str(bricks_array[x][y]) + " " | |
showFont( str_x, pos_x, pos_y, color_red) | |
pos_y = pos_y + 28 | |
# 更新方塊 | |
posX = 0 | |
posY = 0 | |
for y in range(4): | |
str_x = "" | |
for x in range(4): | |
if (bricks[x][y] != 0): | |
posX = container_x + x | |
posY = container_y + y | |
if (posX >= 0 and posY >= 0): | |
str_x = str_x + str(bricks[x][y]) + " " | |
else: | |
str_x = str_x + " " | |
pos_x = 15 + (container_x * 26) | |
pos_y = 20 + (posY * 28) | |
showFont( str_x, pos_x, pos_y, color_white) | |
# 顯示訊息. | |
showFont( u"下次出現方塊", 588, 16, color_gray) | |
showFont( u"最大連線數", 588, 190, color_gray) | |
showFont( str(int(lines_number_max)), 588, 220, color_gray) | |
showFont( u"本局連線數", 588, 260, color_gray) | |
showFont( str(int(lines_number)), 588, 290, color_gray) | |
# 顯示FPS. | |
# 除錯訊息. | |
if(debug_message): | |
showFont( u"FPS:" + str(clock.get_fps()), 6, 0, color_gray_green) | |
# 更新畫面. | |
pygame.display.update() | |
clock.tick(60) | |
# 離開遊戲. | |
pygame.quit() | |
quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment