Optimization 此PyGame代码能否以60fps的速度运行>;40只小动物?

Optimization 此PyGame代码能否以60fps的速度运行>;40只小动物?,optimization,pygame,Optimization,Pygame,,一些海报要求查看代码,并建议我提出一个新问题。根据要求,以下是我正在使用的大部分代码。我删除了Vector类,只是因为它有很多代码。我从其他人那里得到的数学知识是很容易理解的(),而cProfile对那里的任何函数都没有太多的介绍。我在代码中提供了一个链接,如果你想让它可以运行的话 如果将向量类粘贴到代码中指定的位置,则应运行此代码 问题是,一旦我得到20个以上的生物,帧速率从60帧快速下降到11帧,大约50个生物 请原谅意大利面代码。其中大部分是诊断混乱或预编码,我打算将其删除或转化为行为(

,一些海报要求查看代码,并建议我提出一个新问题。根据要求,以下是我正在使用的大部分代码。我删除了Vector类,只是因为它有很多代码。我从其他人那里得到的数学知识是很容易理解的(),而cProfile对那里的任何函数都没有太多的介绍。我在代码中提供了一个链接,如果你想让它可以运行的话

如果将向量类粘贴到代码中指定的位置,则应运行此代码

问题是,一旦我得到20个以上的生物,帧速率从60帧快速下降到11帧,大约50个生物

请原谅意大利面代码。其中大部分是诊断混乱或预编码,我打算将其删除或转化为行为(而不是硬编码的值)

这个应用程序基本上由4个对象组成

向量对象提供抽象的向量操作

热块能够跟踪自身的“热”水平,增加和减少它。它也可以自己画

import pygame
from pygame import gfxdraw
import pygame.locals
import os
import math
import random
import time

(I got a nice vector class from someone else. It's large, and mostly likely not the problem.)
(INSERT CONTENTS OF VECTOR.PY FROM https://gist.github.com/mcleonard/5351452 HERE)


pygame.init()

#some global constants
BLUE = (0, 0, 255)
WHITE = (255,255,255)
diagnostic = False
SPAWN_TIME = 1 #number of seconds between creating new critters
FLOCK_LIMIT = 30 #number of critters at which the flock begins being culled
GUIDs = [0] #list of guaranteed unique IDs for identifying each critter

# Set the position of the OS window
position = (30, 30)
os.environ['SDL_VIDEO_WINDOW_POS'] = str(position[0]) + "," + str(position[1])

# Set the position, width and height of the screen [width, height]
size_x = 1000
size_y = 500
size = (size_x, size_y)
FRAMERATE = 60
SECS_FOR_DYING = 1
screen = pygame.display.set_mode(size)
screen.set_alpha(None)
pygame.display.set_caption("My Game")

# Used to manage how fast the screen updates
clock = pygame.time.Clock()


def random_float(lower, upper):
    num = random.randint(lower*1000, upper*1000)
    return num/1000


def new_GUID():
    num = GUIDs[-1]
    num = num + 1
    while num in GUIDs:
        num += 1
    GUIDs.append(num)
    return num


class HeatBlock:
    def __init__(self,_tlx,_tly,h,w):
        self.tlx = int(_tlx)
        self.tly = int(_tly)
        self.height = int(h)+1
        self.width = int(w)
        self.heat = 255.0
        self.registered = False

    def register_tresspasser(self):
        self.registered = True
        self.heat = max(self.heat - 1, 0)

    def cool_down(self):
        if not self.registered:
            self.heat = min(self.heat + 0.1, 255)
        self.registered = False

    def hb_draw_self(self):
        screen.fill((255,int(self.heat),int(self.heat)), [self.tlx, self.tly, self.width, self.height])


class HeatMap:
    def __init__(self, _h, _v):
        self.h_freq = _h #horizontal frequency
        self.h_rez = size_x/self.h_freq #horizontal resolution
        self.v_freq = _v #vertical frequency
        self.v_rez = size_y/self.v_freq #vertical resolution
        self.blocks = [] 

    def make_map(self):
        h_size = size_x/self.h_freq
        v_size = size_y/self.v_freq
        for h_count in range(0, self.h_freq):
            TLx = h_count * h_size #TopLeft corner, x
            col = []
            for v_count in range(0, self.v_freq):
                TLy = v_count * v_size #TopLeft corner, y
                col.append(HeatBlock(TLx,TLy,v_size,h_size))
            self.blocks.append(col)

    def hm_draw_self(self):
        for col in self.blocks:
            for block in col:
                block.cool_down()
                block.hb_draw_self()

    def register(self, x, y):
        #convert the given coordinates of the trespasser into a col/row block index
        col = max(int(math.floor(x / self.h_rez)),0)
        row = max(int(math.floor(y / self.v_rez)),0)
        self.blocks[col][row].register_tresspasser()


class Critter:
    def __init__(self):
        self.color = (random.randint(1, 200), random.randint(1, 200), random.randint(1, 200))
        self.linear_speed = random_float(20, 100)
        self.radius = int(round(10 * (100/self.linear_speed)))
        self.angular_speed = random_float(0.1, 2)
        self.x = int(random.randint(self.radius*2, size_x - (self.radius*2)))
        self.y = int(random.randint(self.radius*2, size_y - (self.radius*2)))
        self.orientation = Vector(0, 1).rotate(random.randint(-180, 180))
        self.sensor = Vector(0, 20)
        self.sensor_length = 20
        self.new_orientation = self.orientation
        self.draw_bounds = False
        self.GUID = new_GUID()
        self.condition = 0 #0 = alive, [1-fps] = dying, >fps = dead
        self.delete_me = False

    def c_draw_self(self):
        #if we're alive and not dying, draw our normal self
        if self.condition == 0:
            #diagnostic
            if self.draw_bounds:
                pygame.gfxdraw.rectangle(screen, [int(self.x), int(self.y), 1, 1], BLUE)
                temp = self.orientation * (self.linear_speed * 20)
                pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x + temp[0]), int(self.y + temp[1]), BLUE)
            #if there's a new orientation, match it gradually
            temp = self.new_orientation * self.linear_speed
            #draw my body
            pygame.gfxdraw.aacircle(screen, int(self.x), int(self.y), self.radius, self.color)
            #draw a line indicating my new direction
            pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x + temp[0]), int(self.y + temp[1]), BLUE)
            #draw my sensor (a line pointing forward)
            self.sensor = self.orientation.normalize() * self.sensor_length
            pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x + self.sensor[0]), int(self.y + self.sensor[1]), BLUE)
        #otherwise we're dying, draw our dying animation
        elif 1 <= self.condition <= FRAMERATE*SECS_FOR_DYING:
            #draw some lines in a spinningi circle
            for num in range(0,10):
                line = Vector(0, 1).rotate((num*(360/10))+(self.condition*23))
                line = line*self.radius
                pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x+line[0]), int(self.y+line[1]), self.color)

    def print_self(self):
        #diagnostic
        print("==============")
        print("radius:", self.radius)
        print("color:", self.color)
        print("linear_speed:", self.linear_speed)
        print("angular_speed:", self.angular_speed)
        print("x:", self.x)
        print("y:", int(self.y))
        print("orientation:", self.orientation)

    def avoid_others(self, _flock):
        for _critter in _flock:
            #if the critter isn't ME...
            if _critter.GUID is not self.GUID and _critter.condition == 0:
                #and it's touching me...
                if self.x - _critter.x <= self.radius + _critter.radius:
                    me = Vector(self.x, int(self.y))
                    other_guy = Vector(_critter.x, _critter.y)
                    distance = me - other_guy

                    #give me new orientation that's away from the other guy
                    if distance.norm() <= ((self.radius) + (_critter.radius)):
                        new_direction = me - other_guy
                        self.orientation = self.new_orientation = new_direction.normalize()

    def update_location(self, elapsed):
        boundary = '?'
        while boundary != 'X':
            boundary = self.out_of_bounds()
            if boundary == 'N':
                self.orientation = self.new_orientation = Vector(0, 1).rotate(random.randint(-20, 20))
                self.y = (self.radius) + 2
            elif boundary == 'S':
                self.orientation = self.new_orientation = Vector(0,-1).rotate(random.randint(-20, 20))
                self.y = (size_y - (self.radius)) - 2
            elif boundary == 'E':
                self.orientation = self.new_orientation = Vector(-1,0).rotate(random.randint(-20, 20))
                self.x = (size_x - (self.radius)) - 2
            elif boundary == 'W':
                self.orientation = self.new_orientation = Vector(1,0).rotate(random.randint(-20, 20))
                self.x = (self.radius) + 2
            point = Vector(self.x, self.y)
            self.x, self.y = (point + (self.orientation * (self.linear_speed*(elapsed/1000))))
            boundary = self.out_of_bounds()

    def update_orientation(self, elapsed):
        #randomly choose a new direction, from time to time
        if random.randint(0, 100) > 98:
            self.choose_new_orientation()
        difference = self.orientation.argument() - self.new_orientation.argument()
        self.orientation = self.orientation.rotate((difference * (self.angular_speed*(elapsed/1000))))

    def still_alive(self, elapsed):
        return_value = True #I am still alive
        if self.condition == 0:
            return_value = True
        elif self.condition <= FRAMERATE*SECS_FOR_DYING:
            self.condition = self.condition + (elapsed/17)
            return_value = True
        if self.condition > FRAMERATE*SECS_FOR_DYING:
            return_value = False

        return return_value

    def choose_new_orientation(self):
        if self.new_orientation:
            if (self.orientation.argument() - self.new_orientation.argument()) < 5:
                rotation = random.randint(-300, 300)
                self.new_orientation = self.orientation.rotate(rotation)

    def out_of_bounds(self):
        if self.x >= (size_x - (self.radius)):
            return 'E'
        elif self.y >= (size_y - (self.radius)):
            return 'S'
        elif self.x <= (0 + (self.radius)):
            return 'W'
        elif self.y <= (0 + (self.radius)):
            return 'N'
        else:
            return 'X'


# -------- Main Program Loop -----------
# generate critters
flock = [Critter()]
# generate heat map
heatMap = HeatMap(60, 40)
heatMap.make_map()
# set some settings
last_spawn = time.clock()
run_time = time.perf_counter()
frame_count = 0
max_time = 0
ms_elapsed = 1
avg_fps = [1]
# Loop until the user clicks the close button.
done = False
while not done:
    # --- Main event loop only processes one event
    frame_count = frame_count + 1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # --- Game logic should go here
    #check if it's time to make another critter
    if time.clock() - last_spawn > SPAWN_TIME:
        flock.append(Critter())
        last_spawn = time.clock()
    if len(flock) >= FLOCK_LIMIT:
        #if we're over the flock limit, cull the herd
        counter = FLOCK_LIMIT
        for critter in flock[0:len(flock)-FLOCK_LIMIT]:
            #this code allows a critter to be "dying" for a while, to play an animation
            if critter.condition == 0:
                critter.condition = 1
            elif not critter.still_alive(ms_elapsed):
                critter.delete_me = True
    counter = 0

    #delete all the critters that have finished dying
    while counter < len(flock):
        if flock[counter].delete_me:
            del flock[counter]
        else:
            counter = counter+1

    #----loop on all critters once, doing all functions for each critter
    for critter in flock:
        if critter.condition == 0:
            critter.avoid_others(flock)
            if critter.condition == 0:
                heatMap.register(critter.x, critter.y)
            critter.update_location(ms_elapsed)
            critter.update_orientation(ms_elapsed)
            if diagnostic:
                critter.print_self()

    #----alternately, loop for each function. Speed seems to be similar either way
    #for critter in flock:
    #    if critter.condition == 0:
    #        critter.update_location(ms_elapsed)
    #for critter in flock:
    #    if critter.condition == 0:
    #        critter.update_orientation(ms_elapsed)

    # --- Screen-clearing code goes here

    # Here, we clear the screen to white. Don't put other drawing commands
    screen.fill(WHITE)

    # --- Drawing code should go here
    #draw the heat_map
    heatMap.hm_draw_self()
    for critter in flock:
        critter.c_draw_self()

    #draw the framerate
    myfont = pygame.font.SysFont("monospace", 15)
    #average the framerate over 60 frames
    temp = sum(avg_fps)/float(len(avg_fps)) 
    text = str(round(((1/temp)*1000),0))+"FPS | "+str(len(flock))+" Critters"
    label = myfont.render(text, 1, (0, 0, 0))
    screen.blit(label, (5, 5))

    # --- Go ahead and update the screen with what we've drawn.
    pygame.display.update()

    # --- Limit to 60 frames per second
    #only run for 30 seconds
    if time.perf_counter()-run_time >= 30:
        done = True
    #limit to 60fps
    #add this frame's time to the list
    avg_fps.append(ms_elapsed)
    #remove any old frames
    while len(avg_fps) > 60:
        del avg_fps[0]
    ms_elapsed = clock.tick(FRAMERATE)
    #track longest frame
    if ms_elapsed > max_time:
        max_time = ms_elapsed

#print some stats once the program is finished
print("Count:", frame_count)
print("Max time since last flip:", str(max_time)+"ms")
print("Total Time:", str(int(time.perf_counter()-run_time))+"s")
print("Average time for a flip:", str(int(((time.perf_counter()-run_time)/frame_count)*1000))+"ms")
# Close the window and quit.
pygame.quit()
热图由在屏幕上平铺的热图块组成。给定坐标后,它可以选择这些坐标所在的块

一个生物有许多特性,使它能够在屏幕上游荡,撞出墙壁和其他生物,选择一个新的随机方向,然后死亡

主回路循环遍历“群”中的每一种生物,并更新其“状态”(无论它是否“死亡”)、位置、方向和当前所处的热块。循环也会在每个热块上迭代,以使其“冷却”

然后主循环要求热量图绘制自己,然后羊群中的每一个生物绘制自己

import pygame
from pygame import gfxdraw
import pygame.locals
import os
import math
import random
import time

(I got a nice vector class from someone else. It's large, and mostly likely not the problem.)
(INSERT CONTENTS OF VECTOR.PY FROM https://gist.github.com/mcleonard/5351452 HERE)


pygame.init()

#some global constants
BLUE = (0, 0, 255)
WHITE = (255,255,255)
diagnostic = False
SPAWN_TIME = 1 #number of seconds between creating new critters
FLOCK_LIMIT = 30 #number of critters at which the flock begins being culled
GUIDs = [0] #list of guaranteed unique IDs for identifying each critter

# Set the position of the OS window
position = (30, 30)
os.environ['SDL_VIDEO_WINDOW_POS'] = str(position[0]) + "," + str(position[1])

# Set the position, width and height of the screen [width, height]
size_x = 1000
size_y = 500
size = (size_x, size_y)
FRAMERATE = 60
SECS_FOR_DYING = 1
screen = pygame.display.set_mode(size)
screen.set_alpha(None)
pygame.display.set_caption("My Game")

# Used to manage how fast the screen updates
clock = pygame.time.Clock()


def random_float(lower, upper):
    num = random.randint(lower*1000, upper*1000)
    return num/1000


def new_GUID():
    num = GUIDs[-1]
    num = num + 1
    while num in GUIDs:
        num += 1
    GUIDs.append(num)
    return num


class HeatBlock:
    def __init__(self,_tlx,_tly,h,w):
        self.tlx = int(_tlx)
        self.tly = int(_tly)
        self.height = int(h)+1
        self.width = int(w)
        self.heat = 255.0
        self.registered = False

    def register_tresspasser(self):
        self.registered = True
        self.heat = max(self.heat - 1, 0)

    def cool_down(self):
        if not self.registered:
            self.heat = min(self.heat + 0.1, 255)
        self.registered = False

    def hb_draw_self(self):
        screen.fill((255,int(self.heat),int(self.heat)), [self.tlx, self.tly, self.width, self.height])


class HeatMap:
    def __init__(self, _h, _v):
        self.h_freq = _h #horizontal frequency
        self.h_rez = size_x/self.h_freq #horizontal resolution
        self.v_freq = _v #vertical frequency
        self.v_rez = size_y/self.v_freq #vertical resolution
        self.blocks = [] 

    def make_map(self):
        h_size = size_x/self.h_freq
        v_size = size_y/self.v_freq
        for h_count in range(0, self.h_freq):
            TLx = h_count * h_size #TopLeft corner, x
            col = []
            for v_count in range(0, self.v_freq):
                TLy = v_count * v_size #TopLeft corner, y
                col.append(HeatBlock(TLx,TLy,v_size,h_size))
            self.blocks.append(col)

    def hm_draw_self(self):
        for col in self.blocks:
            for block in col:
                block.cool_down()
                block.hb_draw_self()

    def register(self, x, y):
        #convert the given coordinates of the trespasser into a col/row block index
        col = max(int(math.floor(x / self.h_rez)),0)
        row = max(int(math.floor(y / self.v_rez)),0)
        self.blocks[col][row].register_tresspasser()


class Critter:
    def __init__(self):
        self.color = (random.randint(1, 200), random.randint(1, 200), random.randint(1, 200))
        self.linear_speed = random_float(20, 100)
        self.radius = int(round(10 * (100/self.linear_speed)))
        self.angular_speed = random_float(0.1, 2)
        self.x = int(random.randint(self.radius*2, size_x - (self.radius*2)))
        self.y = int(random.randint(self.radius*2, size_y - (self.radius*2)))
        self.orientation = Vector(0, 1).rotate(random.randint(-180, 180))
        self.sensor = Vector(0, 20)
        self.sensor_length = 20
        self.new_orientation = self.orientation
        self.draw_bounds = False
        self.GUID = new_GUID()
        self.condition = 0 #0 = alive, [1-fps] = dying, >fps = dead
        self.delete_me = False

    def c_draw_self(self):
        #if we're alive and not dying, draw our normal self
        if self.condition == 0:
            #diagnostic
            if self.draw_bounds:
                pygame.gfxdraw.rectangle(screen, [int(self.x), int(self.y), 1, 1], BLUE)
                temp = self.orientation * (self.linear_speed * 20)
                pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x + temp[0]), int(self.y + temp[1]), BLUE)
            #if there's a new orientation, match it gradually
            temp = self.new_orientation * self.linear_speed
            #draw my body
            pygame.gfxdraw.aacircle(screen, int(self.x), int(self.y), self.radius, self.color)
            #draw a line indicating my new direction
            pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x + temp[0]), int(self.y + temp[1]), BLUE)
            #draw my sensor (a line pointing forward)
            self.sensor = self.orientation.normalize() * self.sensor_length
            pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x + self.sensor[0]), int(self.y + self.sensor[1]), BLUE)
        #otherwise we're dying, draw our dying animation
        elif 1 <= self.condition <= FRAMERATE*SECS_FOR_DYING:
            #draw some lines in a spinningi circle
            for num in range(0,10):
                line = Vector(0, 1).rotate((num*(360/10))+(self.condition*23))
                line = line*self.radius
                pygame.gfxdraw.line(screen, int(self.x), int(self.y), int(self.x+line[0]), int(self.y+line[1]), self.color)

    def print_self(self):
        #diagnostic
        print("==============")
        print("radius:", self.radius)
        print("color:", self.color)
        print("linear_speed:", self.linear_speed)
        print("angular_speed:", self.angular_speed)
        print("x:", self.x)
        print("y:", int(self.y))
        print("orientation:", self.orientation)

    def avoid_others(self, _flock):
        for _critter in _flock:
            #if the critter isn't ME...
            if _critter.GUID is not self.GUID and _critter.condition == 0:
                #and it's touching me...
                if self.x - _critter.x <= self.radius + _critter.radius:
                    me = Vector(self.x, int(self.y))
                    other_guy = Vector(_critter.x, _critter.y)
                    distance = me - other_guy

                    #give me new orientation that's away from the other guy
                    if distance.norm() <= ((self.radius) + (_critter.radius)):
                        new_direction = me - other_guy
                        self.orientation = self.new_orientation = new_direction.normalize()

    def update_location(self, elapsed):
        boundary = '?'
        while boundary != 'X':
            boundary = self.out_of_bounds()
            if boundary == 'N':
                self.orientation = self.new_orientation = Vector(0, 1).rotate(random.randint(-20, 20))
                self.y = (self.radius) + 2
            elif boundary == 'S':
                self.orientation = self.new_orientation = Vector(0,-1).rotate(random.randint(-20, 20))
                self.y = (size_y - (self.radius)) - 2
            elif boundary == 'E':
                self.orientation = self.new_orientation = Vector(-1,0).rotate(random.randint(-20, 20))
                self.x = (size_x - (self.radius)) - 2
            elif boundary == 'W':
                self.orientation = self.new_orientation = Vector(1,0).rotate(random.randint(-20, 20))
                self.x = (self.radius) + 2
            point = Vector(self.x, self.y)
            self.x, self.y = (point + (self.orientation * (self.linear_speed*(elapsed/1000))))
            boundary = self.out_of_bounds()

    def update_orientation(self, elapsed):
        #randomly choose a new direction, from time to time
        if random.randint(0, 100) > 98:
            self.choose_new_orientation()
        difference = self.orientation.argument() - self.new_orientation.argument()
        self.orientation = self.orientation.rotate((difference * (self.angular_speed*(elapsed/1000))))

    def still_alive(self, elapsed):
        return_value = True #I am still alive
        if self.condition == 0:
            return_value = True
        elif self.condition <= FRAMERATE*SECS_FOR_DYING:
            self.condition = self.condition + (elapsed/17)
            return_value = True
        if self.condition > FRAMERATE*SECS_FOR_DYING:
            return_value = False

        return return_value

    def choose_new_orientation(self):
        if self.new_orientation:
            if (self.orientation.argument() - self.new_orientation.argument()) < 5:
                rotation = random.randint(-300, 300)
                self.new_orientation = self.orientation.rotate(rotation)

    def out_of_bounds(self):
        if self.x >= (size_x - (self.radius)):
            return 'E'
        elif self.y >= (size_y - (self.radius)):
            return 'S'
        elif self.x <= (0 + (self.radius)):
            return 'W'
        elif self.y <= (0 + (self.radius)):
            return 'N'
        else:
            return 'X'


# -------- Main Program Loop -----------
# generate critters
flock = [Critter()]
# generate heat map
heatMap = HeatMap(60, 40)
heatMap.make_map()
# set some settings
last_spawn = time.clock()
run_time = time.perf_counter()
frame_count = 0
max_time = 0
ms_elapsed = 1
avg_fps = [1]
# Loop until the user clicks the close button.
done = False
while not done:
    # --- Main event loop only processes one event
    frame_count = frame_count + 1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # --- Game logic should go here
    #check if it's time to make another critter
    if time.clock() - last_spawn > SPAWN_TIME:
        flock.append(Critter())
        last_spawn = time.clock()
    if len(flock) >= FLOCK_LIMIT:
        #if we're over the flock limit, cull the herd
        counter = FLOCK_LIMIT
        for critter in flock[0:len(flock)-FLOCK_LIMIT]:
            #this code allows a critter to be "dying" for a while, to play an animation
            if critter.condition == 0:
                critter.condition = 1
            elif not critter.still_alive(ms_elapsed):
                critter.delete_me = True
    counter = 0

    #delete all the critters that have finished dying
    while counter < len(flock):
        if flock[counter].delete_me:
            del flock[counter]
        else:
            counter = counter+1

    #----loop on all critters once, doing all functions for each critter
    for critter in flock:
        if critter.condition == 0:
            critter.avoid_others(flock)
            if critter.condition == 0:
                heatMap.register(critter.x, critter.y)
            critter.update_location(ms_elapsed)
            critter.update_orientation(ms_elapsed)
            if diagnostic:
                critter.print_self()

    #----alternately, loop for each function. Speed seems to be similar either way
    #for critter in flock:
    #    if critter.condition == 0:
    #        critter.update_location(ms_elapsed)
    #for critter in flock:
    #    if critter.condition == 0:
    #        critter.update_orientation(ms_elapsed)

    # --- Screen-clearing code goes here

    # Here, we clear the screen to white. Don't put other drawing commands
    screen.fill(WHITE)

    # --- Drawing code should go here
    #draw the heat_map
    heatMap.hm_draw_self()
    for critter in flock:
        critter.c_draw_self()

    #draw the framerate
    myfont = pygame.font.SysFont("monospace", 15)
    #average the framerate over 60 frames
    temp = sum(avg_fps)/float(len(avg_fps)) 
    text = str(round(((1/temp)*1000),0))+"FPS | "+str(len(flock))+" Critters"
    label = myfont.render(text, 1, (0, 0, 0))
    screen.blit(label, (5, 5))

    # --- Go ahead and update the screen with what we've drawn.
    pygame.display.update()

    # --- Limit to 60 frames per second
    #only run for 30 seconds
    if time.perf_counter()-run_time >= 30:
        done = True
    #limit to 60fps
    #add this frame's time to the list
    avg_fps.append(ms_elapsed)
    #remove any old frames
    while len(avg_fps) > 60:
        del avg_fps[0]
    ms_elapsed = clock.tick(FRAMERATE)
    #track longest frame
    if ms_elapsed > max_time:
        max_time = ms_elapsed

#print some stats once the program is finished
print("Count:", frame_count)
print("Max time since last flip:", str(max_time)+"ms")
print("Total Time:", str(int(time.perf_counter()-run_time))+"s")
print("Average time for a flip:", str(int(((time.perf_counter()-run_time)/frame_count)*1000))+"ms")
# Close the window and quit.
pygame.quit()
导入pygame
从pygame导入gfxdraw
输入pygame.locals
导入操作系统
输入数学
随机输入
导入时间
(我从其他人那里得到了一个很好的向量类。它很大,很可能不是问题所在。)
(从中插入VECTOR.PY的内容)https://gist.github.com/mcleonard/5351452 这里)
pygame.init()
#一些全局常数
蓝色=(0,0255)
白色=(255255)
诊断=错误
繁殖时间=1#创建新生物之间的秒数
FLOCK_LIMIT=30#开始扑杀羊群的生物数量
GUID=[0]#用于识别每个生物的保证唯一ID列表
#设置操作系统窗口的位置
位置=(30,30)
os.environ['SDL_VIDEO_WINDOW_POS']=str(位置[0])+,“+str(位置[1]))
#设置屏幕的位置、宽度和高度[宽度、高度]
尺寸x=1000
尺寸y=500
大小=(大小x,大小y)
帧率=60
死亡秒数=1
screen=pygame.display.set_模式(大小)
屏幕。设置_alpha(无)
pygame.display.set_标题(“我的游戏”)
#用于管理屏幕更新的速度
clock=pygame.time.clock()
def随机_浮动(下部、上部):
num=random.randint(下限*1000,上限*1000)
返回数/1000
def new_GUID():
num=GUIDs[-1]
num=num+1
而在guid中的num:
num+=1
追加(num)
返回数
等级隔热块:
定义初始值(self,tlx,tly,h,w):
self.tlx=int(_tlx)
self.tly=int(_tly)
自高度=整数(h)+1
self.width=int(w)
self.heat=255.0
self.registed=False
def寄存器\u tresspasser(自身):
self.registed=True
self.heat=max(self.heat-1,0)
def冷却(自):
如果不是自行注册的:
self.heat=min(self.heat+0.1255)
self.registed=False
def hb_draw_self(自):
屏幕填充((255,int(self.heat),int(self.heat)),[self.tlx,self.tly,self.width,self.height])
班级热图:
定义初始值(self,h,v):
self.h#freq=_h#水平频率
self.h_rez=大小x/self.h_频率水平分辨率
self.v_freq=_v#垂直频率
self.v_rez=尺寸y/self.v_频率垂直分辨率
self.blocks=[]
def make_映射(自):
h_尺寸=尺寸x/self.h_频率
v_size=尺寸y/self.v_频率
对于范围内的h_计数(0,self.h_freq):
TLx=h_计数*h_大小#左上角,x
col=[]
对于范围内的v_计数(0,self.v_freq):
TLy=v_计数*v_大小#左上角,y
列附加(热块(TLx、TLy、v_尺寸、h_尺寸))
self.blocks.append(col)
def hm_draw_self(自):
对于self.block中的列:
对于col中的块:
block.cool_down()
block.hb\u draw\u self()
def寄存器(自、x、y):
#将侵入者的给定坐标转换为列/行块索引
col=max(整数(数学层(x/self.h_rez)),0)
行=最大值(整数(数学楼层(y/self.v_rez)),0)
self.blocks[col][row]。寄存器\u tresspasser()
类生物:
定义初始化(自):
self.color=(random.randint(1200),random.randint(1200),random.randint(1200))
自线性速度=随机浮动(20100)
自半径=整数(圆形(10*(100/自线性速度)))
自转角速度=随机浮动(0.1,2)
self.x=int(random.randint(self.radius*2,size_x-(self.radius*2)))
self.y=int(random.randint(self.radius*2,size_y-(self.radius*2)))
self.orientation=Vector(0,1)。旋转(random.randint(-180,180))
self.sensor=矢量(0,20)
自我传感器长度=20
self.new_定向=self.orientation
self.draw_bounds=False
self.GUID=new_GUID()
self.condition=0#0=存活,[1-fps]=死亡,>fps=死亡
self.delete_me=False
def c_draw_self(自):
#如果我们活着而不是死去,画出我们正常的自己
如果self.condition==0:
#诊断的
如果self.draw_界限:
矩形(屏幕,[int(self.x),int(self.y),1,1],蓝色)
温度=自定向*(自线性速度*20)
皮加梅