├── 1.jpg ├── 2.jpg ├── 演示视频.mp4 ├── resources ├── font.TTF ├── audios │ ├── bg.mp3 │ ├── badswap.wav │ ├── match0.wav │ ├── match1.wav │ ├── match2.wav │ ├── match3.wav │ ├── match4.wav │ └── match5.wav └── images │ ├── gem1.png │ ├── gem2.png │ ├── gem3.png │ ├── gem4.png │ ├── gem5.png │ ├── gem6.png │ └── gem7.png ├── config.py ├── main.py ├── README.md └── utils.py /1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/1.jpg -------------------------------------------------------------------------------- /2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/2.jpg -------------------------------------------------------------------------------- /演示视频.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/演示视频.mp4 -------------------------------------------------------------------------------- /resources/font.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/font.TTF -------------------------------------------------------------------------------- /resources/audios/bg.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/bg.mp3 -------------------------------------------------------------------------------- /resources/images/gem1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem1.png -------------------------------------------------------------------------------- /resources/images/gem2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem2.png -------------------------------------------------------------------------------- /resources/images/gem3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem3.png -------------------------------------------------------------------------------- /resources/images/gem4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem4.png -------------------------------------------------------------------------------- /resources/images/gem5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem5.png -------------------------------------------------------------------------------- /resources/images/gem6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem6.png -------------------------------------------------------------------------------- /resources/images/gem7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/images/gem7.png -------------------------------------------------------------------------------- /resources/audios/badswap.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/badswap.wav -------------------------------------------------------------------------------- /resources/audios/match0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/match0.wav -------------------------------------------------------------------------------- /resources/audios/match1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/match1.wav -------------------------------------------------------------------------------- /resources/audios/match2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/match2.wav -------------------------------------------------------------------------------- /resources/audios/match3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/match3.wav -------------------------------------------------------------------------------- /resources/audios/match4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/match4.wav -------------------------------------------------------------------------------- /resources/audios/match5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackHCC/Elimination-Game/HEAD/resources/audios/match5.wav -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | '''定义一些超参''' 5 | WIDTH = 600 6 | HEIGHT = 600 7 | NUMGRID = 8 8 | GRIDSIZE = 64 9 | XMARGIN = (WIDTH - GRIDSIZE * NUMGRID) // 2 10 | YMARGIN = (HEIGHT - GRIDSIZE * NUMGRID) // 2 11 | ROOTDIR = os.getcwd() 12 | FPS = 30 -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pygame 3 | from utils import * 4 | from config import * 5 | 6 | 7 | '''游戏主程序''' 8 | def main(): 9 | pygame.init() 10 | screen = pygame.display.set_mode((WIDTH, HEIGHT)) 11 | pygame.display.set_caption('消消乐') 12 | # 加载背景音乐 13 | pygame.mixer.init() 14 | pygame.mixer.music.load(os.path.join(ROOTDIR, "resources/audios/bg.mp3")) 15 | pygame.mixer.music.set_volume(0.6) 16 | pygame.mixer.music.play(-1) 17 | # 加载音效 18 | sounds = {} 19 | sounds['mismatch'] = pygame.mixer.Sound(os.path.join(ROOTDIR, 'resources/audios/badswap.wav')) 20 | sounds['match'] = [] 21 | for i in range(6): 22 | sounds['match'].append(pygame.mixer.Sound(os.path.join(ROOTDIR, 'resources/audios/match%s.wav' % i))) 23 | # 加载字体 24 | font = pygame.font.Font(os.path.join(ROOTDIR, 'resources/font.TTF'), 25) 25 | # 图片加载 26 | gem_imgs = [] 27 | for i in range(1, 8): 28 | gem_imgs.append(os.path.join(ROOTDIR, 'resources/images/gem%s.png' % i)) 29 | # 主循环 30 | game = gemGame(screen, sounds, font, gem_imgs) 31 | while True: 32 | score = game.start() 33 | flag = False 34 | # 一轮游戏结束后玩家选择重玩或者退出 35 | while True: 36 | for event in pygame.event.get(): 37 | if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE): 38 | pygame.quit() 39 | sys.exit() 40 | elif event.type == pygame.KEYUP and event.key == pygame.K_r: 41 | flag = True 42 | if flag: 43 | break 44 | screen.fill((135, 206, 235)) 45 | text0 = 'Final score: %s' % score 46 | text1 = 'Press to restart the game.' 47 | text2 = 'Press to quit the game.' 48 | y = 150 49 | for idx, text in enumerate([text0, text1, text2]): 50 | text_render = font.render(text, 1, (85, 65, 0)) 51 | rect = text_render.get_rect() 52 | if idx == 0: 53 | rect.left, rect.top = (212, y) 54 | elif idx == 1: 55 | rect.left, rect.top = (122.5, y) 56 | else: 57 | rect.left, rect.top = (126.5, y) 58 | y += 100 59 | screen.blit(text_render, rect) 60 | pygame.display.update() 61 | game.reset() 62 | 63 | 64 | '''test''' 65 | if __name__ == '__main__': 66 | main() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 消消乐记分小游戏GUI界面 2 | 3 | ### 文件结构规划 4 | 1. 定义config.py文件存储相关参数:包括界面的宽高,整个方格行列个数,总格数等等。 5 | 2. 定义utils.py文件用于存放基础的类和函数:包括整个消除拼图类,游戏类,拼图块移动函数,坐标设置与获取函数,开始游戏主函数,初始化随机生成拼图函数,时间倒计时展示函数,显示得分函数,加分函数,消除函数以及消除后新拼图块生成函数,拼图交换位置函数等等。 6 | 3. 定义main.py主函数:主要用于界面初始化开启游戏主程序 7 | 8 | ### 实现方法 9 | 1. config参数设置: 10 | ``` 11 | WIDTH = 600 12 | HEIGHT = 600 13 | NUMGRID = 8 14 | GRIDSIZE = 64 15 | XMARGIN = (WIDTH - GRIDSIZE * NUMGRID) // 2 16 | YMARGIN = (HEIGHT - GRIDSIZE * NUMGRID) // 2 17 | ROOTDIR = os.getcwd() 18 | FPS = 30 19 | ``` 20 | 2. utils类与函数设置 21 | 22 | 1) 导入库:time计时,random生成随机数,pygame跨平台Python模块主要用于游戏图形化界面生成以及音频播放,config自己定义的相关变量 23 | ``` 24 | import time 25 | import random 26 | import pygame 27 | from config import * 28 | ``` 29 | 2) 定义拼图类 30 | ``` 31 | class gemSprite(pygame.sprite.Sprite): 32 | ``` 33 | 主要有函数: 34 | + 初始化函数:self=类具体化对象本身,img_path=图片文件所在路径,size=整个界面大小,position=拼图块位置,downlen=消除拼图块后下降格数 35 | ``` 36 | def __init__(self, img_path, size, position, downlen, **kwargs): 37 | ``` 38 | + 移动函数:主要通过鼠标控制拼图块交换方向,有上下左右四个方向 39 | ``` 40 | def move(self): 41 | ``` 42 | + 获取坐标函数:获取当前拼图块坐标,主要通过左(left)和上(top)两个方向定义坐标距离 43 | ``` 44 | def getPosition(self): 45 | ``` 46 | + 设置坐标函数:设置拼图块坐标 47 | ``` 48 | def setPosition(self, position): 49 | ``` 50 | 3) 定义游戏类: 51 | ``` 52 | class gemGame(): 53 | ``` 54 | 主要函数有: 55 | + 初始化函数:self=类具体化对象本身,screen=屏幕,sounds=音频,font=字体,gem_imgs=拼图块图片 56 | ``` 57 | def __init__(self, screen, sounds, font, gem_imgs, **kwargs): 58 | ``` 59 | + 开始游戏函数:游戏开始主循环 60 | ``` 61 | def start(self): 62 | ``` 63 | + 随机拼图块生成函数:消除后随机生成新的拼图模块 64 | ``` 65 | def reset(self): 66 | ``` 67 | + 显示游戏倒计时时间函数: 68 | ``` 69 | def showRemainingTime(self): 70 | ``` 71 | + 显示得分函数: 72 | ``` 73 | def drawScore(self): 74 | ``` 75 | + 分数计算函数: 76 | ``` 77 | def drawAddScore(self, add_score): 78 | ``` 79 | + 新拼图块生成函数: 80 | ``` 81 | def generateNewGems(self, res_match): 82 | ``` 83 | + 消除匹配成功的拼图块:行或列三个一样的拼图块出现即消除 84 | ``` 85 | def removeMatched(self, res_match): 86 | ``` 87 | + 界面网格绘制: 88 | ``` 89 | def drawGrids(self): 90 | ``` 91 | + 画矩形框: 92 | ``` 93 | def drawBlock(self, block, color=(255, 0, 255), size=4): 94 | ``` 95 | + 新的拼图块出现下落特效: 96 | ``` 97 | def dropGems(self, x, y): 98 | ``` 99 | + 检查有无拼图块被选中: 100 | ``` 101 | def checkSelected(self, position): 102 | ``` 103 | + 有无行列三个拼图块相同判断: 104 | ``` 105 | def isMatch(self): 106 | ``` 107 | + 交换拼图函数: 108 | ``` 109 | def swapGem(self, gem1_pos, gem2_pos): 110 | ``` 111 | 3. 主函数Main配置: 112 | 113 | 1) 导入库 114 | ``` 115 | import os 116 | import pygame 117 | from utils import * 118 | from config import * 119 | ``` 120 | 2) 游戏主程序定义: 121 | ``` 122 | def main(): 123 | ``` 124 | 主要功能: 125 | + 游戏界面初始化: 126 | ``` 127 | pygame.init() 128 | screen = pygame.display.set_mode((WIDTH, HEIGHT)) 129 | pygame.display.set_caption('消消乐') 130 | ``` 131 | + 加载音效资源: 132 | ``` 133 | # 加载背景音乐 134 | pygame.mixer.init() 135 | pygame.mixer.music.load(os.path.join(ROOTDIR, "resources/audios/bg.mp3")) 136 | pygame.mixer.music.set_volume(0.6) 137 | pygame.mixer.music.play(-1) 138 | # 加载音效 139 | sounds = {} 140 | sounds['mismatch'] = pygame.mixer.Sound(os.path.join(ROOTDIR, 'resources/audios/badswap.wav')) 141 | sounds['match'] = [] 142 | for i in range(6): 143 | sounds['match'].append(pygame.mixer.Sound(os.path.join(ROOTDIR, 'resources/audios/match%s.wav' % i))) 144 | ``` 145 | + 加载字体资源: 146 | ``` 147 | font = pygame.font.Font(os.path.join(ROOTDIR, 'resources/font.TTF'), 25) 148 | ``` 149 | + 加载图片资源: 150 | ``` 151 | gem_imgs = [] 152 | for i in range(1, 8): 153 | gem_imgs.append(os.path.join(ROOTDIR, 'resources/images/gem%s.png' % i)) 154 | ``` 155 | + 游戏主循环: 156 | ``` 157 | game = gemGame(screen, sounds, font, gem_imgs) 158 | while True: 159 | score = game.start() 160 | flag = False 161 | # 一轮游戏结束后玩家选择重玩或者退出 162 | while True: 163 | for event in pygame.event.get(): 164 | if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE): 165 | pygame.quit() 166 | sys.exit() 167 | elif event.type == pygame.KEYUP and event.key == pygame.K_r: 168 | flag = True 169 | if flag: 170 | break 171 | screen.fill((135, 206, 235)) 172 | text0 = 'Final score: %s' % score 173 | text1 = 'Press to restart the game.' 174 | text2 = 'Press to quit the game.' 175 | y = 150 176 | for idx, text in enumerate([text0, text1, text2]): 177 | text_render = font.render(text, 1, (85, 65, 0)) 178 | rect = text_render.get_rect() 179 | if idx == 0: 180 | rect.left, rect.top = (212, y) 181 | elif idx == 1: 182 | rect.left, rect.top = (122.5, y) 183 | else: 184 | rect.left, rect.top = (126.5, y) 185 | y += 100 186 | screen.blit(text_render, rect) 187 | pygame.display.update() 188 | game.reset() 189 | ``` 190 | 191 | + 主程序: 192 | ``` 193 | if __name__ == '__main__': 194 | main() 195 | ``` 196 | ### 运行结果图 197 | + 初始化界面 198 | 199 | ![1](/1.jpg) 200 | 201 | + 消除几个后的界面 202 | 203 | ![2](/2.jpg) 204 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import random 4 | import pygame 5 | from config import * 6 | 7 | 8 | '''拼图精灵类''' 9 | class gemSprite(pygame.sprite.Sprite): 10 | def __init__(self, img_path, size, position, downlen, **kwargs): 11 | pygame.sprite.Sprite.__init__(self) 12 | self.image = pygame.image.load(img_path) 13 | self.image = pygame.transform.smoothscale(self.image, size) 14 | self.rect = self.image.get_rect() 15 | self.rect.left, self.rect.top = position 16 | self.downlen = downlen 17 | self.target_x = position[0] 18 | self.target_y = position[1] + downlen 19 | self.type = img_path.split('/')[-1].split('.')[0] 20 | self.fixed = False 21 | self.speed_x = 10 22 | self.speed_y = 10 23 | self.direction = 'down' 24 | '''拼图块移动''' 25 | def move(self): 26 | if self.direction == 'down': 27 | self.rect.top = min(self.target_y, self.rect.top+self.speed_y) 28 | if self.target_y == self.rect.top: 29 | self.fixed = True 30 | elif self.direction == 'up': 31 | self.rect.top = max(self.target_y, self.rect.top-self.speed_y) 32 | if self.target_y == self.rect.top: 33 | self.fixed = True 34 | elif self.direction == 'left': 35 | self.rect.left = max(self.target_x, self.rect.left-self.speed_x) 36 | if self.target_x == self.rect.left: 37 | self.fixed = True 38 | elif self.direction == 'right': 39 | self.rect.left = min(self.target_x, self.rect.left+self.speed_x) 40 | if self.target_x == self.rect.left: 41 | self.fixed = True 42 | '''获取坐标''' 43 | def getPosition(self): 44 | return self.rect.left, self.rect.top 45 | '''设置坐标''' 46 | def setPosition(self, position): 47 | self.rect.left, self.rect.top = position 48 | 49 | 50 | '''游戏类''' 51 | class gemGame(): 52 | def __init__(self, screen, sounds, font, gem_imgs, **kwargs): 53 | self.info = 'Gemgem-微信公众号:Charles的皮卡丘' 54 | self.screen = screen 55 | self.sounds = sounds 56 | self.font = font 57 | self.gem_imgs = gem_imgs 58 | self.reset() 59 | '''开始游戏''' 60 | def start(self): 61 | clock = pygame.time.Clock() 62 | # 遍历整个游戏界面更新位置 63 | overall_moving = True 64 | # 指定某些对象个体更新位置 65 | individual_moving = False 66 | # 定义一些必要的变量 67 | gem_selected_xy = None 68 | gem_selected_xy2 = None 69 | swap_again = False 70 | add_score = 0 71 | add_score_showtimes = 10 72 | time_pre = int(time.time()) 73 | # 游戏主循环 74 | while True: 75 | for event in pygame.event.get(): 76 | if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE): 77 | pygame.quit() 78 | sys.exit() 79 | elif event.type == pygame.MOUSEBUTTONUP: 80 | if (not overall_moving) and (not individual_moving) and (not add_score): 81 | position = pygame.mouse.get_pos() 82 | if gem_selected_xy is None: 83 | gem_selected_xy = self.checkSelected(position) 84 | else: 85 | gem_selected_xy2 = self.checkSelected(position) 86 | if gem_selected_xy2: 87 | if self.swapGem(gem_selected_xy, gem_selected_xy2): 88 | individual_moving = True 89 | swap_again = False 90 | else: 91 | gem_selected_xy = None 92 | if overall_moving: 93 | overall_moving = not self.dropGems(0, 0) 94 | # 移动一次可能可以拼出多个3连块 95 | if not overall_moving: 96 | res_match = self.isMatch() 97 | add_score = self.removeMatched(res_match) 98 | if add_score > 0: 99 | overall_moving = True 100 | if individual_moving: 101 | gem1 = self.getGemByPos(*gem_selected_xy) 102 | gem2 = self.getGemByPos(*gem_selected_xy2) 103 | gem1.move() 104 | gem2.move() 105 | if gem1.fixed and gem2.fixed: 106 | res_match = self.isMatch() 107 | if res_match[0] == 0 and not swap_again: 108 | swap_again = True 109 | self.swapGem(gem_selected_xy, gem_selected_xy2) 110 | self.sounds['mismatch'].play() 111 | else: 112 | add_score = self.removeMatched(res_match) 113 | overall_moving = True 114 | individual_moving = False 115 | gem_selected_xy = None 116 | gem_selected_xy2 = None 117 | self.screen.fill((135, 206, 235)) 118 | self.drawGrids() 119 | self.gems_group.draw(self.screen) 120 | if gem_selected_xy: 121 | self.drawBlock(self.getGemByPos(*gem_selected_xy).rect) 122 | if add_score: 123 | if add_score_showtimes == 10: 124 | random.choice(self.sounds['match']).play() 125 | self.drawAddScore(add_score) 126 | add_score_showtimes -= 1 127 | if add_score_showtimes < 1: 128 | add_score_showtimes = 10 129 | add_score = 0 130 | self.remaining_time -= (int(time.time()) - time_pre) 131 | time_pre = int(time.time()) 132 | self.showRemainingTime() 133 | self.drawScore() 134 | if self.remaining_time <= 0: 135 | return self.score 136 | pygame.display.update() 137 | clock.tick(FPS) 138 | '''初始化''' 139 | def reset(self): 140 | # 随机生成各个块(即初始化游戏地图各个元素) 141 | while True: 142 | self.all_gems = [] 143 | self.gems_group = pygame.sprite.Group() 144 | for x in range(NUMGRID): 145 | self.all_gems.append([]) 146 | for y in range(NUMGRID): 147 | gem = gemSprite(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+x*GRIDSIZE, YMARGIN+y*GRIDSIZE-NUMGRID*GRIDSIZE], downlen=NUMGRID*GRIDSIZE) 148 | self.all_gems[x].append(gem) 149 | self.gems_group.add(gem) 150 | if self.isMatch()[0] == 0: 151 | break 152 | # 得分 153 | self.score = 0 154 | # 拼出一个的奖励 155 | self.reward = 10 156 | # 时间 157 | self.remaining_time = 300 158 | '''显示剩余时间''' 159 | def showRemainingTime(self): 160 | remaining_time_render = self.font.render('CountDown: %ss' % str(self.remaining_time), 1, (85, 65, 0)) 161 | rect = remaining_time_render.get_rect() 162 | rect.left, rect.top = (WIDTH-201, 6) 163 | self.screen.blit(remaining_time_render, rect) 164 | '''显示得分''' 165 | def drawScore(self): 166 | score_render = self.font.render('SCORE:'+str(self.score), 1, (85, 65, 0)) 167 | rect = score_render.get_rect() 168 | rect.left, rect.top = (10, 6) 169 | self.screen.blit(score_render, rect) 170 | '''显示加分''' 171 | def drawAddScore(self, add_score): 172 | score_render = self.font.render('+'+str(add_score), 1, (255, 100, 100)) 173 | rect = score_render.get_rect() 174 | rect.left, rect.top = (250, 250) 175 | self.screen.blit(score_render, rect) 176 | '''生成新的拼图块''' 177 | def generateNewGems(self, res_match): 178 | if res_match[0] == 1: 179 | start = res_match[2] 180 | while start > -2: 181 | for each in [res_match[1], res_match[1]+1, res_match[1]+2]: 182 | gem = self.getGemByPos(*[each, start]) 183 | if start == res_match[2]: 184 | self.gems_group.remove(gem) 185 | self.all_gems[each][start] = None 186 | elif start >= 0: 187 | gem.target_y += GRIDSIZE 188 | gem.fixed = False 189 | gem.direction = 'down' 190 | self.all_gems[each][start+1] = gem 191 | else: 192 | gem = gemSprite(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+each*GRIDSIZE, YMARGIN-GRIDSIZE], downlen=GRIDSIZE) 193 | self.gems_group.add(gem) 194 | self.all_gems[each][start+1] = gem 195 | start -= 1 196 | elif res_match[0] == 2: 197 | start = res_match[2] 198 | while start > -4: 199 | if start == res_match[2]: 200 | for each in range(0, 3): 201 | gem = self.getGemByPos(*[res_match[1], start+each]) 202 | self.gems_group.remove(gem) 203 | self.all_gems[res_match[1]][start+each] = None 204 | elif start >= 0: 205 | gem = self.getGemByPos(*[res_match[1], start]) 206 | gem.target_y += GRIDSIZE * 3 207 | gem.fixed = False 208 | gem.direction = 'down' 209 | self.all_gems[res_match[1]][start+3] = gem 210 | else: 211 | gem = gemSprite(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+res_match[1]*GRIDSIZE, YMARGIN+start*GRIDSIZE], downlen=GRIDSIZE*3) 212 | self.gems_group.add(gem) 213 | self.all_gems[res_match[1]][start+3] = gem 214 | start -= 1 215 | '''移除匹配的gem''' 216 | def removeMatched(self, res_match): 217 | if res_match[0] > 0: 218 | self.generateNewGems(res_match) 219 | self.score += self.reward 220 | return self.reward 221 | return 0 222 | '''游戏界面的网格绘制''' 223 | def drawGrids(self): 224 | for x in range(NUMGRID): 225 | for y in range(NUMGRID): 226 | rect = pygame.Rect((XMARGIN+x*GRIDSIZE, YMARGIN+y*GRIDSIZE, GRIDSIZE, GRIDSIZE)) 227 | self.drawBlock(rect, color=(0, 0, 255), size=1) 228 | '''画矩形block框''' 229 | def drawBlock(self, block, color=(255, 0, 255), size=4): 230 | pygame.draw.rect(self.screen, color, block, size) 231 | '''下落特效''' 232 | def dropGems(self, x, y): 233 | if not self.getGemByPos(x, y).fixed: 234 | self.getGemByPos(x, y).move() 235 | if x < NUMGRID-1: 236 | x += 1 237 | return self.dropGems(x, y) 238 | elif y < NUMGRID-1: 239 | x = 0 240 | y += 1 241 | return self.dropGems(x, y) 242 | else: 243 | return self.isFull() 244 | '''是否每个位置都有拼图块了''' 245 | def isFull(self): 246 | for x in range(NUMGRID): 247 | for y in range(NUMGRID): 248 | if not self.getGemByPos(x, y).fixed: 249 | return False 250 | return True 251 | '''检查有无拼图块被选中''' 252 | def checkSelected(self, position): 253 | for x in range(NUMGRID): 254 | for y in range(NUMGRID): 255 | if self.getGemByPos(x, y).rect.collidepoint(*position): 256 | return [x, y] 257 | return None 258 | '''是否有连续一样的三个块(无--返回0/水平--返回1/竖直--返回2)''' 259 | def isMatch(self): 260 | for x in range(NUMGRID): 261 | for y in range(NUMGRID): 262 | if x + 2 < NUMGRID: 263 | if self.getGemByPos(x, y).type == self.getGemByPos(x+1, y).type == self.getGemByPos(x+2, y).type: 264 | return [1, x, y] 265 | if y + 2 < NUMGRID: 266 | if self.getGemByPos(x, y).type == self.getGemByPos(x, y+1).type == self.getGemByPos(x, y+2).type: 267 | return [2, x, y] 268 | return [0, x, y] 269 | '''根据坐标获取对应位置的拼图对象''' 270 | def getGemByPos(self, x, y): 271 | return self.all_gems[x][y] 272 | '''交换拼图''' 273 | def swapGem(self, gem1_pos, gem2_pos): 274 | margin = gem1_pos[0] - gem2_pos[0] + gem1_pos[1] - gem2_pos[1] 275 | if abs(margin) != 1: 276 | return False 277 | gem1 = self.getGemByPos(*gem1_pos) 278 | gem2 = self.getGemByPos(*gem2_pos) 279 | if gem1_pos[0] - gem2_pos[0] == 1: 280 | gem1.direction = 'left' 281 | gem2.direction = 'right' 282 | elif gem1_pos[0] - gem2_pos[0] == -1: 283 | gem2.direction = 'left' 284 | gem1.direction = 'right' 285 | elif gem1_pos[1] - gem2_pos[1] == 1: 286 | gem1.direction = 'up' 287 | gem2.direction = 'down' 288 | elif gem1_pos[1] - gem2_pos[1] == -1: 289 | gem2.direction = 'up' 290 | gem1.direction = 'down' 291 | gem1.target_x = gem2.rect.left 292 | gem1.target_y = gem2.rect.top 293 | gem1.fixed = False 294 | gem2.target_x = gem1.rect.left 295 | gem2.target_y = gem1.rect.top 296 | gem2.fixed = False 297 | self.all_gems[gem2_pos[0]][gem2_pos[1]] = gem1 298 | self.all_gems[gem1_pos[0]][gem1_pos[1]] = gem2 299 | return True 300 | '''info''' 301 | def __repr__(self): 302 | return self.info --------------------------------------------------------------------------------