Pygame如何记录玩游戏时的键盘动作

Pygame how to record keyboard movement while playing the game

所以我正在尝试制作也能记录玩家移动然后回放的俄罗斯方块,将其视为回放功能。

我尝试过实现键盘库,但问题是当我尝试 record(recorded_events = keyboard.record("esc")) 时,整个游戏冻结,直到我按下“esc”,当我尝试播放它时,它冻结并且什么都不做。

我注意到的是,如果我将打印语句放在播放旁边,它会在游戏冻结时打印整个键盘输入,但无论如何都无法播放。

IDK 做什么

我的代码片段接受输入并打勾并将它们放入文本文件中。

if event.key == pygame.K_DOWN:
                increaseGravity = True
                u = " s\n"
                time = str(pygame.time.get_ticks())
                e = time + "," + u 
                f.writelines(str(e))

以及负责播放的代码部分!

if event.key == pygame.K_h:
                f = open("m.txt", "r")
                currtick = pygame.time.get_ticks()
                for x in f:
                    b = x.split(',')
                    cc = int(b[0])

                if cc == currtick:
                    print(" works")
                    keyboard.press_and_release(b[1].strip)                    
              

这就是文本文件的样子,第一个是报价,第二个是移动

1453, d
1763, d
2752, a

以下建议:

if event.key == pygame.K_h:
                currtick = pygame.time.get_ticks()
                for x in keyList:
                    # Variable that counts
                    cx = 0
                    # current tick time combined with the movment tick
                    cc = (int(keyList[cx][0])) + currtick
                    
                    # puts key id into xx variable
                    xx= int(keyList[cx][1])
                    
                    #prints both
                    print(keyList[cx][0],keyList[cx][1])
                    #adds +1 to cx
                    cx =+ 1
                # if current tick + time when pressed is equal to current game tick it executes print and presses the key
                if cc == currtick:
                    print(" works")
                    if(xx == 1073741904):
                        keyboard.press_release('a')

我创建了一个示例,可以记录事件,然后在事件之间大致相同的时间重播事件。

当按下鼠标左键时,记录被启用并且 KEYDOWN 事件连同它们发​​生的时间附加到列表中。 Left-clicking 再次禁用录音。 Right-clicking 将开始播放 scheduling a custom event to occur. When that event occurs, the recorded event is inserted into the event queue 录制的事件。然后使用刚刚发布的事件和下一个事件之间的时间差设置计时器。

import time
import random
import pygame

CUSTOM_PLAYBACK_EVENT = pygame.USEREVENT + 1


def queue_next_event(event_list, event_index):
    """Set a timer for the next playback event"""
    if event_index == 0:
        timer_duration = 100  # effectively immediate
    else:
        elapsed_time = event_list[event_index][1] - event_list[event_index - 1][1]
        timer_duration = round(elapsed_time * 1000)  # convert to milliseconds
    pygame.time.set_timer(CUSTOM_PLAYBACK_EVENT, timer_duration)
    print(f"{time.time()} Set timer for {timer_duration} ms")


class Block(pygame.sprite.Sprite):
    def __init__(self, size, pos):
        pygame.sprite.Sprite.__init__(self)
        self.size = size
        self.image = pygame.Surface([size[0], size[1]])
        self.image.fill(pygame.color.Color("blueviolet"))
        self.rect = self.image.get_rect()
        self.rect[0] = pos[0]
        self.rect[1] = pos[1]
        # initially stationary
        self.speedx = 0
        self.speedy = 0

    def update(self):
        """Move, but stay within window bounds"""
        width, height = screen.get_size()
        if not (self.size[0] // 2) < self.rect.center[0] < (width - self.size[0] // 2):
            self.speedx *= -1  # reverse direction
        self.rect.x += self.speedx

        if not (self.size[1] // 2) < self.rect.center[1] < (height - self.size[1] // 2):
            self.speedy *= -1  # reverse direction
        self.rect.y += self.speedy

    def draw(self, screen):
        # Add this draw function so we can draw individual sprites
        screen.blit(self.image, self.rect)

    def handle_event(self, event):
        # update speeds based one keypress
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                self.speedx -= 1
            elif event.key == pygame.K_RIGHT:
                self.speedx += 1
            elif event.key == pygame.K_UP:
                self.speedy -= 1
            elif event.key == pygame.K_DOWN:
                self.speedy += 1
            elif event.key == pygame.K_SPACE:
                self.speedx = 0
                self.speedy = 0
            else:
                pass


# initialise screen
screen = pygame.display.set_mode((800, 800), pygame.RESIZABLE | pygame.NOFRAME)
pygame.init()
sprite_list = pygame.sprite.Group()

# create a cube at a random position
cube = Block((80, 80), (random.randint(100, 700), random.randint(100, 700)))
clock = pygame.time.Clock()
# variables for recording
recording = False
playback = False
playback_index = 0
recorded_events = []

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False
            else:
                # handle the event
                cube.handle_event(event)
                if recording:
                    # save the event and the time
                    recorded_events.append((event, time.time()))  # event
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # Left click
                recording = not recording  # toggle recording
            elif event.button == 3:  # Right click toggles playback
                playback = not playback
                if playback:
                    if recorded_events:
                        playback_index = 0  # always start playback at zero
                        queue_next_event(recorded_events, playback_index)
                    else:
                        playback = False  # can't playback no events
                else:  # disable playback timer
                    pygame.time.set_timer(CUSTOM_PLAYBACK_EVENT, 0)
        elif event.type == CUSTOM_PLAYBACK_EVENT:
            pygame.time.set_timer(CUSTOM_PLAYBACK_EVENT, 0)  # disable playback timer
            # post the next event
            pygame.event.post(recorded_events[playback_index][0])
            playback_index += 1
            if playback_index < len(recorded_events):
                queue_next_event(recorded_events, playback_index)
            else:
                playback = False
    # clear the screen
    screen.fill(pygame.Color("white"))
    # update sprites
    cube.update()
    # draw sprites
    cube.draw(screen)
    # refresh display
    pygame.display.update()
    clock.tick(60)  # limit to 60 FPS

pygame.quit()

记录的事件不会被清除,所以如果您停止和开始记录会有更大的差距,有一个调试 print 语句可以帮助跟踪事情。理想情况下会有一些记录和回放的视觉指示。