如何在Python 游戏中模拟引力


Posted in Python onMarch 27, 2020

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

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

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

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

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

添加一个引力函数

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

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

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

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

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

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

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

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

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

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

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

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

给引力添加一个地板

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

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

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

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

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

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

def gravity(self):
    self.movey += 3.2 # 玩家掉落的多快
    
    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)

总结

到此这篇关于在你的 Python 游戏中模拟引力的文章就介绍到这了,更多相关在你的 Python 游戏中模拟引力内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
低版本中Python除法运算小技巧
Apr 05 Python
Python中的测试模块unittest和doctest的使用教程
Apr 14 Python
Python给定一个句子倒序输出单词以及字母的方法
Dec 20 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
Jan 15 Python
用Pycharm实现鼠标滚轮控制字体大小的方法
Jan 15 Python
Python 存储字符串时节省空间的方法
Apr 23 Python
python使用Qt界面以及逻辑实现方法
Jul 10 Python
Pytorch卷积层手动初始化权值的实例
Aug 17 Python
python torch.utils.data.DataLoader使用方法
Apr 02 Python
在keras中对单一输入图像进行预测并返回预测结果操作
Jul 09 Python
python基于win32api实现键盘输入
Dec 09 Python
python的变量和简单数字类型详解
Sep 15 Python
Python 实现平台类游戏添加跳跃功能
Mar 27 #Python
django配置app中的静态文件步骤
Mar 27 #Python
使用卷积神经网络(CNN)做人脸识别的示例代码
Mar 27 #Python
django实现HttpResponse返回json数据为中文
Mar 27 #Python
python对XML文件的操作实现代码
Mar 27 #Python
Python Socketserver实现FTP文件上传下载代码实例
Mar 27 #Python
使用python从三个角度解决josephus问题的方法
Mar 27 #Python
You might like
基于PHP常用函数的用法详解
2013/05/10 PHP
Joomla语言翻译类Jtext用法分析
2016/05/05 PHP
PHP+JS实现的实时搜索提示功能
2018/03/13 PHP
laravel在中间件内生成参数并且传递到控制器中的2种姿势
2019/10/15 PHP
js下用层来实现select的title提示属性
2010/02/23 Javascript
来自国外的30个基于jquery的Web下拉菜单
2012/06/22 Javascript
完美兼容各大浏览器获取HTTP_REFERER方法总结
2014/06/24 Javascript
angularjs指令中的compile与link函数详解
2014/12/06 Javascript
通过XMLHttpRequest和jQuery实现ajax的几种方式
2015/08/28 Javascript
Bootstrap 布局组件(全)
2016/07/18 Javascript
利用Angular.js编写公共提示模块的方法教程
2017/05/28 Javascript
详解React-Native全球化多语言切换工具库react-native-i18n
2017/11/03 Javascript
vue中mint-ui的使用方法
2018/04/04 Javascript
JavaScript中的ES6 Proxy的具体使用
2019/06/16 Javascript
使用vue cli4.x搭建vue项目的过程详解
2020/05/08 Javascript
[04:56]经典回顾:前Ehome 与 前LGD
2015/02/26 DOTA
[00:11]战神迅矛
2019/03/06 DOTA
[01:02:54]完美世界DOTA2联赛PWL S2 FTD vs GXR 第一场 11.22
2020/11/26 DOTA
Python函数中定义参数的四种方式
2014/11/30 Python
Python字符串逐字符或逐词反转方法
2015/05/21 Python
django加载本地html的方法
2018/05/27 Python
python format 格式化输出方法
2018/07/16 Python
Python爬虫库requests获取响应内容、响应状态码、响应头
2020/01/25 Python
Python代码注释规范代码实例解析
2020/08/14 Python
python des,aes,rsa加解密的实现
2021/01/16 Python
日本PLST在线商店:日本时尚杂志刊载的人气服装
2016/12/10 全球购物
意大利中国电子产品购物网站:Geekmall.com
2019/09/30 全球购物
Fossil德国官网:化石手表、手袋、珠宝及配件
2019/12/07 全球购物
教师实习期自我鉴定
2013/10/06 职场文书
安全责任书模板
2014/07/22 职场文书
教师四风自我剖析材料
2014/09/30 职场文书
北京英语导游词
2015/02/12 职场文书
地球一小时活动总结
2015/02/27 职场文书
2016大学迎新晚会开场白
2015/11/24 职场文书
安全生产协议书
2016/03/22 职场文书
利用Nginx代理如何解决前端跨域问题详析
2021/04/02 Servers