我是法国人,请原谅我的语言错误。
我尝试用球状物理制作一些 pygame-zero 游戏。 所以我想及时精确地控制一个球形物体 。
我创建了一个Ball类,实现了内置的Rect对象(以防万一使用默认碰撞)。
import pygame
WIDTH = 300
HEIGHT = 300
class Color:
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
class Ball(pygame.Rect):
def __init__(self, cx, cy, radius, color: Color = Color.WHITE):
position = (cx - radius, cy - radius)
size = (radius * 2, radius * 2)
super(Ball, self).__init__(position, size)
self.radius = radius
self.color = color
@property
def cx(self):
return self.x + self.radius
@cx.setter
def cx(self, cx):
self.x = cx - self.radius
@property
def cy(self):
return self.y + self.radius
@cy.setter
def cy(self, cy):
self.y = cy - self.radius
def draw(self):
position = (self.cx, self.cy)
screen.draw.filled_circle(position, self.radius, self.color);
# screen.draw.rect(self, Color.RED) # draw hitbox
我实例化一个球对象,并希望使其在x位置0到300。(窗口的宽度)。
在更新功能中,我使用默认的增量时间(每帧1/60之间经过的时间,以毫秒为单位)。
以100像素*增量时间的速度,球将在3秒(逻辑)上穿越屏幕。
但这不是...经过一些操作后,我创建了第二个球(我切换了球的名称),而当我使用变量时,一切正常。
cl = 0 # get time elpased at launch
ball = Ball(0, 10, 10, Color.RED)
x = ball.cx
ball2 = Ball(0, 30, 10, Color.BLUE)
speed = 100
def draw():
screen.clear()
ball.draw()
ball2.draw()
screen.draw.text(f"{cl:7.2f}", (0, 150))
def update(dt):
global cl, x
if ball.cx <= WIDTH:
cl += dt
# the ball make 3 seconds exactly
x += speed * dt
ball.cx = x
ball2.cx += speed * dt # don't make 3 seconds WHY ?
我的问题...为什么? 创建一个自定义属性,它比经典的变量定义要慢得多吗?
答案 0 :(得分:1)
如果要确保时间精确的计算,则必须使用浮点值进行所有计算。仅在将对象绘制为整数像素位置时,才将坐标转换为整数数据类型。
.cx
属性具有整数数据类型。每当位置增加时,相加的数字的小数部分都会丢失。这导致不准确性增加。该对象似乎比预期的慢。
请注意,如果帧速率更高,则如果每帧的步距小于1.0,则对象甚至将静止不动。值<1.0的整数部分为0。
注意
ball2.cx += speed * dt
与
相同ball2.cx += int(speed * dt)
x
变量是浮点值。它以完全精度递增。当将精确值赋给.cx
属性时,该值将强制转换为int,但是不精确度始终小于1.0,因此几乎可以忽略不计。
x += speed * dt ball.cx = x
与
相同x += speed * dt
ball.cx = int(x)