마우스를 움직일 때 스프라이트 플레이어가 더 빨리 움직이는 이유는 무엇입니까?


17

Pygame (Python 라이브러리)으로 만든 간단한 게임을 개발하려고합니다.

나는 sprite객체를 가지고 있으며 player화살표 키를 사용하여 움직입니다. 마우스를 움직이지 않으면 스프라이트가 정상적으로 움직이지만 마우스를 움직이면 스프라이트가 더 빨리 움직입니다 (x2 또는 x3처럼). player객체는 내부 charsGroupVAR.

나는 W7과 우분투에서 게임을 운영했다. 두 OS 모두에서 동일한 일이 발생합니다.

NPC와 총알처럼 움직이는 엔티티가 더 많지만 플레이어에게는 영향을 미치지 않습니다. 이를 감안할 때 문제가 플레이어 이동 시스템 (화살표 키)과 직접 연결되어 있다고 생각합니다.

객체 의 update()방법은 다음과 같습니다 player.

def update(self):

    for event in pygame.event.get():
        key = pygame.key.get_pressed()
        mouseX, mouseY = pygame.mouse.get_pos()
        if event.type == pygame.MOUSEBUTTONDOWN:
            self.bulletsGroup.add(Bullet(pygame.image.load("bullet.png"),
                                          self.rect.x + (self.image.get_width()/2),
                                           self.rect.y + (self.image.get_height()/2),
                                            mouseX, mouseY, 50, 50))

        if key[pygame.K_RIGHT]:
            if not self.checkCollision():
                self.rect.x += 10
            else:
                self.rect.x -= 10
        if key[pygame.K_LEFT]:
            if not self.checkCollision():
                self.rect.x -= 10
            else:
                self.rect.x += 10
        if key[pygame.K_UP]:
            if not self.checkCollision():
                self.rect.y -= 10
            else:
                self.rect.y += 10
        if key[pygame.K_DOWN]:
            if not self.checkCollision():
                self.rect.y += 10
            else:
                self.rect.y -= 10

그리고 여기 while 루프가 있습니다 :

while True:

    if PLAYER.healthBase <= 0:
        GAMEOVER = True

    if not GAMEOVER:
        mapTilesGroup.draw(SCREEN)
        charsGroup.update()
        charsGroup.draw(SCREEN)
        npcsGroup.update()
        npcsGroup.draw(SCREEN)
        drawBullets()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

    if GAMEOVER:
        myfont = pygame.font.SysFont("monospace", 30)
        label = myfont.render("GAME OVER!", 1, (255, 255, 0))
        SCREEN.blit(label, (400, 300))

    freq.tick(0)

    pygame.display.flip() 

나는 당신이 나를 도울 수있는 것이 무엇인지 모르지만 필요한 정보 (더 많은 정보 또는 코드)를 요구합니다!


5
정확한 버그는 실제로 많은 응용 프로그램에 존재합니다. 큰 문서에서 선택을 드래그하고 가장자리 밖으로 커서를 이동하십시오. 일반적으로 프로그램의 가장자리 스크롤이 시작되어 서서히 더 많은 문서를 선택합니다. 마우스를 좌우로 움직이면 스크롤 속도가 이벤트 루프에 연결되고 X 모션이 이벤트 루프를 반복적으로 깨우기 때문에 일반적으로 훨씬 빠르게 스크롤됩니다.
벤 잭슨

2
@ BenJackson 스크롤이 느리게 시작될 때 유용한 버그가되는 것을 알았습니다.
user253751

1
이것은 버그와 관련이 없지만 이미지를 한 번로드하고 객체에 저장하는 것이 좋습니다. BULLET_IMAGE = pygame.image.load("bullet.png")그리고 나중에self.bulletsGroup.add(Bullet(BULLET_IMAGE...
DJMcMayhem

@DJMcMayhem 당신은 완전히 옳습니다, 나는 나머지 이미지로 그것을 해냈지만 이것으로 그것을 놓쳤습니다 .. 감사합니다! :)
Drumnbass

답변:


42

tl; dr이벤트 루프 게임 루프를 .

마우스를 움직이면 게임에 많은 pygame.MOUSEMOTION이벤트가 수신 됩니다. 실제로 이러한 이벤트를 사용하여 마우스 위치를 업데이트하지는 않습니다.pygame.mouse.get_pos() . 비효율적이지만 문제가 아닙니다.

문제는 이벤트 루프 내에서 플레이어 위치를 업데이트하는 것입니다 !

이것이 일어날 일입니다.

game loop:
    event loop # get key presses, mouse moves etc.)
    if key pressed in the event loop:
        move the player

이것이 코드가하는 일입니다.

game loop:
    event loop:
        if key pressed:
            move the player

마우스를 움직이면 이벤트 루프가 프레임 당 여러 번 실행됩니다. 그러나 어떤 키를 눌렀는지 확인할 때pygame.key.get_pressed() 하면 나중에 를 놓을 때까지 눌려져 있습니다. 따라서 이벤트 루프가 마우스 이동 이벤트를 통해 변경되면 플레이어 이동이 반복적으로 다시 적용됩니다.

해결책은 간단합니다. 플레이어를 이벤트 루프 밖으로 옮기십시오.


1
감사! 그것은 지금 완벽하게 작동하며 아마도 무슨 일이 일어나고 있는지 몰랐을 것입니다! Btw, 왜 그것이 pygame.mouse.get_pos()비효율적 이라고 말 합니까? 어떤 대안이 있습니까?
Drumnbass

안녕하세요 @ congusbongus, 저에게 설명해 주시겠습니까? 감사.
Drumnbass

@Drumnbass pygame.mouse.get_pos()는 이벤트 대기열에 관계없이 마우스의 최신 위치를 가져 오므로 이벤트 루프 안에 넣을 필요가 없습니다. 대안은 모든 것을 pygame.MOUSEMOTION스스로 처리하는 것이지만, 모든 행사가 필요하지 않은 경우 (예 : 회화 프로그램을 작성하는 경우), 최신 직책이 수행됩니다.
congusbongus

3

기존 답변 을 보완 할 수 있는 몇 가지 생각이 있습니다.

Gaffer On Games 는 모든 곳에서 참조 된 게임 루프에 대한 훌륭한 기사를 제공 합니다.

게임 루프는 입력, 업데이트, 렌더 등 서로 다른 독립 단계를 가져야합니다.

예를 들어 초당 30 회 (또는 더 나은 응답 성을 위해 실시간으로) 입력을 읽거나 초당 30 회 업데이트를 수행하고 초당 60 프레임을 렌더링하거나 게임에 적합한 값을 얻을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.