pygame實(shí)現(xiàn)一個(gè)類似滿天星游戲流程詳解
編寫(xiě)類滿天星游戲,目前自己設(shè)定需要用到的算法內(nèi)容,包括第一點(diǎn)點(diǎn)擊某一個(gè)圖標(biāo)后,自動(dòng)檢查圖標(biāo)上下左右是有與之相同的圖形,如果包括自身在內(nèi)有三個(gè)以上的圖形,則可以消除。第二,當(dāng)界面中有圖形消除后,那么需要根據(jù)列來(lái)下移圖標(biāo),同時(shí)產(chǎn)生新的圖標(biāo)。第三,自動(dòng)檢查界面中是否還有能夠匹配的圖案,如果沒(méi)有,那么重新生成游戲。第四,游戲機(jī)制設(shè)定為倒計(jì)時(shí),在倒計(jì)時(shí)完成前,盡可能多消除,多得分。并且考慮每次消除4個(gè)以上,按比例增加時(shí)間。
首先完成最簡(jiǎn)單的部分,配置pygame的基本參數(shù),并且繪制游戲界面,也就是畫(huà)橫縱線。
考慮把游戲界面畫(huà)成一個(gè)10*10的方格,并且在上方留出空位顯示等分等信息,具體還需不需要?jiǎng)e的,待定…
直接使用之前貪食蛇的畫(huà)格子和初始化的代碼,先略作修改。
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 = []
# 畫(huà)格子
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ǎn)單修改一下,后期有需要再來(lái)修改代碼。
運(yùn)行結(jié)果如下:

有一個(gè)大體的框架了,接下來(lái)就是把星星放到游戲界面當(dāng)中來(lái)了。嗯,因?yàn)槲覀冇行切?,所以我找了免費(fèi)的餅干來(lái)代替星星。這些餅干也是五子連珠的棋子??。

一共有七種餅干,考慮到游戲的難度,我們一開(kāi)始只使用其中的四種。
把之前snake = []刪除,新創(chuàng)建一個(gè)列表,用來(lái)存放"星星"
stars = [‘Cookie’, ‘Croissant’, ‘Cupcake’, ‘Danish’]
在方框內(nèi)放滿“星星”。
生成一個(gè)二維列表,列表中隨機(jī)放入“星星”
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ù),在繪制星星之前呢,需要確定星星的位置,同時(shí)還是按照下標(biāo)來(lái)計(jì)算游戲界面橫縱坐標(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)一下,這樣圖片比較居中,誰(shuí)讓釘在左上角呢
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)運(yùn)行程序

感覺(jué)“星星”太少了,所以還是再加點(diǎn)吧。
stars = [‘Cookie’, ‘Croissant’, ‘Cupcake’, ‘Danish’, ‘Donut’, ‘Ginger’, ‘Macaroon’]

感覺(jué)好多了。接下來(lái)開(kāi)始消除吧。
消除部分,比較簡(jiǎn)單,需要編寫(xiě)的內(nèi)容主要是當(dāng)鼠標(biāo)點(diǎn)擊時(shí),我們需要知道是哪個(gè)位置的哪個(gè)“星星”被點(diǎn)擊了,也就是說(shuō)我們需要定位到main_board的具體下標(biāo)是多少。是[0][0],[1][2],或者是別的。然后我們確定位置和“星星后”,找到該位置“星星”的上下左右,看能否找到相同的“星星”,如果有且數(shù)量大于或者等于3,那么可以實(shí)現(xiàn)消除。同時(shí)為了以后動(dòng)畫(huà)效果,我準(zhǔn)備使用一個(gè)列表中帶字典變量的方式來(lái)存儲(chǔ)這些相同的“星星”的位置和種類信息。
先完成第一步,對(duì)應(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]代表第四行第六列,但是對(duì)應(yīng)游戲界面的坐標(biāo)則3用來(lái)計(jì)算y坐標(biāo),5用來(lái)計(jì)算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)點(diǎn)擊位置,打印出二維列表下標(biāo),看看效果。
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.MOUSEBUTTONUP:
# 鼠標(biāo)左鍵點(diǎn)擊后抬起
if event.button == 1:
pos_x, pos_y = event.pos
print(get_spot_clicked(main_board, pos_x, pos_y))
實(shí)際測(cè)試,鼠標(biāo)點(diǎn)擊位置和二維列表下標(biāo)匹配。
接下來(lái)則需要開(kāi)始尋找點(diǎn)擊位置四個(gè)方向上是否有相同"星星"。
# 查找"星星"的相同情況
def check_around(board, star_pos):
store_stars = set()
has_three_stars = False
shape_type = board[star_pos[0]][star_pos[1]]
# 查找上下兩個(gè)方向是否有與當(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ù)返回所有需要消除的點(diǎn)的二維列表下標(biāo)。再編寫(xiě)一個(gè)函數(shù)用于清除對(duì)坐標(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)
運(yùn)行程序。
程序報(bào)錯(cuò)了,因?yàn)槔L制“星星”的函數(shù)并沒(méi)有考慮到二維列表的內(nèi)容為empty的情況,所以需要修改這個(gè)函數(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))
運(yùn)行程序

確實(shí)能消除了,但是出現(xiàn)了一個(gè)意外情況,比如上圖[4][3]這個(gè)位置的甜甜圈有三個(gè)相同的圖形,我所編寫(xiě)的算法里,只是檢查了點(diǎn)擊處的上下左右,那么如果我點(diǎn)擊[4][3]這個(gè)位置,[4][2],[4][3],[5][3]的內(nèi)容都會(huì)消失,這個(gè)沒(méi)問(wèn)題,但是如果我點(diǎn)擊的是[5][3],那么根據(jù)算法,該位置上有左右僅有一個(gè)相同的,所以不會(huì)發(fā)生消除情況。這貌似與滿天星游戲方式不同,所以,我們需要修改消除算法。算法應(yīng)該修改為從一個(gè)位置出發(fā),尋找上下左右相同的圖標(biāo),如果找到,再以該位置作為中心,繼續(xù)尋找上下左右是否有相同點(diǎn),直到?jīng)]有為止??梢钥紤]使用回溯+棧的方式來(lái)修改算法。
# 查找"星星"的相同情況
def check_around(board, star_pos):
stars_temp = []
store_stars = set()
has_three_stars = False
shape_type = board[star_pos[0]][star_pos[1]]
# 查找上下兩個(gè)方向是否有與當(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修改以后,從任意點(diǎn)擊位置開(kāi)始,都可以發(fā)現(xiàn)所有相同“星星了”
馬上開(kāi)始比較麻煩的地方了,動(dòng)畫(huà)下移。
關(guān)于動(dòng)畫(huà)下移的思路則是首先,按列尋找需要下移的“星星”,找到以后,無(wú)論這個(gè)星星(不加引號(hào)了,太麻煩),下面有多少空間都只移動(dòng)一格,找到所有的需要移動(dòng)的星星,動(dòng)畫(huà)移動(dòng)一格,然后再尋找可以移動(dòng)的星星,移動(dòng)一格,再尋找,直到?jīng)]有可以移動(dòng)的為止。
到此這篇關(guān)于pygame實(shí)現(xiàn)一個(gè)類似滿天星游戲流程詳解的文章就介紹到這了,更多相關(guān)pygame滿天星游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Pygame改編飛機(jī)大戰(zhàn)制作兔子接月餅游戲
- Python+Pygame實(shí)現(xiàn)海洋之神大冒險(xiǎn)游戲
- Python pygame 動(dòng)畫(huà)游戲循環(huán)游戲時(shí)鐘實(shí)現(xiàn)原理
- Python+Pygame實(shí)戰(zhàn)之實(shí)現(xiàn)小蜜蜂歷險(xiǎn)記游戲
- Python+Pygame實(shí)戰(zhàn)之英文版猜字游戲的實(shí)現(xiàn)
- Pygame游戲開(kāi)發(fā)之太空射擊實(shí)戰(zhàn)盾牌篇
- Pygame游戲開(kāi)發(fā)之太空射擊實(shí)戰(zhàn)碰撞改進(jìn)篇
- Pygame游戲開(kāi)發(fā)之太空射擊實(shí)戰(zhàn)添加圖形篇
- Pygame游戲開(kāi)發(fā)之太空射擊實(shí)戰(zhàn)子彈與碰撞處理篇
相關(guān)文章
Python中定時(shí)器用法詳解之Timer定時(shí)器和schedule庫(kù)
目前所在的項(xiàng)目組需要經(jīng)常執(zhí)行一些定時(shí)任務(wù),于是選擇使用 Python 的定時(shí)器,下面這篇文章主要給大家介紹了關(guān)于Python中定時(shí)器用法詳解之Timer定時(shí)器和schedule庫(kù)的相關(guān)資料,需要的朋友可以參考下2024-02-02
Python開(kāi)發(fā)之迭代器&生成器的實(shí)戰(zhàn)案例分享
在 Python 中,迭代器和生成器都是用來(lái)遍歷數(shù)據(jù)集合的工具,可以按需逐個(gè)生成或返回?cái)?shù)據(jù),從而避免一次性加載整個(gè)數(shù)據(jù)集合所帶來(lái)的性能問(wèn)題和內(nèi)存消耗問(wèn)題。本文主要和大家分享幾個(gè)貼近實(shí)際運(yùn)維開(kāi)發(fā)工作中的場(chǎng)景案例,希望對(duì)大家有所幫助2023-04-04
python非阻塞式后臺(tái)如何運(yùn)行bat腳本
這篇文章主要介紹了python非阻塞式后臺(tái)如何運(yùn)行bat腳本問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Python xlrd模塊導(dǎo)入過(guò)程及常用操作
這篇文章主要介紹了Python xlrd模塊導(dǎo)入過(guò)程及常用操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
Python練習(xí)之操作SQLite數(shù)據(jù)庫(kù)
這篇文章主要介紹了Python練習(xí)之操作SQLite數(shù)據(jù)庫(kù),主要通過(guò)三個(gè)問(wèn)題如何創(chuàng)建SQLite數(shù)據(jù)庫(kù)?如何向SQLite表中插入數(shù)據(jù)?如何查詢SQLite表中的數(shù)據(jù)?展開(kāi)文章主題詳情,需要的朋友可以參考一下2022-06-06
Python根據(jù)區(qū)號(hào)生成手機(jī)號(hào)碼的方法
這篇文章主要介紹了Python根據(jù)區(qū)號(hào)生成手機(jī)號(hào)碼的方法,涉及Python隨機(jī)數(shù)與字符串的相關(guān)操作技巧,需要的朋友可以參考下2015-07-07

