- 本文章将会说明,把俄罗斯方块从面向过程到面向对象的改进,以及个性化功能的添加
- 个性化功能包括:
- 暂停
- 重新开始
- 结束动画
- AD广告板
- 显示下一个
- 面对对象的设计我主要分为三个类:
Wall
,HouseWorker
,和Brick
- 下面一个一个类来说明
- 有些简单的功能我只提一提函数名,需要讲解的话请评论
class Wall():
global GRID_NUM_WIDTH
global LINE_COLOR
global HEIGHT
global HEIGHT
def __init__(self):
pass
# 绘制背景格子
def draw_grids(self):
pass
# 根据颜色矩阵绘制格子
def draw_matrix(self):
pass
# 满行消除
def remove_full_line(self):
pass
# 欢迎界面
def show_welcome(self):
pass
def show_text(self, text, size, x, y, color=(0xff, 0xff, 0xff),bgColor = None):
fontObj = pygame.font.Font('font/font.ttc', size)
textSurfaceObj = fontObj.render(text, True, color,bgColor)
textRectObj = textSurfaceObj.get_rect()
textRectObj.center = (x, y)
screen.blit(textSurfaceObj, textRectObj)
def draw_score(self):
global heightScore
self.show_text( u'得分 : {}'.format(score), 18, WIDTH + SIDE_WIDTH // 2, 180)
if heightScore is None:
self.getHeightScore()
if score>heightScore:
heightScore = score
self.show_text( u'level : {} 最高分 : {}'.format(level,heightScore), 15, WIDTH + SIDE_WIDTH // 2, 205)
# 暂停界面的显示
def showPause(self):
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 128)
self.show_text(u'暂停中...', 50, 250, 200, BLUE , GREEN)
pygame.display.update()
# 因为文字描述(最高分,当前分,基本操作提示以及等级)多了,所以我干脆封装一个函数全部显示这些东西
def drawAll(self):
# 更新屏幕
screen.fill(BLACK)
self.draw_grids()
self.draw_matrix()
self.draw_score()
self.drawNextBrick()
self.show_text( u'再来一次:R',13, WIDTH+100,HEIGHT-140 , WHITE )
self.show_text( u'我要暂停:P',13, WIDTH+100,HEIGHT-120 , WHITE )
self.show_text( u'我要变形:↑',13, WIDTH+100,HEIGHT-100 , WHITE )
self.show_text( u'左右移动: ← or →',13, WIDTH+100,HEIGHT-80 , WHITE )
self.show_text( u'下落一步:↓',13, WIDTH+100,HEIGHT-60 , WHITE )
self.show_text( u'一步到底:SPACE',13, WIDTH+100,HEIGHT-40 , WHITE )
self.show_text( u'Author:Charming(2018.4)',13, SCREEN_WIDTH-100,HEIGHT-10 , WHITE )
# 个性化功能-AD广告板,当我暂停的时候,广告板的文字会变,更具趣味性
if pause :
self.showAD(u'突然暂停', u'害怕了吗')
else:
self.showAD()
if live_cube is not None:
live_cube.draw()
if gameover:
self.show_welcome()
new_cube
和live_cube
,然后当上一个下落完成之后,把new_cube
赋值给live_cube
,然后再生成新的new_cube
即可 # 绘制下一个方块
def drawNextBrick(self):
global new_cube
if new_cube is not None:
new_cube.drawNext()
# 读取文件,获取最高分
def getHeightScore(self):
global heightScore
f = open('score.txt', 'r')
heightScore = int( f.read() )
# 把最高分写入文件
def writeHeightScore(self):
global heightScore
f = open('score.txt', 'w')
f.write( str(heightScore) )
f.close()
# 显示广告板
def showAD(self,text1 = None , text2 = None):
global CUBE_COLORS
global colorBool
line1 = ['哇塞萌新', '运气好而已', '回去吧', '是不是快挂了', '年轻人不简单', '哇塞!!', '围观大佬']
line2 = ['你会玩吗', '狗屎运而已', '后面太难了', '哈哈哈', '看走眼了', '这样都行?', '大佬请喝茶']
if level > len(line1):
num = len(line1)-1
else:
num = level
if text1 is None and text2 is None:
if gameover:
text1 = u'广告位招租'
text2 = u'非诚勿扰'
else:
text1 = line1[num - 1].decode('utf-8')
text2 = line2[num - 1].decode('utf-8')
GREEN = (0, 255, 0)
# 广告底板和边框
pygame.draw.rect(screen, BLACK,
(WIDTH + 20, 240,
160, 80))
pygame.draw.rect(screen, GREEN,
(WIDTH + 20, 240,
160, 80), 1)
# 这里有一个彩蛋,当你正常运行程序时,按c键,广告板的文字会闪动
if colorBool :
color = CUBE_COLORS[num]
else :
color = CUBE_COLORS[random.randint(0, len(CUBE_COLORS) - 1)]
# 广告的文字信息
self.show_text( text1,18, WIDTH+100,265 , color )
self.show_text( text2,18, WIDTH+100,295 , color )
与上一章的
CubeShape
类类似,代码略
# 在特定的位置绘制下一方块
def drawNext(self):
for cube in self.get_all_gridpos((0,0)):
pygame.draw.rect(screen, self.color,
(cube[1] * GRID_WIDTH+WIDTH+100, cube[0] * GRID_WIDTH+70,
GRID_WIDTH, GRID_WIDTH))
pygame.draw.rect(screen, WHITE,
(cube[1] * GRID_WIDTH+WIDTH+100, cube[0] * GRID_WIDTH+70,
GRID_WIDTH, GRID_WIDTH),1)
下面是最长的代码,也是最重要的逻辑部分,大家可以喝杯茶冷静下再来看
# 这些是全局参数,参数指结束动画的初始位置和xy方向的速度
x, y = 10., 10.
speed_x, speed_y = 133., 170.
class HouseWorker():
# 开始游戏
# 开始游戏没得说的,就是初始化好各种参数
def start(self):
global gameover
global live_cube
global new_cube
global score
global screen_color_matrix
gameover = False
live_cube = Brick()
new_cube = Brick()
score = 0
screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
pass
# 暂停操作
# 暂停就是改变pause的值,具体的情况看whenPause函数
def pause(self):
global pause
if pause:
pause = False
else :
pause = True
pause_count
来决定不同时候窗口的不同状态即可P,R,ESC
三个按键的操作 # 当暂停时
def whenPause(self):
# 暂停动画
global pause_count
global score
global live_cube
global level
global screen_color_matrix
global colorBool
global dead
pause_count += 1
if pause_count % FPS > 10 and pause_count % FPS < 20:
w.drawAll()
else:
w.showPause()
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
hw.pause()
elif event.key == pygame.K_ESCAPE:
hw.pause()
w.writeHeightScore()
# 退出pygame
pygame.quit()
# 退出系统
sys.exit()
# 重新开始
elif event.key == pygame.K_r:
w.writeHeightScore()
hw.pause()
score = 0
live_cube = Brick()
level = 1
dead = False
screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
# ad广告板闪动的彩蛋
elif event.key == pygame.K_c:
if colorBool :
colorBool = False
else:
colorBool = True
else:
pass
# 当正常时
def whenNormal(self):
global score
global live_cube
global level
global screen_color_matrix
global gameover
global running
global counter
global new_cube
global colorBool
global dead
# 正常运行时
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and pause == False:
# 初始化是gameover是True,会显示欢迎界面
if gameover:
# hw.start()函数包括把gameover改成False的操作
hw.start()
break
# 上下左右的监控
if event.key == pygame.K_LEFT:
live_cube.left()
elif event.key == pygame.K_RIGHT:
live_cube.right()
elif event.key == pygame.K_DOWN:
live_cube.down()
elif event.key == pygame.K_UP:
live_cube.rotate()
elif event.key == pygame.K_SPACE:
while live_cube.down() == True:
pass
elif event.key == pygame.K_ESCAPE:
w.writeHeightScore()
# 退出pygame
pygame.quit()
# 退出系统
sys.exit()
# 重新开始
elif event.key == pygame.K_r:
w.writeHeightScore()
score = 0
live_cube = Brick()
new_cube = Brick()
colorBool = True
dead = False
level = 1
screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
elif event.key == pygame.K_c:
if colorBool :
colorBool = False
else:
colorBool = True
elif event.key == pygame.K_p:
hw.pause()
# 判断是否结束函数和执行down动作
if gameover is False and counter % (FPS // level) == 0:
if live_cube.down() == False:
for cube in live_cube.get_all_gridpos():
screen_color_matrix[cube[0]][cube[1]] = live_cube.color
live_cube = new_cube
new_cube = Brick()
# 这里游戏结束
# 这里是到顶的意思
if live_cube.conflict(live_cube.center):
w.writeHeightScore()
dead = True
gameover = True
colorBool = False
# 消除满行
w.remove_full_line()
# 计时作用
counter += 1
if not dead:
w.drawAll()
pygame.display.update()
def whenGameOver(self):
global score
global live_cube
global new_cube
global level
global screen_color_matrix
global colorBool
global dead
global speed_x
global speed_y
global SCREEN_WIDTH
global x
global y
# 以下部分是结束动画的弹动,没有封装成函数是我的错。
GREEN = (0, 255, 0)
BLUE = (0, 0, 128)
w.drawAll()
w.showAD(u'挂了挂了', u'哈哈哈')
w.show_text(u'Game Over', 50, x, y, BLUE, GREEN)
w.show_text(u'按任意键重新开始', 25, x, y+38, BLUE, GREEN)
time_passed = clock.tick(30)
time_passed_seconds = time_passed / 1000.0
x += speed_x * time_passed_seconds
y += speed_y * time_passed_seconds
# 到达边界则把速度反向
if x > SCREEN_WIDTH - 150:
speed_x = -speed_x
x = SCREEN_WIDTH - 150
elif x < 150:
speed_x = -speed_x
x = 150.
if y > HEIGHT-38 - 25:
speed_y = -speed_y
y = HEIGHT-38 - 25
elif y < 25:
speed_y = -speed_y
y = 25.
pygame.display.update()
# 结束动画的弹动到这里结束
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if gameover and dead:
dead = False
colorBool = True
hw.start()
break
if event.key == pygame.K_ESCAPE:
# 退出pygame
pygame.quit()
# 退出系统
sys.exit()
# 重新开始
elif event.key == pygame.K_r:
w.writeHeightScore()
score = 0
live_cube = Brick()
new_cube = Brick()
level = 1
colorBool = True
dead = False
screen_color_matrix = [[None] * GRID_NUM_WIDTH for i in range(GRID_NUM_HEIGHT)]
elif event.key == pygame.K_c:
if colorBool:
colorBool = False
else:
colorBool = True
else:
pass
之所以叫游戏的主逻辑是因为我不知道怎么命名。。。
# 新建两个类
w = Wall()
hw = HouseWorker()
while running:
# 设定帧数
clock.tick(FPS)
# 暂停时的事件循环
if pause == True:
hw.whenPause()
continue
if dead:
hw.whenGameOver()
continue
# 正常时的事件循环
hw.whenNormal()