如何在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 Web框架Flask中使用新浪SAE云存储实例
Feb 08 Python
使用Python解析JSON数据的基本方法
Oct 15 Python
Python下的常用下载安装工具pip的安装方法
Nov 13 Python
你真的了解Python的random模块吗?
Dec 12 Python
python队列queue模块详解
Apr 27 Python
Python实现自定义读写分离代码实例
Nov 16 Python
PyTorch 对应点相乘、矩阵相乘实例
Dec 27 Python
PyCharm刷新项目(文件)目录的实现
Feb 14 Python
Python 捕获代码中所有异常的方法
Aug 03 Python
解决阿里云邮件发送不能使用25端口问题
Aug 07 Python
Pycharm配置lua编译环境过程图解
Nov 28 Python
Python读取图像并显示灰度图的实现
Dec 01 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求小于1000的所有水仙花数的代码
2012/01/10 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
PHP7 新增功能
2021/03/09 PHP
js鼠标滑过图片震动特效的方法
2015/02/17 Javascript
jQuery实现数秒后自动提交form的方法
2015/03/05 Javascript
Javascript代码实现仿实例化类
2015/04/03 Javascript
jQuery链式操作实例分析
2015/11/16 Javascript
jquery表单验证插件formValidator使用方法
2016/04/01 Javascript
Javascript动画效果(4)
2016/10/11 Javascript
详谈ES6中的迭代器(Iterator)和生成器(Generator)
2017/07/31 Javascript
jQuery EasyUI的TreeGrid查询功能实现方法
2017/08/08 jQuery
IScroll5实现下拉刷新上拉加载的功能实例
2017/08/11 Javascript
ES6解构赋值实例详解
2017/10/31 Javascript
详解webpack+ES6+Sass搭建多页面应用
2018/11/05 Javascript
仿vue-cli搭建属于自己的脚手架的方法步骤
2019/04/17 Javascript
JS实现处理时间,年月日,星期的公共方法示例
2019/05/31 Javascript
浅谈vue权限管理实现及流程
2020/04/23 Javascript
Nodejs实现微信分账的示例代码
2021/01/19 NodeJs
[07:43]《辉夜杯》公开赛晋级外卡赛战队—TRG训练生活探秘
2015/12/11 DOTA
[58:18]2018DOTA2亚洲邀请赛3月29日 小组赛B组 iG VS Mineski
2018/03/30 DOTA
[06:53]2018DOTA2国际邀请赛寻真——为复仇而来的Newbee
2018/08/15 DOTA
[53:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第一场 1月31日
2021/03/11 DOTA
Win7下搭建python开发环境图文教程(安装Python、pip、解释器)
2016/05/17 Python
Python中的复制操作及copy模块中的浅拷贝与深拷贝方法
2016/07/02 Python
Python3.5 Pandas模块缺失值处理和层次索引实例详解
2019/04/23 Python
Pycharm安装Qt Design快捷工具的详细教程
2020/11/18 Python
美国体育用品在线:Modell’s Sporting Goods
2018/06/07 全球购物
惠普香港官方商店:HP香港
2019/04/30 全球购物
英国发展最快的在线超市之一:Click Marketplace
2021/02/15 全球购物
致跳远运动员加油稿
2014/02/11 职场文书
违反工作纪律检讨书
2014/02/15 职场文书
村容村貌整治方案
2014/05/21 职场文书
借款协议书
2014/09/16 职场文书
2014院党委领导班子对照检查材料思想汇报
2014/09/24 职场文书
爱护环境建议书
2015/09/14 职场文书
2015年幼儿园班主任个人工作总结
2015/10/22 职场文书