So I'm trying to build myself a 3D display 'engine', or whatever it ought to be called. I've been experimenting with PyGame, as it's familiar to me.
In a way this has almost been more an excuse to learn the math than to actually build a 'game engine' or anything like that, though ultimately that's why we're all programmers right? To code the next Super Mario Brothers. :) Anyway, this isn't that, it's a learning project, but unfortunately I seem to have hit a wall and I'm not entirely sure how to proceed or what to look for.
I'm unsure of how to move items smoothly on the Z-axis. 0 is the 'closest' a point gets to the screen, whereas N is the 'furthest' it could go. In the interest of (hopefully) keeping my math similar across calculations, I've set HEIGHT, WIDTH, and DEPTH all to an arbitrary value of 600.
It would appear that moving objects along the Z-axis is not quite the same as moving them along X and Y. Whereas X and Y are just addition and subtraction, Z is apparently only really effective as a percentage. Unfortunately I can't seem to find a method of incrementing Z in any way that doesn't stretch the shapes as if they're going into Warp when I move them closer to the horizon point. Likewise they squash nearly flat as they move closer to the screen.
I believe that the two most likely code candidates for weirdness are the following two snippets; one is the model's "move all the points" method, the other is a view method. Hopefully the code I'm not sharing is self-evident; Zpt is a class that contains x, y, z coordinates, and so on.
def move_pts_to_pt(self, newX=None, newY=None, newZ=None):
##This is how the model moves its points
oldCtr = self.center
if newX is not None:
deltaX = newX - oldCtr.x
else: deltaX = 0
if newY is not None:
deltaY = newY - oldCtr.y
else: deltaY = 0
if newZ is not None:
deltaZ = newZ
else: deltaZ = 1
for zpt in self.zpts + [self.center]:
zpt.x += deltaX
zpt.y += deltaY
zpt.z *= deltaZ
def zshape_draw(shapelist, objcolor=(255, 0, 0), objwidth=2):
##This is the view's drawing method for points with a z coordinate
for shape in shapelist:
drawnpoints = []
for zpt in shape:
z = zpt.z
horzoff = z / DEPTH
invhorz = 1.0 - horzoff
newX = (zpt.x * invhorz) + (WIDTH * HOR_X * horzoff)
newY = (zpt.y * invhorz) + (HEIGHT * HOR_Y * horzoff)
drawnpoints.append((newX, newY))
pygame.draw.polygon(SCREEN, objcolor, drawnpoints, objwidth)
I apologize if I've left any code out; I'm happy to re-edit my post. In any event, I cannot suss out what it is I need to do to prevent the z-values that are closest to the 'back' of the screen from increasing much faster than those closer to the screen, while still maintaining their intended 'shape' -- that is, generally looking like they aren't changing in depth as they move from z=0 to z=600 (or, whatever ends up being 100% 'away' from the screen).