[Python] Python: pygame.gfxdraw.texturedpolygon

Discussão em 'Python' iniciado por Stack, Agosto 12, 2025.

  1. Stack

    Stack Membro Participativo

    So, I've been coding in Python for a few weeks and I felt like trying to make a game. I've gotten to a point where I have no clue what is wrong with my code except for the fact that when I try to draw a textured polygon the texture stretches across the display and only reveals on the cubes. It creates a really cool effect but it isn't what I'm looking for. The goal is to render the texture onto the face of the cube like in 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
    if vert_list[2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True ; break

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


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

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

    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)

    Continue reading...

Compartilhe esta Página