Python:pygame.gfxdraw.texturedpolygon

2024-06-16 14:21:01 发布

您现在位置:Python中文网/ 问答频道 /正文

所以,我用Python编写代码已经有几个星期了,我想尝试制作一个游戏。我已经到了一个地步,我不知道我的代码有什么问题,除了一个事实,当我试图绘制一个有纹理的多边形时,纹理会在显示屏上延伸,只在立方体上显示出来。它创造了一个非常酷的效果,但这不是我想要的。目标是将纹理渲染到立方体的表面上,就像在Minecraft中一样。在

import pygame, sys, os, math
from pygame import gfxdraw

def rotate2d(pos,rad) : x,y=pos; s,c = math.sin(rad), math.cos(rad); return x*c-y*s, y*c+x*s

class Cam:
    def __init__(self,pos=(0,0,0), rot=(0,0)):
        self.pos = list(pos)
        self.rot = list(rot)

    def events (self, event):
        if event.type == pygame.MOUSEMOTION:
            x,y = event.rel; x/=200; y/=200
            self.rot[0]+=y; self.rot[1]+=x

    def update(self,dt,key):
        s = dt*10

        if key[pygame.K_c]: self.pos[1]+=s
        if key[pygame.K_SPACE]: self.pos[1]-=s

        x,y = s*math.sin(self.rot[1]),s*math.cos(self.rot[1])

        if self.rot[0] <= -1.58:
            self.rot[0] = -1.58

        if self.rot[0] >= 1.58:
            self.rot[0] = 1.58

        if key[pygame.K_w]: self.pos[0]+=x; self.pos[2]+=y
        if key[pygame.K_s]: self.pos[0]-=x; self.pos[2]-=y
        if key[pygame.K_a]: self.pos[0]-=y; self.pos[2]+=x
        if key[pygame.K_d]: self.pos[0]+=y; self.pos[2]-=x

        if key[pygame.K_ESCAPE]: pygame.quit(); sys.exit() #Quits Game#

pygame.init()
w,h = 800,600; cx,cy = w//2, h//2; fov = min(w,h)
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.display.set_caption('PyCraft')
screen = pygame.display.set_mode((w,h))
clock = pygame.time.Clock()

## Textures ##
dirt_texture = pygame.image.load("textures/dirt.png").convert()
stone_texture = pygame.image.load("textures/stone.png").convert()
bedrock_texture = pygame.image.load("textures/bedrock.png").convert()

class Dirt:
    vertices = (-1,-1,-1),(1,-1,-1),(1,1,-1),(-1,1,-1),(-1,-1,1),(1,-1,1),(1,1,1),(-1,1,1)
    edges = (0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)
    faces = (0,1,2,3),(4,5,6,7),(0,1,5,4),(2,3,7,6),(0,3,7,4),(1,2,6,5)
    colours = (225,10,0),(255,128,0),(10,250,250),(128,128,128),(0,0,255),(0,255,0)
    texture = dirt_texture

    def __init__(self,pos=(0,0,0)):
        x,y,z = pos
        self.verts = [(x+X/2,y+Y/2,z+Z/2) for X,Y,Z in self.vertices]

class Stone:
    vertices = (-1,-1,-1),(1,-1,-1),(1,1,-1),(-1,1,-1),(-1,-1,1),(1,-1,1),(1,1,1),(-1,1,1)
    edges = (0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)
    faces = (0,1,2,3),(4,5,6,7),(0,1,5,4),(2,3,7,6),(0,3,7,4),(1,2,6,5)
    colours = (0,255,0),(255,128,0),(0,0,250),(128,133,128),(0,0,200),(200,0,255)
    texture = stone_texture

    def __init__(self,pos=(0,0,0)):
        x,y,z = pos
        self.verts = [(x+X/2,y+Y/2,z+Z/2) for X,Y,Z in self.vertices]

def TextUI(msg,colour,pos):
    screen_text = font.render(msg, True, colour)
    screen.blit(screen_text, (pos))

def Draw_Crosshair(colour, width):

    pygame.draw.line(screen, colour, (cursorpos1, cursorpos2), (cursorpos3,cursorpos4), width)
    pygame.draw.line(screen, colour, (cursorpos5, cursorpos6), (cursorpos7,cursorpos8), width)


cam = Cam((0,0,-5))
pygame.event.get(); pygame.mouse.get_rel()
pygame.mouse.set_visible(0); pygame.event.set_grab(1)
font = pygame.font.SysFont("calibri", 25)
cursorpos1, cursorpos2, cursorpos3, cursorpos4 = w/2, h/2+10, w/2, h/2-10
cursorpos5, cursorpos6, cursorpos7, cursorpos8 = w/2+10, h/2, w/2-10, h/2

cubes = [Dirt((0,0,0)),Stone((2,0,0)),Stone((-2,0,0)),Dirt((0,2,0)),Stone((2,2,0)),Dirt((-2,2,0))]
##cubes = [Dirt((1,0,0)), Dirt((2,0,0)),Dirt((3,0,0)),Dirt((4,0,0)),Dirt((5,0,0)),Dirt((5,1,0)),Dirt((6,1,0)),]

while True:

    dt = clock.tick()/1000

    for event in pygame.event.get():
        if event.type == pygame.QUIT: pygame.quit(); sys.exit()
        cam.events(event)

    screen.fill((100,100,100))

    face_list = []; face_colour = []; depth = [];

    for obj in cubes:

            vert_list = []; screen_coords = []
            for x,y,z in obj.verts:
                x-=cam.pos[0]; y-=cam.pos[1]; z-=cam.pos[2]
                x,z = rotate2d((x,z), cam.rot[1])
                y,z = rotate2d((y,z), cam.rot[0])
                vert_list += [(x,y,z)]
                f = fov/z
                x,y = x*f,y*f
                screen_coords+=[(cx+int(x),cy+int(y))]

            for f in range (len(obj.faces)):
                face = obj.faces[f]

                on_screen = False

                for i in face:
                    x,y = screen_coords[i]
                    if vert_list[i][2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True ; break

                if on_screen:
                    coords = [screen_coords[i] for i in face]
                    face_list += [coords]
                    face_colour += [obj.colours[f]]
                    depth += [sum(sum(vert_list[j][i] for j in face) **2 for i in range (3))]


    order = sorted(range(len(face_list)), key=lambda i:depth[i], reverse=1)
    for i in order:
        try: pygame.gfxdraw.textured_polygon(screen, face_list[i], obj.texture, 0, 0); pygame.gfxdraw.aapolygon(screen, face_list[i], (0,0,0))
        except: pass

## OLD CODE - pygame.draw.polygon(screen, face_colour[i], face_list[i]) ##
## NEW CODE - pygame.gfxdraw.textured_polygon(screen, face_list[i], obj.texture, 0, 0) ##
## TEST CODE - pygame.gfxdraw.filled_polygon(screen, face_list[i], face_colour[i]) ##

    Draw_Crosshair((255,255,255),2)

    TextUI("Press ESCAPE to exit", (255,255,255), (20,20))
    TextUI("Movement Controls: W, A, S, D, SPACE and C", (255,255,255), (20,60))

    pygame.display.update()

    key = pygame.key.get_pressed()
    cam.update(dt, key)

Tags: keyinposselfeventforifscreen
1条回答
网友
1楼 · 发布于 2024-06-16 14:21:01

这是一个漂亮的代码,它的工作方式完全符合预期,二维多边形填充了平坦的纹理。要超越二维来渲染实体对象(仍然是从pygame开始),您需要转到OpenGL。在

相关问题 更多 >