2014-01-30 7 views
1

Я столкнулся с проблемой после написания небольшой программы с pygame. Программа принимает разделить .GIF анимации и загружает изображения (кадры GIF) с помощью:Значок события ввода клавиатуры Pygame

pygame.image.load(filename) 

Это возвращает объект Pygame поверхность, которая затем добавляется в массив. Программа загружает около 15 кадров в массив, используя 6 массивов всего.

Проблема, возникающая у меня возникает, когда принимаю вход через мой while loop. Петля играет свою анимацию ожидания и работает анимация отлично, однако на прием ввода с клавиатуры (захватывая ввод из списка событий Pygame в ...)

for event in pygame.event.get(): через pygame.KEYDOWN

Существует очень заметное отставание, конструкция для не отвечающий анимация комплект переключение. Если я сделаю игру, используя этот метод, он должен быть исправлен. Я уверен, что мой код неэффективен, но недостаточно создавать паузы. Любая помощь будет фантастической.

Мое предположение? pygame.clock.tick() создает своего рода событие lag, но я не уверен, как это сделать, если событие отставание даже в случае.

Вот цикл, который я подозреваю, будет проблематично:

while running == 2: 
pygame.display.flip() 
#mouse = pygame.mouse.get_pos() 
#events = pygame.event.get() 
#(pygame.QUIT, pygame.KEYDOWN, pygame.KEYUP) 
for event in pygame.event.get(): 
#event = pygame.event.wait() 
    if event.type == pygame.QUIT: 
     sys.exit(0) 
    elif event.type == pygame.KEYDOWN: 
     print event.key 
     wait = 0 
     if event.key == pygame.K_d: 
      tmpcache = wr 
      lastkey = "wr" 
     elif event.key == pygame.K_a: 
      tmpcache = wl 
      lastkey = "wl" 
    elif event.type == pygame.KEYUP: 
     wait = 1 
     if lastkey == "wr": 
      tmpcache = sr 
     elif lastkey == "wl": 
      tmpcache = sl 

if wait == 1:   
    for frame in tmpcache: 
     screen.blit(test, (0,0)) 
     screen.blit(frame, (currentchar.posx, currentchar.posy)) 
     pygame.display.flip() 
     clock.tick(charfps) 

else: 
    for frame in tmpcache: 
     screen.blit(test, (0,0)) 
     screen.blit(frame, (currentchar.posx, currentchar.posy)) 
     pygame.display.flip() 
     clock.tick(charfps) 

некоторые переменные не показаны здесь, но используются:

charfps = 30
currentchar.posx, currentchar.posy оба являются кортежей набор на (300, 240)

+1

появляется этот вопрос быть не по теме, потому что она принадлежит по HTTP : //gamedev.stackexchange.com – jonrsharpe

+0

Было бы лучше на игровом деве, но это все еще о программировании. –

ответ

3

Ваша проблема в том, что вы создаете суб-петли внутри основного контура:

while running == 2: 
    pygame.display.flip() 
    for event in pygame.event.get(): 
     ... 
    for frame in tmpcache: 
     screen.blit(test, (0,0)) 
     screen.blit(frame, (currentchar.posx, currentchar.posy)) 
     pygame.display.flip() 
     clock.tick(charfps) 

Так что, если есть 15 элементов в tmpcache, вы звоните clock.tick() 15 раз за кадр, и в то время как код работает внутри этого подвида цикла, не протекающие события.

Просто позвоните pygame.display.flip() и clock.tick(charfps)только один раз за кадр должен решить вашу проблему.

Вот простой пример, изменяя образ анимации три раза в секунду, при работе на 60 FPS:

import pygame 
from collections import deque 

pygame.init() 
screen = pygame.display.set_mode((300, 300)) 
clock = pygame.time.Clock() 

# just some colored squares for our animation 
def get_cache(colors): 
    tmp=[] 
    for c in colors: 
     s = pygame.surface.Surface((50,50)) 
     s.fill(pygame.color.Color(c)) 
     tmp.append(s) 
    return tmp 

walk_left, walk_right = get_cache(('red', 'yellow', 'blue')), get_cache(('black', 'white', 'grey')) 

rect = walk_left[0].get_rect(top=100, right=100) 
cachedeque = deque(walk_left) 
state = None 
quit = False 

# a simple variable to keep track of time 
timer = 0 

# a dict of {key: (animation, direction)} 
moves = {pygame.K_LEFT: (walk_left, (-2, 0)), 
     pygame.K_RIGHT: (walk_right, (2, 0))} 

while not quit: 
    quit = pygame.event.get(pygame.QUIT) 
    pygame.event.poll() 

    # state of the keys 
    keys = pygame.key.get_pressed() 

    # filter for the keys we're interessted in 
    pressed = ((key, _) for (key, _) in moves.iteritems() if keys[key]) 
    key, (cache, dir) = next(pressed, (None, (None, None))) 

    # if a key of the 'moves' dict is pressed: 
    if key: 
     # if we change the direction, we need another animation 
     if state != key: 
      cachedeque = deque(cache) 
      state = key 
     # move the square     
     rect.move_ip(dir) 
    else: 
     state = None 

    screen.fill(pygame.color.Color('green')) 

    # display first image in cachedeque  
    screen.blit(cachedeque[0], rect) 

    # rotate cachedeque to the left, so the second image becomes the first 
    # do this three times a second: 
    if state and timer >= 1000./3: 
     cachedeque.rotate(-1) 
     timer = 0 

    # call flip() and tick() only once per frame 
    pygame.display.flip() 

    # keep track of how long it took to draw this frame 
    timer += clock.tick(60) 

enter image description here

+0

Я понимаю, что вы говорите, обновляя дисплей и отмечая часы только один раз за кадр. То, что вы мне дали, просто не работает. Это дает мне второй кадр в анимации при нажатии соответствующей клавиши.Я хочу, чтобы анимация воспроизводилась с частотой 30 кадров в секунду (всего 15 кадров) в цикле в зависимости от того, удерживается ли клавиша или нет, фактически не влияя на время ввода (создавая задержку при ожидании анимация, чтобы закончить цикл). – CR0SS0V3R

+0

Я обновил свой ответ с лучшим примером. – sloth

+0

Это определенно помогло мне понять, что было там, я никогда раньше не использовал deque, и я считаю, что это поможет мне в будущих проектах программирования. Я обновил свой код с помощью той же техники, которую вы показали мне, и теперь все отлично работает, спасибо! – CR0SS0V3R

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