Python 现代开发学习笔记

(五)连续按键与二维方向

1. 从按键状态组成方向向量

先让方块在窗口内上下左右移动。右减左得到 x 方向,下减上得到 y 方向;同时按住相反方向时相互抵消:

# 项目文件:demos/move_dt.py
# 连续按键决定方向;单位方向乘速度和秒数,浮点位置最后再投影到整数Rect。
import pygame


def main():
    pygame.init()
    try:
        screen = pygame.display.set_mode((480, 320))
        clock = pygame.time.Clock()
        position = pygame.Vector2(216, 142)
        player = pygame.Rect(round(position.x), round(position.y), 48, 36)
        running = True
        while running:
            dt = clock.tick(60) / 1000
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
            if not running:
                break
            keys = pygame.key.get_pressed()
            direction = pygame.Vector2(
                int(keys[pygame.K_d]) - int(keys[pygame.K_a]),
                int(keys[pygame.K_s]) - int(keys[pygame.K_w]),
            )
            if direction.length_squared() > 0:
                direction = direction.normalize()
            position += direction * 240 * dt
            position.x = max(0, min(480 - player.width, position.x))
            position.y = max(0, min(320 - player.height, position.y))
            player.topleft = round(position.x), round(position.y)
            screen.fill("#F5F7FB")
            pygame.draw.rect(screen, "#087F82", player)
            pygame.display.flip()
    finally:
        pygame.quit()


if __name__ == "__main__":
    main()

Vector2 保存两个浮点分量,可以读取 x、y,也可以整体乘以速度与秒数。get_pressed() 的结果按键常量索引,交回当前是否按着这个键;先处理事件队列,再读取这一帧的状态。持续键盘状态

position 保存真实计算位置,player 是用于绘制的整数矩形。每次先完成浮点更新和位置限制,再把它映射到 Rect,不能每一步都把小数运动丢掉。

2. 斜向输入先归一化

只向右时方向为 (1, 0),长度为 1;同时向右下时是 (1, 1),长度为 2\sqrt{2}。若直接乘速度,斜向移动就会更快。

length_squared() 计算 x*x + y*y,用它判断方向是否为零。代码在方向非零时调用 normalize,把它变成长度为 1 的新向量。斜向分量约为 (0.7071, 0.7071);乘每秒 240 后,两个分量约为 169.7,合成速度仍为 240。没有方向输入时保持零向量,停在原处。

右下方向先由两个单位分量形成长度根号二,再缩为单位方向后乘相同速度

笔记正文与全部题解 · Ctrl / ⌘ K