Pygame 建立貪吃蛇遊戲
在本教程中,你將學習如何構建遊戲貪吃蛇。遊戲是街機遊戲,它具有非常簡單的邏輯,這就是為什麼它是演示如何使用 Pygame 構建遊戲的理想示例。
玩家被表示為蛇,如果它吃蘋果就會長大。遊戲的目標是儘可能多地吃掉蘋果,而不能碰到自己。這在遊戲的早期階段非常容易,但隨著蛇的長度增長而變得越來越困難。
入門:基本結構和事件處理
我們定義了一個類 Player
,它保持玩家在螢幕上的位置以及它移動的速度。此外,我們定義了 Player
例項可以執行的操作(移動):
class Player:
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
可以建立玩家物件,並可以使用移動方法修改變數。
我們將這些方法與事件聯絡起來。在 Pygame 中,我們可以使用以下程式碼獲得非阻塞鍵盤輸入:
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
print "Right arrow pressed."
完整的程式碼使我們能夠在螢幕上移動 Player
:
from pygame.locals import *
import pygame
class Player:
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self.player = Player()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
你現在可以使用箭頭鍵在螢幕上移動塊。
![pygame 的例子。在螢幕上移動塊](/img/Tutorial/Pygame/pygame_move block.webp)
建立 Player
(蛇)
Player
控制具有初始長度的蛇。當按下箭頭鍵時,這條蛇總是在移動並改變它移動的方向。為此,請更新 Player
類:
class Player:
x = 0
y = 0
speed = 32
direction = 0
def update(self):
if self.direction == 0:
self.x = self.x + self.speed
if self.direction == 1:
self.x = self.x - self.speed
if self.direction == 2:
self.y = self.y - self.speed
if self.direction == 3:
self.y = self.y + self.speed
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
並且不要忘記在遊戲迴圈中新增延遲。
import time
time.sleep (100.0 / 1000.0);
這開始更像是一條蛇,但它還沒有基本長度。我們跟蹤蛇的舊位置並移動蛇的頭部。我們還將繪圖方法移到了蛇身上。複製程式碼,你將有一條可以移動的蛇:
from pygame.locals import *
import pygame
import time
class Player:
x = []
y = []
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,length):
self.x.append(0)
self.y.append(0)
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class App:
windowWidth = 800
windowHeight = 600
player = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self.player = Player(10)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.player.update()
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
結果:
貪吃蛇遊戲邏輯
蛇遊戲有一些規則:
- 如果蛇吃了一個蘋果,蘋果就會移動到一個新的位置。
- 如果蛇吃了一個蘋果,蛇的長度就會增長。
- 如果一條蛇與自身相碰,遊戲結束。
我們首先建立一個新類,使我們能夠建立蘋果:
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
為簡單起見,我們將蘋果顯示為綠色立方體。我們有這個基本程式碼,但它比 Player
類要簡單些:
from pygame.locals import *
import pygame
import time
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
class Player:
x = []
y = []
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,length):
self.x.append(0)
self.y.append(0)
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class App:
windowWidth = 800
windowHeight = 600
player = 0
apple = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self._apple_surf = None
self.player = Player(10)
self.apple = Apple(5,5)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("pygame.png").convert()
self._apple_surf = pygame.image.load("apple.png").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.player.update()
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
self.apple.draw(self._display_surf, self._apple_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
現在我們新增了遊戲邏輯。要知道蛇的位置是否與蘋果位置匹配,我們必須進行碰撞檢測。這簡單地意味著蛇的座標與蘋果的座標相交。我們建立了一個新方法:
def isCollision(self,x1,y1,x2,y2,bsize):
if x1 >= x2 and x1 <= x2 + bsize:
if y1 >= y2 and y1 <= y2 + bsize:
return True
return False
如果座標 (x1,y1)
與其 (x2,y2)
在給定塊尺寸 bsize
內相交的話,它將返回 True
。我們稱這種方法來確定蛇是否與蘋果碰撞。我們需要為整條蛇檢查這個,而不僅僅是頭部,因為我們不希望蘋果的新位置在蛇的某個地方。我們使用相同的 isCollision
方法來確定蛇是否與自身發生碰撞(=輸掉遊戲)。
完整程式碼:
from pygame.locals import *
from random import randint
import pygame
import time
class Apple:
x = 0
y = 0
step = 44
def __init__(self,x,y):
self.x = x * self.step
self.y = y * self.step
def draw(self, surface, image):
surface.blit(image,(self.x, self.y))
class Player:
x = [0]
y = [0]
step = 44
direction = 0
length = 3
updateCountMax = 2
updateCount = 0
def __init__(self, length):
self.length = length
for i in range(0,2000):
self.x.append(-100)
self.y.append(-100)
# initial positions, no collision.
self.x[1] = 1*44
self.x[2] = 2*44
def update(self):
self.updateCount = self.updateCount + 1
if self.updateCount > self.updateCountMax:
# update previous positions
for i in range(self.length-1,0,-1):
self.x[i] = self.x[i-1]
self.y[i] = self.y[i-1]
# update position of head of snake
if self.direction == 0:
self.x[0] = self.x[0] + self.step
if self.direction == 1:
self.x[0] = self.x[0] - self.step
if self.direction == 2:
self.y[0] = self.y[0] - self.step
if self.direction == 3:
self.y[0] = self.y[0] + self.step
self.updateCount = 0
def moveRight(self):
self.direction = 0
def moveLeft(self):
self.direction = 1
def moveUp(self):
self.direction = 2
def moveDown(self):
self.direction = 3
def draw(self, surface, image):
for i in range(0,self.length):
surface.blit(image,(self.x[i],self.y[i]))
class Game:
def isCollision(self,x1,y1,x2,y2,bsize):
if x1 >= x2 and x1 <= x2 + bsize:
if y1 >= y2 and y1 <= y2 + bsize:
return True
return False
class App:
windowWidth = 800
windowHeight = 600
player = 0
apple = 0
def __init__(self):
self._running = True
self._display_surf = None
self._image_surf = None
self._apple_surf = None
self.game = Game()
self.player = Player(3)
self.apple = Apple(5,5)
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
pygame.display.set_caption('Pygame pythonspot.com example')
self._running = True
self._image_surf = pygame.image.load("block.jpg").convert()
self._apple_surf = pygame.image.load("block.jpg").convert()
def on_event(self, event):
if event.type == QUIT:
self._running = False
def on_loop(self):
self.player.update()
# does snake eat apple?
for i in range(0,self.player.length):
if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44):
self.apple.x = randint(2,9) * 44
self.apple.y = randint(2,9) * 44
self.player.length = self.player.length + 1
# does snake collide with itself?
for i in range(2,self.player.length):
if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40):
print("You lose! Collision: ")
print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")")
exit(0)
pass
def on_render(self):
self._display_surf.fill((0,0,0))
self.player.draw(self._display_surf, self._image_surf)
self.apple.draw(self._display_surf, self._apple_surf)
pygame.display.flip()
def on_cleanup(self):
pygame.quit()
def on_execute(self):
if self.on_init() == False:
self._running = False
while( self._running ):
pygame.event.pump()
keys = pygame.key.get_pressed()
if (keys[K_RIGHT]):
self.player.moveRight()
if (keys[K_LEFT]):
self.player.moveLeft()
if (keys[K_UP]):
self.player.moveUp()
if (keys[K_DOWN]):
self.player.moveDown()
if (keys[K_ESCAPE]):
self._running = False
self.on_loop()
self.on_render()
time.sleep (50.0 / 1000.0);
self.on_cleanup()
if __name__ == "__main__" :
theApp = App()
theApp.on_execute()
結論:
你學習瞭如何使用 Python 建立遊戲蛇以及碰撞檢測,影象載入和事件處理等概念。很多東西都可以新增到這個小玩具遊戲中,但這只是一個非常簡單的例子。🙂