如何在Python 游戏中模拟引力

学习如何使用 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 游戏中模拟引力内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python 实现平台类游戏添加跳跃功能

    在本期使用 Python Pygame 模块编写视频游戏中,学会如何使用跳跃来对抗重力. 在本系列的前一篇文章 中,你已经模拟了重力.但现在,你需要赋予你的角色跳跃的能力来对抗重力. 跳跃是对重力作用的暂时延缓.在这一小段时间里,你是向上跳,而不是被重力拉着向下落.但你一旦到达了跳跃的最高点,重力就会重新发挥作用,将你拉回地面. 在代码中,这种变化被表示为变量.首先,你需要为玩家精灵建立一个变量,使得 Python 能够跟踪该精灵是否正在跳跃中.一旦玩家精灵开始跳跃,他就会再次受到重力的作用,并

  • Python实现打砖块小游戏代码实例

    这次用Python实现的是一个接球打砖块的小游戏,需要导入pygame模块,有以下两条经验总结: 1.多父类的继承2.碰撞检测的数学模型 知识点稍后再说,我们先看看游戏的效果和实现: 一.游戏效果 二.游戏代码 #导入模块 import pygame from pygame.locals import * import sys,random,time,math class GameWindow(object): '''创建游戏窗口类''' def __init__(self,*args,**kw

  • python贪吃蛇游戏代码

    本文实例为大家分享了python贪吃蛇游戏的具体代码,供大家参考,具体内容如下 贪吃蛇游戏截图: 首先安装pygame,可以使用pip安装pygame: pip install pygame 运行以下代码即可: #!/usr/bin/env python import pygame,sys,time,random from pygame.locals import * # 定义颜色变量 redColour = pygame.Color(255,0,0) blackColour = pygame.

  • python实现飞机大战游戏

    飞机大战(Python)代码分为两个python文件,工具类和主类,需要安装pygame模块,能完美运行(网上好多不完整的,调试得心累.实现出来,成就感还是满满的),如图所示: 完整代码如下: 1.工具类plane_sprites.py import random import pygame # 屏幕大小的常量 SCREEN_RECT = pygame.Rect(0, 0, 480, 700) # 刷新的帧率 FRAME_PER_SEC = 60 # 创建敌机的定时器常量 CREATE_ENEM

  • 如何在Python 游戏中模拟引力

    学习如何使用 Python 的 Pygame 模块编程电脑游戏,并开始操作引力. 真实的世界充满了运动和生活.物理学使得真实的生活如此忙碌和动态.物理学是物质在空间中运动的方式.既然一个电脑游戏世界没有物质,它也就没有物理学规律,使用游戏程序员不得不模拟物理学. 从大多数电脑游戏来说,这里基本上仅有两个方面的物理学是重要的:引力和碰撞. 当你添加一个敌人到你的游戏中时,你实现了一些碰撞检测,但是这篇文章要添加更多的东西,因为引力需要碰撞检测.想想为什么引力可能涉及碰撞.如果你不能想到任何原因,不

  • 如何在python字符串中输入纯粹的{}

    python的format函数通过{}来格式化字符串 >>> a='{0}'.format(123) >>> a '123' 如果需要在文本中包含{}字符,这样使用就会报错: >>> a='{123} {0}'.format('123') Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: tup

  • 如何在Python项目中引入日志

    Logging模块的使用 简单使用 Logging 模块提供了一系列便利的函数 它们分别是 debug(), info(), warning(), error(), critical() import logging logging.debug('debug log test') logging.info('info log test') logging.warning('warning log test') logging.error('error log test') logging.cri

  • 举例讲解如何在Python编程中进行迭代和遍历

    迭代 首先理解下什么是迭代,python中所有从左往右扫面对象的方式都是可迭代的 有哪些方式是可迭代的: 1.文件操作 我们读取文件的时候,会用到一个readline()方法,其实它就是一个迭代器,它会返回当前的数据,然后自动的调用内置的next()方法来让文件的读取头自动的移动到当前的下面一行,准备下次的读取,到达文件末尾时,就会返回空字符串. >>> f=open('hello.py') >>> f.readline() '#!/usr/bin/python2.5\

  • 对于Python编程中一些重用与缩减的建议

    返璞归真 许多流行的玩具都以这样一个概念为基础:简单的积木.这些简单的积木可通过多种方式组合在一起构造出全新的作品 -- 有时甚至完全令人出乎意料.这一概念同样适用于现实生活中的建筑领域,将基本原材料组合在一起,形成有用的建筑物.平凡无奇的材料.技术和工具简化了新建筑物的建造过程,同样也简化了对新踏入此领域的人员的培训. 相同的基本概念也适用于计算机程序开发技术,包括以 Python 编程语言编写的程序.本文介绍了使用 Python 创建基本构件 (building block) 的方法,可用于

  • celery在python爬虫中定时操作实例讲解

    使用定时功能对于我们想要快速获取某个数据来说,是一个非常好的方法.这样我们就不用苦苦守在电脑屏幕前,只为蹲到某个想要的东西.在之前我们已经讲过time函数进行定时操作,这算是time函数的比较基础的一个用法了.其实定时功能同样可以用celery实现,具体的方法我们往下看: 爬虫由于其特殊性,可能需要定时做增量抓取,也可能需要定时做模拟登陆,以防止cookie过期,而celery恰恰就实现了定时任务的功能.在上述基础上,我们将`tasks.py`文件改成如下内容 from celery impor

  • python基于pygame实现响应游戏中事件的方法(附源码)

    本文实例讲述了python基于pygame实现响应游戏中事件的方法.分享给大家供大家参考,具体如下: 先看一下我做的demo效果: 当玩家按下键盘上的:上,下,左,右键的时候,后台会打印出玩家所按键的数字值,而图形会随之移动 这是客观上面存在的现象. 那么啥是事件呢? 你叫我做出定义,我不知道,我只能举个例子说明,例如接下来的代码中,列出来一些关于游戏中的事件 ''' 事件 产生途径 参数 QUIT 用户按下关闭按钮 none ATIVEEVENT Pygame被激活或者隐藏 gain, sta

  • 如何在python中实现随机选择

    这篇文章主要介绍了如何在python中实现随机选择,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 想从一个序列中随机抽取若干元素,或者想生成几个随机数. random 模块有大量的函数用来产生随机数和随机选择元素.比如,要想从一个序列中随机的抽取一个元素,可以使用random.choice() : >>> import random >>> values = [1, 2, 3, 4, 5, 6] >>>

  • 如何在python中写hive脚本

    这篇文章主要介绍了如何在python中写hive脚本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.直接执行.sql脚本 import numpy as np import pandas as pd import lightgbm as lgb from pandas import DataFrame from sklearn.model_selection import train_test_split from io import St

  • Python编程在flask中模拟进行Restful的CRUD操作

    这篇文章中我们将通过对HelloWorld的message进行操作,介绍一下如何使用flask进行Restful的CRUD. 概要信息 事前准备:flask liumiaocn:flask liumiao$ which flask /usr/local/bin/flask liumiaocn:flask liumiao$ flask --version Flask 1.0.2 Python 2.7.10 (default, Jul 15 2017, 17:16:57) [GCC 4.2.1 Co

随机推荐