2016-10-03 88 views
0

我学习蟒蛇*\(^o^)/*简单的pygame的动画口吃

我使用Pygame得出一个简单的跳动框窗口。除了一个小小的烦恼之外,一切似乎都正常运作。它不断结巴!我不知道什么可能导致口吃。我认为这可能是滞后的,所以我实施了一个固定的时间步骤来让循环赶上,但这没有效果。

#--- initialize pygame window ---# 
import pygame 
import time 
pygame.init() 
size = (1200,500) 
screen = pygame.display.set_mode(size, pygame.RESIZABLE) 
fps = 60 

#--- define color palette ---# 
black = (0,0,0) 
white = (255,255,255) 

#--- define the player ---# 
class player: 
    def __init__(self,screen,surface, color): 
     self.speed = 3 
     self.direction_x = 1 
     self.direction_y = 1 
     self.screen = screen 
     self.surface = surface 
     self.rect = self.surface.get_rect() 
     self.color = color 
    def set_pos(self, x,y): 
     self.rect.x = x 
     self.rect.y = y 
    def advance_pos(self): 
     screen_width, screen_height = screen.get_size() 
     if self.rect.x + self.rect.width > screen_width or player1.rect.x < 0: 
      player1.direction_x *= -1 
      player1.speed = 3 
     elif player1.rect.y + player1.rect.height > screen_height or player1.rect.y < 0: 
      player1.direction_y *= -1 
      player1.speed = 3 
     else: 
      player1.speed -= 0.001 
     self.rect.x += self.speed * self.direction_x 
     self.rect.y += self.speed * self.direction_y 
    def draw(self): 
     pygame.draw.rect(self.surface, self.color, [0,0,self.rect.width,self.rect.height]) 
    def blit(self): 
     screen.blit(self.surface, self.rect) 
player1 = player(screen, pygame.Surface((50,50)), white) 
player1.set_pos(50,50) 
player1.draw() 

#--- define game variables ---# 
previous = time.time() * 1000 
lag = 0.0 
background = black 
done = False 

#--- game ---# 
while not done: 

    #--- update time step ---# 
    current = time.time() * 1000 
    elapsed = current - previous 
    lag += elapsed 
    previous = current 

    #--- process events ---# 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      done = True 
      break 
     if event.type == pygame.VIDEORESIZE: 
      screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE) 

    #--- update logic ---# 

    while True: 
     player1.advance_pos() 
     lag -= fps 
     if lag <= fps: 
      break 

    #--- draw to screen ---# 
    screen.fill(background) 
    player1.blit() 
    pygame.display.update() 
    pygame.time.Clock().tick(fps) 
+0

你已经采取了看看[这里](http://gamedev.stackexchange.com/questions/102586/locking-the-frame-rate-in-pygame)链接?那里提供的答案有一些有用的建议。如果你正好需要60 fps,你需要vsync,我不确定pygame提供什么,除非你使用pyopengl来进行pygame渲染。 – CodeSurgeon

+0

我不知道PyOpenGL。谢谢! – Jace

+0

从头学习OpenGL可能会非常具有挑战性,如果您之前没有使用它。如果可以帮助,我可以发布一个演示,复制你已经使用pygame和pyopengl编写的内容。 – CodeSurgeon

回答

1

这是您的代码的重写,它使用opengl代替渲染。主要变化如下:

  1. 我使用了opengl即时模式,这是过时的,不推荐使用,但起初很容易理解。大部分gl调用都在player.draw()方法或主循环中。
  2. 我修好了定时器的工作方式。我不是只做clock.tick(fps),而是手动记录对帧进行所有处理所需的时间,并添加适当的毫秒延迟以达到60 fps。在迁移到opengl之前,您可以使用现有的pygame代码尝试修改,因为这可能足以删除大部分的结构。

    import pygame 
    import time 
    from OpenGL.GL import * 
    
    class Player: 
        def __init__(self, screen, width, height, color): 
         self.x = 0 
         self.y = 0 
         self.speed = 3 
         self.direction_x = 1 
         self.direction_y = 1 
         self.screen = screen 
         self.width = width 
         self.height = height 
         self.color = color 
    
        def set_pos(self, x, y): 
         self.x = x 
         self.y = y 
    
        def advance_pos(self): 
         screen_width, screen_height = screen.get_size() 
         if self.x + self.width > screen_width or self.x < 0: 
          self.direction_x *= -1 
          self.speed = 3 
         elif self.y + self.height > screen_height or self.y < 0: 
          self.direction_y *= -1 
          self.speed = 3 
         else: 
          self.speed -= 0.001 
         self.x += self.speed * self.direction_x 
         self.y += self.speed * self.direction_y 
    
        def draw(self): 
         glMatrixMode(GL_MODELVIEW) 
         glLoadIdentity() 
         glTranslate(self.x, self.y, 0) 
         glBegin(GL_QUADS) 
         glColor(*self.color) 
         glVertex(0, 0, 0) 
         glVertex(self.width, 0, 0) 
         glVertex(self.width, self.height, 0) 
         glVertex(0, self.height, 0) 
         glEnd() 
    
    if __name__ == "__main__": 
        pygame.init() 
        size = width, height = (550, 400) 
        screen = pygame.display.set_mode(size, pygame.RESIZABLE | pygame.DOUBLEBUF | pygame.OPENGL) 
        fps = 60 
        black = (0,0,0,255) 
        white = (255,255,255,255) 
    
        player1 = Player(screen, 50, 50, white) 
        player1.set_pos(50,50) 
    
        done = False 
        previous = time.time() * 1000 
        glClearColor(*black) 
        glMatrixMode(GL_PROJECTION) 
        glLoadIdentity() 
        glOrtho(0, width, height, 0, -1, 1) 
        clock = pygame.time.Clock() 
    
        while not done: 
         current = time.time() * 1000 
         elapsed = current - previous 
         previous = current 
         delay = 1000.0/fps - elapsed 
         delay = max(int(delay), 0) 
    
         for event in pygame.event.get(): 
          if event.type == pygame.QUIT: 
           done = True 
           break 
          if event.type == pygame.VIDEORESIZE: 
           size = width, height = event.w, event.h 
           screen = pygame.display.set_mode(size, pygame.RESIZABLE | pygame.DOUBLEBUF | pygame.OPENGL) 
           glMatrixMode(GL_PROJECTION) 
           glLoadIdentity() 
           glOrtho(0, width, height, 0, -1, 1) 
           glViewport(0, 0, width, height) 
    
           #reset player movement and position to avoid glitches where player is trapped outside new window borders 
           player1.set_pos(50, 50) 
           player1.direction_x = 1 
           player1.direction_y = 1 
    
         player1.advance_pos() 
         glClear(GL_COLOR_BUFFER_BIT) 
         glClear(GL_DEPTH_BUFFER_BIT) 
         player1.draw() 
         pygame.display.flip() 
         pygame.time.delay(delay) 
    
+0

优秀!谢谢你的帮助。 OpenGL将会非常有趣。 – Jace