【程式設計6】貪吃蛇遊戲(python+pygame)
阿新 • • 發佈:2018-12-18
效果圖~新鮮出爐
- 開始介面
- 遊戲中
- 結束介面
一、pygame模組概覽
模組名稱 | 功能 |
---|---|
pygame.cdrom | 訪問光碟機 |
pygame.cursors | 載入游標 |
pygame.display | 訪問顯示裝置 |
pygame.draw | 繪製形狀、線和點 |
pygame.event | 管理事件 |
pygame.font | 使用字型 |
pygame.image | 載入和儲存圖片 |
pygame.joystick | 使用遊戲手柄或類似的東西 |
pygame.key | 讀取鍵盤按鍵 |
pygame.mixer | 聲音 |
pygame.mouse | 滑鼠 |
pygame.movie | 播放視訊 |
pygame.music | 播放音訊 |
pygame.overlay | 訪問高階視訊疊加 |
pygame | 目前學習的 |
pygame.rect | 管理矩形區域 |
pygame.sndarray | 操作聲音資料 |
pygame.sprite | 操作移動影象 |
pygame.surface | 管理影象和螢幕 |
pygame.surfarray | 管理點陣影象資料 |
pygame.time | 管理時間和幀資訊 |
pygame.transform | 縮放和移動影象 |
二、核心程式碼
思路
- 首頁面:會涉及圖片和文字提示的顯示,進入(任意鍵)或退出(ESC)遊戲;
- 遊戲頁面:主要涉及食物的建立繪製,蛇的移動和顯示,蛇是否吃到食物或者是否撞到邊界或自身,再者就是音效的實現(背景音樂+gameover音效);
- 結束頁面:會涉及圖片和文字提示的顯示,重來(任意鍵)或退出(ESC)遊戲。
核心程式碼
- 主函式
def main():
pygame.init()
# 建立Pygame時鐘物件,控制每個迴圈多長時間執行一次。
# 例如:snake_speed_clock(60)代表每秒內迴圈要執行的 60 次
# 每秒60個迴圈(或幀)時,每個迴圈需要1000/60=16.66ms(大約17ms)如果迴圈中的程式碼執行時間超過17ms,
# 在clock指出下一次迴圈時當前迴圈將無法完成。
snake_speed_clock = pygame.time.Clock()
screen = pygame.display.set_mode((windows_width, windows_height))
screen.fill(white)
pygame.display.set_caption("貪吃蛇~")
show_start_info(screen)
while True:
music()
running_game(screen, snake_speed_clock)
show_end_info(screen)
- 遊戲執行程式碼
def running_game(screen,snake_speed_clock):
start_x = random.randint(3, map_width - 8) #開始位置
start_y = random.randint(3, map_height - 8)
snake_coords = [{'x': start_x, 'y': start_y}, #初始貪吃蛇
{'x': start_x - 1, 'y': start_y},
{'x': start_x - 2, 'y': start_y}]
direction = RIGHT # 開始時向右移動
food = get_random_location() #實物隨機位置
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
direction = LEFT
elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
direction = RIGHT
elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
direction = UP
elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
direction = DOWN
elif event.key == K_ESCAPE:
terminate()
move_snake(direction, snake_coords) #移動蛇
ret = snake_is_alive(snake_coords)
if not ret:
gameover_music()
break #蛇死了. 遊戲結束
snake_is_eat_food(snake_coords, food) #判斷蛇是否吃到食物
screen.fill(BG_COLOR)
draw_snake(screen, snake_coords)
draw_food(screen, food)
show_score(screen, len(snake_coords) - 3)
pygame.display.update()
snake_speed_clock.tick(snake_speed) #控制fps
- 食物繪製
def draw_food(screen, food):
x = food['x'] * cell_size
y = food['y'] * cell_size
appleRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, red, appleRect)
- 貪吃蛇繪製
def draw_snake(screen, snake_coords):
for coord in snake_coords:
x = coord['x'] * cell_size
y = coord['y'] * cell_size
wormSegmentRect = pygame.Rect(x,y,cell_size,cell_size)
pygame.draw.rect(screen, dark_blue, wormSegmentRect)
wormInnerSegmentRect = pygame.Rect(x+4,y+4,cell_size - 8, cell_size - 8)
pygame.draw.rect(screen, blue, wormInnerSegmentRect)
- 移動貪吃蛇
def move_snake(direction, snake_coords):
if direction == UP:
newHead = {'x':snake_coords[HEAD]['x'], 'y':snake_coords[HEAD]['y'] - 1}
elif direction == DOWN:
newHead = {'x':snake_coords[HEAD]['x'], 'y':snake_coords[HEAD]['y'] + 1}
elif direction == LEFT:
newHead = {'x':snake_coords[HEAD]['x'] - 1, 'y':snake_coords[HEAD]['y']}
elif direction == RIGHT:
newHead = {'x':snake_coords[HEAD]['x'] + 1, 'y':snake_coords[HEAD]['y']}
snake_coords.insert(0, newHead)
- 判斷蛇死沒有死
def snake_is_alive(snake_coords):
tag = True
# 頭座標超出地圖範圍
if(snake_coords[HEAD]['x'] == -1 \
or snake_coords[HEAD]['x'] == map_width \
or snake_coords[HEAD]['y'] == -1 \
or snake_coords[HEAD]['y'] == map_height):
tag = False
# 頭座標等於身體某節座標
for snake_body in snake_coords[1:]:
if snake_body['x'] == snake_coords[HEAD]['x'] and snake_body['y'] == snake_coords[HEAD]['y']:
tag = False
return tag
- 判斷蛇是否吃到食物
def snake_is_eat_food(snake_coords, food):
if(snake_coords[HEAD]['x'] == food['x'] and snake_coords[HEAD]['y'] == food['y']):
## 重新生成食物
food['x'] = random.randint(0, map_width - 1)
food['y'] = random.randint(0, map_height - 1)
else:
# 如果沒有吃到實物, 就向前移動, 那麼尾部一格刪掉
del snake_coords[-1]
- 隨機生成食物
def get_random_location():
return {'x':random.randint(0, map_width - 1),'y':random.randint(0, map_height - 1)}
- 開始資訊顯示
def show_start_info(screen):
# 建立Font字型物件,使用render方法寫字
font = pygame.font.Font("simsun.ttc", 40)
tip = font.render('按任意鍵開始遊戲', True,(65,105,255))
# 載入圖片
gamestart = pygame.image.load('startlogo.jpg').convert()
# 通過blit方法輸出在螢幕上
screen.blit(gamestart,(140, 30))
screen.blit(tip,(240, 550))
## 重新整理螢幕
pygame.display.update()
while True: # 監聽鍵盤
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN: # 任意鍵按下
return
if (event.key == K_ESCAPE): # 若為ESC,則終止程式
terminate()
else:
return
- 聲音設定
def music():
pygame.mixer.init()
pygame.mixer.music.load('111.mp3')
pygame.mixer.music.play(1, 0)
def gameover_music():
pygame.mixer.init()
pygame.mixer.music.load('gameover.mp3')
pygame.mixer.music.play(1,0)
- 結束資訊顯示
def show_end_info(screen):
font = pygame.font.Font("simsun.ttc", 40)
tip = font.render("按ESC退出遊戲,按任意鍵重新開始遊戲",True,(65,105,255))
# gamestart = pygame.image.load('gameover.png')
# screen.blit(gamestart,(60, 0))
screen.blit(tip,(80, 300))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
terminate()
else:
return
- 成績資訊顯示
def show_score(screen, score):
font = pygame.font.Font("simsun.ttc", 30)
scoreSurf = font.render("得分:%s" % score, True, green)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (windows_width - 120, 10)
screen.blit(scoreSurf,scoreRect)
- 程式終止
def terminate():
pygame.quit()
sys.exit()