2017-07-29 18 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

あなたが範囲(40)中のxのために '置き換えることで、より快適になります'一覧でボールのための 'によっては、 ] '、' ball [1] '...どこでも – PRMoureu

+0

http://codereview.stackexchange.com/にコードを投稿してヒントを得ることができます。 – skrx

+0

https://codereview.stackexchange.com/にコードを投稿してください。あなたの例だけでなく、受け入れられた答えで改善することができる多くのことがあります。 – skrx

答えて

1

skrxの回答に加えて、コードをリファクタリングして、重複した通話を避けることもできます。また、配列BALLSを直接索引付けすると、パフォーマンスがわずかに向上する可能性があります。

一般に、大文字の関数内に変数の名前を付けないでください。これらの名前は通常、ファイルの先頭に定義された定数に与えられます。その後、 `と`ボール[0呼び出し:

私が思いついたのバージョンは以下の通りです:

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

関連する問題