Увеличение позиции спрайта очень быстро без задержки - Python
Я делаю PONG-игру для школьного проекта с использованием Kivy в Python. Пока благодаря этому форуму я сделал себе немного искусственного интеллекта для весла NPC. Это код:
if self.ball.y < self.player2.center_y:
self.player2.center_y = self.player2.center_y - 4
if self.ball.y > self.player2.center_y:
self.player2.center_y = self.player2.center_y + 4
Это в методе класса PongGame(), который называется ArtificialIntelligence().
Я использую это, чтобы назвать это:
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Это позволяет мне вызывать его раз в 1/300-ю секунды. Тем не менее, ничего больше, чем 1/300, мне кажется, нет никакой разницы. Т.е. 1/9001 не вызывает его раз в 1/9001 секунду.
Он работает так, что увеличивает координату y на 4 пикселя относительно положения шаров, и делает это один раз каждые 1/300 секунды, поэтому он не "лагает" с такой скоростью. Это в основном "легкий" режим для игрока. Если я хочу сделать "жесткий" режим, мне нужно сделать NPC более точным. Я могу сделать это, делая
self.player2.center_y = self.player2.center_y + 20
Что-то вроде этого. Это было бы чрезвычайно точно. ОДНАКО, это не выглядит "жидким", это выглядит "медленным". Я предполагаю, что мог бы получить такое же количество движения, вызывая метод чаще, вместо того, чтобы изменять величину, которую он перемещает, изменяя движение пикселя. Однако я не знаю, как это сделать, потому что, как я уже сказал, изменение его где-либо выше 1/300, кажется, не имеет значения.
Вот как я использую весло:
if touch.x < self.width/3:
self.player1.center_y = touch.y
и я могу перемещать его так быстро, как я хочу, потому что это обновляется, когда я двигаю мышь. И он выглядит плавным, потому что он обновляется так часто, как это необходимо для обновления. Я не знаю, как это сделать с моим ИИ.
Кто-нибудь знает, как я мог бы в основном сделать весло NPC более точным, позволяя мне делать Easy-Normal-Hard и т. Д., Сохраняя при этом текучесть и отсутствие лагов? Я вижу только один способ сделать это: увеличить количество вызываемых методов.
Однако я уверен, что есть лучший способ, и я не знаю, как это сделать. У кого-нибудь есть идеи, как мне это сделать? Благодарю.
Изменить: похоже, я могу сделать это так:
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)
Но это кажется ДЕЙСТВИТЕЛЬНО уродливым и ДЕЙСТВИТЕЛЬНО неэффективным... Я НАМНОГО предпочел бы более чистый путь.
3 ответа
При скорости 300 кадров в секунду проблема заключается не в частоте обновлений, поскольку вы превышаете способность человеческого глаза воспринимать движение в 50 и более раз.
Резкое движение происходит из-за того, что мяч движется по линейной траектории, в то время как весло просто прыгает туда, где сейчас находится мяч. В идеале, ваш компьютерный игрок может вычислить, где будет находиться мяч, когда он достигнет плоскости компьютерного весла, а затем очень плавно пройти к этому месту со скоростью 30 кадров в секунду или меньше. Конечно, математика предсказания требует небольшого количества тригонометрии, но это "правильный" способ сделать это в том смысле, как хороший игрок будет играть, предвидя.
Было бы намного проще просто увеличить размер весла компьютера, что также дало бы визуальный признак игроку, насколько сложнее игра. Когда весло компьютера станет стеной, игрок увидит, что выиграть невозможно. Больший весло будет иметь побочный эффект быть менее резким, но будет ли это "хороший" способ, ваше решение.
Мой совет - использовать триг, чтобы определить, где будет находиться мяч, и переместить весло, чтобы перехватить его.
Анимация будет плавной со скоростью 30 кадров в секунду.
При создании игрового ИИ в наши дни очень важно, чтобы игрок не видел, что он "обманывает", и предоставление ему большего весла или способности телепортироваться, было бы очевидными признаками этого. Он должен играть так же, как человек, только лучше - без использования какого-либо механизма, к которому у игрока нет доступа. "Эта игра - отстой, потому что процессор жульничает" - очень распространенный негативный комментарий на форумах по видеоиграм.
Поэтому, если вам нужен пропущенный компьютер, убедитесь, что его триггерные вычисления отключены случайным образом, чтобы игрок не мог отличить свою игру от игры человека.
edit: Например: если random (X) <= скорость мяча, то перехватывать правильно, в противном случае пропустить случайные (Y) единицы.
Спасибо за вашу помощь, ребята, я смог решить это с моим учителем, основываясь на вашей и его помощи.
Он разработал этот алгоритм (хотя он сделал это так быстро, что я не смог его понять!), Но по сути он использует триггер для генерации того, куда пойдет весло (заметьте, я не использую угол, поскольку у меня есть другие значения что можно использовать)
def AIController(self, *args):
ballsFuturePos = self.ball.center_y + ((self.width - self.ball.center_x) / self.ball.velocity_x) * self.ball.velocity_y
numIterations = ((self.width - self.ball.center_x) / self.ball.velocity_x)
#print ballsFuturePos
#print numIterations
if numIterations > 0:
self.wantedPos = self.player2.center_y +(ballsFuturePos - self.player2.center_y) / numIterations
#print wantedPos
#self.player2.center_y = wantedPos + (error / wantedPos) * 100
if self.player2.center_y < self.wantedPos:
self.player2.center_y = self.player2.center_y + 9
if self.player2.center_y > self.wantedPos:
self.player2.center_y = self.player2.center_y - 9
Таким образом, я определяю, где мяч должен попасть в крайнюю правую часть экрана, получая положение шариков у, добавляя (ширина - положение шарика х) (что дает мне расстояние до самой правой части экрана). х пикселей), затем я сделал это по скорости х, а умножил все на скорость у, что дает мне наклон (я думаю), и теперь, когда наклон вычислен, это также означает, что он имеет траекторию и таким образом, можно предсказать, где мяч попадет на экран.
Я рассчитываю количество итераций, необходимых для того, чтобы добраться до мяча, беря ширину экрана и уменьшая ее по положению шариков х, которое вычисляет, насколько далеко оно находится до самой правой части экрана, и делю это на скорость. Это дает мне номер, который я могу использовать для итерации.
теперь я перебираю это и создаю переменную wantedPos, куда я и хочу, чтобы мой весло пошло. При этом используется позиция весла y, добавление (где будет мяч - где весло), которое дает мне расстояние между мячом и веслом, деленное на количество итераций, что дает мне положение, в котором будет весло. быть в том же положении на балу. По мере того, как нумерация уменьшается в каждом вызове, увеличивается и значение wantedPos, что означает, что разрыв становится меньше. Затем я поворачиваю весло ближе к мячу, используя 9 в качестве скорости, что позволяет мне увеличивать или уменьшать сложность.
Благодарю. Если я испортил какую-либо логику, пытаясь описать его действия, расскажите, пожалуйста! Я думаю, что понимаю это, но подтверждение было бы неплохо:)