[英]Why does this pygame code lag?
我正在嘗試編寫這個簡單的pygame pong游戲。 我尚未完成,但是我的代碼有很多滯后,我不知道為什么。 當球從球拍上彈起時,就會出現延遲,這似乎是意外的速度爆發。 看到這種情況的最好方法是運行代碼:
import pygame, sys
import time
from pygame.locals import *
pygame.init()
fpsClock=pygame.time.Clock()
screen= pygame.display.set_mode((640,480))
pygame.display.set_caption('Test')
fontobj= pygame.font.Font('LCD_Solid.ttf',50)
mousex,mousey=0,0
x_1=15
x_2=600 #these varaibles (x_1, x_2) are different, but they are constants-- they will never change; think jon, the paddle will not move from left to right
y=0 #the y variable changes, but for this test it will be the same for both paddles bc they are moving in unisen.
x_ball=320
y_ball=240
direction=""
def draw_stuff (y):
msg=str(x_ball)
global x_ball,y_ball,direction
textobj=fontobj.render(msg, False , pygame.Color('green'))
screen.blit(textobj,(160,5))
screen.blit(textobj,(480,5))
pygame.draw.line(screen,pygame.Color('grey'),(320,0), (320,480), 4)
pygame.draw.line(screen,pygame.Color('grey'),(0,3), (640,3), 10)
pygame.draw.line(screen,pygame.Color('grey'),(0,475), (640,475), 10)
pygame.draw.rect(screen, pygame.Color('grey'),(x_1,y,30,192))
pygame.draw.rect(screen, pygame.Color('grey'),(x_2,y,30,192))
if x_ball==60 or x_ball==570:
print "we have reached the side",fpsClock.get_fps()
if ball_hit(y,x_ball,y_ball):
topl,middlel,bottoml=loc_of_ball_hitl(y,x_ball,y_ball)
topr,middler,bottomr=loc_of_ball_hitr(y,x_ball,y_ball)
if topl:
direction="upleft"
elif middlel:
direction='midleft'
elif bottoml:
direction='downleft'
elif topr:
direction="upright"
elif middler:
direction="midright"
elif bottomr:
direction="downright"
else:
direction=""
if not direction:
print "we have ",fpsClock.get_fps()
x_ball+=2
elif direction=="upleft":
x_ball+=2
y_ball-=2
elif direction=="midleft":
x_ball+=2
elif direction=="downleft":
x_ball+=2
y_ball+=2
elif direction=="upright":
x_ball-=2
y_ball-=2
elif direction=="midright":
x_ball-=2
elif direction=="downright":
x_ball-=2
y_ball+=2
ball(x_ball,y_ball)
def ball(x,y):
pygame.draw.circle(screen, pygame.Color('red'), (x,y), 15, 0)
pygame.display.update()
def ball_hit(y,ball_x,ball_y):
if ball_x==60 and ball_y>=y and ball_y<y+192 or ball_x==570 and ball_y>=y and ball_y<y+192:
return True
return False
def loc_of_ball_hitl(y,ball_x,ball_y):
middle=False
top=False
bottom=False
if ball_x==60 and ball_y>=y+64 and ball_y<y+128:
middle=True
elif ball_x==60 and ball_y>=y and ball_y<y+64:
top=True
elif ball_x==60 and ball_y>=y+128 and ball_y<y+192:
bottom=True
return top, middle, bottom
def loc_of_ball_hitr(y,ball_x,ball_y):
middle=False
top=False
bottom=False
if ball_x==570 and ball_y>=y+64 and ball_y<y+128:
middle=True
elif ball_x==570 and ball_y>=y and ball_y<y+64:
top=True
elif ball_x==570 and ball_y>=y+128 and ball_y<y+192:
bottom=True
return top, middle, bottom
while True:
screen.fill(pygame.Color('black'))
if mousey>y:
draw_stuff(y)
y+=2
if mousey<y:
draw_stuff(y)
y-=2
if mousey==y:
draw_stuff(y)
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type== MOUSEMOTION:
mousex,mousey=event.pos
pygame.display.update()
fpsClock.tick(200)
四個主要錯誤:
您的球以2個像素的速度垂直和水平移動( x+=2
分別為y+=2
)。 但是,如果您的球垂直移動(讓x+=2
和y+=2
),那么球的實際速度不是2,而是sqrt(2**2 + 2**2)
= 2.828 。
因此,要進行對角線運動之類的操作,您可以移動以創建運動矢量,對其進行歸一化,然后對其施加速度(通過乘法)。
通過Font
渲染文本是非常昂貴的操作。 您應該緩存新創建的曲面,這樣就不必一次又一次地渲染相同的文本。 如果您使用大量文本,這將大大提高性能。
每個循環可以多次調用draw_stuff
。
200 FPS是很高的方法。 嘗試更低的速度,例如60 FPS
修正了這些問題的完整代碼(我的更改在###
注釋下方):
import pygame, sys
import time
from pygame.locals import *
import math
### some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637
def magnitude(v):
return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))
def add(u, v):
return [ u[i]+v[i] for i in range(len(u)) ]
def sub(u, v):
return [ u[i]-v[i] for i in range(len(u)) ]
def dot(u, v):
return sum(u[i]*v[i] for i in range(len(u)))
def normalize(v):
vmag = magnitude(v)
return [ v[i]/vmag for i in range(len(v)) ]
pygame.init()
fpsClock=pygame.time.Clock()
screen= pygame.display.set_mode((640,480))
pygame.display.set_caption('Test')
fontobj= pygame.font.SysFont('Arial',50)
mousex,mousey=0,0
x_1=15
x_2=600 #these varaibles (x_1, x_2) are different, but they are constants-- they will never change; think jon, the paddle will not move from left to right
y=0 #the y variable changes, but for this test it will be the same for both paddles bc they are moving in unisen.
x_ball=320
y_ball=240
direction=""
### the speed of the ball and the paddles
speed = 5
### a cache for font objects
cache={}
def get_msg(msg):
if not msg in cache:
cache[msg] = fontobj.render(msg, False , pygame.Color('green'))
return cache[msg]
def draw_stuff (y):
msg=str(x_ball)
global x_ball,y_ball,direction
### get the font surface from the cache
textobj=get_msg(msg)
screen.blit(textobj,(160,5))
screen.blit(textobj,(480,5))
pygame.draw.line(screen,pygame.Color('grey'),(320,0), (320,480), 4)
pygame.draw.line(screen,pygame.Color('grey'),(0,3), (640,3), 10)
pygame.draw.line(screen,pygame.Color('grey'),(0,475), (640,475), 10)
pygame.draw.rect(screen, pygame.Color('grey'),(x_1,y,30,192))
pygame.draw.rect(screen, pygame.Color('grey'),(x_2,y,30,192))
if x_ball==60 or x_ball==570:
print "we have reached the side",fpsClock.get_fps()
if ball_hit(y,x_ball,y_ball):
topl,middlel,bottoml=loc_of_ball_hitl(y,x_ball,y_ball)
topr,middler,bottomr=loc_of_ball_hitr(y,x_ball,y_ball)
if topl:
direction="upleft"
elif middlel:
direction='midleft'
elif bottoml:
direction='downleft'
elif topr:
direction="upright"
elif middler:
direction="midright"
elif bottomr:
direction="downright"
else:
direction=""
### create a vector
move = (0, 0)
if not direction:
print "we have ",fpsClock.get_fps()
move = (1, 0)
elif direction=="upleft":
move = (1, -1)
elif direction=="midleft":
move = (1, 0)
elif direction=="downleft":
move = (1, 1)
elif direction=="upright":
move = (-1, -1)
elif direction=="midright":
move = (-1, 0)
elif direction=="downright":
move = (-1, 1)
### normalize it and apply the speed
move = [int(c * speed) for c in normalize(move)]
### update ball position with movement vector
x_ball, y_ball = x_ball + move[0], y_ball + move[1]
ball(x_ball, y_ball)
def ball(x,y):
pygame.draw.circle(screen, pygame.Color('red'), (x,y), 15, 0)
pygame.display.update()
def ball_hit(y,ball_x,ball_y):
if ball_x==60 and ball_y>=y and ball_y<y+192 or ball_x==570 and ball_y>=y and ball_y<y+192:
return True
return False
def loc_of_ball_hitl(y,ball_x,ball_y):
middle=False
top=False
bottom=False
if ball_x==60 and ball_y>=y+64 and ball_y<y+128:
middle=True
elif ball_x==60 and ball_y>=y and ball_y<y+64:
top=True
elif ball_x==60 and ball_y>=y+128 and ball_y<y+192:
bottom=True
return top, middle, bottom
def loc_of_ball_hitr(y,ball_x,ball_y):
middle=False
top=False
bottom=False
if ball_x==570 and ball_y>=y+64 and ball_y<y+128:
middle=True
elif ball_x==570 and ball_y>=y and ball_y<y+64:
top=True
elif ball_x==570 and ball_y>=y+128 and ball_y<y+192:
bottom=True
return top, middle, bottom
while True:
screen.fill(pygame.Color('black'))
if mousey>y:
y+=speed
if mousey<y:
y-=speed
### call draw_stuff only once
draw_stuff(y)
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type== MOUSEMOTION:
mousex,mousey=event.pos
pygame.display.update()
### realistic framerate
fpsClock.tick(60)
請注意,還可以進行其他一些改進,但這可以解決您的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.