Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >在Python游戏中模拟重力【Programming(Python)】

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

作者头像
Potato
修改于 2019-12-02 03:22:41
修改于 2019-12-02 03:22:41
2.3K00
代码可运行
举报
运行总次数:0
代码可运行

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

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

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

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

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

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

添加重力函数

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 def gravity(self):
  self.movey += 3.2 # how fast player falls

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     player.gravity() # check gravity
     player.update()

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

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

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

为重力添加地板

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 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
代码运行次数:0
运行
AI代码解释
复制
 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
代码运行次数:0
运行
AI代码解释
复制
 #!/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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
图像二值化方法汇总介绍
ImageJ中图像二值化方法介绍 概述 二值图像分析在对象识别与模式匹配中有重要作用,同时也在机器人视觉中也是图像处理的关键步骤,选择不同图像二值化方法得到的结果也不尽相同。本文介绍超过十种以上的基于
OpenCV学堂
2018/04/04
4.7K1
图像二值化方法汇总介绍
Task05 图像分割/二值化
该部分的学习内容是对经典的阈值分割算法进行回顾,图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单、计算量小、性能较稳定而成为图像分割中最基本和应用最广泛的分割技术。它特别适用于目标和背景占据不同灰度级范围的图像。它不仅可以极大的压缩数据量,而且也大大简化了分析和处理步骤,因此在很多情况下,是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。图像阈值化的目的是要按照灰度级,对像素集合进行一个划分,得到的每个子集形成一个与现实景物相对应的区域,各个区域内部具有一致的属性,而相邻区域不具有这种一致属性。这样的划分可以通过从灰度级出发选取一个或多个阈值来实现。
致Great
2020/05/06
1.3K0
OpenCV基础 | 11.图像二值化
学习视频可参见python+opencv3.3视频教学 基础入门[1] outline 图像二值化 二值图像 图像二值化方法 OpenCV相关API使用 图像二值化 1.二值图像 二值图像就是将灰度图转化成黑白图,没有灰,在一个值之前为黑,之后为白 2.二值化方法 全局阈值 对整幅图像都是用一个统一的阈值来进行二值化 局部阈值 像素的邻域块的像素值分布来确定该像素位置上的二值化阈值 3.OpenCV中图像二值化方法 二值化函数threshold 函数原型 关于常见的阈值使用方法如下表 OTSU(最大类间方差
快学Python
2021/08/09
8160
Python opencv图像处理基础总结(四) 模板匹配 图像二值化
模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的局限性,主要表现在它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。
叶庭云
2022/05/09
1.6K0
Python opencv图像处理基础总结(四) 模板匹配 图像二值化
【从零学习OpenCV 4】图像二值化
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。
小白学视觉
2019/11/27
1K0
【从零学习OpenCV 4】图像二值化
Python opencv图像处理基础总结(四) 模板匹配 图像二值化
模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的局限性,主要表现在它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。
叶庭云
2020/09/17
4.9K0
Python  opencv图像处理基础总结(四)  模板匹配  图像二值化
二值化算法OTSU源码解析
概述: 本文中小编将会跟大家分享一下OpenCV3.1.0中图像二值化算法OTSU的基本原理与源代码解析,最终还通过几行代码演示了一下如何使用OTSU算法API实现图像二值化。 一:基本原理 该方法是
OpenCV学堂
2018/04/04
2K0
二值化算法OTSU源码解析
一文搞懂图像二值化算法
传统的机器视觉通常包括两个步骤:预处理和物体检测。而沟通二者的桥梁则是图像分割(Image Segmentation)[1]。图像分割通过简化或改变图像的表示形式,使得图像更易于分析。
不脱发的程序猿
2021/05/08
3.4K0
一文搞懂图像二值化算法
Wellner 自适应阈值二值化算法
参考文档: Adaptive Thresholding for the DigitalDesk.pdf
用户1138785
2019/09/11
4.1K0
Wellner 自适应阈值二值化算法
opencv 5 -- 图像阈值
二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓
wust小吴
2019/07/08
8690
OpenCV与图像处理(十)
图像处理是利用计算机对图像进行去噪、增强、复原、重建、编码、压缩、几何变换、分割,提取特征等的理论、方法和技术。图像处理中,输入的是低质量的图像,输出的是改善质量后的图像。
Must
2020/07/27
1.4K0
有赞零售小票打印图片二值化方案
小票打印是零售商家的基础功能,在小票信息中,必然会存在一些相关店铺的信息。比如,logo 、店铺二维码等。对于商家来说,上传 logo 及店铺二维码时,基本都是彩图,但是小票打印机基本都是只支持黑白二值图打印。为了商家的服务体验,我们没有对商家上传的图片进行要求,商家可以根据实际情况上传自己的个性化图片,因此就需要我们对商家的图片进行二值图处理后进行打印。
有赞coder
2020/08/25
9270
有赞零售小票打印图片二值化方案
基于OpenCV的图像分割处理!
图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单、计算量小、性能较稳定而成为图像分割中最基本和应用最广泛的分割技术。它特别适用于目标和背景占据不同灰度级范围的图像。它不仅可以极大的压缩数据量,而且也大大简化了分析和处理步骤,因此在很多情况下,是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。
Datawhale
2020/07/09
3.6K0
基于OpenCV的图像分割处理!
系列4 | CV领域入门,马上开始进阶咯
元宵节看样子快到了,才立春、才春节、才开工,不知不觉到了元宵,估摸着2019确实过得挺快的!
计算机视觉研究院
2019/03/07
4790
系列4 | CV领域入门,马上开始进阶咯
CV学习笔记(十二):二值化操作
图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。
云时之间
2020/03/19
9190
数字图像处理知识点总结概述
1.直方图:一幅图像由不同灰度值的像素组成,图像中灰度的分布情况是该图像的一个重要特征。图像的灰度直方图就描述了图像中灰度分布情况,能够很直观的展示出图像中各个灰度级所占的多少。图像的灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其中,横坐标是灰度级,纵坐标是该灰度级出现的频率。
小白学视觉
2022/09/28
1.9K0
OTSU (大津法)阈值选择算法
大津法(OTSU)是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
为为为什么
2022/08/09
3.7K0
OTSU (大津法)阈值选择算法
OpenCV-Python学习(10)—— OpenCV 图像二值化处理(cv.threshold)
1. 学习目标 理解图像的分类,不同类型的图像的区别; 对图像进行二值化处理,对【 cv.threshold 】函数的理解。 2. 图像分类 2.1 不同类型图像说明 按照颜色对图像进行分类,可以分为二值图像、灰度图像和彩色图像。 二值图像:只有黑色和白色两种颜色的图像。 每个像素点可以用 0/1 表示,0 表示黑色,1 表示白色。 灰度图像:只有灰度的图像。 每个像素点用 8bit 数字 [0,255] 表示灰度,如:0 表示纯黑,255 表示纯白。 彩色图像:彩色图像通常 采用红色(R)、绿色(
Rattenking
2022/10/24
3.5K0
OpenCV-Python学习(10)—— OpenCV 图像二值化处理(cv.threshold)
CV学习笔记(十二):二值化操作
图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。
云时之间
2020/03/06
1K0
没想到图像直方图有这么多应用场景
之前写过很多图像直方图相关的知识跟OpenCV程序演示,这篇算是把之前的都回顾一波。做好自己的知识梳理。
OpenCV学堂
2020/02/21
1.9K0
相关推荐
图像二值化方法汇总介绍
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验