Home > Blockchain >  Creating class objects at random from a list in pygame
Creating class objects at random from a list in pygame

Time:09-14

I am developing a game in python 3.10.4 using pygame but I am struggling to generate a flow of user class objects in the main loop from a list using random.choice.

def run_game(self):
    """Start the main loop for the game."""
    list_of_particles = [Particle__SO2(self),Particle__H20(self),Particle__CO2(self),Particle__H2S(self), Particle__CO2(self)]
    while True:
        self._check_events()
        self.clock.tick(25)
        new_particle = random.choice(list_of_particles)
        self.particles.add(new_particle)
        self._update_particles()

The code works but the list seemingly exhausts itself after generating each object exactly once and I am at a loss to see why. Full code below:

import sys
import pygame
from pygame.sprite import Sprite
import random

class Volcano_game:
    """Overall class to manage game assets and behavior."""

    def __init__(self):
        """Initialize the game, and create game resources."""
        pygame.init()
        self.screen = pygame.display.set_mode((1920, 1080))
        self.particles = pygame.sprite.Group()
        self.vent_location_xy = (952, 881)
        self.io_surface_y = 950
        self.gravity = 1
        self.clock = pygame.time.Clock()
        self.alpha_surf = pygame.Surface(self.screen.get_size(), pygame.SRCALPHA)

    def run_game(self):
        """Start the main loop for the game."""
        list_of_particles = [Particle__SO2(self),Particle__H20(self),Particle__CO2(self),Particle__H2S(self), Particle__CO2(self)]
        while True:
            self._check_events()
            self.clock.tick(25)
            new_particle = random.choice(list_of_particles)
            self.particles.add(new_particle)
            self._update_particles()
            

            self.update_screen()
            
            self.alpha_surf.fill((255, 255, 255, 250),
                                special_flags=pygame.BLEND_RGBA_MULT)

    def _update_particles(self):
        """Update position of particles and get rid of old particles."""
        # Update bullet positions.
        self.particles.update()

        # Get rid of particles that have landed or gone off screen.
        for particle in self.particles.copy():
            if particle.y > self.io_surface_y:
                self.particles.remove(particle)
            elif particle.y < 0:
                self.particles.remove(particle)
            elif particle.x < 0:
                self.particles.romove(particle)
            elif particle.x > 1920:
                self.particles.remove(particle)

    def update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        self.screen.fill((0, 0, 0))
        
        
        self.screen.blit(self.alpha_surf, (0, 0))
        for particle in self.particles.sprites():
            particle.draw_particle()

        pygame.display.flip()

    def _check_events(self):
        """Respond to keypresses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

class Particle(Sprite):
    """a class to manage sprites fired from the volcano"""

    def __init__(self, vg_game):
        super().__init__()
        self.screen = vg_game.alpha_surf
        self.colour = (60, 255, 60)

        self.rect_x = 952
        self.rect_y = 881
        self.y = self.rect_y
        self.x = self.rect_x
        self.speed_y = -15
        self.speed_x = (random.randint(-11, 11))
        self.gravity = vg_game.gravity

    def update(self):
        """move the particle around the screen"""
        # update the decimal position of the particle
        self.y  = self.speed_y
        self.x  = self.speed_x
        self.speed_y  = self.gravity
        self.rect_y = self.y
        self.rect_x = self.x

    def draw_particle(self):
        """draw the particle on the screen"""
        pygame.draw.circle(self.screen, self.colour,
                            (self.rect_x, self.rect_y), 2)


class Particle__SO2(Particle):

    def __init__(self, vg_game):
        super().__init__(vg_game)
        self.colour = (255, 255, 255)

        self.speed_y = -17


class Particle__H20(Particle):
    def __init__(self, vg_game):
        super().__init__(vg_game)
        self.colour = (0, 0, 255)

        self.speed_y = -52.5


class Particle__CO2(Particle):
    def __init__(self, vg_game):
        super().__init__(vg_game)
        self.colour = (255, 0, 0)

        self.speed_y = -24.72

class Particle__H2S(Particle):
    def __init__(self, vg_game):
        super().__init__(vg_game)
        self.colour = (255, 255, 0)

        self.speed_y = -31.9

if __name__ == '__main__':
    # Make a game instance, and run the game.
    vg = Volcano_game()
    vg.run_game()

CodePudding user response:

The list isn't being "exhausted". The problem is that you only have five particle objects - the ones you defined in list_of_particles. Once a given particle is no longer within your desired bounds you remove it from the volcano game's tracked list of particles (which is fine), but the particle instance itself doesn't get deleted or reset. Your main loop will happily pick a particle instance it has seen before, update its position (which will now be even further outside of your desired bounds), add it to the volcano game's list of tracked particles, and then immediately remove it.

I would suggest instead to randomly pick a type of particle, and then to instantiate that type, so that you have a brand new particle object each time. Something like:

particle_types = [Particle__SO2, Particle__H20, Particle__CO2, Particle__H2S] # Note: We are not instantiating any particle objects. We're creating a list of particle types - referring to the particle classes directly.

ParticleType = random.choice(particle_types)

particle = ParticleType(self)

self.particles.add(particle)
self._update_particles()

CodePudding user response:

You just create 4 particle objects. You need to choose a random particle type (class) and create a new instance object of that type in each iteration of the loop:

class Volcano_game:
    """Overall class to manage game assets and behavior."""

    # [...]

    def run_game(self):
        """Start the main loop for the game."""

        # EDIT:
        # list_of_particles = [Particle__SO2(self),Particle__H20(self),Particle__CO2(self),Particle__H2S(self), Particle__CO2(self)]
        list_of_particles = [Particle__SO2, Particle__H20, Particle__CO2, Particle__H2S, Particle__CO2]
        
        while True:
            self._check_events()
            self.clock.tick(25)

            # EDIT:
            # new_particle = random.choice(list_of_particles)
            new_particle = random.choice(list_of_particles)(self)
            
            self.particles.add(new_particle)
            self._update_particles()
            
            self.update_screen()
            self.alpha_surf.fill((255, 255, 255, 250), special_flags=pygame.BLEND_RGBA_MULT)
  • Related