前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在Python游戏中模拟重力【Programming(Python)】

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

作者头像
Potato
修改2019-12-02 11:22:41
2.2K0
修改2019-12-02 11:22:41
举报
文章被收录于专栏:Opensource翻译专栏

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

图片来源:Public Domain
图片来源:Public Domain

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

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

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

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

添加重力函数

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

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

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

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

代码语言:javascript
复制
 def gravity(self):
  self.movey += 3.2 # how fast player falls

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

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

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

代码语言:javascript
复制
     player.gravity() # check gravity
     player.update()

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

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

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

为重力添加地板

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

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

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

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

代码语言:javascript
复制
 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来使您的玩家弹跳更高:

代码语言:javascript
复制
 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

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

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

代码语言:javascript
复制
 #!/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中创建视频游戏的系列文章的第六部分。

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 添加重力函数
  • 为重力添加地板
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档