是否有PopMatrix,PushMatrix,在pygame中翻译和/或旋转等效方法?
如果没有,开发它们会遇到什么挑战?为什么它们不存在?
答案 0 :(得分:2)
开发矩阵堆栈以跟踪转换将相对简单。这是我制作的一个简单的类(没有仔细检查这段代码的错误),它复制了你在Processing's API reference中可能会看到的很多功能(看看转换 section):
<强> matstack.py 强>
import math
import numpy as np
_stack = [np.identity(4)]
def apply_mat(mat):
_stack[-1] = np.dot(_stack[-1], mat)
def pop_mat():
_stack.pop()
def push_mat():
_stack.append(get_mat())
def get_mat():
return _stack[-1]
def reset_mat():
_stack[-1] = np.identity(4)
def rotate_mat(radians):
c = math.cos(radians)
s = math.sin(radians)
rotate = np.array([
[c, s, 0, 0],
[-s, c, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
], dtype=np.float32)
apply_mat(rotate)
def translate_mat(x_shift, y_shift):
x, y = x_shift, y_shift
translate = np.array([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[x, y, 0, 1],
], dtype=np.float32)
apply_mat(translate)
def scale_mat(x_scale, y_scale):
x, y = x_scale, y_scale
scale = np.array([
[x, 0, 0, 0],
[0, y, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
], dtype=np.float32)
apply_mat(scale)
这个类的用法也很简单:
<强> main.py 强>
import math
import matstack as ms
if __name__ == "__main__":
ms.reset_mat()
ms.translate_mat(rect.x, rect.y)
ms.rotate_mat(math.radians(45))
ms.scale_mat(2, 0.5)
print(ms.get_mat())
然而,问题在于决定我们如何应用这些矩阵,以便它们实际上影响pygame 中的曲面绘制。问题是pygame中的所有内容都围绕着低pygame.Rect
个对象。如果我们查看documentation,我们会发现pygame.Rect
构造函数的格式为Rect(left, top, width, height) -> Rect
。这意味着,从根本上说,pygame.Rect
必须是轴对齐的最小边界框(AABB),其边必须始终与x = 0
和y = 0
平行。这有许多有用的属性(请参阅文档中的所有辅助函数!),但最终可以防止像旋转这样的复杂转换。
至于为什么就是这种情况,我相信这可归因于pygame所依赖的父技术,即SDL,特别是(过时的)SDL 1.2。虽然Processing(可能依赖于OpenGL)之类的东西使用硬件加速来绘制(将4x4矩阵传递给GPU并执行超快速转换),但SDL 1.2是一个软件渲染器,并未考虑GPU设计。由于GPU不能用于执行转换,因此必须在CPU级别完成工作,操作和“blitting”像素框以获得所需的效果。
为了解决这个限制,SDL有一个模块SDL_gfx,这可能是pygame在其pygame.transform
模块下使用的模块。这可以使用内置函数处理几个固定选项,如旋转和缩放。但是,这些函数只返回包含新变换像素的Surface
个对象。因此,管道中没有任何地方可以通过我们的矩阵!
如果你真的需要在你的应用程序中使用矩阵和堆栈,我建议使用PyOpenGL
使用OpenGL。然后你可以使用我在你的问题评论中谈到的固定函数(顺便说一下是非常过时的)矩阵堆栈操作。您可以在此过程中使用pygame来管理窗口和输入。
如果您特别想要一些受处理启发的东西,但对于已经采用此方法的python,我在网上搜索时找到了this p5 library。如果您只想使用Processing生态系统,但使用“python”语法(在Java中实现),python-mode可能是更好的选择。希望这能让您深入了解这个问题以及一些可能的解决方案!