首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在堆叠Sprite时更改透视角度?

如何在堆叠Sprite时更改透视角度?
EN

Stack Overflow用户
提问于 2020-04-20 10:07:22
回答 1查看 428关注 0票数 1

我使用Pygame库在Python中创建了一个精灵堆叠预览程序。当每个单元格堆叠在前一个单元格上时,将精灵工作表在Y轴上偏移-1像素将默认创建45度透视图。当我将单元格间距设置为0时,我也可以获得0度透视。

有一个基于web的精灵堆叠程序,sprite Stack Studio,允许用户选择0,45,60和90度相机角度。我还看到了一个Pico-8墨盒,它允许围绕一个岛屿进行全半球体风格的透视。

我只是好奇这是不是很复杂,或者我是否可以对当前的程序进行一些小的修改,以获得所需的透视图。

我的雪碧表:

渲染图像:

Sprite Stack Studio示例:https://spritestack.io/studio/?cloud_id=349&app=exporter

PICO-8岛示例:https://www.lexaloffle.com/bbs/?pid=15116#p

EN

回答 1

Stack Overflow用户

发布于 2020-04-21 15:31:30

好的,我根据这个PyGame + OpenGL教程做了一个简单的演示:https://stackabuse.com/advanced-opengl-in-python-with-pygame-and-pyopengl/

这段代码不能很好地工作,但它确实将sprite-sheet转换为体素,并将它们渲染到PyGame窗口中。它真的很慢。至少对我来说,我猜它根本没有使用硬件3D。但它确实允许以任何角度渲染模型。

最大的问题是它使得32 * 32 * 19 = 19456体素(减去透明体素)。优化代码以使相同颜色的相邻体素合并为单个矩形体素将有很大帮助。

无论如何,它可能会给你一个推动,让你自己的解决方案工作。

代码语言:javascript
复制
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()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61314087

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档