2016-10-03 3 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 кадров в секунду, вам нужен 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 кадров в секунду. Вы можете попробовать эту модификацию с существующим кодом pygame перед переносом на opengl, поскольку этого может быть достаточно, чтобы удалить большую часть заикания.

    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

Смежные вопросы