Python實(shí)現(xiàn)貪吃蛇小游戲(單人模式)
簡(jiǎn)單用py寫了一個(gè)貪吃蛇游戲,有單人、雙人模式,比較簡(jiǎn)單,適合初學(xué)者練手。基本上每行重要的語(yǔ)句都有注釋,做了什么事一目了然
這里先介紹單人模式
一、游戲設(shè)計(jì)要點(diǎn)
1.游戲主體窗口(尺寸)、畫布(尺寸、位置)、按鈕(尺寸、位置)、文字(大小、顏色、位置)、圖像、背景音樂及相關(guān)響應(yīng)函數(shù)(主要是鼠標(biāo)移動(dòng)及點(diǎn)擊的響應(yīng))的設(shè)計(jì)與合理排布
2.蛇與食物的類的屬性設(shè)計(jì)
3.蛇位置的更新(根據(jù)鍵盤輸入)、吃到食物加分的判定、食物的更新
4.蛇死亡的判定條件設(shè)計(jì)
二、主要模塊
1.pygame
2.sys
3.random
三、用到的類
1.Snake類,定義蛇頭蛇身元素的位置
2.Food類,定義食物元素的位置及單個(gè)元素的顏色
四、主要函數(shù)
1.new_food(),功能:生成一個(gè)不與蛇頭位置重合的食物并返回該食物對(duì)象
def new_food(head): while True: # 循環(huán),不斷實(shí)例化new_food對(duì)象直到生成一個(gè)不與蛇頭重合的食物 new_food = Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255))) # 若new_food和蛇頭重合則不創(chuàng)鍵 if new_food.x != head.x and new_food.y != head.y: break else: continue return new_food
2.draw_snake()、draw_food()函數(shù),功能:繪制蛇與食物的圖像,傳入?yún)?shù)為顏色和對(duì)象:
# 在窗體中繪制貪吃蛇 # 形參:一個(gè)是顏色另一個(gè)是實(shí)例化對(duì)象 def draw_snake(color, object): pygame.draw.circle(window, color, (object.x, object.y), 10) # 在窗體中繪制食物 # 形參:實(shí)例化對(duì)象 def draw_food(food): pygame.draw.circle(window, food.color, (food.x, food.y), 10)
3.show_end函數(shù),功能:顯示單人模式結(jié)束時(shí)的得分界面:
# 游戲結(jié)束時(shí),單人模式顯示得分的窗體的設(shè)置 def show_end_single(): while True: window.blit(init_background, (0, 0)) for event in pygame.event.get(): if event.type == pygame.QUIT: exit_end() # 定義標(biāo)題 pygame.display.set_caption("貪吃蛇大冒險(xiǎn)") # 定義提示文字 font = pygame.font.SysFont("simHei", 40) fontsurf = font.render('游戲結(jié)束! 你的得分為: %s' % score, False, black) window.blit(fontsurf, (250, 100)) button("返回主菜單", 370, 300, 200, 40, blue, brightred, into_game) button("退出游戲", 370, 470, 200, 40, red, brightred, exit_end) pygame.display.update() clock.tick(20)
4.exit_end()函數(shù),功能:在初始界面和游戲結(jié)束顯示得分界面點(diǎn)擊右上角的"×"時(shí),直接退出整個(gè)游戲:
def exit_end(): pygame.quit() sys.exit()
5.start_game()函數(shù),功能:實(shí)現(xiàn)單人正常模式:
def start_game(): # 播放音樂 pygame.mixer.music.play(-1) # 定義存分?jǐn)?shù)的全局變量 global score score = 0 # 定義存放玩家鍵盤輸入運(yùn)動(dòng)方向的變量,初始為向右 run_direction = "right" # 定義貪吃蛇運(yùn)動(dòng)方向的變量,初始為玩家鍵入方向 run = run_direction # 實(shí)例化貪吃蛇和食物對(duì)象 head = Snake(randint(0, 30) * 20, randint(0, 20) * 20) # 實(shí)例化蛇身長(zhǎng)度為2個(gè)單位 snake_body = [Snake(head.x, head.y + 20), Snake(head.x, head.y + 40)] # 實(shí)例化食物列表,列表隨著其中食物被吃掉應(yīng)該不斷縮短 food_list = [Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))] for i in range(1,24): food_list.append(Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))) # 實(shí)例化單個(gè)食物,方便循環(huán)內(nèi)生成單個(gè)新食物 food = Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255))) while True: window.blit(background, (0,0)) # 監(jiān)聽玩家鍵盤輸入的運(yùn)動(dòng)方向值,并根據(jù)輸入轉(zhuǎn)為up、down、right或left,方便程序中調(diào)用 # pygame.event.get()返回一個(gè)列表,存放本次game執(zhí)行中程序遇到的一連串事件(按時(shí)間順序依次存放) for event in pygame.event.get(): # pygame.QUIT事件是指用戶點(diǎn)擊窗口右上角的"×" if event.type == pygame.QUIT: # 顯示結(jié)果界面 show_end() # 若事件類型是按下鍵盤,分↑ ↓ ← →四種情況討論 elif event.type == pygame.KEYDOWN: # 若事件類型是按下鍵盤↑ # key是鍵值,表示按下去的鍵值是什么 if event.key == ord('w'): run_direction = "up" # 若事件類型是按下鍵盤↓ if event.key == ord('s'): run_direction = "down" # 若事件類型是按下鍵盤← if event.key == ord('a'): run_direction = "left" # 若事件類型是按下鍵盤→ if event.key == ord('d'): run_direction = "right" # 繪制初始化的25個(gè)食物圖像(24+1=25) # 隨著該列表中的食物被吃掉,列表應(yīng)該不斷pop以清除已經(jīng)被吃的事物 for item in food_list: draw_food(item) # 繪制被貪吃蛇吃掉后新增的食物圖像 draw_food(food) # 繪制蛇頭圖像 draw_snake(black, head) # 繪制蛇身圖像 for item in snake_body: draw_snake(blue, item) # 判斷貪吃蛇原運(yùn)動(dòng)方向(run)與玩家鍵盤輸入的運(yùn)動(dòng)方向(run_direction)是否違反正常運(yùn)動(dòng)情況 if run == "up" and not run_direction == "down": run = run_direction elif run == "down" and not run_direction == "up": run = run_direction elif run == "left" and not run_direction == "right": run = run_direction elif run == "right" and not run_direction == "left": run = run_direction # 插入蛇頭位置到蛇身列表中 snake_body.insert(0, Snake(head.x, head.y)) # 根據(jù)玩家鍵入方向進(jìn)行蛇頭xy的更新 if run == "up": head.y -= 20 elif run == "down": head.y += 20 elif run == "left": head.x -= 20 elif run == "right": head.x += 20 # 判斷是否死亡 die_flag = False # 遍歷存放貪吃蛇位姿的列表,從第1個(gè)開始,(第0個(gè)位蛇頭) for body in snake_body[1:]: # 如果蛇頭的xy和蛇身xy相等,則判定相撞,設(shè)置flag為ture if head.x == body.x and head.y == body.y: die_flag = True # 若蛇頭的xy在顯示窗體外,或flag為true,則顯示結(jié)束界面,并退出游戲 if die_flag == True or head.x < 0 or head.x > 960 or head.y < 0 or head.y > 600: # 停止播放音樂 pygame.mixer.music.stop() show_end() # die_snake(head, snake_body) # 判斷蛇頭和食物坐標(biāo),若相等,則加分,并生成新的食物 # 定義標(biāo)志,表明是否找到和蛇頭相等的事物 global flag flag = 0 # 如果蛇頭和食物重合 for item in food_list: if head.x == item.x and head.y == item.y or head.x == food.x and head.y == food.y: flag = 1 score += 1 # 彈出被吃掉的這個(gè)食物 food_list.pop(food_list.index(item)) # 再產(chǎn)生一個(gè)食物 food = new_food(head) # 把新食物插入food_list,下一次循環(huán)中會(huì)更新繪制食物全體 food_list.append(food) break if flag == 0: snake_body.pop() font = pygame.font.SysFont("simHei", 25) mode_title = font.render('正常模式', False, grey) socre_title = font.render('得分: %s' % score, False, grey) window.blit(mode_title, (50, 30)) window.blit(socre_title, (50, 65)) # 更新蛇頭蛇身和食物的數(shù)據(jù) pygame.display.update() # 通過幀率設(shè)置貪吃蛇速度 clock.tick(8)
6.start_kgame()函數(shù),功能:實(shí)現(xiàn)單人穿墻模式:
def start_kgame_single(): # 播放音樂 pygame.mixer.music.play(-1) global score score = 0 # 定義存放玩家鍵盤輸入運(yùn)動(dòng)方向的變量,初始為向右 run_direction = "right" # 定義貪吃蛇運(yùn)動(dòng)方向的變量,初始為玩家鍵入方向 run = run_direction # 實(shí)例化蛇頭、蛇身、食物對(duì)象 head = Snake(160, 160) # 實(shí)例化蛇身 snake_body = [Snake(head.x, head.y + 20), Snake(head.x, head.y + 40), Snake(head.x, head.y + 60)] # 實(shí)例化食物列表,列表隨著其中食物被吃掉應(yīng)該不斷縮短 food_list = [Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))] for i in range(1,24): food_list.append(Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255)))) # 實(shí)例化單個(gè)食物,方便循環(huán)內(nèi)生成單個(gè)新食物 food = Food(randint(0, 45) * 20, randint(0, 28) * 20, (randint(10, 255), randint(10, 255), randint(10, 255))) # 死循環(huán),監(jiān)聽鍵盤鍵值 while True: window.blit(background, (0, 0)) for event in pygame.event.get(): if event.type == pygame.QUIT: show_end_single() elif event.type == pygame.KEYDOWN: # 若事件類型是按下鍵盤w # key是鍵值,表示按下去的鍵值是什么 if event.key == ord('w'): run_direction = "up" # 若事件類型是按下鍵盤s if event.key == ord('s'): run_direction = "down" # 若事件類型是按下鍵盤a if event.key == ord('a'): run_direction = "left" # 若事件類型是按下鍵盤d if event.key == ord('d'): run_direction = "right" # 繪制初始化的25個(gè)食物圖像(24+1=25) # 隨著該列表中的食物被吃掉,列表應(yīng)該不斷pop以清除已經(jīng)被吃的事物 for item in food_list: draw_food(item) # 繪制被貪吃蛇吃掉后新增的食物圖像 draw_food(food) # 繪制蛇頭圖像 draw_snake(black, head) # 繪制蛇身圖像 for item in snake_body: draw_snake(blue, item) # 判斷貪吃蛇原運(yùn)動(dòng)方向與玩家鍵盤輸入的運(yùn)動(dòng)方向是否違反正常運(yùn)動(dòng)情況 if run == "up" and not run_direction == "down": # 若運(yùn)動(dòng)方向?yàn)橄蛏?,玩家輸入運(yùn)動(dòng)方向向下,則違背貪吃蛇正常運(yùn)動(dòng)情況 run = run_direction elif run == "down" and not run_direction == "up": run = run_direction elif run == "left" and not run_direction == "right": run = run_direction elif run == "right" and not run_direction == "left": run = run_direction # 插入蛇頭位置到蛇身列表中 snake_body.insert(0, Snake(head.x, head.y)) # 根據(jù)玩家鍵入方向進(jìn)行蛇頭xy的更新 if run == "up": head.y -= 20 elif run == "down": head.y += 20 elif run == "left": head.x -= 20 elif run == "right": head.x += 20 # 穿墻實(shí)現(xiàn) # 定義標(biāo)志位 die_flag = False # 遍歷,蛇頭碰到蛇身時(shí),flag為true退出游戲 for body in snake_body[1:]: if head.x == body.x and head.y == body.y: die_flag = True if die_flag: pygame.mixer.music.stop() show_end() else: # 當(dāng)蛇頭穿出窗體時(shí)有四種情況,分別討論 if head.x < 0: head.x = 960 if head.x > 960: head.x = 0 if head.y < 0: head.y = 600 if head.y > 600: head.y = 0 # 判斷蛇頭和食物坐標(biāo),若相等,則加分,并生成新的食物 # 定義標(biāo)志,表明是否找到和蛇頭相等的事物 global flag flag = 0 # 如果蛇頭和食物重合 for item in food_list: if head.x == item.x and head.y == item.y or head.x == food.x and head.y == food.y: flag = 1 score += 1 # 彈出被吃掉的這個(gè)食物 food_list.pop(food_list.index(item)) # 再產(chǎn)生一個(gè)食物 food = new_food(head) # 把新食物插入food_list,下一次循環(huán)中會(huì)更新繪制食物全體 food_list.append(food) break # 若沒吃到食物則從蛇身pop一個(gè)元素以更新蛇位置 if flag == 0: snake_body.pop() font = pygame.font.SysFont("simHei", 25) mode_title = font.render('穿墻模式', False, grey) socre_title = font.render('得分: %s' % score, False, grey) window.blit(mode_title, (50, 30)) window.blit(socre_title, (50, 65)) # 繪制更新 pygame.display.update() # 通過幀率設(shè)置貪吃蛇速度 clock.tick(8)
7.button()函數(shù),功能:實(shí)現(xiàn)按鈕樣式設(shè)計(jì)和響應(yīng)鼠標(biāo)操作:
def button(msg, x, y, w, h, ic, ac, action=None): # 獲取鼠標(biāo)位置 mouse = pygame.mouse.get_pos() # 獲取鼠標(biāo)點(diǎn)擊情況 click = pygame.mouse.get_pressed() if x + w > mouse[0] > x and y + h > mouse[1] > y: pygame.draw.rect(window, ac, (x, y, w, h)) if click[0] == 1 and action != None: action() else: pygame.draw.rect(window, ic, (x, y, w, h)) # 設(shè)置按鈕中的文字樣式和居中對(duì)齊 font = pygame.font.SysFont('simHei', 20) smallfont = font.render(msg, True, white) smallrect = smallfont.get_rect() smallrect.center = ((x + (w / 2)), (y + (h / 2))) window.blit(smallfont, smallrect)
8.into_game()函數(shù),功能:實(shí)現(xiàn)游戲初始界面,選擇模式:
def into_game(): while True: window.blit(init_background, (0, 0)) for event in pygame.event.get(): if event.type == pygame.QUIT: exit_end() # 設(shè)置字體 font = pygame.font.SysFont("simHei", 50) # 初始界面顯示文字 fontsurf = font.render('歡迎來到貪吃蛇大冒險(xiǎn)!', True, black) # 文字 fontrect = fontsurf.get_rect() fontrect.center = ((480), 200) window.blit(fontsurf, fontrect) button("正常模式", 370, 370, 200, 40, blue, brightred, start_game) button("可穿墻模式", 370, 420, 200, 40, violte, brightred, start_kgame) button("退出游戲", 370, 470, 200, 40, red, brightred, exit_end) pygame.display.update() clock.tick(20)
9.主函數(shù),功能:初始化參數(shù)設(shè)定,進(jìn)入游戲:
if __name__ == '__main__': # 定義需要用到的顏色 white = (255, 255, 255) red = (200, 0, 0) green = (0, 128, 0) blue = (0, 202, 254) violte = (194, 8, 234) brightred = (255, 0, 0) brightgreen = (0, 255, 0) black = (0, 0, 0) grey = (129, 131, 129) # 設(shè)計(jì)窗口 window = pygame.display.set_mode((960, 600)) # 定義標(biāo)題 pygame.display.set_caption("貪吃蛇大冒險(xiǎn)") # 定義背景圖片 init_background = pygame.image.load("image/init_bgimg.jpg") background = pygame.image.load("image/bgimg.jpg") # 背景音樂 pygame.mixer.init() pygame.mixer.music.load("background.mp3") # 創(chuàng)建時(shí)鐘 clock = pygame.time.Clock() # 初始化,自檢所有模塊是否完整 pygame.init() # 初始界面 into_game()
注:其中的圖片、背景音樂需要自己找合適(尺寸要與窗口大小相適應(yīng))的,也可以參考我上傳的資源:貪吃蛇單人版源代碼+背景+音樂
附:Blog:雙人模式詳解
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持本站。
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。