Python 现代开发学习笔记

(六)Rect、浮点位置与对象修改

1. 用矩形属性表达位置关系

# 项目文件:demos/rect_ops.py
# move 交回新Rect,move_ip修改原对象;共享名称会一起看到原对象的变化。
import pygame

player = pygame.Rect(20, 30, 40, 20)
print(player.right, player.bottom, player.center)
moved = player.move(10, -5)
print(player.topleft, moved.topleft)
same = player
player.move_ip(5, 0)
print(same.topleft, player.topleft)
player.clamp_ip(pygame.Rect(0, 0, 50, 40))
print(player.topleft, player.right, player.bottom)

首先输出 60 50 (40, 40),对应右侧结束位置、下侧结束位置和中心。move 取得新矩形,原对象仍位于 (20, 30);move_ip 修改原对象,共享的 same 也看到 (25, 30)。最后把它放入宽 50、高 40 的区域,得到 (10, 20),右侧与下侧结束位置分别为 50、40。

修改 center、topleft、right 等属性也会改变对应位置,而不是在矩形里维护几份互不关联的坐标。第四章的共享引用在这里仍然成立;需要独立副本时用 rect.copy(),不要把再次赋值当作复制。Rect 接口

同一Rect的左上角、宽高、中心与右下结束位置相互关联,move复制而move_ip更新共享对象

2. 小数位移单独累积

# 项目文件:demos/rect_float.py
# 每次写回整数坐标会丢掉小数累积;独立浮点位置保留每步0.4像素。
import pygame

bad = pygame.Rect(0, 0, 48, 36)
x, pixels = 0.0, []
for _ in range(6):
    bad.x += 0.4
    x += 0.4
    pixels.append(round(x))
print("仅Rect", bad.x)
print("浮点位置", f"{x:.1f}", "绘制位置", pixels)

仅使用 Rect 的结果为 0;独立浮点位置累计为 2.4,六次绘制位置依次为 [0, 1, 1, 2, 2, 2]。每步 0.4 都写回整数属性时,分数部分没能累积;浮点 x 则保存这一步还没有形成完整像素的移动,后续会继续加上去。

完整游戏同样让模型保存浮点 x、y,显示精灵的 Rect 再通过 round 取得屏幕位置。逻辑位置与显示位置各自负责自己的精度。

每次写回整数时小数移动反复丢失,单独浮点累计则逐步变成可显示像素

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