在Python游戏中模拟重力【Programming(Python)】

了解如何使用Python的Pygame模块对电子游戏进行编程,并开始操纵重力。

图片来源:Public Domain

现实世界充满了运动和生活。 使现实世界变得如此繁忙和动态的是物理。 物理是物质在太空中移动的方式。因为电子游戏世界没有物理,它也没有物理,所以游戏程序员必须模拟物理。

对于大多数电子游戏而言,物理学上基本上只有两个重要方面:重力和碰撞。

在向游戏中添加敌人时,您实现了一些碰撞检测,但是由于重力需要碰撞检测,因此本文添加了更多内容。 考虑一下为什么重力可能涉及碰撞。 如果您无法想到任何原因,请不要担心-当您处理示例代码时,它将变得显而易见。

现实世界中的重力是物体趋向于相互吸引的趋势。 物体越大,它施加的重力影响越大。 在视频游戏物理学中,您不必创建质量足以证明引力合理的对象; 您只需编程一种趋势,即可使物体掉落到视频游戏世界中最大的物体:世界本身。

添加重力函数

记住,你的玩家已经有一个属性来决定运动。 使用此属性将玩家拉向屏幕底部。

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

在现实世界中,引力影响着一切。 然而,在平台构建者中,重力是有选择性的——如果你在整个游戏世界中加入重力,你所有的平台都会掉到地上。 相反,你只是给你的玩家和敌人增加重力。

首先,在你的玩家类中添加一个引力函数:

 def gravity(self):
  self.movey += 3.2 # how fast player falls

这是一个简单的功能。 首先,无论玩家是否要运动,都将其设置为垂直运动。 换句话说,您已将玩家编程为始终处于下降状态。 这基本上是重力。

为了使重力函数起作用,必须在主循环中调用它。 这样,Python会在循环向您的玩家施加一次下降运动。

在此代码中,将第一行添加到循环中:

     player.gravity() # check gravity
     player.update()

启动你的游戏,看看会发生什么。注意,因为它发生得很快:你的玩家从天上掉下来,就在你的游戏屏幕上。

你的重力模拟起作用了,但也许效果太好了。

作为一个实验,尝试改变玩家下降的速度。

为重力添加地板

您的角色掉落世界的问题是您的游戏无法检测到它。 在某些游戏中,如果玩家摔倒了,该对象将被删除并在新的地方重新生成。 在其他游戏中,玩家失去积分或生命。 当玩家脱离世界时,无论您想发生什么,您都必须能够检测到玩家何时消失在屏幕外。

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

您必须检查玩家是否跌落以及玩家跌落了多远。如果您的玩家跌落到可以到达屏幕底部的程度,那么您可以采取一些措施。为简单起见,请将玩家的位置设置为底部边缘上方20像素。

使您的重力函数看起来像这样:

 def gravity(self):
  self.movey += 3.2 # how fast player falls
  
  if self.rect.y > worldy and self.movey >= 0:
  self.movey = 0
  self.rect.y = worldy-ty

然后启动您的游戏。 您的玩家仍会掉落,但会停在屏幕底部。 不过,您可能无法在地面层后面看到玩家。 一个简单的解决方法是在达到游戏世界最低点之后,通过在其新的Y位置添加另一个-ty来使您的玩家弹跳更高:

 def gravity(self):
  self.movey += 3.2 # how fast player falls
  
  if self.rect.y > worldy and self.movey >= 0:
  self.movey = 0
  self.rect.y = worldy-ty-ty

玩家真正需要的是一种对抗重力的方法。问题在于,除非你有什么东西可以推开,否则你无法抗拒重力。 因此,在下一篇文章中,您将添加地面和平台碰撞以及跳跃能力。 与此同时,试着对敌人施加重力。

到目前为止,所有代码如下:

 #!/usr/bin/env python3
 # draw a world
 # add a player and player control
 # add player movement
 # add enemy and basic collision
 # add platform
 # add gravity
 
 # GNU All-Permissive License
 # Copying and distribution of this file, with or without modification,
 # are permitted in any medium without royalty provided the copyright
 # notice and this notice are preserved.  This file is offered as-is,
 # without any warranty.
 
 import pygame
 import sys
 import os
 
 '''
 Objects
 '''
 
 class Platform(pygame.sprite.Sprite):
  # x location, y location, img width, img height, img file    
  def __init__(self,xloc,yloc,imgw,imgh,img):
         pygame.sprite.Sprite.__init__(self)
  self.image = pygame.image.load(os.path.join('images',img)).convert()
  self.image.convert_alpha()
  self.rect = self.image.get_rect()
  self.rect.y = yloc
  self.rect.x = xloc
 
 class Player(pygame.sprite.Sprite):
  '''
     Spawn a player
     '''
  def __init__(self):
         pygame.sprite.Sprite.__init__(self)
  self.movex = 0
  self.movey = 0
  self.frame = 0
  self.health = 10
  self.score = 1
  self.images = []
  for i in range(1,9):
             img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
             img.convert_alpha()
             img.set_colorkey(ALPHA)
  self.images.append(img)
  self.image = self.images[0]
  self.rect = self.image.get_rect()
 
  def gravity(self):
  self.movey += 3.2 # how fast player falls
  
  if self.rect.y > worldy and self.movey >= 0:
  self.movey = 0
  self.rect.y = worldy-ty-ty
  
  def control(self,x,y):
  '''
         control player movement
         '''
  self.movex += x
  self.movey += y
  
  def update(self):
  '''
         Update sprite position
         '''
 
  self.rect.x = self.rect.x + self.movex
  self.rect.y = self.rect.y + self.movey
 
  # moving left
  if self.movex < 0:
  self.frame += 1
  if self.frame > ani*3:
  self.frame = 0
  self.image = self.images[self.frame//ani]
 
  # moving right
  if self.movex > 0:
  self.frame += 1
  if self.frame > ani*3:
  self.frame = 0
  self.image = self.images[(self.frame//ani)+4]
 
  # collisions
         enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
  for enemy in enemy_hit_list:
  self.health -= 1
  print(self.health)
 
         ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
  for g in ground_hit_list:
  self.health -= 1
  print(self.health)
 
 class Enemy(pygame.sprite.Sprite):
  '''
     Spawn an enemy
     '''
  def __init__(self,x,y,img):
         pygame.sprite.Sprite.__init__(self)
  self.image = pygame.image.load(os.path.join('images',img))
  #self.image.convert_alpha()
  #self.image.set_colorkey(ALPHA)
  self.rect = self.image.get_rect()
  self.rect.x = x
  self.rect.y = y
  self.counter = 0
  
  def move(self):
  '''
         enemy movement
         '''
         distance = 80
         speed = 8
 
  if self.counter >= 0 and self.counter <= distance:
  self.rect.x += speed
  elif self.counter >= distance and self.counter <= distance*2:
  self.rect.x -= speed
  else:
  self.counter = 0
 
  self.counter += 1
 
 class Level():
  def bad(lvl,eloc):
  if lvl == 1:
             enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
             enemy_list = pygame.sprite.Group() # create enemy group 
             enemy_list.add(enemy) # add enemy to group
  
  if lvl == 2:
  print("Level " + str(lvl) )
 
  return enemy_list
 
  def loot(lvl,lloc):
  print(lvl)
 
  def ground(lvl,gloc,tx,ty):
         ground_list = pygame.sprite.Group()
         i=0
  if lvl == 1:
  while i < len(gloc):
                 ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
                 ground_list.add(ground)
                 i=i+1
 
  if lvl == 2:
  print("Level " + str(lvl) )
 
  return ground_list
 
  def platform(lvl,tx,ty):
         plat_list = pygame.sprite.Group()
         ploc = []
         i=0
  if lvl == 1:
             ploc.append((0,worldy-ty-128,3))
             ploc.append((300,worldy-ty-256,3))
             ploc.append((500,worldy-ty-128,4))
 
  while i < len(ploc):
                 j=0
  while j <= ploc[i][2]:
                     plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
                     plat_list.add(plat)
                     j=j+1
  print('run' + str(i) + str(ploc[i]))
                 i=i+1
 
  if lvl == 2:
  print("Level " + str(lvl) )
 
  return plat_list
 
 '''
 Setup
 '''
 worldx = 960
 worldy = 720
 
 fps = 40 # frame rate
 ani = 4 # animation cycles
 clock = pygame.time.Clock()
 pygame.init()
 main = True
 
 BLUE  = (25,25,200)
 BLACK = (23,23,23 )
 WHITE = (254,254,254)
 ALPHA = (0,255,0)
 
 world = pygame.display.set_mode([worldx,worldy])
 backdrop = pygame.image.load(os.path.join('images','stage.png')).convert()
 backdropbox = world.get_rect()
 player = Player() # spawn player
 player.rect.x = 0
 player.rect.y = 0
 player_list = pygame.sprite.Group()
 player_list.add(player)
 steps = 10 # how fast to move
 
 eloc = []
 eloc = [200,20]
 gloc = []
 #gloc = [0,630,64,630,128,630,192,630,256,630,320,630,384,630]
 tx = 64 #tile size
 ty = 64 #tile size
 
 i=0
 while i <= (worldx/tx)+tx:
     gloc.append(i*tx)
     i=i+1
 
 enemy_list = Level.bad( 1, eloc )
 ground_list = Level.ground( 1,gloc,tx,ty )
 plat_list = Level.platform( 1,tx,ty )
 
 '''
 Main loop
 '''
 while main == True:
  for event in pygame.event.get():
  if event.type == pygame.QUIT:
             pygame.quit(); sys.exit()
             main = False
 
  if event.type == pygame.KEYDOWN:
  if event.key == pygame.K_LEFT or event.key == ord('a'):
  print("LEFT")
                 player.control(-steps,0)
  if event.key == pygame.K_RIGHT or event.key == ord('d'):
  print("RIGHT")
                 player.control(steps,0)
  if event.key == pygame.K_UP or event.key == ord('w'):
  print('jump')
 
  if event.type == pygame.KEYUP:
  if event.key == pygame.K_LEFT or event.key == ord('a'):
                 player.control(steps,0)
  if event.key == pygame.K_RIGHT or event.key == ord('d'):
                 player.control(-steps,0)
  if event.key == pygame.K_UP or event.key == ord('w'):
  print('jump')
 
  if event.key == ord('q'):
                 pygame.quit()
  sys.exit()
                 main = False
 
     world.blit(backdrop, backdropbox)
     player.gravity() # check gravity
     player.update()
     player_list.draw(world)
     enemy_list.draw(world)
     ground_list.draw(world)
     plat_list.draw(world)
  for e in enemy_list:
         e.move()
     pygame.display.flip()
     clock.tick(fps)

这是关于使用 Pygame 模块在 Python 3中创建视频游戏的系列文章的第六部分。

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
在Python游戏中模拟重力【Programming(Python)】
现实世界充满了运动和生活。 使现实世界变得如此繁忙和动态的是物理。 物理是物质在太空中移动的方式。因为电子游戏世界没有物理,它也没有物理,所以游戏程序员必须模拟...
<<上一篇
下一篇>>