Python 堆叠精灵时如何更改透视角度?
我使用Pygame库在Python中创建了一个精灵堆叠预览程序。当每个单元堆叠在上一个单元上时,默认情况下,在Y轴上将精灵图纸偏移-1像素将创建45度透视。当我将单元格间距设置为0时,也可以得到0度的透视图 有一个基于web的sprite Stack Studio程序,允许用户选择0、45、60和90度的相机角度。我还看到了一个Pico-8盒带,它可以在一个岛屿周围形成一个完整的半球形透视图 我只是好奇这是不是很复杂,或者我是否可以对我当前的程序进行一些小的修改以获得所需的透视图 我的雪碧床单: 渲染图像: Sprite Stack Studio示例: PICO-8岛示例:Python 堆叠精灵时如何更改透视角度?,python,graphics,pygame,sprite,game-development,Python,Graphics,Pygame,Sprite,Game Development,我使用Pygame库在Python中创建了一个精灵堆叠预览程序。当每个单元堆叠在上一个单元上时,默认情况下,在Y轴上将精灵图纸偏移-1像素将创建45度透视。当我将单元格间距设置为0时,也可以得到0度的透视图 有一个基于web的sprite Stack Studio程序,允许用户选择0、45、60和90度的相机角度。我还看到了一个Pico-8盒带,它可以在一个岛屿周围形成一个完整的半球形透视图 我只是好奇这是不是很复杂,或者我是否可以对我当前的程序进行一些小的修改以获得所需的透视图 我的雪碧床单:
是的,基于这个PyGame+OpenGL教程,我在这里进行了一个快速的游戏: 这段代码工作得不是很好,但它确实将精灵表转换为体素,并将它们渲染到PyGame窗口中。真的,真的,真的很慢。至少对我来说,我猜它根本不用硬件3D。但它确实允许以任何角度渲染模型 最大的问题是它生成32*32*19=19456体素(减去透明体素)。优化代码,使相同颜色的相邻体素合并为单个矩形体素将非常有帮助 不管怎样,也许它会给你一个推动,让你自己的解决方案工作
import pygame
import random
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 800
DISPLAY_SURFACE = DOUBLEBUF|OPENGL
# A Unit Cube from (0,0,0) -> (1,1,1)
cube_vertices = ( (1,1,1),
(1,1,0),
(1,0,0),
(1,0,1),
(0,1,1),
(0,1,0),
(0,0,0),
(0,0,1) )
# The Surfaces making up each face-square
cube_surfaces = ( (0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6) )
### Class to hold a cube's worth of verticies
class Cube():
def __init__( self, xmove, ymove, zmove, colour ):
global cube_vertices
self.colour = colour
self.vertices = []
for vert in cube_vertices:
new_x = vert[0] + xmove
new_y = vert[1] + ymove
new_z = vert[2] + zmove
self.vertices.append( [new_x, new_y, new_z] )
def drawCube( self ):
""" Call the openGL function to render the cube """
global cube_surfaces
glBegin(GL_QUADS)
for surface in cube_surfaces:
glColor3fv( self.colour )
for vertex in surface:
glVertex3fv( self.vertices[ vertex ])
glEnd()
### Class to convert a 2D sprite sheet into a (huge) set of
### voxels-per-pixels
class SpriteSheet3D():
def __init__( self, sheet_filename, sheet_count, sprite_width, sprite_height ):
self.cube_list = []
self.image = pygame.image.load( sheet_filename ).convert_alpha()
# TODO: sanity check sprite image matches supplied dimensions
# Iterate through each sheet's pixels creating cubes/voxels
# TODO: optimise voxels to combine pixels of the same colour into a single, bigger prism
for z in range( 0, sheet_count ):
for y in range( 0, sprite_height ):
for x in range( 0, sprite_width ):
offset_x = x + ( z * sprite_width )
pixel_colour = self.image.get_at( ( offset_x, y ) )
# Only create opaque pixels (Pixels are RGBA)
if ( pixel_colour[3] > 128 ): # TODO: handle translucent pixels
self.createVoxel( x, y, z, pixel_colour )
def createVoxel( self, x, y, z, pixel_colour ):
""" Create a 3D Unit-Cube at (x,y,z) """
# Pygame maps colours 0-255 for RGBA
# OpenGL maps colour 0-1 for RGB
gl_colour = ( pixel_colour[0]/255, pixel_colour[1]/255, pixel_colour[2]/255 )
self.cube_list.append( Cube( x, y, z, gl_colour ) )
def drawCubes( self ):
""" Paint all the cubes """
for cube in self.cube_list:
cube.drawCube()
### Main
pygame.init()
pygame.display.set_mode( ( DISPLAY_WIDTH, DISPLAY_HEIGHT ), DISPLAY_SURFACE )
glEnable( GL_DEPTH_TEST )
gluPerspective( 45, DISPLAY_WIDTH/DISPLAY_HEIGHT, 0.1, 200.0 )
glTranslatef( -16, -16, -150 ) # move camera here
sprite_3d = SpriteSheet3D( 'sprite_stack.png', 19, 32, 32 )
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef( 3.6, 0,1,1 ) # rotate 3.6 degrees about Y and Z-axiz
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT )
sprite_3d.drawCubes()
pygame.display.flip()
pygame.time.wait(1)
pygame.quit()
quit()
好的,我在这个PyGame+OpenGL教程的基础上快速地玩了一下: 这段代码工作得不是很好,但它确实将精灵表转换为体素,并将它们渲染到PyGame窗口中。真的,真的,真的很慢。至少对我来说,我猜它根本不用硬件3D。但它确实允许以任何角度渲染模型 最大的问题是它生成32*32*19=19456体素(减去透明体素)。优化代码,使相同颜色的相邻体素合并为单个矩形体素将非常有帮助 不管怎样,也许它会给你一个推动,让你自己的解决方案工作
import pygame
import random
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 800
DISPLAY_SURFACE = DOUBLEBUF|OPENGL
# A Unit Cube from (0,0,0) -> (1,1,1)
cube_vertices = ( (1,1,1),
(1,1,0),
(1,0,0),
(1,0,1),
(0,1,1),
(0,1,0),
(0,0,0),
(0,0,1) )
# The Surfaces making up each face-square
cube_surfaces = ( (0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6) )
### Class to hold a cube's worth of verticies
class Cube():
def __init__( self, xmove, ymove, zmove, colour ):
global cube_vertices
self.colour = colour
self.vertices = []
for vert in cube_vertices:
new_x = vert[0] + xmove
new_y = vert[1] + ymove
new_z = vert[2] + zmove
self.vertices.append( [new_x, new_y, new_z] )
def drawCube( self ):
""" Call the openGL function to render the cube """
global cube_surfaces
glBegin(GL_QUADS)
for surface in cube_surfaces:
glColor3fv( self.colour )
for vertex in surface:
glVertex3fv( self.vertices[ vertex ])
glEnd()
### Class to convert a 2D sprite sheet into a (huge) set of
### voxels-per-pixels
class SpriteSheet3D():
def __init__( self, sheet_filename, sheet_count, sprite_width, sprite_height ):
self.cube_list = []
self.image = pygame.image.load( sheet_filename ).convert_alpha()
# TODO: sanity check sprite image matches supplied dimensions
# Iterate through each sheet's pixels creating cubes/voxels
# TODO: optimise voxels to combine pixels of the same colour into a single, bigger prism
for z in range( 0, sheet_count ):
for y in range( 0, sprite_height ):
for x in range( 0, sprite_width ):
offset_x = x + ( z * sprite_width )
pixel_colour = self.image.get_at( ( offset_x, y ) )
# Only create opaque pixels (Pixels are RGBA)
if ( pixel_colour[3] > 128 ): # TODO: handle translucent pixels
self.createVoxel( x, y, z, pixel_colour )
def createVoxel( self, x, y, z, pixel_colour ):
""" Create a 3D Unit-Cube at (x,y,z) """
# Pygame maps colours 0-255 for RGBA
# OpenGL maps colour 0-1 for RGB
gl_colour = ( pixel_colour[0]/255, pixel_colour[1]/255, pixel_colour[2]/255 )
self.cube_list.append( Cube( x, y, z, gl_colour ) )
def drawCubes( self ):
""" Paint all the cubes """
for cube in self.cube_list:
cube.drawCube()
### Main
pygame.init()
pygame.display.set_mode( ( DISPLAY_WIDTH, DISPLAY_HEIGHT ), DISPLAY_SURFACE )
glEnable( GL_DEPTH_TEST )
gluPerspective( 45, DISPLAY_WIDTH/DISPLAY_HEIGHT, 0.1, 200.0 )
glTranslatef( -16, -16, -150 ) # move camera here
sprite_3d = SpriteSheet3D( 'sprite_stack.png', 19, 32, 32 )
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef( 3.6, 0,1,1 ) # rotate 3.6 degrees about Y and Z-axiz
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT )
sprite_3d.drawCubes()
pygame.display.flip()
pygame.time.wait(1)
pygame.quit()
quit()
你能澄清一下你所说的“雪碧堆”是什么意思吗。链接读起来就像每个精灵是一个通过3d对象的“切片”,其中每个像素成为3d“体素”。在这种情况下,这实际上是一大串1单位立方体的3d投影,每个像素一个。堆栈的顺序控制体素的z顺序。听起来很接近吗?体素-还有这个软件有一个描述:这里有一些PyGame 3D投影的示例代码:它不会很快“硬件3D”。是的,基本上是一个传统的精灵表,除了多个细胞组成一个图像,形成一个体素类型的图像。这是一个看起来像3D的2D图像。我不认为3D原理适用于这种情况。你能澄清一下你所说的“精灵堆栈”的确切含义吗。链接读起来就像每个精灵是一个通过3d对象的“切片”,其中每个像素成为3d“体素”。在这种情况下,这实际上是一大串1单位立方体的3d投影,每个像素一个。堆栈的顺序控制体素的z顺序。听起来很接近吗?体素-还有这个软件有一个描述:这里有一些PyGame 3D投影的示例代码:它不会很快“硬件3D”。是的,基本上是一个传统的精灵表,除了多个细胞组成一个图像,形成一个体素类型的图像。这是一个看起来像3D的2D图像。但我不认为3D原理适用于这种情况。我的程序有一个功能性转换器,其中每个像素都保存到一个带有X、Y和Z(精灵表单元格编号)的文本文件中。文本文件还存储RGBA值。我最初的想法是允许为RGBA值指定物理属性,如生命点、声音等。我相信我在这个项目上可能达到了数学极限。我想知道是否有一种“愚蠢”的方法可以至少获得设置的透视值,例如90度或60度,而不必将我的精灵表转换为实际的3D立方体。顺便说一下,谢谢你花了这么多时间,你的想法真的很酷,我很感激。我很高兴你喜欢它——这是一个有趣的问题。但我仍然认为,如果我想设定观点,还有一个更简单的方法。如果我能想出如何用精灵表获得90度视图,我将是一个快乐的露营者。我的程序有一个功能性转换器,其中每个像素都保存到一个带有X、Y和Z(精灵表单元格编号)的文本文件中。文本文件还存储RGBA值。我最初的想法是允许为RGBA值指定物理属性,如生命点、声音等。我相信我在这个项目上可能达到了数学极限。我想知道是否有一种“愚蠢”的方法可以至少获得设置的透视值,例如90度或60度,而不必将我的精灵表转换为实际的3D立方体。顺便说一下,谢谢你花了这么多时间,你的想法真的很酷,我很感激。我很高兴你喜欢它——这是一个有趣的问题。但我仍然认为,如果我想设定观点,还有一个更简单的方法。如果我能想出如何用雪碧床单获得90度的视野,我将是一个快乐的露营者。