Pygame技术问题:如何将PNG纹理1:1映射到矩形
Pygame Flappy Bird管道纹理映射问题
我是Pygame新手,正在制作Flappy Bird克隆作为首个Pygame项目。目前已有基础框架,但为矩形添加纹理时遇到问题:用两个矩形表示上下管道,仅显示矩形时尺寸位置符合预期,但添加PNG管道纹理后,纹理无法与矩形正确映射。
我的代码如下:
import pygame import random pygame.init() screen = pygame.display.set_mode((250,500)) clock = pygame.time.Clock() run = True background = pygame.image.load('graphics/background-day.png') ground = pygame.image.load('graphics/base.png') birdRec = pygame.Rect(0, 0, 30, 24) birdRec.center = (100,300) bottomPipeHeight = random.randrange(50, 350) pipeRecBottom = pygame.Rect(0,0, 50, bottomPipeHeight) pipeRecBottom.midbottom = (150, 450) pipeRecTop = pygame.Rect(0,0,50,500) pipeRecTop.midbottom = pipeRecBottom.midtop pipeRecTop.y -= 100 gravity = 0 pipeBottomTexture = pygame.image.load("graphics/pipe-green.png").convert_alpha() while run: #poll for events #pygame.QUIT event means the user clicked x for event in pygame.event.get(): if event.type == pygame.QUIT: run = False gravity += .1 birdRec.y += gravity keys = pygame.key.get_pressed() if keys[pygame.K_w]: birdRec.y -= 7 gravity = 0 if keys[pygame.K_s]: birdRec.y += 2 if keys[pygame.K_d]: birdRec.x += 2 if keys[pygame.K_a]: birdRec.x -= 2 pipeRecBottom.x -= 1 pipeRecTop.x -= 1 if(birdRec.colliderect(pipeRecTop) or birdRec.colliderect(pipeRecBottom)): print("Collision") # RENDER GAME screen.blit(background,(0,0)) screen.blit(ground,(0,450)) #PROBLOMATIC AREA BEGIN pygame.draw.rect(screen, "Black", pipeRecBottom) #screen.blit(pipeBottomTexture, pipeRecBottom) #PROBLOMATIC AREA END pygame.draw.rect(screen, "Green", pipeRecTop) pygame.draw.rect(screen, "Red", birdRec) if pipeRecBottom.right < -30: pipeRecBottom.height = random.randrange(50,350) pipeRecBottom.bottomleft = (280,450) if pipeRecTop.right < -30: pipeRecTop.midbottom = pipeRecBottom.midtop pipeRecTop.y -= 100 pygame.display.flip() clock.tick(60) pygame.quit()
我尝试注释掉问题区域的第一行,仅保留第二行,原本以为可将纹理直接贴在计算好位置的矩形上,但纹理出现偏移,底部管道会穿入地面。我认为底部管道的顶部映射位置正确,希望解决纹理穿入地面的问题。
正确效果:
错误效果:
两者的高度差异是因为管道高度随机生成,即使固定高度,仍存在穿入问题。
解决方法
问题根源是你定义的管道矩形尺寸和管道PNG的原始尺寸不匹配,直接用blit(纹理, 矩形)时,Pygame会把纹理左上角对齐矩形左上角,但不会缩放纹理适配矩形大小,导致纹理实际尺寸和你预期的矩形尺寸不符,底部管道就会因为纹理过高穿入地面。
步骤1:初始化时缩放并翻转纹理
# 加载并处理底部管道纹理 pipeBottomTexture = pygame.image.load("graphics/pipe-green.png").convert_alpha() pipeBottomTexture = pygame.transform.scale(pipeBottomTexture, (pipeRecBottom.width, pipeRecBottom.height)) # 加载并处理顶部管道纹理(需要垂直翻转) pipeTopTexture = pygame.image.load("graphics/pipe-green.png").convert_alpha() pipeTopTexture = pygame.transform.flip(pipeTopTexture, False, True) # 垂直翻转 pipeTopTexture = pygame.transform.scale(pipeTopTexture, (pipeRecTop.width, pipeRecTop.height))
步骤2:绘制时使用矩形位置绘制缩放后的纹理
替换问题区域的代码:
# PROBLOMATIC AREA BEGIN screen.blit(pipeBottomTexture, pipeRecBottom.topleft) # PROBLOMATIC AREA END screen.blit(pipeTopTexture, pipeRecTop.topleft)
步骤3:管道重置时重新缩放纹理
因为每次管道高度会随机变化,所以重置管道后要重新适配纹理尺寸:
if pipeRecBottom.right < -30: pipeRecBottom.height = random.randrange(50,350) pipeRecBottom.bottomleft = (280,450) # 重新缩放底部管道纹理 pipeBottomTexture = pygame.transform.scale(pipeBottomTexture, (pipeRecBottom.width, pipeRecBottom.height)) if pipeRecTop.right < -30: pipeRecTop.midbottom = pipeRecBottom.midtop pipeRecTop.y -= 100 # 重新缩放顶部管道纹理 pipeTopTexture = pygame.transform.scale(pipeTopTexture, (pipeRecTop.width, pipeRecTop.height))
这样处理后,纹理就会完全适配你定义的管道矩形尺寸,不会出现穿入地面的问题了。
内容的提问来源于stack exchange,提问作者ZacharyyK
相关产品推荐
相关产品推荐

