如何扭曲图像

时间:2018-02-03 20:34:53

标签: python python-3.x pygame pygame-surface

我开始在python中使用我自己的Super Mario Kart版本,就像我自己的一个小项目一样。到目前为止,我已经设法将图像转换为看起来像玩家正在伪3D轨道上移动。然而,根本没有视角,这有点破坏了3D的幻觉。我知道我可以解决这个问题,如果我有一种方法可以使图像偏斜,使表面的底部比顶部宽,因为这有助于模拟透视。

我一直在网上寻找相当长的一段时间,看看是否有办法实现这一点,因为我真的不知道从哪里开始。虽然我的搜索没有结果,但我没有找到任何有用的信息。

那么我该怎么做才能扭曲轨道的形象呢?

到目前为止,这是我的代码:

import os, sys, pygame
from pygame.locals import *
from math import *

pygame.init()

path, file_name = os.path.split(__file__)
path            = os.path.join(path, 'data')

WIDTH  = 800
HEIGHT = 600
SCREEN = pygame.display.set_mode((WIDTH,HEIGHT))
CLOCK  = pygame.time.Clock()
FPS    = 30

pygame.mouse.set_visible(False)
pygame.display.set_caption('Mario Kart')

class Driver(object):
    def __init__(self, image, start_pos):
        self.surface = pygame.image.load(os.path.join(path, image)).convert()
        self.surface.set_colorkey(MAGENTA)
        self.surface = pygame.transform.scale(self.surface, (64, 64))

        self.pos = list(start_pos)
        self.angle = 0
        self.velocity = 0

    def move(self):
        keys = pygame.key.get_pressed()

        if keys[K_a] or keys[K_LEFT]:
            self.angle -= 14 / (1 + e ** (-0.3 * self.velocity)) - 7
            #Sigmoid function to contain the angular velocity between 7 and -7

        if keys[K_d] or keys[K_RIGHT]:
            self.angle += 14 / (1 + e ** (-0.3 * self.velocity)) - 7

        if keys[K_w] or keys[K_UP]:
            self.velocity += 3

        elif keys[K_s] or keys[K_DOWN]:
            self.velocity -= 1

        self.velocity *= 0.85

        self.pos[0] += self.velocity * sin(radians(self.angle))
        self.pos[1] -= self.velocity * cos(radians(self.angle))

    def render(self):
        SCREEN.blit(self.surface, (WIDTH / 2 - 32, HEIGHT / 2 - 32))

class Track(object):
    def __init__(self, image, tilt = 1, zoom = 1):
        self.surface = pygame.image.load(os.path.join(path, image)).convert_alpha()
        self.angle = 0
        self.tilt = tilt
        self.zoom = zoom
        self.rect = self.surface.get_rect()
        self.rect.center = (WIDTH / 2, HEIGHT / 2)

        self.image = self.surface
        self.image_rect = self.image.get_rect()

    def render(self, angle, center = (0, 0)):
        self.angle = angle

        self.image = self.surface 
        self.image = pygame.transform.rotate(self.image, self.angle)
        self.image_rect = self.image.get_rect()

        self.image = pygame.transform.scale(self.image, (int(self.image_rect.width * self.zoom), int((self.image_rect.height * self.zoom) / self.tilt)))

        self.image_rect = self.image.get_rect(center = (self.rect.centerx - ((center[0] * self.zoom) * cos(radians(-self.angle)) - (center[1] * self.zoom) * sin(radians(-self.angle))),
                                                        self.rect.centery - ((center[0] * self.zoom) * sin(radians(-self.angle)) + (center[1] * self.zoom) * cos(radians(-self.angle))) / self.tilt))

        SCREEN.blit(self.image, self.image_rect)


def main():
    track = Track('MushroomCup1.png', tilt = 4, zoom = 7)
    toad = Driver('Toad Sprite.png', (408, 90))

    while True:
        SCREEN.fill((255, 255, 255))

        toad.move() 

        track.render(toad.angle, toad.pos)
        toad.render()

        events = pygame.event.get()
        for event in events:
            if event.type == QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()

        pygame.display.update()
        CLOCK.tick(FPS)

if __name__ == '__main__':
    main()
  • MushroomCup1.png

Mushroom Cup Track 1

  • Toad Sprite.png

Toad Kart Sprite

1 个答案:

答案 0 :(得分:1)

如果你想获得真正的3D,你将不得不尝试像PyOpenGL或Pyglet这样的东西。 PyGame实际上只适用于传统的2D表面/透视。

那就是说,我确实写了一个运行在纯PyGame(here's a JS port)上的Mario Kart风格的3D驾驶游戏。我为道路设置坐标,将道路分解为单个三角形,并进行了大量的矩阵数学运算。这主要是一个幽默的练习,看看我,而不是我应该做的事情。这只是几何原语。对于图像来说,它变得更加复杂。

如果你真的想要,你可能会做一些事情,比如预处理图像资源,以简化并将其分解为一堆大型方块,并采用类似的方法将这些分解成具有大量矩阵数学的三角形。它不会很快,但它在技术上可行并且只需要PyGame。

基本上我所说的是,精神上没有Pygame解决方案,如果你想要3D,你将不得不转移到支持它的框架(如Pyglet或PyOpenGL)。