pygame實現(xiàn)一個類似滿天星游戲流程詳解
編寫類滿天星游戲,目前自己設(shè)定需要用到的算法內(nèi)容,包括第一點點擊某一個圖標(biāo)后,自動檢查圖標(biāo)上下左右是有與之相同的圖形,如果包括自身在內(nèi)有三個以上的圖形,則可以消除。第二,當(dāng)界面中有圖形消除后,那么需要根據(jù)列來下移圖標(biāo),同時產(chǎn)生新的圖標(biāo)。第三,自動檢查界面中是否還有能夠匹配的圖案,如果沒有,那么重新生成游戲。第四,游戲機制設(shè)定為倒計時,在倒計時完成前,盡可能多消除,多得分。并且考慮每次消除4個以上,按比例增加時間。
首先完成最簡單的部分,配置pygame的基本參數(shù),并且繪制游戲界面,也就是畫橫縱線。
考慮把游戲界面畫成一個10*10的方格,并且在上方留出空位顯示等分等信息,具體還需不需要別的,待定…
直接使用之前貪食蛇的畫格子和初始化的代碼,先略作修改。
import random import time import pygame # 30幀 fps = 30 fps_clock = pygame.time.Clock() screen_width = 1024 screen_height = 768 # 分辨率,標(biāo)題 display = pygame.display.set_mode((screen_width, screen_height), 0, 32) pygame.display.set_caption('好似滿天星') tile_size = 60 tile_width = 60 tile_height = 60 x_margin = 400 y_margin = 100 # 列 columns = 10 # 行 rows = 11 # 配色RGB white = (255, 255, 255) black = 'black' bg_color = 'sky blue' border_color = white body_color = 'purple' inter_body_color = 'green' line_color = white directions = ['up', 'down', 'left', 'right'] text_color = (144, 59, 28) my_score = 0 snake = [] # 畫格子 def draw_chest(): for i in range(rows + 1): pygame.draw.line(display, border_color, (x_margin/2, y_margin/2 + i * tile_size), (x_margin/2 + (columns * tile_size), y_margin/2 + i * tile_size), 2) for j in range(columns + 1): pygame.draw.line(display, border_color, (x_margin/2 + j * tile_size, y_margin/2), (x_margin/2 + j * tile_size, y_margin/2 + (rows * tile_size)), 2) if __name__ == '__main__': pygame.init() bad_touch = pygame.mixer.Sound('badswap.wav') match_three = pygame.mixer.Sound('match3.wav') match_more_than_three = pygame.mixer.Sound('match4.wav') display.fill(bg_color) while True: draw_chest() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() pygame.display.update() fps_clock.tick(fps)
目前不知道后續(xù)還有些什么需求,所以簡單修改一下,后期有需要再來修改代碼。
運行結(jié)果如下:
有一個大體的框架了,接下來就是把星星放到游戲界面當(dāng)中來了。嗯,因為我們有星星,所以我找了免費的餅干來代替星星。這些餅干也是五子連珠的棋子??。
一共有七種餅干,考慮到游戲的難度,我們一開始只使用其中的四種。
把之前snake = []刪除,新創(chuàng)建一個列表,用來存放"星星"
stars = [‘Cookie’, ‘Croissant’, ‘Cupcake’, ‘Danish’]
在方框內(nèi)放滿“星星”。
生成一個二維列表,列表中隨機放入“星星”
def make_stars(): board = [] for i in range(rows): temp = [] for j in range(columns): star = random.choice(stars) temp.append(star) board.append(temp) return board
還需要繪制星星的函數(shù),在繪制星星之前呢,需要確定星星的位置,同時還是按照下標(biāo)來計算游戲界面橫縱坐標(biāo),那么:
def get_left_top_location(x, y): left_position = y * tile_size + x_margin/2 top_position = x * tile_size + y_margin/2 return left_position, top_position def draw_stars(board): for i in range(len(board)): for j in range(len(board[i])): path = 'gems/' + board[i][j] + '.png' star = pygame.image.load(path) star = pygame.transform.scale(star, (tile_size-5, tile_size-5)) left, top = get_left_top_location(i, j) # 微調(diào)一下,這樣圖片比較居中,誰讓釘在左上角呢 display.blit(star, (left+3, top+3))
在主程序中增加繪制星星代碼
if __name__ == '__main__': pygame.init() bad_touch = pygame.mixer.Sound('badswap.wav') match_three = pygame.mixer.Sound('match3.wav') match_more_than_three = pygame.mixer.Sound('match4.wav') display.fill(bg_color) main_board = make_stars() print(main_board) while True: draw_chest() draw_stars(main_board) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() pygame.display.update() fps_clock.tick(fps)
運行程序
感覺“星星”太少了,所以還是再加點吧。
stars = [‘Cookie’, ‘Croissant’, ‘Cupcake’, ‘Danish’, ‘Donut’, ‘Ginger’, ‘Macaroon’]
感覺好多了。接下來開始消除吧。
消除部分,比較簡單,需要編寫的內(nèi)容主要是當(dāng)鼠標(biāo)點擊時,我們需要知道是哪個位置的哪個“星星”被點擊了,也就是說我們需要定位到main_board的具體下標(biāo)是多少。是[0][0],[1][2],或者是別的。然后我們確定位置和“星星后”,找到該位置“星星”的上下左右,看能否找到相同的“星星”,如果有且數(shù)量大于或者等于3,那么可以實現(xiàn)消除。同時為了以后動畫效果,我準(zhǔn)備使用一個列表中帶字典變量的方式來存儲這些相同的“星星”的位置和種類信息。
先完成第一步,對應(yīng)二維列表下標(biāo)。
# 將游戲中的界面坐標(biāo)轉(zhuǎn)換為main_board中的位置 def get_spot_clicked(board, x, y): for i in range(len(board)): for j in range(len(board[i])): # 注意在二維數(shù)組里我們的查詢順序是比如maze[3][5]代表第四行第六列,但是對應(yīng)游戲界面的坐標(biāo)則3用來計算y坐標(biāo),5用來計算x坐標(biāo) left, top = get_left_top_location(i, j) tile_rect = pygame.Rect(left, top, tile_width, tile_height) if tile_rect.collidepoint(x, y): return i, j return None, None
然后在主循環(huán)中加入鼠標(biāo)響應(yīng)代碼。根據(jù)鼠標(biāo)點擊位置,打印出二維列表下標(biāo),看看效果。
if event.type == pygame.QUIT: pygame.quit() elif event.type == pygame.MOUSEBUTTONUP: # 鼠標(biāo)左鍵點擊后抬起 if event.button == 1: pos_x, pos_y = event.pos print(get_spot_clicked(main_board, pos_x, pos_y))
實際測試,鼠標(biāo)點擊位置和二維列表下標(biāo)匹配。
接下來則需要開始尋找點擊位置四個方向上是否有相同"星星"。
# 查找"星星"的相同情況 def check_around(board, star_pos): store_stars = set() has_three_stars = False shape_type = board[star_pos[0]][star_pos[1]] # 查找上下兩個方向是否有與當(dāng)前棋子類型一樣的棋子 store_stars.add(star_pos) # 向上的方向上尋找 star_i = star_pos[0] - 1 up_and_down_star = set() while star_i >= 0 and board[star_i][star_pos[1]] == shape_type: store_stars.add((star_i, star_pos[1])) star_i -= 1 # 向下的方向?qū)ふ? star_i = star_pos[0] + 1 while star_i < rows and board[star_i][star_pos[1]] == shape_type: store_stars.add((star_i, star_pos[1])) star_i += 1 # 向左的方向上尋找 star_j = star_pos[1] - 1 while star_j >= 0 and board[star_pos[0]][star_j] == shape_type: store_stars.add((star_pos[0], star_j)) star_j -= 1 # 向右的方向?qū)ふ? star_j = star_pos[1] + 1 while star_j < columns and board[star_pos[0]][star_j] == shape_type: store_stars.add((star_pos[0], star_j)) star_j += 1 if len(store_stars) >= 3: has_three_stars = True return store_stars, has_three_stars
該函數(shù)返回所有需要消除的點的二維列表下標(biāo)。再編寫一個函數(shù)用于清除對坐標(biāo)的二維列表中的內(nèi)容。把需要清除的位置設(shè)定為empty。然后在主循環(huán)中調(diào)用。
def remove_stars(board, removed_stars): for star in removed_stars: board[star[0]][star[1]] = 'empty'
if event.button == 1: pos_x, pos_y = event.pos x, y = get_spot_clicked(main_board, pos_x, pos_y) need_to_removed, remove_or_not = check_around(main_board, (x, y)) if remove_or_not: remove_stars(main_board, need_to_removed) display.fill(bg_color) draw_chest() draw_stars(main_board)
運行程序。
程序報錯了,因為繪制“星星”的函數(shù)并沒有考慮到二維列表的內(nèi)容為empty的情況,所以需要修改這個函數(shù)內(nèi)容。
def draw_stars(board): for i in range(len(board)): for j in range(len(board[i])): if board[i][j] != 'empty': path = 'gems/' + board[i][j] + '.png' star = pygame.image.load(path) star = pygame.transform.scale(star, (tile_size-5, tile_size-5)) left, top = get_left_top_location(i, j) display.blit(star, (left+3, top+3))
運行程序
確實能消除了,但是出現(xiàn)了一個意外情況,比如上圖[4][3]這個位置的甜甜圈有三個相同的圖形,我所編寫的算法里,只是檢查了點擊處的上下左右,那么如果我點擊[4][3]這個位置,[4][2],[4][3],[5][3]的內(nèi)容都會消失,這個沒問題,但是如果我點擊的是[5][3],那么根據(jù)算法,該位置上有左右僅有一個相同的,所以不會發(fā)生消除情況。這貌似與滿天星游戲方式不同,所以,我們需要修改消除算法。算法應(yīng)該修改為從一個位置出發(fā),尋找上下左右相同的圖標(biāo),如果找到,再以該位置作為中心,繼續(xù)尋找上下左右是否有相同點,直到?jīng)]有為止??梢钥紤]使用回溯+棧的方式來修改算法。
# 查找"星星"的相同情況 def check_around(board, star_pos): stars_temp = [] store_stars = set() has_three_stars = False shape_type = board[star_pos[0]][star_pos[1]] # 查找上下兩個方向是否有與當(dāng)前棋子類型一樣的棋子 store_stars.add(star_pos) stars_temp.append(star_pos) while len(stars_temp): current_star = stars_temp[0] del stars_temp[0] # 向上的方向上尋找 star_i = current_star[0] - 1 while star_i >= 0 and board[star_i][current_star[1]] == shape_type: if (star_i, current_star[1]) not in store_stars: store_stars.add((star_i, current_star[1])) stars_temp.append((star_i, current_star[1])) star_i -= 1 # 向下的方向?qū)ふ? star_i = current_star[0] + 1 while star_i < rows and board[star_i][current_star[1]] == shape_type: if (star_i, current_star[1]) not in store_stars: store_stars.add((star_i, current_star[1])) stars_temp.append((star_i, current_star[1])) star_i += 1 # 向左的方向上尋找 star_j = current_star[1] - 1 while star_j >= 0 and board[current_star[0]][star_j] == shape_type: if (current_star[0], star_j) not in store_stars: store_stars.add((current_star[0], star_j)) stars_temp.append((current_star[0], star_j)) star_j -= 1 # 向右的方向?qū)ふ? star_j = current_star[1] + 1 while star_j < columns and board[current_star[0]][star_j] == shape_type: if (current_star[0], star_j) not in store_stars: store_stars.add((current_star[0], star_j)) stars_temp.append((current_star[0], star_j)) star_j += 1 if len(store_stars) >= 2: has_three_stars = True #print('stars: ', store_stars) #input() return store_stars, has_three_stars
修改以后,從任意點擊位置開始,都可以發(fā)現(xiàn)所有相同“星星了”
馬上開始比較麻煩的地方了,動畫下移。
關(guān)于動畫下移的思路則是首先,按列尋找需要下移的“星星”,找到以后,無論這個星星(不加引號了,太麻煩),下面有多少空間都只移動一格,找到所有的需要移動的星星,動畫移動一格,然后再尋找可以移動的星星,移動一格,再尋找,直到?jīng)]有可以移動的為止。
到此這篇關(guān)于pygame實現(xiàn)一個類似滿天星游戲流程詳解的文章就介紹到這了,更多相關(guān)pygame滿天星游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Pygame改編飛機大戰(zhàn)制作兔子接月餅游戲
- Python+Pygame實現(xiàn)海洋之神大冒險游戲
- Python pygame 動畫游戲循環(huán)游戲時鐘實現(xiàn)原理
- Python+Pygame實戰(zhàn)之實現(xiàn)小蜜蜂歷險記游戲
- Python+Pygame實戰(zhàn)之英文版猜字游戲的實現(xiàn)
- Pygame游戲開發(fā)之太空射擊實戰(zhàn)盾牌篇
- Pygame游戲開發(fā)之太空射擊實戰(zhàn)碰撞改進(jìn)篇
- Pygame游戲開發(fā)之太空射擊實戰(zhàn)添加圖形篇
- Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇
相關(guān)文章
Python中定時器用法詳解之Timer定時器和schedule庫
目前所在的項目組需要經(jīng)常執(zhí)行一些定時任務(wù),于是選擇使用 Python 的定時器,下面這篇文章主要給大家介紹了關(guān)于Python中定時器用法詳解之Timer定時器和schedule庫的相關(guān)資料,需要的朋友可以參考下2024-02-02Python開發(fā)之迭代器&生成器的實戰(zhàn)案例分享
在 Python 中,迭代器和生成器都是用來遍歷數(shù)據(jù)集合的工具,可以按需逐個生成或返回數(shù)據(jù),從而避免一次性加載整個數(shù)據(jù)集合所帶來的性能問題和內(nèi)存消耗問題。本文主要和大家分享幾個貼近實際運維開發(fā)工作中的場景案例,希望對大家有所幫助2023-04-04Python練習(xí)之操作SQLite數(shù)據(jù)庫
這篇文章主要介紹了Python練習(xí)之操作SQLite數(shù)據(jù)庫,主要通過三個問題如何創(chuàng)建SQLite數(shù)據(jù)庫?如何向SQLite表中插入數(shù)據(jù)?如何查詢SQLite表中的數(shù)據(jù)?展開文章主題詳情,需要的朋友可以參考一下2022-06-06