|
|
51CTO旗下网站
|
|
移动端

在你的Python游戏中模拟引力

本文来学习如何使用 Python 的 Pygame 模块编程电脑游戏,并开始操作引力。

作者:Seth Kenlon来源:Linux中国|2020-01-14 12:05

 

学习如何使用 Python 的 Pygame 模块编程电脑游戏,并开始操作引力。

真实的世界充满了运动和生活。物理学使得真实的生活如此忙碌和动态。物理学是物质在空间中运动的方式。既然一个电脑游戏世界没有物质,它也就没有物理学规律,使用游戏程序员不得不模拟物理学。

从大多数电脑游戏来说,这里基本上仅有两个方面的物理学是重要的:引力和碰撞。

当你添加一个敌人到你的游戏中时,你实现了一些碰撞检测,但是这篇文章要添加更多的东西,因为引力需要碰撞检测。想想为什么引力可能涉及碰撞。如果你不能想到任何原因,不要担心 —— 它会随着你开发示例代码工作而且显然。

在真实世界中的引力是有质量的物体来相互吸引的倾向性。物体(质量)越大,它施加越大的引力作用。在电脑游戏物理学中,你不必创建质量足够大的物体来证明引力的正确;你可以在电脑游戏世界本身中仅编程一个物体落向假设的最大的对象的倾向。

添加一个引力函数

记住你的玩家已经有了一个决定动作的属性。使用这个属性来将玩家精灵拉向屏幕底部。

在 Pygame 中,较高的数字更接近屏幕的底部边缘。

在真实的世界中,引力影响一切。然而,在平台游戏中,引力是有选择性的 —— 如果你添加引力到你的整个游戏世界,你的所有平台都将掉到地上。反之,你可以仅添加引力到你的玩家和敌人精灵中。

首先,在你的 Player 类中添加一个 gravity 函数:

  1.     def gravity(self):
  2.         self.movey += 3.2 # 玩家掉落的多快

这是一个简单的函数。首先,不管你的玩家是否想运动,你设置你的玩家垂直运动。也就是说,你已经编程你的玩家总是在下降。这基本上就是引力。

为使引力函数生效,你必须在你的主循环中调用它。这样,当每一个处理循环时,Python 都应用下落运动到你的玩家。

在这代码中,添加第一行到你的循环中:

  1.     player.gravity() # 检查引力
  2.     player.update()

启动你的游戏来看看会发生什么。要注意,因为它发生的很快:你是玩家从天空上下落,马上掉出了你的游戏屏幕。

你的引力模拟是工作的,但是,也许太好了。

作为一次试验,尝试更改你玩家下落的速度。

给引力添加一个地板

你的游戏没有办法发现你的角色掉落出世界的问题。在一些游戏中,如果一个玩家掉落出世界,该精灵被删除,并在某个新的位置重生。在另一些游戏中,玩家会丢失分数或一条生命。当一个玩家掉落出世界时,不管你想发生什么,你必须能够侦测出玩家何时消失在屏幕外。

在 Python 中,要检查一个条件,你可以使用一个 if 语句。

你必需查看你玩家是否正在掉落,以及你的玩家掉落的程度。如果你的玩家掉落到屏幕的底部,那么你可以做一些事情。简化一下,设置玩家精灵的位置为底部边缘上方 20 像素。

使你的 gravity 函数看起来像这样:

  1.     def gravity(self):
  2.         self.movey += 3.2 # 玩家掉落的多快
  3.        
  4.         if self.rect.y > worldy and self.movey >= 0:
  5.             self.movey = 0
  6.             self.rect.y = worldy-ty

然后,启动你的游戏。你的精灵仍然下落,但是它停在屏幕的底部。不过,你也许不能看到你在地面层之上的精灵。一个简单的解决方法是,在精灵碰撞游戏世界的底部后,通过添加另一个 -ty 到它的新 Y 位置,从而使你的精灵弹跳到更高处:

  1.     def gravity(self):
  2.         self.movey += 3.2 # 玩家掉落的多快
  3.        
  4.         if self.rect.y > worldy and self.movey >= 0:
  5.             self.movey = 0
  6.             self.rect.y = worldy-ty-ty

现在你的玩家在屏幕底部弹跳,恰好在你地面精灵上面。

你的玩家真正需要的是反抗引力的方法。引力问题是,你不能反抗它,除非你有一些东西来推开引力作用。因此,在接下来的文章中,你将添加地面和平台碰撞以及跳跃能力。在这期间,尝试应用引力到敌人精灵。

到目前为止,这里是全部的代码:

  1. #!/usr/bin/env python3
  2. # draw a world
  3. # add a player and player control
  4. # add player movement
  5. # add enemy and basic collision
  6. # add platform
  7. # add gravity
  8.  
  9. # GNU All-Permissive License
  10. # Copying and distribution of this file, with or without modification,
  11. # are permitted in any medium without royalty provided the copyright
  12. # notice and this notice are preserved. This file is offered as-is,
  13. # without any warranty.
  14.  
  15. import pygame
  16. import sys
  17. import os
  18.  
  19. '''
  20. Objects
  21. '''
  22.  
  23. class Platform(pygame.sprite.Sprite):
  24. # x location, y location, img width, img height, img file
  25. def __init__(self,xloc,yloc,imgw,imgh,img):
  26. pygame.sprite.Sprite.__init__(self)
  27. self.image = pygame.image.load(os.path.join('images',img)).convert()
  28. self.image.convert_alpha()
  29. self.rect = self.image.get_rect()
  30. self.rect.y = yloc
  31. self.rect.x = xloc
  32.  
  33. class Player(pygame.sprite.Sprite):
  34. '''
  35. Spawn a player
  36. '''
  37. def __init__(self):
  38. pygame.sprite.Sprite.__init__(self)
  39. self.movex = 0
  40. self.movey = 0
  41. self.frame = 0
  42. self.health = 10
  43. self.score = 1
  44. self.images = []
  45. for i in range(1,9):
  46. img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
  47. img.convert_alpha()
  48. img.set_colorkey(ALPHA)
  49. self.images.append(img)
  50. self.image = self.images[0]
  51. self.rect = self.image.get_rect()
  52.  
  53. def gravity(self):
  54. self.movey += 3.2 # how fast player falls
  55. if self.rect.y > worldy and self.movey >= 0:
  56. self.movey = 0
  57. self.rect.y = worldy-ty-ty
  58. def control(self,x,y):
  59. '''
  60. control player movement
  61. '''
  62. self.movex += x
  63. self.movey += y
  64. def update(self):
  65. '''
  66. Update sprite position
  67. '''
  68.  
  69. self.rect.x = self.rect.x + self.movex
  70. self.rect.y = self.rect.y + self.movey
  71.  
  72. # moving left
  73. if self.movex < 0:
  74. self.frame += 1
  75. if self.frame > ani*3:
  76. self.frame = 0
  77. self.image = self.images[self.frame//ani]
  78.  
  79. # moving right
  80. if self.movex > 0:
  81. self.frame += 1
  82. if self.frame > ani*3:
  83. self.frame = 0
  84. self.image = self.images[(self.frame//ani)+4]
  85.  
  86. # collisions
  87. enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
  88. for enemy in enemy_hit_list:
  89. self.health -= 1
  90. print(self.health)
  91.  
  92. ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
  93. for g in ground_hit_list:
  94. self.health -= 1
  95. print(self.health)
  96.  
  97. class Enemy(pygame.sprite.Sprite):
  98. '''
  99. Spawn an enemy
  100. '''
  101. def __init__(self,x,y,img):
  102. pygame.sprite.Sprite.__init__(self)
  103. self.image = pygame.image.load(os.path.join('images',img))
  104. #self.image.convert_alpha()
  105. #self.image.set_colorkey(ALPHA)
  106. self.rect = self.image.get_rect()
  107. self.rect.x = x
  108. self.rect.y = y
  109. self.counter = 0
  110. def move(self):
  111. '''
  112. enemy movement
  113. '''
  114. distance = 80
  115. speed = 8
  116.  
  117. if self.counter >= 0 and self.counter <= distance:
  118. self.rect.x += speed
  119. elif self.counter >= distance and self.counter <= distance*2:
  120. self.rect.x -= speed
  121. else:
  122. self.counter = 0
  123.  
  124. self.counter += 1
  125.  
  126. class Level():
  127. def bad(lvl,eloc):
  128. if lvl == 1:
  129. enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
  130. enemy_list = pygame.sprite.Group() # create enemy group
  131. enemy_list.add(enemy) # add enemy to group
  132. if lvl == 2:
  133. print("Level " + str(lvl) )
  134.  
  135. return enemy_list
  136.  
  137. def loot(lvl,lloc):
  138. print(lvl)
  139.  
  140. def ground(lvl,gloc,tx,ty):
  141. ground_list = pygame.sprite.Group()
  142. i=0
  143. if lvl == 1:
  144. while i < len(gloc):
  145. ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
  146. ground_list.add(ground)
  147. i=i+1
  148.  
  149. if lvl == 2:
  150. print("Level " + str(lvl) )
  151.  
  152. return ground_list
  153.  
  154. def platform(lvl,tx,ty):
  155. plat_list = pygame.sprite.Group()
  156. ploc = []
  157. i=0
  158. if lvl == 1:
  159. ploc.append((0,worldy-ty-128,3))
  160. ploc.append((300,worldy-ty-256,3))
  161. ploc.append((500,worldy-ty-128,4))
  162.  
  163. while i < len(ploc):
  164. j=0
  165. while j <= ploc[i][2]:
  166. plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
  167. plat_list.add(plat)
  168. j=j+1
  169. print('run' + str(i) + str(ploc[i]))
  170. i=i+1
  171.  
  172. if lvl == 2:
  173. print("Level " + str(lvl) )
  174.  
  175. return plat_list
  176.  
  177. '''
  178. Setup
  179. '''
  180. worldx = 960
  181. worldy = 720
  182.  
  183. fps = 40 # frame rate
  184. ani = 4 # animation cycles
  185. clock = pygame.time.Clock()
  186. pygame.init()
  187. main = True
  188.  
  189. BLUE = (25,25,200)
  190. BLACK = (23,23,23 )
  191. WHITE = (254,254,254)
  192. ALPHA = (0,255,0)
  193.  
  194. world = pygame.display.set_mode([worldx,worldy])
  195. backdrop = pygame.image.load(os.path.join('images','stage.png')).convert()
  196. backdropbox = world.get_rect()
  197. player = Player() # spawn player
  198. player.rect.x = 0
  199. player.rect.y = 0
  200. player_list = pygame.sprite.Group()
  201. player_list.add(player)
  202. steps = 10 # how fast to move
  203.  
  204. eloc = []
  205. eloc = [200,20]
  206. gloc = []
  207. #gloc = [0,630,64,630,128,630,192,630,256,630,320,630,384,630]
  208. tx = 64 #tile size
  209. ty = 64 #tile size
  210.  
  211. i=0
  212. while i <= (worldx/tx)+tx:
  213. gloc.append(i*tx)
  214. i=i+1
  215.  
  216. enemy_list = Level.bad( 1, eloc )
  217. ground_list = Level.ground( 1,gloc,tx,ty )
  218. plat_list = Level.platform( 1,tx,ty )
  219.  
  220. '''
  221. Main loop
  222. '''
  223. while main == True:
  224. for event in pygame.event.get():
  225. if event.type == pygame.QUIT:
  226. pygame.quit(); sys.exit()
  227. main = False
  228.  
  229. if event.type == pygame.KEYDOWN:
  230. if event.key == pygame.K_LEFT or event.key == ord('a'):
  231. print("LEFT")
  232. player.control(-steps,0)
  233. if event.key == pygame.K_RIGHT or event.key == ord('d'):
  234. print("RIGHT")
  235. player.control(steps,0)
  236. if event.key == pygame.K_UP or event.key == ord('w'):
  237. print('jump')
  238.  
  239. if event.type == pygame.KEYUP:
  240. if event.key == pygame.K_LEFT or event.key == ord('a'):
  241. player.control(steps,0)
  242. if event.key == pygame.K_RIGHT or event.key == ord('d'):
  243. player.control(-steps,0)
  244. if event.key == pygame.K_UP or event.key == ord('w'):
  245. print('jump')
  246.  
  247. if event.key == ord('q'):
  248. pygame.quit()
  249. sys.exit()
  250. main = False
  251.  
  252. world.blit(backdrop, backdropbox)
  253. player.gravity() # check gravity
  254. player.update()
  255. player_list.draw(world)
  256. enemy_list.draw(world)
  257. ground_list.draw(world)
  258. plat_list.draw(world)
  259. for e in enemy_list:
  260. e.move()
  261. pygame.display.flip()
  262. clock.tick(fps)
【责任编辑:庞桂玉 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

Python应用场景实战手册

Python应用场景实战手册

Python应用场景实战手册
共3章 | KaliArch

16人订阅学习

一步到位玩儿透Ansible

一步到位玩儿透Ansible

Ansible
共17章 | 骏马金龙1

182人订阅学习

云架构师修炼手册

云架构师修炼手册

云架构师的必备技能
共3章 | Allen在路上

131人订阅学习

读 书 +更多

公钥基础设施PKI及其应用

公钥基础设施PKI(Public Key Infrastructure)是利用公钥概念和加密技术为网上通信提供的符合标准的一整套安全基础平台。公钥基础设施能为...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微