救命!
我的pygame程序为什么会卡顿呢?
具体是这样的:
我是想做一个小游戏(主要是没事做),就用pygame做了一个小游戏(废话文学)
因为现在是测试阶段,所以暂时影响不大
但是我下一步要做关卡了
而我的pygame会在运行了一段时间后变得卡顿
注:是在运行了一段时间后才出现的卡顿
我有查过内存占用和CPU占用,都在非常健康的水平(甚至比开网页都低)
我也在Windows以及Mac OS上都试过,结果一样!
这对我继续下下去影响很大!
我是自学的pygame,部分代码不太规范,请见谅(包括命名方式,毕竟是闲的没事写的)
哪位贵人来教教我吧(悲)
以下是具体代码:
主文件:
import pygame
import sys
import math
from settings import *
from Lead import *
from Monster import *
from Bullet import *
from pygame.sprite import *
from Pic_show import *
clock = pygame.time.Clock()
class Game:
#此函数负责屏幕刷新、关闭,角色关闭
def _update_screen(self):
if self.Run_key == True:
#经验值刷新(掉落物)
for experience in self.experiences.sprites():
experience.blitme(self)
#小怪刷新
for monster in self.monsters.sprites():
if monster.preliminary == False:
monster.blitme(self)
#小怪刷新
for monster in self.monsters.sprites():
if monster.preliminary == True:
monster.blitme(self)
#主角刷新
self.lead.blitme(self)
self.progressbar_experience.progress_set((self.experience,self.LV **2 + 6*(self.LV+1)))
self.progressbar_experience.blitme(self)
#数字的刷新
for blood_number in self.blood_numbers.sprites():
blood_number.blitme(self)
for score_number in self.score_numbers.sprites():
score_number.blitme(self)
for LV_number in self.LV_numbers.sprites():#等级显示数字
LV_number.blitme(self)
#子弹刷新
for bullet in self.bullets.sprites():
bullet.blitme()
#刷新血量显示的爱心
self.heart.blitme(self)
#刷新受伤时的红色背景
self.hurt_back.blitme(self)
#经验值等级计算
if self.experience >= self.LV **2 + 6*(self.LV+1):
self.experience -= self.LV **2 + 6*(self.LV+1)
self.LV += 1
#print(self.experience_cartoon)
self.experience_all = self.experience_com(self.experience,self.LV)
#屏幕刷新
self.hurtb_show()
self.keys = pygame.key.get_pressed()
self.fps = clock.get_fps()
self.dt = 60/(clock.get_fps()+1)
print(clock.get_fps())
#刷新“LV”这个图片,非运算等级
self.LV_pic.blitme(self)
pygame.display.update()
elif self.Run_key == False:
#死亡时的刷新机制(仅显示‘GameOver’)
#背景渲染
self.screen.fill(self.settings.bg_color)
#生成GameOver图片
GameOver = Pic(self,'Game Over',340,320,130,16,4)
GameOver.blitme(self)
#刷新
pygame.display.update()
elif self.Run_key == 'Set':
#即开始界面
if self.start.clicked == True and self.mouse_d == False:
self.Run_key = True
#print(self.start.clicked)
self.start.update(self.mouse_d,pygame.mouse.get_pos())
self.start.blitme(self)
pygame.display.flip()
#各种初始化设置
def __init__(self):
#pygame初始化
pygame.init()
#精灵组初始化
self.bullets = pygame.sprite.Group()#子弹精灵组
self.blood_numbers = pygame.sprite.Group()#显示血量的精灵组
self.monsters = pygame.sprite.Group()#怪物精灵组
self.score_numbers = pygame.sprite.Group()#显示分数的精灵组
self.experiences = pygame.sprite.Group()
self.LV_numbers = pygame.sprite.Group()
#从Settings文件里获取初始化设置,将self.settings设置为Settings
self.settings = Settings()
pygame.display.set_caption("Shawn_yxh-Game")#屏幕名字设置
self.screen = pygame.display.set_mode((self.settings.screen_width,self.settings.screen_height))#屏幕尺寸设置
self.bg_color = self.settings.bg_color#屏幕背景颜色设置
#列表、变量初始化
self.mouse_pressed = []#键盘事件列表
self.last_time = 0#发射子弹时的上次发射时间
self.monster_t = 0#时间重置
self.lead_xspeed = 0#主角移动速度
self.lead_yspeed = 0#主角移动速度
self.score = 0#分数
self.hurtb_run = False
self.nihao = 'nihao'
self.mouse_d = False#mouse_d --- mouse_down
self.experience = 0#计算经验值
self.experience_all = 0#总经验值计算
self.experience_s = 0#用来给进度条计算的经验值
self.LV = 0#计算等级
self.keys = pygame.key.get_pressed()
self.fps = clock.get_fps()
self.dt = 60/(self.fps+1)
self.lead = Lead(self)#主角生成
#self.monster_add()#游戏开始时怪物生成
self.Run_key = 'Set'#游戏主程序是否运行
#各种图片的生成(加载)
self.pic_handle()
def pic_handle(self):
#血量显示的心
self.heart = Pic(self,'heart',10,50,16,16,2)
self.heart.blitme(self)
#“LV”这个图片
self.LV_pic = Pic(self,'LV',20,157,36,16,0.9)
self.LV_pic.blitme(self)
#受伤时的红屏
self.hurt_back = Pic(self,'hurt_back',0,0,1200,800,2)
self.hurt_back.image.set_alpha(0)
self.hurt_back.blitme(self)
#Start这个按钮
self.start = Button(self,'Button-Start',473,464,85,24,2)
self.start.blitme(self)
self.start.image_pressed('Button-Start_pressed',85,24,2)
#经验值的进度条
self.progressbar_experience = progressbar(self,('progressbar_frame',13,90),'progressbar_block',10,152,2)
self.progressbar_experience.blitme(self)
#子弹发射函数
def shoot(self,mouse_x,mouse_y,lead_x,lead_y,time):
self.t = pygame.time.get_ticks()#获取现在的时间
if self.t - self.last_time >= time:
self.last_time = self.t
new_bullet = Bullet(self,mouse_x,mouse_y,lead_x,lead_y)
self.bullets.add(new_bullet)
def monster_add(self):
new_monster = Monster(self)
self.monsters.add(new_monster)
def keyboard_event(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if self.Run_key:
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
mouse_x,mouse_y = pygame.mouse.get_pos()
self.shoot(mouse_x,mouse_y,self.lead.rect.centerx,self.lead.rect.centery,100)
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 3:
self.mouse_pressed.remove(3)
self.mouse_d = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 3:
self.mouse_pressed.append(3)
self.mouse_d = True
if event.type == pygame.KEYDOWN:
if self.keys[pygame.K_0]:
self.Run_key = True
self.lead.blood = 20
self.mouse_pressed.clear()
def lead_move(self):
key_w = 119
key_s = 115
key_a = 97
key_d = 100
key_space = 32
right_mouse = 3
#速度增加
if self.keys[key_w]:
if abs(self.lead.yspeed) <= abs(self.lead.m_speed):
self.lead.yspeed -= self.lead.y_alt*self.dt
if self.keys[key_s]:
if abs(self.lead.yspeed) <= abs(self.lead.m_speed):
self.lead.yspeed += self.lead.y_alt*self.dt
if self.keys[key_a]:
if abs(self.lead.xspeed) <= abs(self.lead.m_speed):
self.lead.xspeed -= self.lead.x_alt*self.dt
if self.keys[key_d]:
if abs(self.lead.xspeed) <= abs(self.lead.m_speed):
self.lead.xspeed += self.lead.x_alt*self.dt
if right_mouse in self.mouse_pressed:
mouse_x,mouse_y = pygame.mouse.get_pos()
self.shoot(mouse_x,mouse_y,self.lead.rect.centerx,self.lead.rect.centery,10)
if self.keys[key_space]:
self.lead.m_speed,self.lead.x_alt,self.lead.y_alt = 14,1.5,1.5#这里的最大速度计算其实约等于减速度乘以20
else:
self.lead.m_speed,self.lead.x_alt,self.lead.y_alt = 7,0.8,0.9#这里的最大速度计算其实约等于减速度乘以10
if abs(self.lead.xspeed) >= 0.5:
self.lead.xspeed *= 0.92
else:
self.lead.xspeed = 0
if abs(self.lead.yspeed) >= 0.5:
self.lead.yspeed *= 0.92
else:
self.lead.yspeed = 0
#print(self.lead.xspeed,self.lead.yspeed)
if self.lead.rect.centerx + self.lead.xspeed >= 15 and self.lead.rect.centerx + self.lead.xspeed <= 1185:
self.lead.rect.centerx += self.lead.xspeed
if self.lead.rect.centery + self.lead.yspeed >= 15 and self.lead.rect.centery + self.lead.yspeed <= 785:
self.lead.rect.centery += self.lead.yspeed
def number_handle(self,number,x,interval):
number = str(number)
number_xposition = []
number_v = []#数字的值
for i,num in enumerate(number):
number_xposition.append(x+i*interval)
number_v.append(num)
return number_v,number_xposition
def blood_show(self):
if self.lead.blood > 0:
blood_v,blood_xposition = self.number_handle(self.lead.blood,70,30)
for number in self.blood_numbers:
#self.blood_numbers.remove(number)
number.kill()
for i,xposition in enumerate(blood_xposition):
new_number = Number(self,blood_v[i],xposition,50,2)
self.blood_numbers.add(new_number)
def score_show(self):
if self.lead.blood > 0:
score_v,score_xposition = self.number_handle(self.score,536,30)
for score_number in self.score_numbers:
#elf.score_numbers.remove(score_number)
score_number.kill()
for i,xposition in enumerate(score_xposition):
new_number = Number(self,score_v[i],xposition,40,2)
self.score_numbers.add(new_number)
def expercience_show(self):
if self.lead.blood > 0:
experience_v,experience_xposition = self.number_handle(self.LV,55,14)
for LV_number in self.LV_numbers:
#self.LV_numbers.remove(exerience_number)
LV_number.kill()
for i,xposition in enumerate(experience_xposition):
new_number = Number(self,experience_v[i],xposition,157,0.9)
self.LV_numbers.add(new_number)
def hurtb_show(self):
for i in range(1,40,4):
if i < 20:
if self.hurtb_run == 'T' + str(i):
self.hurt_back.image.set_alpha(i + 4)
#self.hurt_back.blitme(self)
self.hurtb_run = 'T' + str(i + 4)
break
elif i <= 40:
if self.hurtb_run == 'T' + str(i):
self.hurt_back.image.set_alpha(40-i)
#self.hurt_back.blitme(self)
self.hurtb_run = 'T' + str(i + 4)
break
if self.hurtb_run == 'T41':
self.hurt_back.image.set_alpha(0)
#self.hurt_back.blitme(self)
self.hurtb_run = False
if self.hurtb_run == True:
self.hurt_back.image.set_alpha(1)
#self.hurt_back.blitme(self)
self.hurtb_run = 'T' + str(1)
def experience_com(self,experience,LV):
exp = 0
for i in range(LV + 1):
exp += i ** 2 + 6*(i + 1)
exp += experience
return exp
def run_game(self):
monster_t = pygame.time.get_ticks()
while True:
if self.Run_key == True:
if pygame.time.get_ticks() - monster_t > 750:
self.monster_add()
monster_t = pygame.time.get_ticks()
clock.tick(60)
if pygame.time.get_ticks()%10000 <= 100:
for monster in self.monsters:
self.monsters.remove(monster)
#print(self.Run_key)
#print(self.hurtb_run)
self.bullets.update(self)
self.monsters.update(self)
self.lead_move()
self.experiences.update(self)
#血量显示
self.blood_show()
self.score_show()
self.expercience_show()
if self.Run_key == 'Set':
self.start.blitme(self)
self.keyboard_event()
self.screen.fill(self.settings.bg_color)
self._update_screen()
if __name__ == '__main__':
game = Game()
game.run_game()
lead文件:
import pygame
import sys
from Pic_show import *
#高为49
#宽为49
class Lead:
def __init__(self,game):
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
#主角加载
self.image = pygame.image.load('pic/lead.png')
self.image = pygame.transform.scale(self.image, (32, 32))
self.rect = self.image.get_rect()
self.rect.midbottom = self.screen_rect.midbottom
self.hurt_event = []
self.blood = 20
self.xspeed = 0
self.yspeed = 0
self.x_alt = 1#x_acceleration(x加速度)
self.y_alt = 1
self.m_speed = 10#most_speed最大速度
#self.rect.center = (6,6)
def blitme(self,game):
self.screen.blit(self.image,self.rect)
#print(self.blood)
if self.blood < 1:
self.blood = 0
game.Run_key = False
#清除血量显示并显示0
for number in game.blood_numbers.sprites():
number.kill()
number = Number(self,0,70,50,2)
game.blood_numbers.add(number)
for number in game.blood_numbers.sprites():
number.blitme(game)
for hurt_event in self.hurt_event:
if hurt_event == 'c_hurt':
self.blood -= 1
self.hurt_event.remove('c_hurt')
if game.hurtb_run == False:
game.hurtb_run = True
#print(self.hurt_event)
monster文件:
import pygame
import random
from pygame.sprite import Sprite
import math
from Pic_show import *
clock = pygame.time.Clock()
class Monster(pygame.sprite.Sprite):
def __init__(self,game):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
#小怪加载
self.image = pygame.image.load('pic/monster.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (32, 32))
self.image_p = pygame.image.load('pic/monster_preliminary.png').convert_alpha()
self.image_p = pygame.transform.scale(self.image_p,(32,32))
self.rect = self.image_p.get_rect()
#self.rect.midbottom = self.screen_rect.midbottom
nihao = True
while nihao:
x = random.randint(0,1200)
y = random.randint(0,800)
dx = game.lead.rect.centerx - x
dy = game.lead.rect.centery - y
if math.sqrt(dx*dx+dy*dy) > 100:
self.rect.centerx = x
self.rect.centery = y
nihao = False
#self.rect.centerx = random.randint(0,1200)
#self.rect.centery = random.randint(0,800)
self.blood = 5
self.preliminary = False
self.lh_time = 0#lh_time (lasthurt_time)(上次攻击的时间)
self.born_time = pygame.time.get_ticks()
self.image_p.set_alpha(0)
def blitme(self,game):
if pygame.time.get_ticks() - self.born_time <= 3000:
if self.image_p.get_alpha() < 255:
self.image_p.set_alpha(self.image_p.get_alpha()+ 1.5)
else:
self.image_p.set_alpha(0)
pass
self.screen.blit(self.image_p,self.rect)
else:
self.image.set_alpha(255)
self.screen.blit(self.image,self.rect)
self.preliminary = True
def update(self,game):
if self.preliminary:
dx = game.lead.rect.centerx - self.rect.centerx
dy = game.lead.rect.centery - self.rect.centery
angle = math.atan2(dy, dx)
speed = 3
if math.sqrt(dx*dx+dy*dy) > 0:
self.rect.centerx += speed * math.cos(angle)
self.rect.centery += speed * math.sin(angle)
for bullet in game.bullets:
if self.rect.colliderect(bullet.rect):
##pygame.sprite.groupcollide(game.bullets,game.monsters,True,not self.blood-1)#删除触碰的bullet
game.bullets.remove(bullet)
self.blood -= 1
if self.blood < 1:
diamond = diamond_handle(game,self.rect.centerx,self.rect.centery)
game.experiences.add(diamond)
game.score += 10
#game.monsters.remove(self)
self.kill()
if self.rect.colliderect(game.lead.rect):
if pygame.time.get_ticks() - self.lh_time >= 1000:
game.lead.hurt_event.append('c_hurt')#往lead_hurt里添加‘c_hurt'(common_hurt)(普通攻击)
self.lh_time = pygame.time.get_ticks()
#print(self.time)
bullet文件:
import pygame
import math
from pygame.sprite import Sprite
class Bullet(pygame.sprite.Sprite):
def __init__(self,game,mouse_x,mouse_y,lead_x,lead_y):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
self.image = pygame.image.load('pic/bullet.png')
self.image = pygame.transform.scale(self.image,(4,4))
self.rect = self.image.get_rect()
self.rect.centerx = lead_x
self.rect.centery = lead_y
self.run_update = True
self.mouse_x = mouse_x
self.mouse_y = mouse_y
self.lead_x = lead_x
self.lead_y = lead_y
self.dx = self.mouse_x - self.lead_x
self.dy = self.mouse_y - self.lead_y
angle = math.atan2(self.dy, self.dx)
self.image = pygame.transform.rotozoom(self.image, -math.degrees(angle)+90, 1)
self.rect = self.image.get_rect(center=self.rect.center)
def blitme(self):
self.screen.blit(self.image,self.rect)
def update(self,game):
speed = 20
#dx = self.mouse_x - self.lead_x
#dy = self.mouse_y - self.lead_y
angle = math.atan2(self.dy, self.dx)
self.rect.centerx += speed * math.cos(angle)
self.rect.centery += speed * math.sin(angle)
if self.rect.centerx >= 1200 and self.rect.centerx <= 0:
#game.bullets.remove(self)
self.kill()
if self.rect.centery >= 800 and self.rect.centery <= 0:
#game.bullets.remove(self)
self.kill()
Pic_show文件:
import pygame
import math
from pygame.sprite import Sprite
import random
class Number(pygame.sprite.Sprite):
def __init__(self,game,number,x,y,size):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
self.image = pygame.image.load(f'pic/nums/{number}.png')
self.image = pygame.transform.scale(self.image, (16*size,16*size))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def blitme(self,game):
self.screen.blit(self.image,self.rect)
class Pic(pygame.sprite.Sprite):
def __init__(self,game,name,x,y,weight,height,size):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
self.image = pygame.image.load(f'pic/Pic/{name}.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (size*weight,size*height))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def blitme(self,game):
self.screen.blit(self.image,self.rect)
class Button(pygame.sprite.Sprite):
def __init__(self,game,name,x,y,weight,height,size):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
self.image = pygame.image.load(f'pic/button/{name}.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (size*weight,size*height))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.clicked = False
self.image_ph = False
def image_pressed(self,name_p,height,weight,size):
self.image_p = pygame.image.load(f'pic/button/{name_p}.png').convert_alpha()
self.image_p = pygame.transform.scale(self.image_p, (size*height,size*weight))
self.rect_p = self.image_p.get_rect()
self.rect_p.x = self.rect.x
self.rect_p.y = self.rect.y
self.image_ph = True
def blitme(self,game):
if self.clicked == False:
self.screen.blit(self.image,self.rect)
elif self.clicked == True and self.image_ph == True:
self.screen.blit(self.image_p,self.rect_p)
elif self.clicked == True and self.image_ph == False:
self.screen.blit(self.image,self.rect)
def update(self,key,mouse_pos):
x,y = mouse_pos
if self.rect.collidepoint(x,y):
if key == True:
self.clicked = True
if key == False:
self.clicked = False
class diamond_handle(pygame.sprite.Sprite):
def __init__(self,game,x,y):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
self.image = pygame.image.load('pic/Pic/experience.png').convert_alpha()
self.image = pygame.transform.scale(self.image, (16, 16))
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.born_time = pygame.time.get_ticks()
self.image.set_alpha(255)
def blitme(self,game):
self.screen.blit(self.image,self.rect)
def update(self,game):
dx = game.lead.rect.centerx - self.rect.centerx
dy = game.lead.rect.centery - self.rect.centery
angle = math.atan2(dy, dx)
speed = 10
if math.sqrt(dx*dx + dy*dy) <150:
self.rect.centerx += speed * math.cos(angle)
self.rect.centery += speed * math.sin(angle)
if self.rect.colliderect(game.lead.rect):
#game.diamonds.remove(self)
self.kill()
game.experience += 5
class progressbar(pygame.sprite.Sprite):
def __init__(self,game,frame_image,progress_image,x,y,size):
super().__init__()
self.screen = game.screen
self.screen_rect = game.screen.get_rect()
self.size = size
self.progress = 0
self.frame_image = pygame.image.load(f'pic/Pic/{frame_image[0]}.png').convert_alpha()
self.frame_image = pygame.transform.scale(self.frame_image, (size*frame_image[2],size*frame_image[1]))
self.frame_rect = self.frame_image.get_rect()
self.frame_rect.x = x
self.frame_rect.y = y
self.progress_image_o = pygame.image.load(f'pic/Pic/{progress_image}.png').convert_alpha()
self.progress_image = pygame.transform.scale(self.progress_image_o, (size*(frame_image[2]-2),size*(frame_image[1]-2)))
self.progress_rect = self.progress_image.get_rect()
self.progress_rect.x = x + 1*size
self.progress_rect.y = y + 1*size
def blitme(self,game):
self.screen.blit(self.frame_image,self.frame_rect)
self.screen.blit(self.progress_image,self.progress_rect)
def progress_set_alpha(self,progress):
#这个函数是alpha并不代表它优于原版,反而原版更好,这仅是留作备用
self.progress = (progress[0]/progress[1])*(self.frame_rect.width-self.size*2)
self.progress_image = pygame.transform.scale(self.progress_image_o, (round(self.progress),self.progress_rect.height))
def progress_set(self,progress):
if self.progress != progress[0]:
if abs(progress[0] - self.progress) >= progress[1]/10000:
self.progress += ((progress[0] - self.progress)*0.1)
else:
self.progress = progress[0]
nihao = (self.progress/progress[1])*(self.frame_rect.width-self.size*2)
self.progress_image = pygame.transform.scale(self.progress_image_o, (round(nihao),self.progress_rect.height))
settings文件:
import pygame
class Settings:
def __init__(self):
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (80,80,80)#(80,80,80)对应(红,绿,蓝)