2017-07-29 39 views
3

我想知道如何加快使用pygam編寫的Python代碼的平滑度。我猜我必須以某種方式提高效率?運行時,一些球在一個設定的區域內隨機移動,但每個球的新位置並不平滑,每次運動之間會有一個跳躍,因爲週期非常緩慢。我該如何解決?或者有沒有關於如何改進它的建議? 這是我到目前爲止的代碼:Python - 如何加快pygame的平滑度?

import pygame 
from pygame import * 
import random 
pygame.init() 
size = width, height = 800, 600 
screen = display.set_mode(size) 
pygame.display.set_caption("Year 12: Ideal Gas Simulation") 


BLACK = (0, 0, 0) 
RED = (255, 0, 0) 
BLUE = (0, 0, 255) 
WHITE=(255,255,255) 
GREEN = (0, 255, 0) 
BALLX = 0 
BALLY = 1 
BALLSPEEDX = 2 
BALLSPEEDY = 3 
List=[] 
radius=5 

running=True 
myClock=time.Clock() 


myClock.tick(60) 
def initBall(): 


     for n in range(40): 
      ballx = random.randint(0, 800) # randomly setting the x position 
      bally = random.randint(0, 600) # randomly setting the y position 
      dirx = random.randint(-5,5) # randomly setting the x speed 
      diry = random.randint(-5,5) # randomly setting the y speed 

      data=[ballx, bally, dirx, diry] 
      List.append(data) 
      # returning a list with all the data the ball needs 
     return List # returning the list 


def drawScreen(List): 
    draw.rect(screen, WHITE, (0, 0, 800, 600)) 
    for x in range(40): 
     BALLX=List[x][0] 
     BALLY=List[x][1] 
     draw.circle(screen, GREEN, (BALLX,BALLY),radius) 
     display.flip() 
     pygame.draw.rect(screen, BLACK, (100-radius,100-radius,600+(2*radius),400+(2*radius)), 1) 

     f=pygame.font.SysFont(None,60) 
     text=f.render("PV=nRT",True,(0,0,0)) 
     screen.blit(text,(300,height/20)) 


def moveBall(List): 
    for x in range(40): 
     BALLX=List[x][0] 
     BALLY=List[x][1] 
     SPEEDX=List[x][2]#####data[BALLX]== the first index of each list [x][0] 
     SPEEDY=List[x][3]##data[BALLSPEEDX]= List[x][2] 
     age=SPEEDX+BALLX 
     List[x][0]=age 
     # increases the position of the ball 
     plus=SPEEDY+BALLY 
     List[x][1]=plus 
    # checks to see if the ball is hitting the walls in the x direction 
     if BALLX > 700: 
      List[x][0] = 700#NORMALLY 800 
      third=List[x][2] 
      answer=third*-1 
      List[x][2]=answer 
     elif BALLX < 100:#NORMALLY 0 
      List[x][0] = 100 
      third=List[x][2] 
      answer=third*-1 
      List[x][2]=answer 

    # checks to see if the ball is hitting the walls in the y direction 
     if BALLY < 100: 
      List[x][1] = 100#NORMALLY 0 
      third=List[x][3] 
      answer=third*-1 
      List[x][3]=answer 
     elif BALLY > 500: 
      List[x][1] = 500#NORMALLY 600 
      third=List[x][3] 
      answer=third*-1 
      List[x][3]=answer 
    return List#return updated list 


List=initBall() 
while running==True: 
    for evnt in event.get(): 
     if evnt.type==QUIT: 
      running=False 
      quit() 
     if evnt.type==MOUSEBUTTONDOWN: 
      mx,my=evnt.pos 
      button=evnt.button 

    drawScreen(List) 
    List=moveBall(List) 
+1

你會在範圍內更換'對於x更舒適(40)'的'在列表球:'然後調用'球[0 ]','ball [1]'... Everywhere – PRMoureu

+0

您可以在http://codereview.stackexchange.com/上發佈您的代碼以獲取更多提示。 – skrx

+0

請在https://codereview.stackexchange.com/上發佈您的代碼。在您的示例中以及接受的答案中,有很多可以改進的地方。 – skrx

回答

1

除了skrx的回答,您還可以重構代碼並避免大量重複調用。此外,直接編制BALLS陣列可能會略微提高性能。

通常,避免在函數內用大寫命名變量。這些名稱通常是給定在文件頂部的常量。

我想出了版本低於:

import array 
import pygame 
pygame.init() 
import random 

from pygame import * 

size = WIDTH, HEIGHT = 800, 600 
screen = display.set_mode(size) 
pygame.display.set_caption("Year 12: Ideal Gas Simulation") 


BLACK = (0, 0, 0) 
RED = (255, 0, 0) 
BLUE = (0, 0, 255) 
WHITE = (255,255,255) 
GREEN = (0, 255, 0) 
BALLX = 0 
BALLY = 1 
BALLSPEEDX = 2 
BALLSPEEDY = 3 
RADIUS = 5 

BALLS = [] 

myClock = time.Clock() 

myClock.tick(60) 
def initBalls(): 
    for n in range(40): 
     props = array.array('i', [ 
      random.randint(0, WIDTH), 
      random.randint(0, HEIGHT), 
      random.randint(-5, 5), 
      random.randint(-5, 5), 
     ]) 
     BALLS.append(props) 


def drawScreen(): 
    draw.rect(screen, WHITE, (0, 0, 800, 600)) 
    props = (100-RADIUS, 100-RADIUS, 600+(2*RADIUS), 400+(2*RADIUS)) 
    pygame.draw.rect(screen, BLACK, props, 1) 
    f = pygame.font.SysFont(None, 60) 
    text = f.render("PV=nRT", True,(0, 0, 0)) 
    screen.blit(text,(300, HEIGHT/20)) 
    for i in range(len(BALLS)): 
     draw.circle(screen, GREEN, BALLS[i][:2],RADIUS) 
    display.flip() 


def moveBalls(): 
    for i in range(len(BALLS)): 

     if BALLS[i][0] > 700: 
      BALLS[i][0] = 700 
      BALLS[i][2] *= -1 
     elif BALLS[i][0] < 100: 
      BALLS[i][0] = 100 
      BALLS[i][2] *= -1 
     else: 
      BALLS[i][0] += BALLS[i][2] 

     if BALLS[i][1] < 100: 
      BALLS[i][1] = 100 
      BALLS[i][3] *= -1 
     elif BALLS[i][1] > 500: 
      BALLS[i][1] = 500 
      BALLS[i][3] *= -1 
     else: 
      BALLS[i][1] += BALLS[i][3] 


def main(): 
    initBalls() 
    while True: 
     for evnt in event.get(): 
      if evnt.type == QUIT: 
       pygame.quit() 
       return 
      elif evnt.type == MOUSEBUTTONDOWN: 
       mx, my = evnt.pos 
       button = evnt.button 

     drawScreen() 
     moveBalls() 


if __name__ == "__main__": 
    main() 
1

呼叫pygame.display.flip()每幀只有一次。

def drawScreen(List): 
    draw.rect(screen, WHITE, (0, 0, 800, 600)) 
    for x in range(40): 
     BALLX=List[x][0] 
     BALLY=List[x][1] 
     draw.circle(screen, GREEN, (BALLX,BALLY),radius) 
     # display.flip() # Don't call `display.flip()` here. 
     pygame.draw.rect(screen, BLACK, (100-radius,100-radius,600+(2*radius),400+(2*radius)), 1) 

     screen.blit(text,(300,height/20)) 

    pygame.display.flip() # Call it here. 

我也推薦使用pygame.time.Clock來限制幀速率。

# Define the font object as a global constant. 
FONT = pygame.font.SysFont(None, 60) 
# If the text doesn't change you can also define it here. 
TEXT = FONT.render("PV=nRT", True, (0,0,0)) 
# Instantiate a clock to limit the frame rate. 
clock = pygame.time.Clock() 
running = True 

while running: # `== True` is not needed. 
    for evnt in event.get(): 
     if evnt.type == QUIT: 
      running = False 
      # Better use `pygame.quit` and `sys.exit` to quit. 
      pygame.quit() 
      sys.exit() 

    drawScreen(List) 
    List = moveBall(List) 

    clock.tick(30) # Limit frame rate to 30 fps. 
+1

謝謝!它現在非常流暢! –

+1

@ashash你也可以避免在循環的每次迭代中寫入文本和框架,你可以將drawScreen中的最後4行移動到循環的上方 – PRMoureu

+1

@PRMoureu好點。我會把這個添加到這個例子中。灰燼,你是打算在運行期間最終改變文本,還是應該保持不變? – skrx