一些想法
自學python已經(jīng)有快三個月了 最近這段時間沒有怎么寫過python 很多東西反而又遺忘了 準備翻以前的筆記復習一下在博客上記錄下來 自己也沒能夠做出什么厲害的東西 小鳥游戲算是目前自己寫的最好的一個代碼了
基本游戲界面就是這樣

分析需要的功能
我的構思是將游戲分成三個部分
游戲里的角色和道具則使用類
因為是使用pygame模塊 我對這個模塊也很不熟悉 很多功能都是論壇參考其他大神的 比如
pygame.transform 里面的各種變化功能
pygame.sprite 精靈模塊里面的方法
構建整體框架
1.導入pygame和random
pygame擁有豐富的制作游戲的功能
random是隨機模塊 游戲里各種隨機事件就是通過這個模塊功能實現(xiàn)
import pygame
import random
2.我們寫一個小的項目之前 需要將每個功能分成不同的代碼塊
定義的變量都寫到最上面
MAP_WIDTH = 288 # 地圖大小
MAP_HEIGHT = 512
FPS = 30 # 刷新率
PIPE_GAPS = [110, 120, 130, 140, 150, 160] # 缺口的距離 有這6個隨機距離
# 寫的途中的全局變量都可以寫在最上面
全局變量我一般喜歡使用大寫來區(qū)分
3.游戲窗口的設置
pygame.init() # 進行初始化
SCREEN = pygame.display.set_mode((MAP_WIDTH, MAP_HEIGHT)) # 屏幕大小
pygame.display.set_caption('飛行小鳥') # 標題
CLOCK = pygame.time.Clock()
4.加載素材
加載游戲圖片和音樂
SPRITE_FILE = './images'
IMAGES = {}
IMAGES['guide'] = pygame.image.load(SPRITE_FILE + 'guide.png')
IMAGES['gameover'] = pygame.image.load(SPRITE_FILE + 'gameover.png')
IMAGES['floor'] = pygame.image.load(SPRITE_FILE + 'floor.png')
SPRITE_SOUND = './audio/'
SOUNDS = {}
SOUNDS['start'] = pygame.mixer.Sound(SPRITE_SOUND + 'start.wav')
SOUNDS['die'] = pygame.mixer.Sound(SPRITE_SOUND + 'die.wav')
SOUNDS['hit'] = pygame.mixer.Sound(SPRITE_SOUND + 'hit.wav')
SOUNDS['score'] = pygame.mixer.Sound(SPRITE_SOUND + 'score.wav')
5.執(zhí)行函數(shù)
就是執(zhí)行程序的函數(shù)
def main():
menu_window()
result = game_window()
end_window(result)
6.程序入口
if __name__ == '__main__':
main()
7.我將游戲分成了三個界面
def menu_window():
pass
def game_window():
pass
def end_window(result):
pass
# 這里就是寫運行三種游戲界面的代碼
8.因為要顯示游戲得分
所以專門寫一個方法在游戲主界面代碼里面直接調用這個方法 讓代碼不會顯得冗余
9.最后就是我們游戲角色和道具的類方法
class Bird(pygame.sprite.Sprite):
def __init__(self, x, y):
# super(Bird, self).__init__(x, y)
pygame.sprite.Sprite.__init__(self)
pass
def update(self, flap=False):
pass
def go_die(self):
pass
class Pipe(pygame.sprite.Sprite):
def __init__(self, x, y, upwards=True):
pygame.sprite.Sprite.__init__(self)
pass
def update(self):
pass
我們把整體框架搭建好之后 就可以著手完善代碼
著手完整代碼
"""
Project: pygame
Creator: stan Z
Create time: 2021-03-08 19:37
IDE: PyCharm
Introduction:
"""
import pygame
import random
######################################## 定義變量
MAP_WIDTH = 288 # 地圖大小
MAP_HEIGHT = 512
FPS = 30 # 刷新率
PIPE_GAPS = [90, 100, 110, 120, 130, 140] # 缺口的距離 有這6個隨機距離
# PIPE_GAPS1 = []
PIPE_HEIGHT_RANGE = [int(MAP_HEIGHT * 0.3), int(MAP_HEIGHT * 0.7)] # 管道長度范圍
PIPE_DISTANCE = 120 # 管道之間距離
######################################## 游戲基本設置
pygame.init() # 進行初始化
SCREEN = pygame.display.set_mode((MAP_WIDTH, MAP_HEIGHT)) # 調用窗口設置屏幕大小
pygame.display.set_caption('飛行小鳥byStanZ') # 標題
CLOCK = pygame.time.Clock() # 建立時鐘
######################################## 加載素材
SPRITE_FILE = './images'
# 列表推導式 獲得三種不同的鳥和三種狀態(tài)
BIRDS = [[f'{SPRITE_FILE}{bird}-{move}.png' for move in ['up', 'mid', 'down']] for bird in ['red', 'blue', 'yellow']]
BGPICS = [SPRITE_FILE + 'day.png', SPRITE_FILE + 'night.png']
PIPES = [SPRITE_FILE + 'green-pipe.png', SPRITE_FILE + 'red-pipe.png']
NUMBERS = [f'{SPRITE_FILE}{n}.png' for n in range(10)]
# 將圖片設置成一個大字典 里面通過key-value存不同的場景圖
IMAGES = {}
IMAGES['numbers'] = [pygame.image.load(number) for number in NUMBERS] # 數(shù)字素材有10張 因此遍歷
IMAGES['guide'] = pygame.image.load(SPRITE_FILE + 'guide.png')
IMAGES['gameover'] = pygame.image.load(SPRITE_FILE + 'gameover.png')
IMAGES['floor'] = pygame.image.load(SPRITE_FILE + 'floor.png')
# 地板的高是一個很常用的變量 因此我們專門拿出來
FLOOR_H = MAP_HEIGHT - IMAGES['floor'].get_height() # 屏幕高減去floor圖片的高 就是他在屏幕里的位置
SPRITE_SOUND = './sound'
SOUNDS = {} # 同理聲音素材也這樣做
SOUNDS['start'] = pygame.mixer.Sound(SPRITE_SOUND + 'start.wav')
SOUNDS['die'] = pygame.mixer.Sound(SPRITE_SOUND + 'die.wav')
SOUNDS['hit'] = pygame.mixer.Sound(SPRITE_SOUND + 'hit.wav')
SOUNDS['score'] = pygame.mixer.Sound(SPRITE_SOUND + 'score.wav')
SOUNDS['flap'] = pygame.mixer.Sound(SPRITE_SOUND + 'flap.wav')
SOUNDS['death'] = pygame.mixer.Sound(SPRITE_SOUND + 'death.wav')
SOUNDS['main'] = pygame.mixer.Sound(SPRITE_SOUND + 'main_theme.ogg')
SOUNDS['world_clear'] = pygame.mixer.Sound(SPRITE_SOUND + 'world_clear.wav')
# 執(zhí)行函數(shù)
def main():
while True:
IMAGES['bgpic'] = pygame.image.load(random.choice(BGPICS)) # random的choice方法可以隨機從列表里返回一個元素 白天或者黑夜
IMAGES['bird'] = [pygame.image.load(frame) for frame in random.choice(BIRDS)] # 列表推導式 鳥也是隨機
pipe = pygame.image.load(random.choice(PIPES))
IMAGES['pipe'] = [pipe, pygame.transform.flip(pipe, False, True)] # flip是翻轉 將管道放下面和上面 Flase水平不動,True上下翻轉
SOUNDS['start'].play()
# SOUNDS['main'].play()
menu_window()
result = game_window()
end_window(result)
def menu_window():
SOUNDS['world_clear'].play()
floor_gap = IMAGES['floor'].get_width() - MAP_WIDTH # 地板間隙 336 - 288 = 48
floor_x = 0
# 標題位置
guide_x = (MAP_WIDTH - IMAGES['guide'].get_width()) / 2
guide_y = MAP_HEIGHT * 0.12
# 小鳥位置
bird_x = MAP_WIDTH * 0.2
bird_y = MAP_HEIGHT * 0.5 - IMAGES['bird'][0].get_height() / 2
bird_y_vel = 1 # 小鳥飛行的速率 按y坐標向下
max_y_shift = 50 # 小鳥飛行的最大幅度
y_shift = 0 # 小鳥起始幅度為0
idx = 0 # 小鳥翅膀煽動頻率
frame_seq = [0] * 5 + [1] * 5 + [2] * 5 + [1] * 5 # 控制小鳥翅膀運動上中下
while True:
for event in pygame.event.get(): # 監(jiān)控行為
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
return
if floor_x = -floor_gap: # 當?shù)匕迮艿阶畲箝g隔的時候
floor_x = floor_x + floor_gap # 刷新地板的x軸
else:
floor_x -= 4 # 地板 x軸的移動速度
if abs(y_shift) == max_y_shift: # 如果y_shift的絕對值 = 最大幅度
bird_y_vel *= -1 # 調轉方向飛 同時飛行速度為1
else:
bird_y += bird_y_vel
y_shift += bird_y_vel # 小鳥y軸正負交替 上下飛
# 小鳥翅膀
idx += 1 # 翅膀煽動頻率
idx %= len(frame_seq) # 通過取余得到 0 1 2
frame_index = frame_seq[idx] # 小鳥圖片的下標 就是翅膀的狀態(tài)
SCREEN.blit(IMAGES['bgpic'], (0, 0))
SCREEN.blit(IMAGES['floor'], (floor_x, FLOOR_H))
SCREEN.blit(IMAGES['guide'], (guide_x, guide_y))
SCREEN.blit(IMAGES['bird'][frame_index], (bird_x, bird_y))
pygame.display.update()
CLOCK.tick(FPS) # 以每秒30幀刷新屏幕
def game_window():
SOUNDS['world_clear'].stop()
SOUNDS['main'].play()
score = 0
floor_gap = IMAGES['floor'].get_width() - MAP_WIDTH # 地板間隙 336 - 288 = 48
floor_x = 0
# 小鳥位置
bird_x = MAP_WIDTH * 0.2
bird_y = MAP_HEIGHT * 0.5 - IMAGES['bird'][0].get_height() / 2
bird = Bird(bird_x, bird_y)
n_pair = round(MAP_WIDTH / PIPE_DISTANCE) # 四舍五入取整數(shù) 屏幕寬度/兩個管道之間的距離 這個距離時候刷新第二個管道 2.4
pipe_group = pygame.sprite.Group() # 是一個集合
# 生成前面的管道
pipe_x = MAP_WIDTH
pipe_y = random.randint(PIPE_HEIGHT_RANGE[0], PIPE_HEIGHT_RANGE[1]) # 管道長度隨機從153.6 到 358.4
pipe1 = Pipe(pipe_x, pipe_y, upwards=True) # 創(chuàng)建一個管道對象
pipe_group.add(pipe1) # 將對象添加到這個精靈集合里面
pipe2 = Pipe(pipe_x, pipe_y - random.choice(PIPE_GAPS), upwards=False) # 翻轉的管道
pipe_group.add(pipe2)
SOUNDS['flap'].play()
while True:
flap = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: # 空格拍翅膀
SOUNDS['flap'].play()
flap = True
bird.update(flap)
if floor_x = -floor_gap: # 當?shù)匕迮艿阶畲箝g隔的時候
floor_x = floor_x + floor_gap # 刷新地板的x軸
else:
floor_x -= 4 # 地板 x軸的移動速度
# 生成最后一個管道
if len(pipe_group) / 2 n_pair: # 當管道組長度2.4 時 意思就是兩個半管道的時候
# sprites()將管道組返回成列表
last_pipe = pipe_group.sprites()[-1]
pipe_x = last_pipe.rect.right + PIPE_DISTANCE
pipe_y = random.randint(PIPE_HEIGHT_RANGE[0], PIPE_HEIGHT_RANGE[1])
pipe1 = Pipe(pipe_x, pipe_y, upwards=True)
pipe_group.add(pipe1)
pipe2 = Pipe(pipe_x, pipe_y - random.choice(PIPE_GAPS), upwards=False)
pipe_group.add(pipe2)
pipe_group.update()
# 鳥的矩形y坐標如果大于地板的高度 就死亡
# pygame.sprite.spritecollideany 碰撞函數(shù) 如果bird和pipe_group碰撞了 就死亡
if bird.rect.y > FLOOR_H or bird.rect.y 0 or pygame.sprite.spritecollideany(bird, pipe_group):
SOUNDS['score'].stop()
SOUNDS['main'].stop()
SOUNDS['hit'].play()
SOUNDS['die'].play()
SOUNDS['death'].play()
# 保存死亡時的鳥兒 分數(shù) 管道 繼續(xù)顯示在結束窗口
result = {'bird': bird, 'score': score, 'pipe_group': pipe_group}
return result
# 當小鳥左邊大于 管道右邊就得分
if pipe_group.sprites()[0].rect.left == 0:
SOUNDS['score'].play()
score += 1
SCREEN.blit(IMAGES['bgpic'], (0, 0))
pipe_group.draw(SCREEN)
SCREEN.blit(IMAGES['floor'], (floor_x, FLOOR_H))
SCREEN.blit(bird.image, bird.rect)
show_score(score)
pygame.display.update()
CLOCK.tick(FPS)
def end_window(result):
# 顯示gameover的圖片
gameover_x = MAP_WIDTH * 0.5 - IMAGES['gameover'].get_width() / 2
gameover_y = MAP_HEIGHT * 0.4
bird = result['bird']
pipe_group = result['pipe_group']
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and bird.rect.y > FLOOR_H:
SOUNDS['death'].stop()
return
# 使用類go_die方法 鳥兒撞墻后 旋轉往下
bird.go_die()
SCREEN.blit(IMAGES['bgpic'], (0, 0))
pipe_group.draw(SCREEN)
SCREEN.blit(IMAGES['floor'], (0, FLOOR_H))
SCREEN.blit(IMAGES['gameover'], (gameover_x, gameover_y))
show_score(result['score'])
SCREEN.blit(bird.image, bird.rect)
pygame.display.update()
CLOCK.tick(FPS)
# 顯示得分
def show_score(score):
score_str = str(score)
w = IMAGES['numbers'][0].get_width()
x = MAP_WIDTH / 2 - 2 * w / 2
y = MAP_HEIGHT * 0.1
for number in score_str: # IMAGES['numbers'] = [pygame.image.load(number) for number in NUMBERS]
SCREEN.blit(IMAGES['numbers'][int(number)], (x, y))
x += w
class Bird(pygame.sprite.Sprite):
def __init__(self, x, y):
# super(Bird, self).__init__(x, y)
pygame.sprite.Sprite.__init__(self)
self.frames = IMAGES['bird'] # 鳥兒框架
self.frame_list = [0] * 5 + [1] * 5 + [2] * 5 + [1] * 5 # 控制小鳥翅膀運動上中下
self.frame_index = 0
self.image = self.frames[self.frame_list[self.frame_index]] # 和菜單界面小鳥扇翅膀一個原理
self.rect = self.image.get_rect() # 鳥兒的矩形
self.rect.x = x
self.rect.y = y
self.gravity = 1 # 重力
self.flap_acc = -10 # 翅膀拍打往上飛 y坐標-10
self.y_vel = -10 # y坐標的速度
self.max_y_vel = 15 # y軸下落最大速度
self.rotate = 0 # 腦袋朝向
self.rotate_vel = -3 # 轉向速度
self.max_rotate = -30 # 最大轉向速度
self.flap_rotate = 45 # 按了空格只會腦袋朝向上30度
def update(self, flap=False):
if flap:
self.y_vel = self.flap_acc # 拍打翅膀 則y速度-10向上
self.rotate = self.flap_rotate
else:
self.rotate = self.rotate + self.rotate_vel
self.y_vel = min(self.y_vel + self.gravity, self.max_y_vel)
self.rect.y += self.y_vel # 小鳥向上移動的距離
self.rorate = max(self.rotate + self.rotate_vel, self.max_rotate)
self.frame_index += 1 # 扇翅膀的速率
self.frame_index %= len(self.frame_list) # 0~20
self.image = self.frames[self.frame_list[self.frame_index]]
self.image = pygame.transform.rotate(self.image, self.rotate) # transform變形方法 旋轉
def go_die(self):
if self.rect.y FLOOR_H:
self.y_vel = self.max_y_vel
self.rect.y += self.y_vel
self.rotate = -90
self.image = self.frames[self.frame_list[self.frame_index]]
self.image = pygame.transform.rotate(self.image, self.rotate)
# 管道類
class Pipe(pygame.sprite.Sprite):
def __init__(self, x, y, upwards=True):
pygame.sprite.Sprite.__init__(self)
self.x_vel = -4 # 管道移動速度
# 默認屬性為真 則是正向管道
if upwards:
self.image = IMAGES['pipe'][0]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.top = y
# 利用flip方法 旋轉管道成為反向管道
else:
self.image = IMAGES['pipe'][1]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.bottom = y
def update(self):
self.rect.x += self.x_vel # 管道x軸加移動速度
if self.rect.right 0:
self.kill()
if __name__ == '__main__':
main()
到此這篇關于pygame面向對象的飛行小鳥實現(xiàn)(Flappy bird)的文章就介紹到這了,更多相關pygame 飛行小鳥內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- pygame可視化幸運大轉盤實現(xiàn)
- pygame多種方式實現(xiàn)屏保操作(自動切換、鼠標切換、鍵盤切換)
- 利用pygame完成動畫精靈和碰撞檢測
- 詳解pygame捕獲鍵盤事件的兩種方式
- pygame實現(xiàn)鍵盤的連續(xù)監(jiān)控
- python使用pygame創(chuàng)建精靈Sprite
- pygame實現(xiàn)鍵盤和鼠標事件的處理
- Pygame做一期吃豆子游戲的示例代碼
- Python Pygame實現(xiàn)俄羅斯方塊
- 五分鐘學會怎么用Pygame做一個簡單的貪吃蛇
- Python使用Pygame繪制時鐘
- pygame實現(xiàn)井字棋之第一步繪制九宮格