Python Turtle体素引擎无绘图输出问题排查求助
你的体素引擎无绘图输出的原因及修复方案
核心问题分析
1. 全局变量未被正确修改
你的trig_vals()、set_point()等函数里,直接赋值sinx = m.sin(rotx)、xcord = x时,创建的是局部变量,并未修改全局作用域的变量。导致后续坐标计算始终使用初始的0或1值,完全失效。
解决:在函数内部用global关键字声明要修改的全局变量,比如:
def trig_vals(): global sinx, cosx, siny, cosy sinx = m.sin(m.radians(rotx)) cosx = m.cos(m.radians(rotx)) siny = m.sin(m.radians(roty)) cosy = m.cos(m.radians(roty))
2. 三角函数参数未转弧度
math.sin()/math.cos()仅接收弧度值,但你代码里的rotx=90、roty=-180是角度,直接传入会得到错误的三角函数值,旋转计算完全错误。
解决:用math.radians()把角度转成弧度,如上例所示。
3. 无限循环重复初始化屏幕
while True里每次调用setup(),会反复创建新的turtle屏幕,覆盖之前的状态;同时没有给turtle的事件循环留运行空间,窗口无法正常刷新。
解决:把setup()移到循环外仅执行一次,用t.mainloop()替代无限循环,或在循环中加入t.update()和延迟。
4. 绘图逻辑无效
Draw_Point()里pendown()后立刻penup(),没有任何实质绘图动作;- 距离计算
dist = (m.sqrt((zcord * zcord) + (zcord * zcord)) / 15)逻辑错误,未正确计算点到相机的距离; - 屏幕坐标转换公式有误,且未处理
zcord为0的情况(会触发除零错误)。
解决:调整绘图逻辑,确保pendown后有绘图动作(比如t.dot()),修正距离与坐标计算逻辑。
修正后的完整代码
import turtle as t import math as m # Voxel positions xcord = 1 ycord = 1 zcord = -50 # Player position camx = 0 camy = 0 camz = 0 # Player Rotation (角度) rotx = 90 roty = -180 # Trig Values sinx = 0 cosx = 0 siny = 0 cosy = 0 # Field of View FOV = 60 # Distance and Pen Size quality = 2 def trig_vals(): global sinx, cosx, siny, cosy # 角度转弧度 sinx = m.sin(m.radians(rotx)) cosx = m.cos(m.radians(rotx)) siny = m.sin(m.radians(roty)) cosy = m.cos(m.radians(roty)) def set_point(x, y, z): global xcord, ycord, zcord xcord = x ycord = y zcord = z def onscreen_point(x, y): global xcord, ycord xcord = x ycord = y def calc_rotation(x, y, z): # 转换到相机坐标系 set_point(x - camx, y - camy, z - camz) # Y轴旋转 new_x = zcord * siny + xcord * cosy new_z = zcord * cosy - xcord * siny set_point(new_x, ycord, new_z) # X轴旋转 new_y = zcord * cosx - ycord * sinx new_z = zcord * sinx + ycord * cosx set_point(xcord, new_y, new_z) def Draw_Point(x, y, z, c): global xcord, ycord, zcord calc_rotation(x, y, z) # 避免除零错误,只处理相机前方的点 if zcord <= 0: return # 透视投影转换 scale = (200 - FOV) / zcord screen_x = xcord * scale screen_y = ycord * scale onscreen_point(screen_x, screen_y) # 检查是否在屏幕范围内 if abs(screen_x) > 240 or abs(screen_y) > 180: return # 计算点到相机的距离,调整画笔大小 dist = m.sqrt(xcord**2 + ycord**2 + zcord**2) / 15 if dist > 99: return t.pencolor(c) t.pensize(max(1, quality * (100 - dist) / 50)) # 根据距离调整点大小 t.penup() t.goto(screen_x, screen_y) t.pendown() t.dot() # 绘制可见的点 t.penup() def setup(): t.hideturtle() t.tracer(0, 0) # 关闭自动刷新,提升性能 screen = t.Screen() screen.setup(480, 360) screen.bgcolor("black") trig_vals() # 初始化与测试 setup() Draw_Point(1, 50, 50, "white") t.update() # 手动刷新屏幕 t.mainloop() # 启动事件循环
额外说明
- 关闭
t.tracer()并手动调用t.update(),能大幅提升批量绘制体素时的性能; - 增加
zcord <=0的判断,避免点在相机后方或重合导致的除零错误; - 用
t.dot()替代无效的pendown/penup组合,确保能绘制出可见的点; - 调整画笔大小计算逻辑,让远处的点更小,符合透视效果。
内容的提问来源于stack exchange,提问作者Frogpants
相关产品推荐
相关产品推荐

