
我们已经实现了pythonpygame实现扫雷游戏之一pythonpygame实现扫雷游戏之二下面就可以实例化MineBlock及响应鼠标消息循环了。其本质就是不停地接收鼠标事件改变二维数组的状态然后“画”在屏幕上就可以了。六、main.py# -*- coding: utf-8 -*- import sys import time import pygame from pygame.locals import * from mineblock import * from gamestatus import * # 游戏屏幕的宽 SCREEN_WIDTH BLOCK_WIDTH * SIZE # 游戏屏幕的高 SCREEN_HEIGHT (BLOCK_HEIGHT 2) * SIZE #要留出上面的位置显示剩余地雷的数量和用时。 def print_text(screen, font, x, y, text, fcolor(255, 255, 255)): imgText font.render(text, True, fcolor) screen.blit(imgText, (x, y)) def main(): pygame.init() screen pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption(扫雷) font1 pygame.font.Font(resources/bdm.TTF, SIZE * 2) # 地雷数量、事件的字体 fwidth, fheight font1.size(888) fontcolor (208, 38, 38) # 加载资源图片因为资源文件大小不一所以smoothscale做了统一的缩放处理 img0 pygame.image.load(resources/0.bmp).convert() img0 pygame.transform.smoothscale(img0, (SIZE, SIZE)) img1 pygame.image.load(resources/1.bmp).convert() img1 pygame.transform.smoothscale(img1, (SIZE, SIZE)) img2 pygame.image.load(resources/2.bmp).convert() img2 pygame.transform.smoothscale(img2, (SIZE, SIZE)) img3 pygame.image.load(resources/3.bmp).convert() img3 pygame.transform.smoothscale(img3, (SIZE, SIZE)) img4 pygame.image.load(resources/4.bmp).convert() img4 pygame.transform.smoothscale(img4, (SIZE, SIZE)) img5 pygame.image.load(resources/5.bmp).convert() img5 pygame.transform.smoothscale(img5, (SIZE, SIZE)) img6 pygame.image.load(resources/6.bmp).convert() img6 pygame.transform.smoothscale(img6, (SIZE, SIZE)) img7 pygame.image.load(resources/7.bmp).convert() img7 pygame.transform.smoothscale(img7, (SIZE, SIZE)) img8 pygame.image.load(resources/8.bmp).convert() img8 pygame.transform.smoothscale(img8, (SIZE, SIZE)) img_blank pygame.image.load(resources/blank.bmp).convert() img_blank pygame.transform.smoothscale(img_blank, (SIZE, SIZE)) img_flag pygame.image.load(resources/flag.bmp).convert() img_flag pygame.transform.smoothscale(img_flag, (SIZE, SIZE)) img_ask pygame.image.load(resources/ask.bmp).convert() img_ask pygame.transform.smoothscale(img_ask, (SIZE, SIZE)) img_mine pygame.image.load(resources/mine.bmp).convert() img_mine pygame.transform.smoothscale(img_mine, (SIZE, SIZE)) img_blood pygame.image.load(resources/blood.bmp).convert() img_blood pygame.transform.smoothscale(img_blood, (SIZE, SIZE)) img_error pygame.image.load(resources/error.bmp).convert() img_error pygame.transform.smoothscale(img_error, (SIZE, SIZE)) face_size int(SIZE * 1.25) img_face_fail pygame.image.load(resources/face_fail.bmp).convert() img_face_fail pygame.transform.smoothscale(img_face_fail, (face_size, face_size)) img_face_normal pygame.image.load(resources/face_normal.bmp).convert() img_face_normal pygame.transform.smoothscale(img_face_normal, (face_size, face_size)) img_face_success pygame.image.load(resources/face_success.bmp).convert() img_face_success pygame.transform.smoothscale(img_face_success, (face_size, face_size)) face_pos_x (SCREEN_WIDTH - face_size) // 2 face_pos_y (SIZE * 2 - face_size) // 2 img_dict { 0: img0, 1: img1, 2: img2, 3: img3, 4: img4, 5: img5, 6: img6, 7: img7, 8: img8 } bgcolor (225, 225, 225) # 背景色 block MineBlock() game_status GameStatus.readied start_time None # 开始时间 elapsed_time 0 # 耗时 while True: # 填充背景色 screen.fill(bgcolor) for event in pygame.event.get(): if event.type QUIT: sys.exit() elif event.type MOUSEBUTTONDOWN: mouse_x, mouse_y event.pos x mouse_x // SIZE y mouse_y // SIZE - 2 bLeft, bMiddle, bRight pygame.mouse.get_pressed() if game_status GameStatus.started: # 鼠标左右键同时按下如果已经标记了所有雷则打开周围一圈 # 如果还未标记完所有雷则有一个周围一圈被同时按下的效果 if bLeft and bRight: mine block.getmine(x, y) if mine.status BlockStatus.opened: if not block.double_mouse_button_down(x, y): game_status GameStatus.over elif event.type MOUSEBUTTONUP: if y 0: if face_pos_x mouse_x face_pos_x face_size \ and face_pos_y mouse_y face_pos_y face_size: game_status GameStatus.readied block MineBlock() start_time time.time() elapsed_time 0 continue if game_status GameStatus.readied: game_status GameStatus.started start_time time.time() elapsed_time 0 if game_status GameStatus.started: mine block.getmine(x, y) if bLeft and not bRight: # 按鼠标左键 if mine.status BlockStatus.normal: if not block.open_mine(x, y): game_status GameStatus.over elif not bLeft and bRight: # 按鼠标右键 if mine.status BlockStatus.normal: mine.status BlockStatus.flag elif mine.status BlockStatus.flag: mine.status BlockStatus.ask elif mine.status BlockStatus.ask: mine.status BlockStatus.normal elif bLeft and bRight: if mine.status BlockStatus.double: block.double_mouse_button_up(x, y) flag_count 0 opened_count 0 for row in block.block: for mine in row: pos (mine.x * SIZE, (mine.y 2) * SIZE) if mine.status BlockStatus.opened: screen.blit(img_dict[mine.around_mine_count], pos) opened_count 1 elif mine.status BlockStatus.double: screen.blit(img_dict[mine.around_mine_count], pos) elif mine.status BlockStatus.bomb: screen.blit(img_blood, pos) elif mine.status BlockStatus.flag: screen.blit(img_flag, pos) flag_count 1 elif mine.status BlockStatus.ask: screen.blit(img_ask, pos) elif mine.status BlockStatus.hint: screen.blit(img0, pos) elif game_status GameStatus.over and mine.value: screen.blit(img_mine, pos) elif mine.value 0 and mine.status BlockStatus.flag: screen.blit(img_error, pos) elif mine.status BlockStatus.normal: screen.blit(img_blank, pos) print_text(screen, font1, 28, (SIZE * 2 - fheight) // 2 - 2, %02d % (MINE_COUNT - flag_count), fontcolor) if game_status GameStatus.started: elapsed_time int(time.time() - start_time) print_text(screen, font1, SCREEN_WIDTH - fwidth - 8, (SIZE * 2 - fheight) // 2 - 2, %03d % elapsed_time, fontcolor) if flag_count opened_count BLOCK_WIDTH * BLOCK_HEIGHT: game_status GameStatus.win if game_status GameStatus.over: screen.blit(img_face_fail, (face_pos_x, face_pos_y)) elif game_status GameStatus.win: screen.blit(img_face_success, (face_pos_x, face_pos_y)) else: screen.blit(img_face_normal, (face_pos_x, face_pos_y)) pygame.display.update() if __name__ __main__: main() #pygame.mouse.get_pressed() —— 获取鼠标按键的情况是否被按下 #返回一个由布尔值组成的列表代表所有鼠标按键被按下的情况。True意味着在调用此方法时该鼠标按键正被按下 #(1, 0, 1) 表示左键和右键被按下(左键、中键、右键) #pygame.mouse.get_pos() —— 获取鼠标光标的位置 #返回鼠标光标的坐标 (x, y)。这个坐标以窗口左上角为基准点 # pygame.mouse.get_rel() —— 获取鼠标与前一位置的偏移量 # pygame.mouse.set_pos(pos) —— 设置鼠标光标的位置 #如果鼠标光标是可视的则光标将会跳到新的坐标上。移动鼠标将会产生一个新的 pygame.MOUSEMOTION 事件 # pygame.mouse.set_visible(bool) —— 隐藏或显示鼠标光标 # bpygame.mouse.set_visible(False) #设置鼠标是否可见 True 可见False 不可见 # 返回值返回在设置之前的状态 # pygame.mouse.get_focused() —— 检查程序界面是否获得鼠标焦点 # 当 pygame 正在接受鼠标输入事件即说鼠标正在处于“active”或“focus”状态返回值为 True # pygame.mouse.set_cursor() —— 设置鼠标光标在程序内的显示图像 # pygame.mouse.get_cursor() —— 获取鼠标光标在程序内的显示图像 # flip函数和update函数的主要区别在于它们处理屏幕重绘的方式和效率。 # flip函数flip函数会重新绘制整个屏幕对应的窗口。这意味着无论屏幕上哪个部分是否发生变化flip函数都会导致整个屏幕被重新绘制。\ # 这种方式适用于需要快速、完全更新屏幕内容的情况例如在场景变化非常频繁的游戏中。 # update函数相比之下Update函数仅重新绘制窗口中有变化的区域。如果屏幕上只有少数物体在移动或变化update函数只会重绘那些实际移动或变化的部分而不会重绘没有变化的部分。\ # 这种方式能够提高效率因为它减少了不必要的屏幕重绘操作从而可能提供更好的性能尤其是在场景变化不是非常频繁的情况下。 # 总的来说flip函数适用于需要快速、完全更新屏幕内容的场景而update函数则更适合于只需要更新屏幕部分内容的场景特别是在性能优化方面有要求的情况下。结合代码理解一下逻辑6.1 一直到bgcolor (225, 225, 225) # 背景色这里都是一些资源的加载没有太多需要理解的6.2 先实例化MineBlock的对象为block将游戏状态设为准备好了GameStatus.readied开始时间耗时等初始化工作6.3 消息循环6.3.1 QUIT6.3.2 鼠标按下游戏场景中只需要监测左右键同时按下事件对应的是MineBlock中的 double_mouse_button_down函数6.3.3 鼠标弹起6.3.3.1 鼠标在笑脸的地方重玩游戏6.3.3.2 GameStatus.readied改成GameStatus.started后只左键弹起对应的是 MineBlock中的open_mine函数6.3.3.3 鼠标右键弹起走马灯效果状态转换normal--flag--ask--normal6.3.3.4 左右键同时弹起对应的是MineBlock中的double_mouse_button_up函数6.4 前面都是返回的状态接下来就将状态和显示的图片资源结合起来即哪个坐标的状态 对应哪个图片将整个屏幕在内存中blit出来6.5 最后pygame.display.update即可当然这个游戏还没有计分升级的功能这就留给大家自行研究和实现老规矩代码及资源