Python Forum
[PyGame] Game boss causing huge slowdown
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Game boss causing huge slowdown
#1
Trying to make a new boss, but I don't know if this method is viable. It's an alien centipede type thing.

I spawn the head and the head spawns the next segment and so on. Each segment to follow to previous... but it runs SLOW.

Is this method even workable? All together it is composed of 6 sprites.

The self.direction are to do with images when they are all set up, and not the movement. The monster just moves in a square, but ultimately I just want to command the head and the rest should/does follow, just the slowdown is unplayable. Is it better to just have a bunch of separate segments with the same movement logic so they only appear to be connected? I'd like to maybe make this creature playable at some point, that's why I picked this method.

Ideas? Thanks.

class Boss2(pg.sprite.Sprite):
         
    def __init__(self, game, x, y):
        self.groups = game.boss_group
        self._layer = 10
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = self.game.boss2_head
        self.rect = self.image.get_rect()
        self.rect.x = x * self.game.block_size 
        self.rect.y = y * self.game.block_size
        self.integretty = 200
        self.pos = pg.math.Vector2(self.rect.center)
        self.direction = "right"
        self.last_update = pg.time.get_ticks()
        self.frame_rate = 100
        self.frame = 0
        self.prev_pos = 0
        
    def update(self, game, dt):
        now = pg.time.get_ticks()
        if self.frame == 1:
            Boss_body_seg(self, self.game, 5)
        if now - self.last_update > self.frame_rate:
            self.last_update = now
            self.frame += 1
            if  self.frame <= 30:
                self.prev_pos = pg.math.Vector2(self.rect.center)
                self.pos += (10, 0)
                self.rect.center = self.pos
                self.direction = "right" 
                self.image = self.game.boss2_right
            if self.frame > 30 and self.frame <= 60:
                self.prev_pos = pg.math.Vector2(self.rect.center)
                self.pos += (0, 10)
                self.rect.center = self.pos
                self.direction = "down"
                self.image = self.game.boss2_down
            if self.frame > 60 and self.frame <= 90:
                self.prev_pos = pg.math.Vector2(self.rect.center)
                self.pos += (-10, 0)
                self.rect.center = self.pos
                self.direction = "left" 
                self.image = self.game.boss2_left
            if self.frame > 90 and self.frame <= 120:
                self.prev_pos = pg.math.Vector2(self.rect.center)
                self.pos += (0, -10)
                self.rect.center = self.pos
                self.direction = "up"
                self.image = self.game.boss2_up
            if self.frame == 120:
                self.frame = 0
            
class Boss_body_seg(pg.sprite.Sprite):
        
    def __init__(self, prev_seg, game, num):
        
        self.groups = game.boss_group
        self._layer = prev_seg._layer - 1
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.prev_seg = prev_seg

        self.image = self.game.boss2_body
        self.rect = self.image.get_rect()
        
        self.integretty = 200
        self.pos = self.prev_seg.prev_pos
        self.num = num - 1
        self.direction = self.prev_seg.direction
        self.last_update = pg.time.get_ticks()
        self.frame_rate = 120
        self.frame = 0
        
    def update(self, game, dt):
        if self.frame == 10 and self.num > 0:
                Boss_body_seg(self, self.game, self.num)
        now = pg.time.get_ticks()
        if now - self.last_update > self.frame_rate:
            
            self.last_update = now
            self.frame += 1
            self.prev_pos = self.rect.center
            self.direction = self.prev_seg.direction
            self.pos = self.prev_seg.prev_pos 
            self.rect.center = self.pos
            self.image = self.game.boss2_downleft
Reply
#2
Do you have a full runnable example of the game?
Recommended Tutorials:
Reply
#3
Sort of. I'll add a help panel and a boss test mode. Then it can be played through with the working boss or test the second. I'll link it here in a few hours.
Reply
#4
How do you know this is the slow part ? Did you profile code ?

Example how you could improve code. Need to improve body movement in my code.
import os
import pygame
from pygame.sprite import Group, Sprite

class SimpleSprite(Sprite):
    def __init__(self, image, position, anchor):
        Sprite.__init__(self)
        self.image = image
        self.rect = image.get_rect(**{anchor: position})

    def draw(self, surface):
        surface.blit(self.image, self.rect)

class VectorSprite(SimpleSprite):
    def __init__(self, image, position, anchor):
        SimpleSprite.__init__(self, image, position, anchor)
        self.center = pygame.Vector2(self.rect.center)

    def move(self, movement):
        self.center += movement
        self.rect.center = self.center

    def set_center(self, center):
        self.center = center
        self.rect.center = self.center

class Boss:
    def __init__(self, area, head_image, body_image, position, anchor):
        self.head = VectorSprite(head_image, position, anchor)
        self.steps = []
        self.body_list = []
        self.body = Group()
        self.create_body(body_image)
        self.vector = pygame.Vector2(-1, 0)
        self.speed = 0.06
        self.area = area
        self.step = 15
        self.max_step = len(self.body_list) * self.step + 1

    def create_body(self, body_image):
        for x in range(5):
            sprite = VectorSprite(body_image, self.head.center, "center")
            self.body_list.append(sprite)
            self.body.add(sprite)

    def draw(self, surface):
        self.body.draw(surface)
        self.head.draw(surface)

    def update(self, delta):
        movement = self.vector * delta * self.speed
        self.head.move(movement)

        if self.head.rect.left < 20:
            self.head.rect.left = 20
            self.head.center = pygame.Vector2(self.head.rect.center)
            self.vector = pygame.Vector2(0, 1) # down
        elif self.head.rect.bottom > self.area.bottom - 20:
            self.head.rect.bottom = self.area.bottom - 20
            self.head.center = pygame.Vector2(self.head.rect.center)
            self.vector = pygame.Vector2(1, 0) # right
        elif self.head.rect.right > self.area.right - 20:
            self.head.rect.right = self.area.right - 20
            self.head.center = pygame.Vector2(self.head.rect.center)
            self.vector = pygame.Vector2(0, -1) # up
        elif self.head.rect.top < 20:
            self.head.rect.top = 20
            self.head.center = pygame.Vector2(self.head.rect.center)
            self.vector = pygame.Vector2(-1, 0) # left

        self.steps.insert(0, pygame.Vector2(self.head.center))

        length = len(self.steps)
        for enum, body in enumerate(self.body_list):
            if length >= self.step * (enum + 1):
                body.set_center(self.steps[self.step * (enum + 1) - 1])

        self.steps = self.steps[:self.max_step]

class DisplayEngine:
    @staticmethod
    def center_screen():
        os.environ['SDL_VIDEO_CENTERED'] = '1'

    @staticmethod
    def screen_position(x, y):
        os.environ['SDL_VIDEO_WINDOW_POS'] = '{}, {}'.format(x, y)

    def __init__(self, caption, width, height, flags=0, fps=60):
        pygame.display.set_caption(caption)
        self.surface = pygame.display.set_mode((width, height), flags)
        self.rect = self.surface.get_rect()
        self.clock = pygame.time.Clock()
        self.running = False
        self.delta = 0
        self.fps = fps

    def idle(self):
        self.delta = self.clock.tick(self.fps)

    def quit(self):
        self.running = False

class Scene:
    def __init__(self, display_engine):
        self.display_engine = display_engine
        self.background = pygame.Color('black')
        self.create_images()

        position = self.display_engine.rect.centerx, 20
        self.boss = Boss(self.display_engine.rect, self.images['head'], self.images['body'], position, "midtop")

    def create_images(self):
        self.images = {}
        self.images['head'] = pygame.Surface((12, 12))
        self.images['head'].fill(pygame.Color('dodgerblue'))
        self.images['body'] = pygame.Surface((8, 8))
        self.images['body'].fill(pygame.Color('dodgerblue'))

    def mainloop(self):
        self.display_engine.running = True
        while self.display_engine.running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.display_engine.quit()
                else:
                    self.on_event(event)

            self.on_update(self.display_engine.delta)
            self.on_draw(self.display_engine.surface)
            pygame.display.flip()
            self.display_engine.idle()

    def on_draw(self, surface):
        surface.fill(self.background)
        self.boss.draw(surface)

    def on_event(self, event):
        pass

    def on_update(self, delta):
        #ticks = pygame.time.get_ticks()
        self.boss.update(delta)

def main():
    pygame.init()
    DisplayEngine.center_screen()
    display_engine = DisplayEngine("Boss Example", 800, 600)
    scene = Scene(display_engine)
    scene.mainloop()

if __name__ == "__main__":
    main()
99 percent of computer problems exists between chair and keyboard.
Reply
#5
Here is what I have. It's a big game, and primitive, but pretty fun. It still uses my old tile map any has plenty bugs, but most features are there.

It will hopefully run as is. You start at top and blast away blocks looking for money to get upgrades and the R, G, and B keys. Then fight a boss. Did lots of the art myself.

Run as is and play it through to kill the working boss.

Change line 114 in main.py to "boss_room2" and the end boss will be the one I posted.

Pressing "p" will give you all upgrades and warp you to boss chamber.

press "h" for controls.

https://github.com/Michaelm1789/All-my-s...ginal_2.7z


I'll look at what you posted here, Winspar.

Let me know if this doesn't run so I can fix it and re-upload.
Reply
#6
I will have to disable your sound. My computer doesn't like your wav sound files.
99 percent of computer problems exists between chair and keyboard.
Reply
#7
linux is case sensitive. Im not changing every single image/sound filename to the correct loaded string name associated with it. For example:
metulburr@ubuntu:~/Downloads/Block_Miner_original$ python3 main.py 
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "main.py", line 1125, in <module>
    'game': Game(),
  File "main.py", line 308, in __init__
    self.load_data()
  File "main.py", line 612, in load_data
    pg.mixer.music.load(path.join(self.snd_dir, "GalacticTemple.ogg"))
pygame.error: Couldn't open 'snd/GalacticTemple.ogg'
You have it camelcase in the code, but the filename is is not
metulburr@ubuntu:~/Downloads/Block_Miner_original/snd$ ls | grep temple
galactictemple.ogg
Recommended Tutorials:
Reply
#8
(Mar-07-2020, 11:58 AM)metulburr Wrote: linux is case sensitive. Im not changing every single image/sound filename to the correct

oh.. I thought I got all those, just for that reason. I fix it right now. Sorry.

(Mar-07-2020, 07:30 AM)Windspar Wrote: I will have to disable your sound. My computer doesn't like your wav sound files.

I used Bfxr for most the sounds. Does it make strange files maybe? I don't reall know how I fix that problem.

https://github.com/Michaelm1789/All-my-s...riginal.7z

There. Pretty I got them all this time.
Reply
#9
I create a bfxr wav file. Download it. It works fine.
I try your wav file. There just error.
Your ogg files work fine.
99 percent of computer problems exists between chair and keyboard.
Reply
#10
(Mar-07-2020, 06:37 PM)Windspar Wrote: I create a bfxr wav file. Download it. It works fine.
I try your wav file. There just error.
Your ogg files work fine.

I was using the standalone version. I make the sounds locally and export it to my snd folder. They all work for me. I'm going to stop that. Is it python that gives you an error or did you try them with your media player too? The ogg files were all downloads.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  (HELP GREATLY APPRECIATED) New user- Huge Pygame Installation Problem! Jbomb 1 2,840 Jan-12-2021, 07:32 PM
Last Post: MK_CodingSpace

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020