Скорость расчета со свойством в класс - PullRequest
1 голос
/ 05 апреля 2019

Я француз, так что извините за ошибку в моем языке.

Я пытаюсь сделать небольшую игру-ноль с физикой мяча. Поэтому я хочу точно контролировать шаровой объект во времени .

Я создал класс 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

Я создаю экземпляр объекта ball и хочу, чтобы он перемещался в позиции от 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 ?

Мой вопрос ... почему? Создать собственное свойство, оно намного медленнее, чем определение классической переменной?

1 Ответ

1 голос
/ 05 апреля 2019

Если вы хотите обеспечить точные вычисления по времени, то все вычисления должны выполняться со значениями с плавающей запятой.Преобразовывать координаты в интегральные типы данных можно только в том случае, если для рисования объектов используется позиция целого пикселя.

Свойство .cx имеет интегральный тип данных.Каждый раз, когда позиция увеличивается, часть дроби добавляемого числа теряется.Это вызывает все большую неточность.Объект кажется медленнее, чем ожидалось.Обратите внимание, что если частота кадров будет выше, то объект будет даже стоять на месте, если шаг на кадр меньше 1,0.Целая часть значения <1.0 равна 0. </p>

Примечание

ball2.cx += speed * dt

делает то же самое, что и

ball2.cx += int(speed * dt)

xПеременная является значением с плавающей запятой.Он увеличивается с полной точностью.Точное значение преобразуется в int, когда оно присваивается свойству .cx, но погрешность всегда меньше 1,0 и, следовательно, почти ничтожна.

x += speed * dt
ball.cx = x  

делает то же самое, что и

x += speed * dt
ball.cx = int(x) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...