Python 为什么这个pygame代码会滞后?

Python 为什么这个pygame代码会滞后?,python,pygame,lag,Python,Pygame,Lag,我想写一个简单的乒乓球游戏。我还没有完成,但我的代码有很多滞后,我不知道为什么。当球从桨上反弹时,会出现延迟,这似乎是无意中爆发了速度。 最好的方法是运行以下代码: 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_ca

我想写一个简单的乒乓球游戏。我还没有完成,但我的代码有很多滞后,我不知道为什么。当球从桨上反弹时,会出现延迟,这似乎是无意中爆发了速度。 最好的方法是运行以下代码:

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)
import pygame,sys
导入时间
从pygame.locals导入*
pygame.init()
fpscall=pygame.time.Clock()
screen=pygame.display.set_模式((640480))
pygame.display.set_标题('Test')
fontobj=pygame.font.font('LCD_Solid.ttf',50)
mousex,mousey=0,0
x_1=15
这些变量(x_1,x_2)是不同的,但它们是常数——它们永远不会改变;想想乔恩,划桨不会从左向右移动
y=0#y变量变化,但在本测试中,两个划桨bc的y变量相同,它们同时移动。
x_球=320
y_球=240
方向=“”
def draw_stuff(y):
msg=str(x_球)
全局x球,y球,方向
textobj=fontobj.render(msg,False,pygame.Color('green'))
屏幕blit(textobj,(160,5))
屏幕blit(textobj,(480,5))
pygame.draw.line(屏幕,pygame.Color('grey'),(320,0),(320480),4)
pygame.draw.line(屏幕,pygame.Color('Gray'),(0,3),(640,3),10)
pygame.draw.line(屏幕,pygame.Color('grey'),(0475),(640475),10)
pygame.draw.rect(屏幕,pygame.Color('grey'),(x_1,y,30192))
pygame.draw.rect(屏幕,pygame.Color('grey'),(x_2,y,30192))
如果x_-ball==60或x_-ball==570:
打印“我们已经到了一边”,fpscall.get_fps()
如果球击中(y,x球,y球):
上、中、下=球的位置(y、x球、y球)
上、中、下=击球手的位置(y、x、y球)
如果是topl:
方向=“英尺”
艾利夫·米德尔:
方向:'中间偏左'
elif Bottoll:
方向为左下'
艾利夫·托普:
方向=“直立”
埃利夫·米德勒:
方向=“中间偏右”
elif打底机:
方向=“完全正确”
其他:
方向=“”
如果不是方向:
打印“我们有”,fpscack.get_fps()
x_球+=2
elif方向==“upleft”:
x_球+=2
y_ball-=2
elif方向==“中间偏左”:
x_球+=2
elif方向==“左下”:
x_球+=2
y_球+=2
elif方向==“垂直”:
x_球-=2
y_ball-=2
elif方向==“中间右侧”:
x_球-=2
elif方向==“向下”:
x_球-=2
y_球+=2
球(x球,y球)
def球(x,y):
pygame.draw.circle(屏幕,pygame.Color('red'),(x,y),15,0)
pygame.display.update()
def ball_hit(y,ball_x,ball_y):
如果ball_x==60且ball_y>=y且ball_y=y且ball_y=y+64且ball_y=y且ball_y=y+128且ball_y=y+64且ball_y=y且ball_y=y+128且ball_yy:
画图(y)
y+=2

如果mousey有四个主要错误:

  • 您的球以2像素的速度垂直和水平移动(
    x+=2
    分别
    y+=2
    )。但是如果你的球垂直移动(让我们看
    x+=2
    y+=2
    ),球的实际速度不是2,而是
    sqrt(2**2+2**2)
    =2.828

    所以要做像对角线运动这样的事情,你需要移动来创建一个运动向量,对它进行规格化,然后对它应用一个速度(通过乘法)

  • 通过
    字体
    呈现文本是一项非常昂贵的操作。您应该缓存新创建的曲面,这样就不必一次又一次地渲染相同的文本。如果使用大量文本,这将大大提高性能

  • draw\u stuff
    可以在每个循环中调用多次

  • 200 FPS的速度真是太高了。试试低一点的,比如每秒60帧

修复了这些问题的完整代码(我的更改在
####
-注释下面):

import pygame,sys
导入时间
从pygame.locals导入*
输入数学
###一些简单的向量辅助函数,从http://stackoverflow.com/a/4114962/142637
def量级(v):
返回math.sqrt(范围(len(v))中i的和(v[i]*v[i]))
def添加(u,v):
返回[u[i]+v[i]表示范围内的i(len(u))]
def接头(u、v):
返回[u[i]-v[i]表示范围内的i(len(u))]
def点(u,v):
范围(len(u))内i的返回和(u[i]*v[i]
def正常化(v):
vmag=震级(v)
返回[v[i]/vmag(len(v))]
pygame.init()
fpscall=pygame.time.Clock()
screen=pygame.display.set_模式((640480))
pygame.display.set_标题('Test')
fontobj=pygame.font.SysFont('Arial',50)
mousex,mousey=0,0
x_1=15
这些变量(x_1,x_2)是不同的,但它们是常数——它们永远不会改变;想想乔恩,划桨不会从左向右移动
y=0#y变量变化,但在本测试中,两个划桨bc的y变量相同,它们同时移动。
x_球=320
y_球=240
方向=“”
###球和桨的速度
速度=5
###字体对象的缓存
缓存={}
def get_味精(味精):
如果缓存中没有消息:
cache[msg]=fontobj.render(msg,False,pygame.Color('green'))
返回缓存[msg]
def draw_stuff(y):
msg=str(x_球)
全局x球,y球,方向
###从缓存中获取字体表面
textobj=get_msg(msg)
屏幕blit(textobj,(160,5))
屏幕blit(textobj,(480,5))
pygame.draw.line(屏幕,pygame.Color('grey'),(320,0),(320480),4)
pygame.draw.line(屏幕,pygame.Color('Gray'),(0,3),(640,3),10)
pygame.draw.line(屏幕,pygame.Color('grey'),(0475),(640475),10)
pygame.draw.rect(屏幕,pygame.Color('grey'),(x_1,y,30192))
pygame.draw.rect(屏幕,pygame.Color('grey'),(x_2,y,30192))
如果x_ball==60或
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)