在 Pygame 中实现二维空间中的平滑运动 [英] Implementing smooth motion in 2d space in Pygame

查看:71
本文介绍了在 Pygame 中实现二维空间中的平滑运动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现平滑运动,加速到最大速度,然后在没有按下任何键的情况下缓慢减速,类似于小行星中太空船的运动.这是我当前的运动代码:

导入pygamepygame.init()display = pygame.display.set_mode((640, 480))时钟 = pygame.time.Clock()灰色 = pygame.Color('gray12')display_width, display_height = display.get_size()x = display_width * 0.45y = 显示高度 * 0.8x_change = 0y_change = 0加速度_x = 0加速度_y = 0最大速度 = 6符号 = lambda a: (a > 0) - (a <0)坠毁 = 错误虽然没有崩溃:键 = pygame.key.get_pressed()对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:坠毁 = 真如果 event.type == pygame.KEYDOWN:# 设置加速度值.如果 event.key == pygame.K_LEFT:打印('左')accel_x = -.2如果 event.key == pygame.K_RIGHT:打印('正确')加速度_x = .2如果 event.key == pygame.K_DOWN:打印('向下')accel_y = .2如果 event.key == pygame.K_UP:打印('向上')accel_y = -.2如果 event.type == pygame.KEYUP:如果 event.key 在 (pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN):打印('按键')加速度_x = 0加速度_y = 0x_change += accel_x # 加速.y_change += accel_yif abs(x_change) >= max_speed: # 如果超过 max_speed.# 标准化 x_change 并将其与 max_speed 相乘.x_change = 符号(x_change)* max_speedif abs(y_change) >= max_speed: # 如果超过 max_speed.# 规范化 y_change 并将其与 max_speed 相乘.y_change = sign(y_change) * max_speed# 如果没有按下任何键,则减速.如果 accel_x == 0:x_change *= 0.98如果 accel_y == 0:y_change *= 0.98x += x_change # 移动对象.y += y_change显示.填充(灰色)pygame.draw.rect(显示, (0, 120, 250), (x, y, 20, 40))pygame.display.update()时钟滴答(60)pygame.quit()

当单独按下箭头键时,运动效果很好,但是如果快速连续按下 2 个键,第二个键被注册,但对象没有运动.我尝试使用 pygame.key.get_pressed() 制作按键列表,并将当前动作与列表中按下的按键进行比较,但这并没有解决问题.

解决方案

您的代码中的主要问题是,当您按下 LEFT 时,然后按住 RIGHT 最后释放LEFT,结果accel_xaccel_y 的状态都是0,因为最后发生的事件是pygame.KEYUP.

我建议评估

crashed = False虽然没有崩溃:对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:坠毁 = 真键 = pygame.key.get_pressed()# 处理左右移动如果keys[pygame.K_LEFT]而不是keys[pygame.K_RIGHT]:x_change = max(x_change-0.2, -max_speed)elif 键[pygame.K_RIGHT] 而不是键[pygame.K_LEFT]:x_change = min(x_change+0.2, max_speed)别的:x_change *= 0.98# 处理上下运动如果keys[pygame.K_UP]而不是keys[pygame.K_DOWN]:y_change = max(y_change-0.2, -max_speed)elif 键[pygame.K_DOWN] 而不是键[pygame.K_UP]:y_change = min(y_change+0.2, max_speed)别的:y_change *= 0.98x += x_change # 移动对象.y += y_change显示.填充(灰色)pygame.draw.rect(显示, (0, 120, 250), (x, y, 20, 40))pygame.display.update()时钟滴答(60)

I want to implement smooth motion that accelerates up to max speed and then decelerates slowly if no keys are pressed, similar to the motion of the space ship in asteroid. Here is my current code for the movement:

import pygame

pygame.init()

display = pygame.display.set_mode((640, 480))

clock = pygame.time.Clock()

GRAY = pygame.Color('gray12')

display_width, display_height = display.get_size()

x = display_width * 0.45
y = display_height * 0.8

x_change = 0
y_change = 0
accel_x = 0
accel_y = 0
max_speed = 6

sign = lambda a: (a > 0) - (a < 0)

crashed = False
while not crashed:
    keys = pygame.key.get_pressed()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True
        if event.type == pygame.KEYDOWN:
            # Set the acceleration value.
            if event.key == pygame.K_LEFT:
                print('left')
                accel_x = -.2
            if event.key == pygame.K_RIGHT:
                print('right')
                accel_x = .2
            if event.key == pygame.K_DOWN:
                print('down')
                accel_y = .2
            if event.key == pygame.K_UP:
                print('up')
                accel_y = -.2
        if event.type == pygame.KEYUP:
            if event.key in (pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN):
                print('key up')
                accel_x = 0
                accel_y = 0

    x_change += accel_x  # Accelerate.
    y_change += accel_y

    if abs(x_change) >= max_speed:  # If max_speed is exceeded.
        # Normalize the x_change and multiply it with the max_speed.
        x_change = sign(x_change) * max_speed

    if abs(y_change) >= max_speed:  # If max_speed is exceeded.
        # Normalize the y_change and multiply it with the max_speed.
        y_change = sign(y_change) * max_speed

    # Decelerate if no key is pressed.
    if accel_x == 0:
        x_change *= 0.98

    if accel_y == 0:
        y_change *= 0.98

    x += x_change  # Move the object.
    y += y_change

    display.fill(GRAY)
    pygame.draw.rect(display, (0, 120, 250), (x, y, 20, 40))

    pygame.display.update()
    clock.tick(60)
pygame.quit()

When pressing the arrow keys individually the motion works perfectly, however if pressing 2 keys in rapid succession, the second key is registered but there is no motion from the object. I've tried making a list of keys using pygame.key.get_pressed() and comparing the current motion with the key pressed in the list, however this didn't solve the problem.

解决方案

The major issue in your code is, that when you press and LEFT, then press and hold RIGHT and finally release LEFT, the resulting states of accel_x and accel_y are both 0, because the last event that happend was pygame.KEYUP.

I recommend to evaluate the states of pygame.key.get_pressed() rather than to use the key events:

  • If UP is pressed and DOWN is not pressed, the increment y_change up to its maximum (y_change = max(y_change-0.2, -max_speed)).
  • If UP is not pressed and DOWN is pressed, the decrement y_change down to its minimum (y_change = min(y_change+0.2, max_speed)).
  • If both keys are pressed simultaneously or no one of them is pressed, then decrease the speed (y_change *= 0.98).

Apply the same principle to x_change, when the keys LEFT and/or RIGHT are pressed:

crashed = False
while not crashed:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True

    keys = pygame.key.get_pressed()

    # handle left and right movement
    if keys[pygame.K_LEFT] and not keys[pygame.K_RIGHT]:
        x_change = max(x_change-0.2, -max_speed)
    elif keys[pygame.K_RIGHT] and not keys[pygame.K_LEFT]:
        x_change = min(x_change+0.2, max_speed)
    else:
        x_change *= 0.98

    # handle up and down movement
    if keys[pygame.K_UP] and not keys[pygame.K_DOWN]:
        y_change = max(y_change-0.2, -max_speed)
    elif keys[pygame.K_DOWN] and not keys[pygame.K_UP]:
        y_change = min(y_change+0.2, max_speed)
    else:
        y_change *= 0.98

    x += x_change  # Move the object.
    y += y_change

    display.fill(GRAY)
    pygame.draw.rect(display, (0, 120, 250), (x, y, 20, 40))

    pygame.display.update()
    clock.tick(60)

这篇关于在 Pygame 中实现二维空间中的平滑运动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆