1 項(xiàng)目簡介
?? Hi,各位同學(xué)好呀,這里是L學(xué)長!
??今天向大家分享一個(gè)今年(2022)最新完成的畢業(yè)設(shè)計(jì)項(xiàng)目作品
python小游戲畢設(shè) 接金幣小游戲設(shè)計(jì)與實(shí)現(xiàn) (源碼)
?? 學(xué)長根據(jù)實(shí)現(xiàn)的難度和等級(jí)對(duì)項(xiàng)目進(jìn)行評(píng)分(最低0分,滿分5分)
-
難度系數(shù):3分
-
工作量:3分
-
創(chuàng)新點(diǎn):3分
1 游戲介紹
基于python實(shí)現(xiàn)的接金幣小游戲。
游戲規(guī)則:
方向鍵控制小人左右移動(dòng)接金幣。
2 實(shí)現(xiàn)效果
3 開發(fā)工具
3.1 環(huán)境配置
-
Python版本:3.6.4
-
相關(guān)模塊:
-
pygame模塊;
-
以及一些Python自帶的模塊。
3.2 Pygame介紹
簡介
Pygame是一系列專門為編寫電子游戲而設(shè)計(jì)的Python模塊(modules)。Pygame在已經(jīng)非常優(yōu)秀的SDL庫的基礎(chǔ)上增加了許多功能。這讓你能夠用Python語言編寫出豐富多彩的游戲程序。
Pygame可移植性高,幾乎能在任何平臺(tái)和操作系統(tǒng)上運(yùn)行。
Pygame已經(jīng)被下載過數(shù)百萬次。
Pygame免費(fèi)開源。它在LGPL許可證(Lesser General Public License,GNU寬通用公共許可證)下發(fā)行。使用Pygame,你可以創(chuàng)造出免費(fèi)開源,可共享,或者商業(yè)化的游戲。詳情請見LGPL許可證。
優(yōu)點(diǎn)
-
能夠輕松使用多核CPU(multi core CPUs) :如今雙核CPU很常用,8核CPU在桌面系統(tǒng)中也很便宜,而利用好多核系統(tǒng),能讓你在你的游戲中實(shí)現(xiàn)更多東西。特定的pygame函數(shù)能夠釋放令人生畏的python GIL(全局解釋器鎖),這幾乎是你用C語言才能做的事。
-
核心函數(shù)用最優(yōu)化的C語言或匯編語言編寫:C語言代碼通常比Python代碼運(yùn)行速度快10-20倍。而匯編語言編寫的代碼(assembly code)比Python甚至快到100多倍。
-
安裝便捷:一般僅需包管理程序或二進(jìn)制系統(tǒng)程序便能安裝。
-
真正地可移植:支持Linux (主要發(fā)行版), Windows (95, 98, ME, 2000, XP, Vista, 64-bit Windows,), Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX等操作系統(tǒng).也能支持AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS and OS/2,但是還沒有受到官方認(rèn)可。你也可以在手持設(shè)備,游戲控制臺(tái), One Laptop Per Child (OLPC) computer項(xiàng)目的電腦等設(shè)備中使用pygame.
-
用法簡單:無論是小孩子還是大人都能學(xué)會(huì)用pygame來制作射擊類游戲。
-
很多Pygame游戲已發(fā)行:其中包括很多游戲大賽入圍作品、非常受歡迎的開源可分享的游戲。
-
由你來控制主循環(huán):由你來調(diào)用pygame的函數(shù),pygame的函數(shù)并不需要調(diào)用你的函數(shù)。當(dāng)你同時(shí)還在使用其他庫來編寫各種各種的程序時(shí),這能夠?yàn)槟闾峁O大的掌控權(quán)。
-
不需要GUI就能使用所有函數(shù):僅在命令行中,你就可以使用pygame的某些函數(shù)來處理圖片,獲取游戲桿輸入,播放音樂……
-
對(duì)bug反應(yīng)迅速:很多bug在被上報(bào)的1小時(shí)內(nèi)就能被我們修復(fù)。雖然有時(shí)候我們確實(shí)會(huì)卡在某一個(gè)bug上很久,但大多數(shù)時(shí)候我們都是很不錯(cuò)的bug修復(fù)者。如今bug的上報(bào)已經(jīng)很少了,因?yàn)樵S多bug早已被我們修復(fù)。
-
代碼量少:pygame并沒有數(shù)以萬計(jì)的也許你永遠(yuǎn)用不到的冗雜代碼。pygame的核心代碼一直保持著簡潔特點(diǎn),其他附加物諸如GUI庫等,都是在核心代碼之外單獨(dú)設(shè)計(jì)研發(fā)的。
-
模塊化:你可以單獨(dú)使用pygame的某個(gè)模塊。想要換著使用一個(gè)別的聲音處理庫?沒問題。pygame的很多核心模塊支持獨(dú)立初始化與使用。
最小開發(fā)框架
import pygame,sys #sys是python的標(biāo)準(zhǔn)庫,提供Python運(yùn)行時(shí)環(huán)境變量的操控
pygame.init() #內(nèi)部各功能模塊進(jìn)行初始化創(chuàng)建及變量設(shè)置,默認(rèn)調(diào)用
size = width,height = 800,600 #設(shè)置游戲窗口大小,分別是寬度和高度
screen = pygame.display.set_mode(size) #初始化顯示窗口
pygame.display.set_caption("小游戲程序") #設(shè)置顯示窗口的標(biāo)題內(nèi)容,是一個(gè)字符串類型
while True: #無限循環(huán),直到Python運(yùn)行時(shí)退出結(jié)束
for event in pygame.event.get(): #從Pygame的事件隊(duì)列中取出事件,并從隊(duì)列中刪除該事件
if event.type == pygame.QUIT: #獲得事件類型,并逐類響應(yīng)
sys.exit() #用于退出結(jié)束游戲并退出
pygame.display.update() #對(duì)顯示窗口進(jìn)行更新,默認(rèn)窗口全部重繪
代碼執(zhí)行流程
4 具體實(shí)現(xiàn)
ok,言歸正傳,首先,我們來進(jìn)行一下游戲的初始化操作(比如初始化游戲窗口,加載一些必要的游戲素材等等),代碼實(shí)現(xiàn)如下:
'''游戲初始化'''
def initGame():
# 初始化pygame, 設(shè)置展示窗口
pygame.init()
screen = pygame.display.set_mode(cfg.SCREENSIZE)
pygame.display.set_caption('catch coins —— 微信公眾號(hào): Charles的皮卡丘')
# 加載必要的游戲素材
game_images = {}
for key, value in cfg.IMAGE_PATHS.items():
if isinstance(value, list):
images = []
for item in value: images.append(pygame.image.load(item))
game_images[key] = images
else:
game_images[key] = pygame.image.load(value)
game_sounds = {}
for key, value in cfg.AUDIO_PATHS.items():
if key == 'bgm': continue
game_sounds[key] = pygame.mixer.Sound(value)
# 返回初始化數(shù)據(jù)
return screen, game_images, game_sounds
接著,為了讓我們在寫小游戲的過程中保持一個(gè)良好的心情,就先讓自己喜歡的游戲背景音樂響起來吧:
# 播放背景音樂
pygame.mixer.music.load(cfg.AUDIO_PATHS['bgm'])
pygame.mixer.music.play(-1, 0.0)
然后選一張好看的背景圖片,這樣才可以在它的基礎(chǔ)上逐漸加入接金幣這個(gè)小游戲涉及到的游戲元素嘛:
源代碼如下:
# 游戲主循環(huán)
clock = pygame.time.Clock()
while True:
# --填充背景
screen.fill(0)
screen.blit(game_images['background'], (0, 0))
# --按鍵檢測
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# --更新屏幕
pygame.display.flip()
clock.tick(cfg.FPS)
接著,我們把用來接金幣的小人放進(jìn)去唄,就像這樣:
代碼實(shí)現(xiàn)如下:
hero = Hero(game_images['hero'], position=(375, 520))
while True:
...
key_pressed = pygame.key.get_pressed()
if key_pressed[pygame.K_a] or key_pressed[pygame.K_LEFT]:
hero.move(cfg.SCREENSIZE, 'left')
if key_pressed[pygame.K_d] or key_pressed[pygame.K_RIGHT]:
hero.move(cfg.SCREENSIZE, 'right')
...
小人的移動(dòng)主要是通過我們自己定義的Hero類里的move函數(shù)實(shí)現(xiàn)的,具體而言代碼實(shí)現(xiàn)如下:
'''定義hero類'''
class Hero(pygame.sprite.Sprite):
def __init__(self, images, position=(375, 520), **kwargs):
pygame.sprite.Sprite.__init__(self)
self.images_right = images[:5]
self.images_left = images[5:]
self.images = self.images_right.copy()
self.image = self.images[0]
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
self.diretion = 'right'
self.speed = 8
self.switch_frame_count = 0
self.switch_frame_freq = 1
self.frame_index = 0
'''左右移動(dòng)hero'''
def move(self, screensize, direction):
assert direction in ['left', 'right']
if direction != self.diretion:
self.images = self.images_left.copy() if direction == 'left' else self.images_right.copy()
self.image = self.images[0]
self.diretion = direction
self.switch_frame_count = 0
self.switch_frame_count += 1
if self.switch_frame_count % self.switch_frame_freq == 0:
self.switch_frame_count = 0
self.frame_index = (self.frame_index + 1) % len(self.images)
self.image = self.images[self.frame_index]
if direction == 'left':
self.rect.left = max(self.rect.left-self.speed, 0)
else:
self.rect.left = min(self.rect.left+self.speed, screensize[0])
'''畫到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
實(shí)現(xiàn)小人左右走動(dòng)這個(gè)效果的核心思路其實(shí)就是根據(jù)函數(shù)輸入的方向來改變小人可以使用的圖片組合(images_right/images_left)。然后對(duì)于正在往某個(gè)方向行動(dòng)中的小人,每隔switch_frame_freq幀游戲畫面就切換一次小人的圖片,游戲中的小人圖片一共十張:
前5張是向右走的圖片組,后5張是向左走的圖片組。
現(xiàn)在,我們開始實(shí)現(xiàn)掉金幣的效果啦,就像這樣:
核心代碼實(shí)現(xiàn)如下:
# 定義食物組
food_sprites_group = pygame.sprite.Group()
generate_food_freq = random.randint(10, 20)
generate_food_count = 0
while True:
...
# --隨機(jī)生成食物
generate_food_count += 1
if generate_food_count > generate_food_freq:
generate_food_freq = random.randint(10, 20)
generate_food_count = 0
food = Food(game_images, random.choice(['gold',] * 10 + ['apple']), cfg.SCREENSIZE)
food_sprites_group.add(food)
# --更新食物
for food in food_sprites_group:
if food.update(): food_sprites_group.remove(food)
...
其中食物類的定義如下:
'''定義食物類'''
class Food(pygame.sprite.Sprite):
def __init__(self, images_dict, selected_key, screensize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.screensize = screensize
self.image = images_dict[selected_key]
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
self.rect.left, self.rect.bottom = random.randint(20, screensize[0]-20), -10
self.speed = random.randrange(5, 10)
self.score = 1 if selected_key == 'gold' else 5
'''更新食物位置'''
def update(self):
self.rect.bottom += self.speed
if self.rect.top > self.screensize[1]:
return True
return False
整個(gè)定義其實(shí)很簡單,蘋果5分,金幣1分,update函數(shù)用于實(shí)時(shí)更新食物的位置以實(shí)現(xiàn)食物下降的效果。
問題來了,我們該怎么實(shí)現(xiàn)接金幣的效果呢,這金幣一直往下掉接不住可咋辦啊。別擔(dān)心,只需要調(diào)用到pygame庫里的碰撞檢測功能就可以啦,具體而言代碼實(shí)現(xiàn)如下:
while True:
...
# --碰撞檢測
for food in food_sprites_group:
if pygame.sprite.collide_mask(food, hero):
game_sounds['get'].play()
food_sprites_group.remove(food)
score += food.score
...
代碼原理其實(shí)很簡單,就是實(shí)時(shí)地檢測小人有沒有接觸到金幣,接觸到的話就發(fā)出接到金幣的聲音,并移除對(duì)應(yīng)的金幣和獲得一定的獎(jiǎng)勵(lì)得分。效果是這樣子的:
最后,我們來完善一下我們的小游戲,讓它看起來更加"規(guī)范"一些:
(1) 加入倒計(jì)時(shí)(在規(guī)定的時(shí)間內(nèi)獲得盡量高的得分)
while True:
...
# --倒計(jì)時(shí)信息
countdown_text = 'Count down: ' + str((90000 - pygame.time.get_ticks()) // 60000) + ":" + str((90000 - pygame.time.get_ticks()) // 1000 % 60).zfill(2)
countdown_text = font.render(countdown_text, True, (0, 0, 0))
countdown_rect = countdown_text.get_rect()
countdown_rect.topright = [cfg.SCREENSIZE[0]-30, 5]
screen.blit(countdown_text, countdown_rect)
...
(2) 顯示得分(顯示當(dāng)前的得分和歷史最高分)文章來源:http://www.zghlxwxcb.cn/news/detail-489157.html
while True:
...
# --顯示得分
score_text = f'Score: {score}, Highest: {highest_score}'
score_text = font.render(score_text, True, (0, 0, 0))
score_rect = score_text.get_rect()
score_rect.topleft = [5, 5]
screen.blit(score_text, score_rect)
...
(3) 添加游戲結(jié)束界面(玩家想結(jié)束游戲還是想重新開始游戲呢?)文章來源地址http://www.zghlxwxcb.cn/news/detail-489157.html
'''游戲結(jié)束畫面'''
def showEndGameInterface(screen, cfg, score, highest_score):
# 顯示的文本信息設(shè)置
font_big = pygame.font.Font(cfg.FONT_PATH, 60)
font_small = pygame.font.Font(cfg.FONT_PATH, 40)
text_title = font_big.render(f"Time is up!", True, (255, 0, 0))
text_title_rect = text_title.get_rect()
text_title_rect.centerx = screen.get_rect().centerx
text_title_rect.centery = screen.get_rect().centery - 100
text_score = font_small.render(f"Score: {score}, Highest Score: {highest_score}", True, (255, 0, 0))
text_score_rect = text_score.get_rect()
text_score_rect.centerx = screen.get_rect().centerx
text_score_rect.centery = screen.get_rect().centery - 10
text_tip = font_small.render(f"Enter Q to quit game or Enter R to restart game", True, (255, 0, 0))
text_tip_rect = text_tip.get_rect()
text_tip_rect.centerx = screen.get_rect().centerx
text_tip_rect.centery = screen.get_rect().centery + 60
text_tip_count = 0
text_tip_freq = 10
text_tip_show_flag = True
# 界面主循環(huán)
clock = pygame.time.Clock()
while True:
screen.fill(0)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
return False
elif event.key == pygame.K_r:
return True
screen.blit(text_title, text_title_rect)
screen.blit(text_score, text_score_rect)
if text_tip_show_flag:
screen.blit(text_tip, text_tip_rect)
text_tip_count += 1
if text_tip_count % text_tip_freq == 0:
text_tip_count = 0
text_tip_show_flag = not text_tip_show_flag
pygame.display.flip()
clock.tick(cfg.FPS)
5 最后
到了這里,關(guān)于python小游戲 接金幣小游戲設(shè)計(jì)與實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!