Windspar

Pygame How Many Moving Sprite Break Steady FPS

May 7th, 2021
777
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import pygame
  2. import random
  3. from pygame.sprite import Group, Sprite
  4.  
  5. # How many moving sprites does it take to break steady fps. Surface Vs Sprite Vs Vector2.
  6.  
  7. class Scene:
  8.     scenes = {}
  9.  
  10.     def __init__(self, engine, scene_name=None):
  11.         self.engine = engine
  12.         self._store_scene(scene_name)
  13.  
  14.     def _store_scene(self, scene_name):
  15.         if scene_name == "":
  16.             scene_name = self.__class__.__name__
  17.  
  18.         if scene_name:
  19.             Scene.scenes[scene_name] = self
  20.  
  21.     def set_scene(self, scene, *args):
  22.         if isinstance(scene, str):
  23.             next_scene = Scene.scenes[scene]
  24.         else:
  25.             next_scene = scene
  26.  
  27.         next_scene.on_focus(*args)
  28.         self.engine.next = next_scene
  29.  
  30.     def on_draw(self, surface):
  31.         pass
  32.  
  33.     def on_event(self, event):
  34.         pass
  35.  
  36.     def on_focus(self, *args):
  37.         pass
  38.  
  39.     def on_lost_focus(self):
  40.         pass
  41.  
  42.     def on_update(self, delta, ticks):
  43.         pass
  44.  
  45.     def on_quit(self):
  46.         self.engine.running = False
  47.  
  48. class DisplayEngine:
  49.     def __init__(self, caption, width, height, flags=0):
  50.         pygame.display.set_caption(caption)
  51.         self.surface = pygame.display.set_mode((width, height), flags)
  52.         self.rect = self.surface.get_rect()
  53.         self.clock = pygame.time.Clock()
  54.         self.running = False
  55.         self.gamespeed = 1
  56.         self.delta = 0
  57.         self.fps = 60
  58.  
  59.         self.scene = Scene(self)
  60.         self.next = None
  61.  
  62.     @property
  63.     def width(self):
  64.         return self.rect.width
  65.  
  66.     @property
  67.     def height(self):
  68.         return self.rect.height
  69.  
  70.     @property
  71.     def size(self):
  72.         return self.rect.size
  73.  
  74.     def main_loop(self):
  75.         self.running = True
  76.         while self.running:
  77.             self.update_scene()
  78.  
  79.             for event in pygame.event.get():
  80.                 if event.type == pygame.QUIT:
  81.                     self.scene.on_quit()
  82.                 else:
  83.                     self.scene.on_event(event)
  84.  
  85.             ticks = pygame.time.get_ticks()
  86.             self.scene.on_draw(self.surface)
  87.             self.scene.on_update(self.delta, ticks)
  88.             pygame.display.flip()
  89.             self.delta = self.clock.tick(self.fps) * 0.001 * self.gamespeed
  90.  
  91.     def update_scene(self):
  92.         if self.next:
  93.             self.scene.on_lost_focus()
  94.             self.scene = self.next
  95.             self.next = None
  96.  
  97. class Box:
  98.     def __init__(self, image, position, direction):
  99.         self.image = image
  100.         self.rect = self.image.get_rect(center=position)
  101.         self.position = self.rect.center
  102.         self.vector = direction
  103.  
  104.     def move(self, x, y):
  105.         self.position = self.position[0] + x, self.position[1] + y
  106.         self.rect.center = self.position
  107.  
  108.     def draw(self, surface):
  109.         surface.blit(self.image, self.rect)
  110.  
  111.     def update(self, delta, area):
  112.         self.position = (self.position[0] + self.vector[0] * delta,
  113.                          self.position[1] + self.vector[1] * delta)
  114.  
  115.         self.rect.center = self.position
  116.  
  117.         boolean = False
  118.         clamp = self.rect.clamp(area)
  119.         if self.rect.x != clamp.x:
  120.             self.vector[0] = -self.vector[0]
  121.             boolean = True
  122.  
  123.         if self.rect.y != clamp.y:
  124.             self.vector[1] = -self.vector[1]
  125.             boolean = True
  126.  
  127.         if boolean:
  128.             self.rect = clamp
  129.             self.position = self.rect.center
  130.  
  131. class SBox(Sprite):
  132.     def __init__(self, image, position, direction):
  133.         super().__init__()
  134.         self.image = image
  135.         self.rect = self.image.get_rect(center=position)
  136.         self.position = self.rect.center
  137.         self.vector = direction
  138.  
  139.     def move(self, x, y):
  140.         self.position = self.position[0] + x, self.position[1] + y
  141.         self.rect.center = self.position
  142.  
  143.     def update(self, delta, area):
  144.         self.position = (self.position[0] + self.vector[0] * delta,
  145.                          self.position[1] + self.vector[1] * delta)
  146.  
  147.         self.rect.center = self.position
  148.  
  149.         boolean = False
  150.         clamp = self.rect.clamp(area)
  151.         if self.rect.x != clamp.x:
  152.             self.vector[0] = -self.vector[0]
  153.             boolean = True
  154.  
  155.         if self.rect.y != clamp.y:
  156.             self.vector[1] = -self.vector[1]
  157.             boolean = True
  158.  
  159.         if boolean:
  160.             self.rect = clamp
  161.             self.position = self.rect.center
  162.  
  163. class VBox(Sprite):
  164.     def __init__(self, image, position, direction):
  165.         super().__init__()
  166.         self.image = image
  167.         self.rect = self.image.get_rect(center=position)
  168.         self.position = pygame.Vector2(self.rect.center)
  169.         self.vector = pygame.Vector2(direction)
  170.  
  171.     def move(self, x, y):
  172.         self.position += pygame.Vector2(x, y)
  173.         self.rect.center = self.position
  174.  
  175.     def update(self, delta, area):
  176.         self.position += self.vector * delta
  177.         self.rect.center = self.position
  178.         boolean = False
  179.  
  180.         clamp = self.rect.clamp(area)
  181.         if self.rect.x != clamp.x:
  182.             self.vector.x = -self.vector.x
  183.             boolean = True
  184.  
  185.         if self.rect.y != clamp.y:
  186.             self.vector.y = -self.vector.y
  187.             boolean = True
  188.  
  189.         if boolean:
  190.             self.rect = clamp
  191.             self.position = self.rect.center
  192.  
  193. class BoxState:
  194.     BASIC = 0
  195.     SPRITE = 1
  196.     VECTOR = 2
  197.     MAX = 3
  198.  
  199. class BoxScene(Scene):
  200.     def __init__(self, engine):
  201.         Scene.__init__(self, engine)
  202.         self.create_images()
  203.         self.state = BoxState.BASIC
  204.         self.load_boxes()
  205.         self.fps_trip = 0
  206.         self.fps_interval = 1000
  207.         self.fps_tick = pygame.time.get_ticks() + self.fps_interval
  208.         self.data = {0:[], 1:[], 2:[]}
  209.  
  210.     def add_box(self):
  211.         if self.state == BoxState.BASIC:
  212.             box_type = Box
  213.         elif self.state == BoxState.SPRITE:
  214.             box_type = SBox
  215.         else:
  216.             box_type = VBox
  217.  
  218.         directions = []
  219.         for i in range(6, 40, 2):
  220.             directions.append(i)
  221.             directions.append(-i)
  222.  
  223.         image = random.choice(self.images)
  224.         w, h = image.get_size()
  225.         sw, sh = self.engine.size
  226.         position = random.randint(0, sw - w), random.randint(0, sh - h)
  227.         direction = [random.choice(directions), random.choice(directions)]
  228.         if self.state == BoxState.BASIC:
  229.             self.boxes.append(box_type(image, position, direction))
  230.         else:
  231.             self.boxes.add(box_type(image, position, direction))
  232.  
  233.     def create_images(self):
  234.         self.images = []
  235.         color_names = "dodgerblue", "lawngreen", "firebrick", "orange", "purple"
  236.         for color_name in color_names:
  237.             for size in range(8, 16, 2):
  238.                 surface = pygame.Surface((size, size))
  239.                 surface.fill(pygame.Color(color_name))
  240.                 self.images.append(surface)
  241.  
  242.     def load_boxes(self):
  243.         self.count = 1000
  244.         if self.state == BoxState.BASIC:
  245.             self.boxes = []
  246.         else:
  247.             self.boxes = Group()
  248.  
  249.         for i in range(0, self.count):
  250.             self.add_box()
  251.  
  252.     def on_draw(self, surface):
  253.         surface.fill(pygame.Color('black'))
  254.         if self.state == BoxState.BASIC:
  255.             for box in self.boxes:
  256.                 box.draw(surface)
  257.         else:
  258.             self.boxes.draw(surface)
  259.  
  260.     def on_update(self, delta, ticks):
  261.         if self.state == BoxState.BASIC:
  262.             for box in self.boxes:
  263.                 box.update(delta, self.engine.rect)
  264.         else:
  265.             self.boxes.update(delta, self.engine.rect)
  266.  
  267.         if ticks > self.fps_tick:
  268.             self.fps_tick += self.fps_interval
  269.             avg = int(self.engine.clock.get_fps())
  270.  
  271.             if self.fps_trip < 4:
  272.                 print(avg)
  273.                 if avg >= self.engine.fps:
  274.                     self.fps_trip = 0
  275.                     print(self.count)
  276.  
  277.                     add = 500
  278.                     self.count += add
  279.                     for i in range(add):
  280.                         self.add_box()
  281.                 else:
  282.                     self.fps_trip += 1
  283.             else:
  284.                 self.data[self.state].append(self.count)
  285.                 if self.state == BoxState.VECTOR and len(self.data[0]) > 3:
  286.                     self.on_quit()
  287.  
  288.                 self.fps_trip = 0
  289.                 self.state += 1
  290.                 self.state %= BoxState.MAX
  291.                 self.load_boxes()
  292.  
  293.     def on_quit(self):
  294.         for i in range(BoxState.MAX):
  295.             print(self.data[i])
  296.  
  297.         Scene.on_quit(self)
  298.  
  299. if __name__ == "__main__":
  300.     pygame.init()
  301.     engine = DisplayEngine("Box Testing", 800, 600)
  302.     engine.scene = BoxScene(engine)
  303.     engine.main_loop()
  304.     pygame.quit()
  305.  
RAW Paste Data