用Python寫個開心消消樂小遊戲
阿新 • • 發佈:2020-12-15
本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯絡我們以作處理
提到開心消消樂這款小遊戲,相信大家都不陌生,其曾在 2015 年獲得過玩家最喜愛的移動單機遊戲獎,受歡迎程度可見一斑,本文我們使用 Python 來做個簡單的消消樂小遊戲。
實現
消消樂的構成主要包括三部分:遊戲主體、計分器、計時器,下面來看一下具體實現。
先來看一下游戲所需 Python 庫。
import os import sys import time import pygame import random
定義一些常量,比如:視窗寬高、網格行列數等,程式碼如下:
WIDTH = 400 HEIGHT = 400 NUMGRID = 8 GRIDSIZE = 36 XMARGIN = (WIDTH - GRIDSIZE * NUMGRID) // 2 YMARGIN = (HEIGHT - GRIDSIZE * NUMGRID) // 2 ROOTDIR = os.getcwd() FPS = 30
接著建立一個主視窗,程式碼如下:
pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('消消樂')
看一下效果:
再接著在視窗中畫一個 8 x 8 的網格,程式碼如下:
screen.fill((255, 255, 220)) # 遊戲介面的網格繪製 def drawGrids(self): for x in range(NUMGRID): for y in range(NUMGRID): rect = pygame.Rect((XMARGIN+x*GRIDSIZE, YMARGIN+y*GRIDSIZE, GRIDSIZE, GRIDSIZE)) self.drawBlock(rect, color=(255, 165, 0), size=1 # 畫矩形 block 框 def drawBlock(self, block, color=(255, 0, 0), size=2): pygame.draw.rect(self.screen, color, block, size)
看一下效果:
再接著在網格中隨機放入各種拼圖塊,程式碼如下:
while True: self.all_gems = [] self.gems_group = pygame.sprite.Group() for x in range(NUMGRID): self.all_gems.append([]) for y in range(NUMGRID): gem = Puzzle(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+x*GRIDSIZE, YMARGIN+y*GRIDSIZE-NUMGRID*GRIDSIZE], downlen=NUMGRID*GRIDSIZE) self.all_gems[x].append(gem) self.gems_group.add(gem) if self.isMatch()[0] == 0: break
看一下效果:
再接著加入計分器和計時器,程式碼如下:
# 顯示得分 def drawScore(self): score_render = self.font.render('分數:'+str(self.score), 1, (85, 65, 0)) rect = score_render.get_rect() rect.left, rect.top = (55, 15) self.screen.blit(score_render, rect) # 顯示加分 def drawAddScore(self, add_score): score_render = self.font.render('+'+str(add_score), 1, (255, 100, 100)) rect = score_render.get_rect() rect.left, rect.top = (250, 250) self.screen.blit(score_render, rect) # 顯示剩餘時間 def showRemainingTime(self): remaining_time_render = self.font.render('倒計時: %ss' % str(self.remaining_time), 1, (85, 65, 0)) rect = remaining_time_render.get_rect() rect.left, rect.top = (WIDTH-190, 15) self.screen.blit(remaining_time_render, rect)
看一下效果:
當設定的遊戲時間用盡時,我們可以生成一些提示資訊,程式碼如下:
while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYUP and event.key == pygame.K_r: flag = True if flag: break screen.fill((255, 255, 220)) text0 = '最終得分: %s' % score text1 = '按 R 鍵重新開始' y = 140 for idx, text in enumerate([text0, text1]): text_render = font.render(text, 1, (85, 65, 0)) rect = text_render.get_rect() if idx == 0: rect.left, rect.top = (100, y) elif idx == 1: rect.left, rect.top = (100, y) y += 60 screen.blit(text_render, rect) pygame.display.update()
看一下效果:
說完了遊戲圖形化介面相關的部分,我們再看一下游戲的主要處理邏輯。
我們通過滑鼠來操縱拼圖塊,因此程式需要檢查有無拼圖塊被選中,程式碼實現如下:
def checkSelected(self, position): for x in range(NUMGRID): for y in range(NUMGRID): if self.getGemByPos(x, y).rect.collidepoint(*position): return [x, y] return None
我們需要將滑鼠連續選擇的拼圖塊進行位置交換,程式碼實現如下:
def swapGem(self, gem1_pos, gem2_pos): margin = gem1_pos[0] - gem2_pos[0] + gem1_pos[1] - gem2_pos[1] if abs(margin) != 1: return False gem1 = self.getGemByPos(*gem1_pos) gem2 = self.getGemByPos(*gem2_pos) if gem1_pos[0] - gem2_pos[0] == 1: gem1.direction = 'left' gem2.direction = 'right' elif gem1_pos[0] - gem2_pos[0] == -1: gem2.direction = 'left' gem1.direction = 'right' elif gem1_pos[1] - gem2_pos[1] == 1: gem1.direction = 'up' gem2.direction = 'down' elif gem1_pos[1] - gem2_pos[1] == -1: gem2.direction = 'up' gem1.direction = 'down' gem1.target_x = gem2.rect.left gem1.target_y = gem2.rect.top gem1.fixed = False gem2.target_x = gem1.rect.left gem2.target_y = gem1.rect.top gem2.fixed = False self.all_gems[gem2_pos[0]][gem2_pos[1]] = gem1 self.all_gems[gem1_pos[0]][gem1_pos[1]] = gem2 return True
每一次交換拼圖塊時,我們需要判斷是否有連續一樣的三個及以上拼圖塊,程式碼實現如下:
def isMatch(self): for x in range(NUMGRID): for y in range(NUMGRID): if x + 2 < NUMGRID: if self.getGemByPos(x, y).type == self.getGemByPos(x+1, y).type == self.getGemByPos(x+2, y).type: return [1, x, y] if y + 2 < NUMGRID: if self.getGemByPos(x, y).type == self.getGemByPos(x, y+1).type == self.getGemByPos(x, y+2).type: return [2, x, y] return [0, x, y]
當出現三個及以上拼圖塊時,需要將這些拼圖塊消除,程式碼實現如下:
def removeMatched(self, res_match): if res_match[0] > 0: self.generateNewGems(res_match) self.score += self.reward return self.reward return 0
將匹配的拼圖塊消除之後,我們還需要隨機生成新的拼圖塊,程式碼實現如下:
def generateNewGems(self, res_match): if res_match[0] == 1: start = res_match[2] while start > -2: for each in [res_match[1], res_match[1]+1, res_match[1]+2]: gem = self.getGemByPos(*[each, start]) if start == res_match[2]: self.gems_group.remove(gem) self.all_gems[each][start] = None elif start >= 0: gem.target_y += GRIDSIZE gem.fixed = False gem.direction = 'down' self.all_gems[each][start+1] = gem else: gem = Puzzle(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+each*GRIDSIZE, YMARGIN-GRIDSIZE], downlen=GRIDSIZE) self.gems_group.add(gem) self.all_gems[each][start+1] = gem start -= 1 elif res_match[0] == 2: start = res_match[2] while start > -4: if start == res_match[2]: for each in range(0, 3): gem = self.getGemByPos(*[res_match[1], start+each]) self.gems_group.remove(gem) self.all_gems[res_match[1]][start+each] = None elif start >= 0: gem = self.getGemByPos(*[res_match[1], start]) gem.target_y += GRIDSIZE * 3 gem.fixed = False gem.direction = 'down' self.all_gems[res_match[1]][start+3] = gem else: gem = Puzzle(img_path=random.choice(self.gem_imgs), size=(GRIDSIZE, GRIDSIZE), position=[XMARGIN+res_match[1]*GRIDSIZE, YMARGIN+start*GRIDSIZE], downlen=GRIDSIZE*3) self.gems_group.add(gem) self.all_gems[res_match[1]][start+3] = gem start -= 1
之後反覆執行這個過程,直至耗盡遊戲時間,遊戲結束。
最後,我們動態看一下游戲效果。
總結
本文我們使用 Python 實現了一個簡單的消消樂遊戲,有興趣的可以對遊戲做進一步擴充套件,比如增加關卡等。
想要獲取更多Python學習資料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起來學習討論吧!