原文: https://pythonspot.com/snake-with-pygame/

Pygame 贪食蛇 - 图1

在本教程中,您将学习如何制作游戏。 该游戏是一款街机游戏,逻辑非常简单,这就是为什么它是演示如何使用 Pygame 构建游戏的理想示例的原因。

玩家被表示为蛇,如果它吃了一个苹果,蛇就会成长。 游戏的目的是在不撞到自己的情况下尽可能多地吃苹果。 在游戏的早期阶段这很容易,但是随着蛇的长度增加,难度变得越来越大。

入门:基本结构和事件处理。

我们定义了一个Player类,它可以保持玩家在屏幕上的位置及其移动的速度。 另外,我们定义Player实例可以执行的动作(动作):

  1. class Player:
  2. x = 10
  3. y = 10
  4. speed = 1
  5. def moveRight(self):
  6. self.x = self.x + self.speed
  7. def moveLeft(self):
  8. self.x = self.x - self.speed
  9. def moveUp(self):
  10. self.y = self.y - self.speed
  11. def moveDown(self):
  12. self.y = self.y + self.speed

可以使用移动方法创建玩家对象,并可以修改变量。
我们将这些方法链接到事件。 在 Pygame 中,我们可以使用以下代码获得非阻塞式键盘输入:

  1. pygame.event.pump()
  2. keys = pygame.key.get_pressed()
  3. if (keys[K_RIGHT]):
  4. print "Right arrow pressed."

完整的代码使我们能够在屏幕上移动玩家:

  1. from pygame.locals import *
  2. import pygame
  3. class Player:
  4. x = 10
  5. y = 10
  6. speed = 1
  7. def moveRight(self):
  8. self.x = self.x + self.speed
  9. def moveLeft(self):
  10. self.x = self.x - self.speed
  11. def moveUp(self):
  12. self.y = self.y - self.speed
  13. def moveDown(self):
  14. self.y = self.y + self.speed
  15. class App:
  16. windowWidth = 800
  17. windowHeight = 600
  18. player = 0
  19. def __init__(self):
  20. self._running = True
  21. self._display_surf = None
  22. self._image_surf = None
  23. self.player = Player()
  24. def on_init(self):
  25. pygame.init()
  26. self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
  27. pygame.display.set_caption('Pygame pythonspot.com example')
  28. self._running = True
  29. self._image_surf = pygame.image.load("pygame.png").convert()
  30. def on_event(self, event):
  31. if event.type == QUIT:
  32. self._running = False
  33. def on_loop(self):
  34. pass
  35. def on_render(self):
  36. self._display_surf.fill((0,0,0))
  37. self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
  38. pygame.display.flip()
  39. def on_cleanup(self):
  40. pygame.quit()
  41. def on_execute(self):
  42. if self.on_init() == False:
  43. self._running = False
  44. while( self._running ):
  45. pygame.event.pump()
  46. keys = pygame.key.get_pressed()
  47. if (keys[K_RIGHT]):
  48. self.player.moveRight()
  49. if (keys[K_LEFT]):
  50. self.player.moveLeft()
  51. if (keys[K_UP]):
  52. self.player.moveUp()
  53. if (keys[K_DOWN]):
  54. self.player.moveDown()
  55. if (keys[K_ESCAPE]):
  56. self._running = False
  57. self.on_loop()
  58. self.on_render()
  59. self.on_cleanup()
  60. if __name__ == "__main__" :
  61. theApp = App()
  62. theApp.on_execute()

现在,您可以使用箭头键在屏幕上移动该块。

Pygame 贪食蛇 - 图2

pygame 的例子。在屏幕上移动块

构建玩家(蛇)

玩家控制具有初始长度的蛇。 按下箭头键时,这条蛇总是在移动并改变其移动方向。 为此,更新玩家类:

  1. class Player:
  2. x = 0
  3. y = 0
  4. speed = 32
  5. direction = 0
  6. def update(self):
  7. if self.direction == 0:
  8. self.x = self.x + self.speed
  9. if self.direction == 1:
  10. self.x = self.x - self.speed
  11. if self.direction == 2:
  12. self.y = self.y - self.speed
  13. if self.direction == 3:
  14. self.y = self.y + self.speed
  15. def moveRight(self):
  16. self.direction = 0
  17. def moveLeft(self):
  18. self.direction = 1
  19. def moveUp(self):
  20. self.direction = 2
  21. def moveDown(self):
  22. self.direction = 3

并且不要忘记增加游戏循环的延迟。

  1. import time
  2. ...
  3. time.sleep (100.0 / 1000.0);

它开始更多地起蛇的作用,但是还没有基本长度。 我们跟踪蛇的旧位置并移动蛇的头部。 我们还将绘制方法移到了蛇中。 复制代码,您将得到一条动静的蛇:

  1. from pygame.locals import *
  2. import pygame
  3. import time
  4. class Player:
  5. x = []
  6. y = []
  7. step = 44
  8. direction = 0
  9. length = 3
  10. updateCountMax = 2
  11. updateCount = 0
  12. def __init__(self, length):
  13. self.length = length
  14. for i in range(0,length):
  15. self.x.append(0)
  16. self.y.append(0)
  17. def update(self):
  18. self.updateCount = self.updateCount + 1
  19. if self.updateCount > self.updateCountMax:
  20. # update previous positions
  21. for i in range(self.length-1,0,-1):
  22. print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
  23. self.x[i] = self.x[i-1]
  24. self.y[i] = self.y[i-1]
  25. # update position of head of snake
  26. if self.direction == 0:
  27. self.x[0] = self.x[0] + self.step
  28. if self.direction == 1:
  29. self.x[0] = self.x[0] - self.step
  30. if self.direction == 2:
  31. self.y[0] = self.y[0] - self.step
  32. if self.direction == 3:
  33. self.y[0] = self.y[0] + self.step
  34. self.updateCount = 0
  35. def moveRight(self):
  36. self.direction = 0
  37. def moveLeft(self):
  38. self.direction = 1
  39. def moveUp(self):
  40. self.direction = 2
  41. def moveDown(self):
  42. self.direction = 3
  43. def draw(self, surface, image):
  44. for i in range(0,self.length):
  45. surface.blit(image,(self.x[i],self.y[i]))
  46. class App:
  47. windowWidth = 800
  48. windowHeight = 600
  49. player = 0
  50. def __init__(self):
  51. self._running = True
  52. self._display_surf = None
  53. self._image_surf = None
  54. self.player = Player(10)
  55. def on_init(self):
  56. pygame.init()
  57. self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
  58. pygame.display.set_caption('Pygame pythonspot.com example')
  59. self._running = True
  60. self._image_surf = pygame.image.load("pygame.png").convert()
  61. def on_event(self, event):
  62. if event.type == QUIT:
  63. self._running = False
  64. def on_loop(self):
  65. self.player.update()
  66. pass
  67. def on_render(self):
  68. self._display_surf.fill((0,0,0))
  69. self.player.draw(self._display_surf, self._image_surf)
  70. pygame.display.flip()
  71. def on_cleanup(self):
  72. pygame.quit()
  73. def on_execute(self):
  74. if self.on_init() == False:
  75. self._running = False
  76. while( self._running ):
  77. pygame.event.pump()
  78. keys = pygame.key.get_pressed()
  79. if (keys[K_RIGHT]):
  80. self.player.moveRight()
  81. if (keys[K_LEFT]):
  82. self.player.moveLeft()
  83. if (keys[K_UP]):
  84. self.player.moveUp()
  85. if (keys[K_DOWN]):
  86. self.player.moveDown()
  87. if (keys[K_ESCAPE]):
  88. self._running = False
  89. self.on_loop()
  90. self.on_render()
  91. time.sleep (50.0 / 1000.0);
  92. self.on_cleanup()
  93. if __name__ == "__main__" :
  94. theApp = App()
  95. theApp.on_execute()

结果:

Pygame 贪食蛇 - 图3

python 贪食蛇

游戏逻辑

蛇游戏有一些规则:

  • 如果蛇吃了一个苹果,那么苹果会移动到新位置。

  • 如果蛇吃了一个苹果,蛇的长度就会增加。

  • 如果一条蛇自行倒下,请继续游戏。

我们首先创建一个新类,使我们能够创建苹果:

  1. class Apple:
  2. x = 0
  3. y = 0
  4. step = 44
  5. def __init__(self,x,y):
  6. self.x = x * self.step
  7. self.y = y * self.step
  8. def draw(self, surface, image):
  9. surface.blit(image,(self.x, self.y))

为简单起见,我们将苹果显示为绿色立方体。 我们有这个基本代码,但是除了移动蛇和显示苹果外,它没有做太多的事情:

  1. from pygame.locals import *
  2. import pygame
  3. import time
  4. class Apple:
  5. x = 0
  6. y = 0
  7. step = 44
  8. def __init__(self,x,y):
  9. self.x = x * self.step
  10. self.y = y * self.step
  11. def draw(self, surface, image):
  12. surface.blit(image,(self.x, self.y))
  13. class Player:
  14. x = []
  15. y = []
  16. step = 44
  17. direction = 0
  18. length = 3
  19. updateCountMax = 2
  20. updateCount = 0
  21. def __init__(self, length):
  22. self.length = length
  23. for i in range(0,length):
  24. self.x.append(0)
  25. self.y.append(0)
  26. def update(self):
  27. self.updateCount = self.updateCount + 1
  28. if self.updateCount > self.updateCountMax:
  29. # update previous positions
  30. for i in range(self.length-1,0,-1):
  31. print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
  32. self.x[i] = self.x[i-1]
  33. self.y[i] = self.y[i-1]
  34. # update position of head of snake
  35. if self.direction == 0:
  36. self.x[0] = self.x[0] + self.step
  37. if self.direction == 1:
  38. self.x[0] = self.x[0] - self.step
  39. if self.direction == 2:
  40. self.y[0] = self.y[0] - self.step
  41. if self.direction == 3:
  42. self.y[0] = self.y[0] + self.step
  43. self.updateCount = 0
  44. def moveRight(self):
  45. self.direction = 0
  46. def moveLeft(self):
  47. self.direction = 1
  48. def moveUp(self):
  49. self.direction = 2
  50. def moveDown(self):
  51. self.direction = 3
  52. def draw(self, surface, image):
  53. for i in range(0,self.length):
  54. surface.blit(image,(self.x[i],self.y[i]))
  55. class App:
  56. windowWidth = 800
  57. windowHeight = 600
  58. player = 0
  59. apple = 0
  60. def __init__(self):
  61. self._running = True
  62. self._display_surf = None
  63. self._image_surf = None
  64. self._apple_surf = None
  65. self.player = Player(10)
  66. self.apple = Apple(5,5)
  67. def on_init(self):
  68. pygame.init()
  69. self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
  70. pygame.display.set_caption('Pygame pythonspot.com example')
  71. self._running = True
  72. self._image_surf = pygame.image.load("pygame.png").convert()
  73. self._apple_surf = pygame.image.load("apple.png").convert()
  74. def on_event(self, event):
  75. if event.type == QUIT:
  76. self._running = False
  77. def on_loop(self):
  78. self.player.update()
  79. pass
  80. def on_render(self):
  81. self._display_surf.fill((0,0,0))
  82. self.player.draw(self._display_surf, self._image_surf)
  83. self.apple.draw(self._display_surf, self._apple_surf)
  84. pygame.display.flip()
  85. def on_cleanup(self):
  86. pygame.quit()
  87. def on_execute(self):
  88. if self.on_init() == False:
  89. self._running = False
  90. while( self._running ):
  91. pygame.event.pump()
  92. keys = pygame.key.get_pressed()
  93. if (keys[K_RIGHT]):
  94. self.player.moveRight()
  95. if (keys[K_LEFT]):
  96. self.player.moveLeft()
  97. if (keys[K_UP]):
  98. self.player.moveUp()
  99. if (keys[K_DOWN]):
  100. self.player.moveDown()
  101. if (keys[K_ESCAPE]):
  102. self._running = False
  103. self.on_loop()
  104. self.on_render()
  105. time.sleep (50.0 / 1000.0);
  106. self.on_cleanup()
  107. if __name__ == "__main__" :
  108. theApp = App()
  109. theApp.on_execute()

因此,我们必须添加游戏逻辑。 要知道蛇的位置是否与苹果的位置匹配,我们必须进行碰撞检测。 这只是意味着要使蛇的坐标与苹果的坐标相交。 我们创建一个新方法来做到这一点:

  1. def isCollision(self,x1,y1,x2,y2,bsize):
  2. if x1 >= x2 and x1 <= x2 + bsize:
  3. if y1 >= y2 and y1 <= y2 + bsize:
  4. return True
  5. return False

给定其块大小bsize,如果坐标(x1, y1)(x2, y2)相交,则它将返回True。 我们调用此方法来确定蛇是否与苹果碰撞。 我们需要检查整个蛇,而不仅是头部,因为我们不希望苹果的新位置位于蛇的某个位置。 我们使用相同的isCollision方法来确定蛇是否与自身碰撞(等于输掉游戏)。

完整来源:

  1. from pygame.locals import *
  2. from random import randint
  3. import pygame
  4. import time
  5. class Apple:
  6. x = 0
  7. y = 0
  8. step = 44
  9. def __init__(self,x,y):
  10. self.x = x * self.step
  11. self.y = y * self.step
  12. def draw(self, surface, image):
  13. surface.blit(image,(self.x, self.y))
  14. class Player:
  15. x = [0]
  16. y = [0]
  17. step = 44
  18. direction = 0
  19. length = 3
  20. updateCountMax = 2
  21. updateCount = 0
  22. def __init__(self, length):
  23. self.length = length
  24. for i in range(0,2000):
  25. self.x.append(-100)
  26. self.y.append(-100)
  27. # initial positions, no collision.
  28. self.x[1] = 1*44
  29. self.x[2] = 2*44
  30. def update(self):
  31. self.updateCount = self.updateCount + 1
  32. if self.updateCount > self.updateCountMax:
  33. # update previous positions
  34. for i in range(self.length-1,0,-1):
  35. self.x[i] = self.x[i-1]
  36. self.y[i] = self.y[i-1]
  37. # update position of head of snake
  38. if self.direction == 0:
  39. self.x[0] = self.x[0] + self.step
  40. if self.direction == 1:
  41. self.x[0] = self.x[0] - self.step
  42. if self.direction == 2:
  43. self.y[0] = self.y[0] - self.step
  44. if self.direction == 3:
  45. self.y[0] = self.y[0] + self.step
  46. self.updateCount = 0
  47. def moveRight(self):
  48. self.direction = 0
  49. def moveLeft(self):
  50. self.direction = 1
  51. def moveUp(self):
  52. self.direction = 2
  53. def moveDown(self):
  54. self.direction = 3
  55. def draw(self, surface, image):
  56. for i in range(0,self.length):
  57. surface.blit(image,(self.x[i],self.y[i]))
  58. class Game:
  59. def isCollision(self,x1,y1,x2,y2,bsize):
  60. if x1 >= x2 and x1 <= x2 + bsize:
  61. if y1 >= y2 and y1 <= y2 + bsize:
  62. return True
  63. return False
  64. class App:
  65. windowWidth = 800
  66. windowHeight = 600
  67. player = 0
  68. apple = 0
  69. def __init__(self):
  70. self._running = True
  71. self._display_surf = None
  72. self._image_surf = None
  73. self._apple_surf = None
  74. self.game = Game()
  75. self.player = Player(3)
  76. self.apple = Apple(5,5)
  77. def on_init(self):
  78. pygame.init()
  79. self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
  80. pygame.display.set_caption('Pygame pythonspot.com example')
  81. self._running = True
  82. self._image_surf = pygame.image.load("block.jpg").convert()
  83. self._apple_surf = pygame.image.load("block.jpg").convert()
  84. def on_event(self, event):
  85. if event.type == QUIT:
  86. self._running = False
  87. def on_loop(self):
  88. self.player.update()
  89. # does snake eat apple?
  90. for i in range(0,self.player.length):
  91. if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44):
  92. self.apple.x = randint(2,9) * 44
  93. self.apple.y = randint(2,9) * 44
  94. self.player.length = self.player.length + 1
  95. # does snake collide with itself?
  96. for i in range(2,self.player.length):
  97. if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40):
  98. print("You lose! Collision: ")
  99. print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
  100. print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")")
  101. exit(0)
  102. pass
  103. def on_render(self):
  104. self._display_surf.fill((0,0,0))
  105. self.player.draw(self._display_surf, self._image_surf)
  106. self.apple.draw(self._display_surf, self._apple_surf)
  107. pygame.display.flip()
  108. def on_cleanup(self):
  109. pygame.quit()
  110. def on_execute(self):
  111. if self.on_init() == False:
  112. self._running = False
  113. while( self._running ):
  114. pygame.event.pump()
  115. keys = pygame.key.get_pressed()
  116. if (keys[K_RIGHT]):
  117. self.player.moveRight()
  118. if (keys[K_LEFT]):
  119. self.player.moveLeft()
  120. if (keys[K_UP]):
  121. self.player.moveUp()
  122. if (keys[K_DOWN]):
  123. self.player.moveDown()
  124. if (keys[K_ESCAPE]):
  125. self._running = False
  126. self.on_loop()
  127. self.on_render()
  128. time.sleep (50.0 / 1000.0);
  129. self.on_cleanup()
  130. if __name__ == "__main__" :
  131. theApp = App()
  132. theApp.on_execute()

结论:

您学习了如何使用 Python 创建游戏蛇以及碰撞检测,图像加载和事件处理等概念。 可以向这个小玩具游戏添加很多东西,但这只是一个非常简单的示例。:-)

下一教程