如何在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开发vim插件及心得分享
Nov 04 Python
用Python编写一个基于终端的实现翻译的脚本
Apr 24 Python
Python利用pandas计算多个CSV文件数据值的实例
Apr 19 Python
Python处理命令行参数模块optpars用法实例分析
May 31 Python
Python利用Django如何写restful api接口详解
Jun 08 Python
python 提取tuple类型值中json格式的key值方法
Dec 31 Python
python中对数据进行各种排序的方法
Jul 02 Python
OpenCV 模板匹配
Jul 10 Python
一行python实现树形结构的方法
Aug 09 Python
python3 自动打印出最新版本执行的mysql2redis实例
Apr 09 Python
Python RabbitMQ实现简单的进程间通信示例
Jul 02 Python
Python 绘制可视化折线图
Jul 22 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 和 MySQL 基础教程(一)
2006/10/09 PHP
PHP模块 Memcached功能多于Memcache
2011/06/14 PHP
php中使用getimagesize获取图片、flash等文件的尺寸信息实例
2014/04/29 PHP
php实现文件下载功能的几个代码分享
2014/05/10 PHP
ThinkPHP中limit()使用方法详解
2016/04/19 PHP
Bootstrap+PHP实现多图上传功能实例详解
2018/04/08 PHP
JS实现浏览器菜单命令
2006/09/05 Javascript
一段非常简单的让图片自动切换js代码
2006/11/10 Javascript
javaScript call 函数的用法说明
2010/04/09 Javascript
jquery学习笔记二 实现可编辑的表格
2010/04/09 Javascript
js 创建快捷方式的代码(fso)
2010/11/19 Javascript
扩展jQuery对象时如何扩展成员变量具体怎么实现
2014/04/25 Javascript
js中的setInterval和setTimeout使用实例
2014/05/09 Javascript
基于touch.js手势库+zepto.js插件开发图片查看器(滑动、缩放、双击缩放)
2016/11/17 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
AngularJS点击添加样式、点击变色设置的实例代码
2017/07/27 Javascript
node通过express搭建自己的服务器
2017/09/30 Javascript
JS中touchstart事件与click事件冲突的解决方法
2018/03/12 Javascript
react router4+redux实现路由权限控制的方法
2018/05/03 Javascript
实例讲解JavaScript 计时事件
2020/07/04 Javascript
在react项目中使用antd的form组件,动态设置input框的值
2020/10/24 Javascript
[48:41]VP vs VG Supermajor小组赛 B组胜者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
Python中每次处理一个字符的5种方法
2015/05/21 Python
Python Socket使用实例
2017/12/18 Python
Python3爬虫爬取英雄联盟高清桌面壁纸功能示例【基于Scrapy框架】
2018/12/05 Python
Python参数类型以及常见的坑详解
2019/07/08 Python
python中web框架的自定义创建
2019/09/08 Python
django drf框架自带的路由及最简化的视图
2019/09/10 Python
俄罗斯卫浴采暖及维修用品超级市场:Dkrussia
2020/05/12 全球购物
美国室内盆栽植物购买网站:Plants.com
2020/04/24 全球购物
最新个人职业生涯规划书
2014/01/22 职场文书
关于逃课的检讨书
2014/01/23 职场文书
2015年世界环境日活动方案
2015/05/05 职场文书
2015年小学总务工作总结
2015/07/21 职场文书
导游词之烟台威海蓬莱
2019/11/14 职场文书