เพิ่มความเร็วในการ blitting


9

ฉันกำลังทำงานกับนักเล่นเกม 2 มิติใน PyGame สำหรับแต่ละแผนที่เราใช้หนึ่งพื้นผิว (นี่คือขนาดที่แท้จริงของพื้นผิว):

พื้นผิวแผนที่

จากนั้นเราโหลดภาพด้วยรหัสนี้:

sprite = pygame.image.load("Maps/MapTesting.png")
sprite.convert()
sprite = pygame.transform.scale(sprite,
              (sprite.get_width()*6, sprite.get_height()*6))

อย่างที่คุณเห็นพื้นผิวจะถูกเป่าขึ้น 6 ครั้งเพื่อสร้างพื้นผิวแผนที่จริง โดยเฉลี่ยแล้วพื้นผิวนี้มีขนาดประมาณ 4500x800 พื้นผิวนี้ต้องถูกทำให้เบลอกับหน้าจอทุกเฟรมเพราะหน้าจอทั้งหมดสกปรก (ขอบคุณการเลื่อนด้านข้าง) เราทำเช่นนั้นโดยใช้รหัสนี้:

screen.blit(sprite, (0, 0),
(cameraposx, cameraposy, windowheight, windowwidth))

และมันใช้งานได้ ปัญหาคือว่ามันค่อนข้างช้า: ฉันได้รับน้อย 40 FPS บนพีซีที่เหมาะสมและนั่นคือไม่มี AI / วัตถุจริงที่เกิดขึ้นในขณะที่เราตั้งเป้าไว้ที่ 60 FPS เราจะเร่งความเร็วนี้ได้อย่างไร?


โปรดทราบว่ารหัสข้างต้นถูกทำให้สะอาดและถูกนำออกจากบริบท รหัสเต็มสามารถดูได้ที่นี่: https://github.com/nightcracker/PyGG2

และสุดท้าย แต่ไม่ท้ายสุดในขณะที่ภาพด้านบนอาจดูเหมือน 8 บิตมีองค์ประกอบในเกมที่ต้องใช้ความลึกบิตมากกว่า


แบ่งออกเป็นขนาดที่มีสติต่อพื้นผิวพูดกว้าง 1024 ต่อบล็อกและแยกสองอย่างที่เกี่ยวข้องในแต่ละครั้ง
Jari Komppa

@ JariKomppa: พยายามไม่มีผลกระทบต่อการระเบิด (pygame ฉลาดพอที่จะทำให้หายไปจากส่วนที่ฉันบอกเท่านั้น) ใช้หน่วยความจำเท่านั้น
orlp

คุณสามารถ ... ไม่ใช้ pygame (trollface.jpg) .... jkjk ในกรณีนี้ฉันเดาว่านั่นไม่ใช่สิ่งที่การชะลอตัวของคุณเกิดขึ้นคุณเคยทดสอบอย่างกว้างขวางหรือไม่?
ultifinitus

@ultifinitus: ใช่ฉันทำประวัติด้วย cProfile
orlp

ความเร็วแตกต่างกันถ้าคุณแสดงตามความละเอียดจริง ถ้าคุณคำนวณภาพที่ใหญ่ขึ้นล่วงหน้า
ultifinitus

คำตอบ:


7

ให้ฉันแสดงรายการการเพิ่มประสิทธิภาพเปรียบเทียบทั่วไปบางอย่างที่เกี่ยวข้องกับการปัดพิกเซลไปยังพื้นผิว (จากประสบการณ์ของฉัน)

1) โดยปกติรูปภาพจานสี (ภาพที่จัดทำดัชนี) เมื่อเบลอจะมีการเปลี่ยนเส้นทางอีกระดับหนึ่ง (เพื่อให้ได้สี) ดังนั้นพวกเขาจะช้าเมื่อทำการ blitting เมื่อเปรียบเทียบกับภาพสีจริง

2) ข้อมูลพิกเซลสีจริง (สมมติโดยไม่ใช้อัลฟ่า - ข้อมูลบิต 24 บิต) สามารถถูกทำให้เบลอได้อย่างรวดเร็วเนื่องจากเราสามารถทำ memcpy สำหรับแต่ละ scanline ของภาพ (ถ้าเราคัดลอกส่วนหนึ่งของภาพ) ไปยังบัฟเฟอร์เฟรมอุปกรณ์ . ถ้าข้อมูลที่จะทำให้เป็นภาพเต็มนั้นเราสามารถบันทึกข้อมูลทั้งหมดได้โดยตรงซึ่งเร็วกว่ามาก!

3) การกระจายข้อมูลพิกเซลอัลฟ่าจะมีค่าใช้จ่ายสูงที่สุดเนื่องจากจะรวมการคำนวณผลลัพธ์แต่ละองค์ประกอบและเราจำเป็นต้องบรรจุข้อมูลอีกครั้งลงในข้อมูล RGB ในแง่ง่าย ๆ การดำเนินการเพิ่มเติมสำหรับแต่ละพิกเซลเพื่อให้ได้สีสุดท้าย

Finalrgb = Alpha*(Srgb) + (1-Alpha)*Drgb (this is for normal blend equation)
    where Srgb is source-rgb (we need to apply for each of the component for final color)
       Drgb is the color that will be there in the destination buffer.

ฉันไม่ได้ทำงานกับ pyGame มาก่อน แต่ดูอย่างรวดเร็วเกี่ยวกับโค้ด souce ทำให้ฉันคิดว่ามันใช้ฟังก์ชั่น 'sdl' Blit ใต้ฝากระโปรง โดยปกติ Sdl blit จะเร็วขึ้นและได้รับการปรับให้เหมาะสมดังนั้นเพียงทำตามจุดและโปรไฟล์ด้านบนอีกครั้ง! โชคดี!

* อัปเดต: * การตั้งค่าปุ่มสีเหมือนการเพิ่มการตรวจสอบพิเศษหนึ่งครั้งเมื่อตัดแต่ละพิกเซลลงบนพื้นผิวบางอย่างเช่นนี้ -

       for(eachPixelColor in allPixels)
         {
            if(eachPixelColor is NOT colorKeyColor)
            {
              copy color to the frame buffer!
            }

         }

ดังนั้นที่นี่ถ้าคุณเห็นเรามีข้อ จำกัด ที่จะไม่ใช้ memcpy เนื่องจากเราต้องตรวจสอบความถูกต้องของสีแต่ละพิกเซล!


ตกลงเพราะเปลี่ยนสายเรียกเข้าเพื่อset_colorkeyเลื่อนลงบนพื้นผิวแผนที่ทำให้เป็นช่องอัลฟา (แพง) convertคงที่และตอนนี้ผมทำงาน 150 FPS ที่มีเสถียรภาพในอึพีซีนี้ ขอบคุณ!
orlp

เฮ้จะแก้ไขที่เกี่ยวข้องกับปุ่มสีแม้ลืมที่จะเพิ่มข้อมูลบางอย่างเกี่ยวกับมัน: D
Ayyappa

5

sprite.convert() ไม่ได้ทำในสิ่งที่คุณคิด

sprite = sprite.convert() คือสิ่งที่คุณต้องการ


woops, ฉันจะมีsprite = sprite.convert()ในรหัสจริงแม้ว่า :)
orlp

อ๊ะดี :) ในกรณีนี้ฉันไม่มีอะไรให้คุณมากนักยกเว้นการพิจารณาใช้ pyglet แทน pygame หรือใช้ pyOpenGL โดยตรงหากคุณพอใจกับ OpenGL
Kylotan

@Kylotan: เพื่อนจับที่ดี! ฉันยังไม่ได้ตรวจสอบ :)
Ayyappa

หรือดียิ่งขึ้น:sprite = pygame.image.load("Maps/MapTesting.png").convert()
MestreLion
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.