Tại sao trình phát sprite của tôi di chuyển nhanh hơn khi tôi di chuyển chuột?


17

Tôi đang cố gắng phát triển một trò chơi đơn giản được tạo bằng Pygame (thư viện Python).

Tôi có một spriteđối tượng playervà tôi di chuyển nó bằng các phím mũi tên. Nếu tôi không di chuyển chuột, sprite sẽ di chuyển bình thường, nhưng khi tôi di chuyển chuột, sprite sẽ di chuyển nhanh hơn (như x2 hoặc x3). Đối playertượng là bên trong charsGroupvar.

Tôi đã chạy trò chơi trong W7 và Ubuntu. Điều tương tự xảy ra trong cả hai hệ điều hành.

Tôi có nhiều thực thể di chuyển như NPC và đạn nhưng chúng không bị ảnh hưởng, chỉ là người chơi. Vì điều này, tôi nghĩ rằng vấn đề có thể có kết nối trực tiếp với hệ thống di chuyển của người chơi (phím mũi tên).

Đây là update()phương thức của playerđối tượng:

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

Và đây là vòng lặp 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() 

Tôi không biết bạn cần thêm gì để giúp tôi, nhưng bất cứ điều gì bạn cần (thêm thông tin hoặc mã) chỉ cần yêu cầu!


5
Lỗi chính xác của bạn thực sự tồn tại trong nhiều ứng dụng. Hãy thử kéo chọn trong một tài liệu lớn và di chuyển con trỏ của bạn ra khỏi cạnh. Thông thường cuộn cạnh của chương trình sẽ khởi động và từ từ chọn thêm tài liệu. Nếu bạn di chuyển chuột từ bên này sang bên kia, nó thường sẽ cuộn nhanh hơn nhiều, vì tốc độ cuộn của chúng được gắn với vòng lặp sự kiện của chúng và chuyển động X đánh thức vòng lặp sự kiện của chúng liên tục.
Ben Jackson

2
@BenJackson Tôi thấy rằng đó là một lỗi hữu ích khi bắt đầu di chuyển chậm khủng khiếp.
dùng253751

1
Điều này không liên quan đến lỗi của bạn, nhưng tôi khuyên bạn nên tải hình ảnh một lần và lưu trữ nó trong một đối tượng. BULLET_IMAGE = pygame.image.load("bullet.png")và sau đóself.bulletsGroup.add(Bullet(BULLET_IMAGE...
DJMcMayhem

@DJMcMayhem Bạn hoàn toàn đúng, tôi đã thực hiện nó với phần còn lại của hình ảnh nhưng tôi đã bỏ lỡ làm điều này với .. cảm ơn! :)
Drumnbass

Câu trả lời:


43

tl; dr không trộn vòng lặp sự kiện của bạn với vòng lặp trò chơi của bạn .

Khi bạn di chuyển chuột, trò chơi sẽ nhận được vô số pygame.MOUSEMOTIONsự kiện. Bạn thực sự không sử dụng những sự kiện này để cập nhật vị trí chuột của mình, bạn đang sử dụng trạng thái hiện tại của chuột pygame.mouse.get_pos(). Đó là không hiệu quả, nhưng nó không phải là vấn đề.

Vấn đề là bạn đang cập nhật vị trí người chơi bên trong vòng lặp sự kiện !

Đây là những gì sẽ xảy ra:

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

Đây là những gì mã của bạn làm:

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

Khi bạn di chuyển chuột, vòng lặp sự kiện sẽ thực thi nhiều lần trên mỗi khung. Nhưng khi bạn kiểm tra phím nào được nhấn pygame.key.get_pressed(), chúng sẽ được nhấn cho đến khi bạn buông tay, một thời gian sau. Vì vậy, khi vòng lặp sự kiện của bạn đang lướt qua các sự kiện di chuyển chuột, nó sẽ áp dụng lại người chơi di chuyển liên tục.

Giải pháp rất đơn giản: di chuyển người chơi ra ngoài vòng lặp sự kiện.


1
Cảm ơn! Nó hoạt động hoàn hảo và có lẽ tôi chưa bao giờ nhận ra chuyện gì đang xảy ra! Btw, tại sao bạn nói rằng pygame.mouse.get_pos()không hiệu quả? Tôi có những lựa chọn thay thế nào?
Drumnbass

Xin chào @congusbongus, bạn có thể giải thích cho tôi không? Cảm ơn.
Drumnbass

@Drumnbass pygame.mouse.get_pos()có được vị trí mới nhất của chuột, bất kể hàng đợi sự kiện, do đó không cần phải đặt nó trong vòng lặp sự kiện. Thay thế sẽ là tự xử lý pygame.MOUSEMOTION, nhưng trừ khi bạn cần mọi sự kiện (ví dụ: bạn đang viết chương trình vẽ tranh), vị trí mới nhất sẽ làm.
congusbongus

3

Dưới đây là một số suy nghĩ để bổ sung cho câu trả lời hiện có .

Gaffer On Gamesmột bài viết tuyệt vời về các vòng lặp trò chơi đã được tham khảo ở khắp mọi nơi.

Vòng lặp trò chơi của bạn nên có các giai đoạn độc lập khác nhau: Nhập liệu, Cập nhật, Kết xuất.

Ví dụ, bạn có thể đọc đầu vào 30 lần mỗi giây (hoặc trong thời gian thực để có độ phản hồi tốt hơn), thực hiện 30 cập nhật mỗi giây và hiển thị 60 khung hình mỗi giây hoặc bất kỳ giá trị nào hoạt động tốt cho trò chơi của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.