ทำไมผู้เล่นสไปรต์ของฉันถึงเคลื่อนที่เร็วขึ้นเมื่อฉันเลื่อนเมาส์


17

ฉันพยายามพัฒนาเกมง่ายๆที่สร้างด้วย Pygame (Python library)

ฉันมีspriteวัตถุที่เป็นplayerและฉันย้ายมันโดยใช้ปุ่มลูกศร ถ้าฉันไม่เลื่อนเม้าส์สไปรต์ก็จะเคลื่อนที่ตามปกติ แต่เมื่อฉันเลื่อนเมาส์สไปรต์จะเคลื่อนที่เร็วขึ้น (เช่น x2 หรือ x3) playerวัตถุอยู่ภายในcharsGroupvar

ฉันใช้งานเกมใน W7 และใน Ubuntu สิ่งเดียวกันเกิดขึ้นในทั้งสองระบบปฏิบัติการ

ฉันมีเอนทิตีมากกว่าที่เคลื่อนไหวเหมือน 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 loop:

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 ทำให้เกิดการวนซ้ำของเหตุการณ์
Ben Jackson

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
ขอบคุณ! มันทำงานได้อย่างสมบูรณ์แบบในตอนนี้และบางทีฉันอาจไม่เคยรู้เลยว่าเกิดอะไรขึ้น! แต่ทำไมคุณถึงบอกว่า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.