6
\$\begingroup\$

I've been working on a fighting game using python and pygame and its quite finished, currently I'm looking for some constructive feedback about any issues/functions I should change in my code.

# Rects Fight V1.4
import pygame
import os
import sys
pygame.init()
screen = pygame.display.set_mode((500, 600))
# Global[ish] Variables
class Global():
    black = (0, 0, 0)
    grey = (192, 192, 192)
    white = (255, 255, 255)
    blue = (91, 154, 255)
    orange = (247, 157, 66)
    green = (0, 159, 18)
    red = (196, 0, 0)
    purple = (205, 43, 255)
    P1Char = 1
    P2Char = 2
    superloop = True
    font = pygame.font.Font(None, 40)
    font2 = pygame.font.Font(None, 20)
    playarea = pygame.Rect(5, 5, 490, 490)
class Media():
    # Blue Medialist
    blue = pygame.image.load(os.path.join('media', 'blue.png')).convert_alpha()
    bulletblue = pygame.image.load(os.path.join('media', 'bulletblue.png')).convert_alpha()
    # Orange Medialist
    orange = pygame.image.load(os.path.join('media', 'orange.png')).convert_alpha()
    bulletorange = pygame.image.load(os.path.join('media', 'bulletorange.png')).convert_alpha()
    # Green Medialist
    green = pygame.image.load(os.path.join('media', 'green.png')).convert_alpha()
    bulletgreen = pygame.image.load(os.path.join('media', 'bulletgreen.png')).convert_alpha()
    # Purple Medialist
    purple = pygame.image.load(os.path.join('media', 'purple.png')).convert_alpha()
    bulletpurple = pygame.image.load(os.path.join('media', 'bulletpurple.png')).convert_alpha()
    # Red Medialist
    red = pygame.image.load(os.path.join('media', 'red.png')).convert_alpha()
    bulletred = pygame.image.load(os.path.join('media', 'bulletred.png')).convert_alpha()
    # HP Medialist
    hp1 = pygame.image.load(os.path.join('media', 'hp1.png')).convert_alpha()
    hp2 = pygame.image.load(os.path.join('media', 'hp2.png')).convert_alpha()
    hp3 = pygame.image.load(os.path.join('media', 'hp3.png')).convert_alpha()
    dead = pygame.image.load(os.path.join('media', 'dead.png')).convert_alpha()
    # Player Soundlist
    shoot = pygame.mixer.Sound(os.path.join('media', 'shoot.wav'))
    hit = pygame.mixer.Sound(os.path.join('media', 'hit.wav'))
    die = pygame.mixer.Sound(os.path.join('media', 'die.wav'))
    # Game Medialist
    paused = pygame.image.load(os.path.join('media', 'paused.png')).convert_alpha()
    title = pygame.image.load(os.path.join('media', 'title.png')).convert_alpha()
    wall = pygame.image.load(os.path.join('media', 'wall.png')).convert_alpha()
    icon = pygame.image.load(os.path.join('media', 'icon.png')).convert_alpha()
    etge = pygame.image.load(os.path.join('media', 'egtg.png')).convert_alpha()
    # Game Soundlist
    pause = pygame.mixer.Sound(os.path.join('media', 'pause.wav'))
    fight = pygame.mixer.Sound(os.path.join('media', 'fight.wav'))
    music = pygame.mixer.Sound(os.path.join('media', 'music.wav'))
    select = pygame.mixer.Sound(os.path.join('media', 'select.wav'))
    start = pygame.mixer.Sound(os.path.join('media', 'start.wav'))
pygame.display.set_caption('Rects Fight!')
pygame.display.set_icon(Media.icon)
def Fetch(typeOfFetch, playerType, toReturn, fill1, fill2):
    if typeOfFetch == 'player':
        if playerType == 'player1':
            if toReturn == 'image':
                if Global.P1Char == 1:
                    return Media.blue
                elif Global.P1Char == 2:
                    return Media.orange
                elif Global.P1Char == 3:
                    return Media.green
                elif Global.P1Char == 4:
                    return Media.purple
                elif Global.P1Char == 5:
                    return Media.red
            elif toReturn == 'bullet':
                if Global.P1Char == 1:
                    return Media.bulletblue
                elif Global.P1Char == 2:
                    return Media.bulletorange
                elif Global.P1Char == 3:
                    return Media.bulletgreen
                elif Global.P1Char == 4:
                    return Media.bulletpurple
                elif Global.P1Char == 5:
                    return Media.bulletred
        elif playerType == 'player2':
            if toReturn == 'image':
                if Global.P2Char == 1:
                    return Media.blue
                elif Global.P2Char == 2:
                    return Media.orange
                elif Global.P2Char == 3:
                    return Media.green
                elif Global.P2Char == 4:
                    return Media.purple
                elif Global.P2Char == 5:
                    return Media.red
            elif toReturn == 'bullet':
                if Global.P2Char == 1:
                    return Media.bulletblue
                elif Global.P2Char == 2:
                    return Media.bulletorange
                elif Global.P2Char == 3:
                    return Media.bulletgreen
                elif Global.P2Char == 4:
                    return Media.bulletpurple
                elif Global.P2Char == 5:
                    return Media.bulletred
    elif typeOfFetch == 'text':
        if playerType == 'player1':
            if Global.P1Char == 1:
                return Global.font.render('Blue', True, Global.blue)
            elif Global.P1Char == 2:
                return Global.font.render('Orange', True, Global.orange)
            elif Global.P1Char == 3:
                return Global.font.render('Green', True, Global.green)
            elif Global.P1Char == 4:
                return Global.font.render('Purple', True, Global.purple)
            elif Global.P1Char == 5:
                return Global.font.render('Red', True, Global.red)
        elif playerType == 'player2':
            if Global.P2Char == 1:
                return Global.font.render('Blue', True, Global.blue)
            elif Global.P2Char == 2:
                return Global.font.render('Orange', True, Global.orange)
            elif Global.P2Char == 3:
                return Global.font.render('Green', True, Global.green)
            elif Global.P2Char == 4:
                return Global.font.render('Purple', True, Global.purple)
            elif Global.P2Char == 5:
                return Global.font.render('Red', True, Global.red)
    elif typeOfFetch == 'playerColor':
        if fill1.health == 0:
            if Global.P1Char == 1:
                return (91, 154, 255)
            if Global.P1Char == 2:
                return (247, 157, 66)
            if Global.P1Char == 3:
                return (0, 159, 18)
            if Global.P1Char == 4:
                return (205, 43, 255)
            if Global.P1Char == 5:
                return (196, 0, 0)
        if fill2.health == 0:
            if Global.P2Char == 1:
                return (91, 154, 255)
            if Global.P2Char == 2:
                return (247, 157, 66)
            if Global.P2Char == 3:
                return (0, 159, 18)
            if Global.P2Char == 4:
                return (205, 43, 255)
            if Global.P2Char == 5:
                return (196, 0, 0)
    elif typeOfFetch == 'hp':
        if playerType == 'player1':
            if fill1.health == 3:
                return pygame.transform.flip(Media.hp1, True, False)
            if fill1.health == 2:
                return pygame.transform.flip(Media.hp2, True, False)
            if fill1.health == 1:
                return pygame.transform.flip(Media.hp3, True, False)
            if fill1.health == 0:
                return pygame.transform.flip(Media.dead, True, False)
        if playerType == 'player2':
            if fill2.health == 3:
                return Media.hp1
            if fill2.health == 2:
                return Media.hp2
            if fill2.health == 1:
                return Media.hp3
            if fill2.health == 0:
                return Media.dead
    elif typeOfFetch == 'timer':        
        if fill1 < 10:
            return (196, 0, 0)
        else:
            return (255, 255, 255)

# Sprites
class Sprites():
    # Player Sprite
    class Player(pygame.sprite.Sprite):
        def __init__(self, pos, enemy_bullets, image, direction, *groups):
            super().__init__(*groups)
            self.image = image
            self.rect = self.image.get_rect(center = pos)
            self.vel = pygame.math.Vector2(0, 0)
            self.pos = pygame.math.Vector2(pos)
            self.fire_direction = pygame.math.Vector2(direction)
            self.health = 3
            self.enemy_bullets = enemy_bullets
            self.toggle = False
        def update(self):
            self.pos += self.vel
            self.rect.center = self.pos
            self.rect.clamp_ip(Global.playarea)
            collided = pygame.sprite.spritecollide(self, self.enemy_bullets, True)
            for bullet in collided:
                self.health -= 1
                Media.hit.play()
                if self.health <= 0:
                    self.kill()
                    self.toggle = True
                    Media.die.play()
    # Bullet Sprite
    class Bullet(pygame.sprite.Sprite):
        def __init__(self, pos, vel, image):
            super().__init__()
            self.image = image
            self.rect = self.image.get_rect(center = pos)
            self.vel = pygame.math.Vector2(vel)
            self.pos = pygame.math.Vector2(pos)
            self.toggle = False
        def update(self):
            if self.toggle == False:
                self.pos += self.vel
                self.rect.center = self.pos
                if not Global.playarea.contains(self):
                    self.kill()
# Game
class Game():
    def Title():
        loop = True
        time = True
        clock = pygame.time.Clock()
        dt = clock.tick(60) / 1000
        timer = 20
        while loop:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        loop = False
                        Media.start.play()
                    elif event.key == pygame.K_ESCAPE:
                        pygame.quit()
            if time:
                timer -= dt
            if timer <= 0:
                time = False
            screen.fill(Global.black)
            screen.blit(Media.title, (0, 0))
            if not time:
                screen.blit(Media.etge, (200, 100))
            pygame.display.flip()
            clock.tick(60)
    def CharSelect():
        loop = True
        clock = pygame.time.Clock()
        while loop:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_w:
                        Global.P1Char += 1
                        if Global.P1Char <= 5:
                            Media.select.play()
                    elif event.key == pygame.K_s:
                        Global.P1Char -= 1
                        if Global.P1Char >= 1:
                            Media.select.play()
                    if event.key == pygame.K_UP:
                        Global.P2Char += 1
                        if Global.P2Char <= 5:
                            Media.select.play()
                    elif event.key == pygame.K_DOWN:
                        Global.P2Char -= 1
                        if Global.P2Char >= 1:
                            Media.select.play()
                    if event.key == pygame.K_SPACE:
                        loop = False
            if Global.P1Char == 6:
                Global.P1Char -= 1
            elif Global.P1Char == 0:
                Global.P1Char += 1
            if Global.P2Char == 6:
                Global.P2Char -= 1
            elif Global.P2Char == 0:
                Global.P2Char += 1
            text1 = Fetch('text', 'player1', None, None, None)
            text2 = Fetch('text', 'player2', None, None, None)
            textS1 = Global.font.render('Choose Your Character', True, Global.white)
            textS2 = Global.font.render('Space To Continue', True, Global.white)
            textS3 = Global.font.render('Player 1: ', True, Global.white)
            textS4 = Global.font.render('Player 2: ', True, Global.white)
            screen.fill(Global.black)
            screen.blit(textS1, (100, 50))
            screen.blit(textS2, (125, 500))
            screen.blit(textS3, (115, 225))
            screen.blit(textS4, (115, 325))
            screen.blit(text1, (240, 225))
            screen.blit(text2, (240, 325))
            screen.blit(Fetch('player', 'player1', 'image', None, None), (355, 210))
            screen.blit(Fetch('player', 'player2', 'image', None, None), (355, 310))
            pygame.display.flip()
            clock.tick(60)
    def Main():
        # Game Variables
        all_sprites = pygame.sprite.Group()
        bullets1 = pygame.sprite.Group()
        bullets2 = pygame.sprite.Group()
        player1 = Sprites.Player((35, 35), bullets2, Fetch('player', 'player1', 'image', None, None), (8, 0), all_sprites)
        player2 = Sprites.Player((465, 465), bullets1, Fetch('player', 'player2', 'image', None, None), (-8, 0), all_sprites)
        clock = pygame.time.Clock()
        textstatic1 = Global.font2.render('Player 1', True, Global.white)
        textstatic2 = Global.font2.render('Player 2', True, Global.white)
        textstatic3 = Global.font2.render('Escape to leave', True, Global.white)
        textstatic4 = Global.font2.render('Enter to restart', True, Global.white)
        # Conditionals
        loop = True
        time = True
        onStart = True
        onEnd = True
        confirm = False
        # Integers
        vel = 8
        vel_reset = 0
        timer = 30
        dt = clock.tick(60) / 1000
        textlocal = (222, 520)
        while loop:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    Global.superloop = False
                    loop = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_e and player1.toggle == False:
                        bullet = Sprites.Bullet(player1.rect.center, pygame.math.Vector2(player1.fire_direction), Fetch('player', 'player1', 'bullet', None, None))
                        Media.shoot.play()
                        bullets1.add(bullet)
                        all_sprites.add(bullet)
                    if event.key == pygame.K_SPACE and player2.toggle == False:
                        bullet = Sprites.Bullet(player2.rect.center, pygame.math.Vector2(player2.fire_direction), Fetch('player', 'player2', 'bullet', None, None))
                        Media.shoot.play()
                        bullets2.add(bullet)
                        all_sprites.add(bullet)
                    if event.key == pygame.K_d and player1.toggle == False:
                        player1.vel.x = 5
                        player1.fire_direction = pygame.math.Vector2(vel, 0)
                    if event.key == pygame.K_a and player1.toggle == False:
                        player1.vel.x = -5
                        player1.fire_direction = pygame.math.Vector2(-vel, 0)
                    if event.key == pygame.K_s and player1.toggle == False:
                        player1.vel.y = 5
                        player1.fire_direction = pygame.math.Vector2(0, vel)
                    if event.key == pygame.K_w and player1.toggle == False:
                        player1.vel.y = -5
                        player1.fire_direction = pygame.math.Vector2(0, -vel)
                    if event.key == pygame.K_RIGHT and player2.toggle == False:
                        player2.vel.x = 5
                        player2.fire_direction = pygame.math.Vector2(vel, 0)
                    if event.key == pygame.K_LEFT and player2.toggle == False:
                        player2.vel.x = -5
                        player2.fire_direction = pygame.math.Vector2(-vel, 0)
                    if event.key == pygame.K_DOWN and player2.toggle == False:
                        player2.vel.y = 5
                        player2.fire_direction = pygame.math.Vector2(0, vel)
                    if event.key == pygame.K_UP and player2.toggle == False:
                        player2.vel.y = -5
                        player2.fire_direction = pygame.math.Vector2(0, -vel)
                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_d:
                        player1.vel.x = vel_reset
                    if event.key == pygame.K_a:
                        player1.vel.x = vel_reset
                    if event.key == pygame.K_s:
                        player1.vel.y = vel_reset
                    if event.key == pygame.K_w:
                        player1.vel.y = vel_reset
                    if event.key == pygame.K_RIGHT:
                        player2.vel.x = vel_reset
                    if event.key == pygame.K_LEFT:
                        player2.vel.x = vel_reset
                    if event.key == pygame.K_DOWN:
                        player2.vel.y = vel_reset
                    if event.key == pygame.K_UP:
                        player2.vel.y = vel_reset
            keys = pygame.key.get_pressed()
            if onStart:
                Media.fight.play()
                Media.music.play()
                onStart = False
            if keys[pygame.K_TAB] and not confirm and onEnd:
                player1.toggle = True
                player2.toggle = True
                confirm = True
                time = False
                for bullet in bullets1:
                    bullet.toggle = True
                for bullet in bullets2:
                    bullet.toggle = True
                pygame.mixer.pause()
                Media.pause.play()
            elif keys[pygame.K_LSHIFT] and confirm:
                player1.toggle = False
                player2.toggle = False
                confirm = False
                time = True
                for bullet in bullets1:
                    bullet.toggle = False
                for bullet in bullets2:
                    bullet.toggle = False
                pygame.mixer.unpause()
                Media.pause.play()
            elif keys[pygame.K_ESCAPE] and confirm:
                Global.superloop = False
                loop = False
            elif keys[pygame.K_RETURN] and confirm:
                Media.music.stop()
                loop = False
            if time:
                timer -= dt
                txt = Global.font.render(str(round(timer, 1)), True, Fetch('timer', None, None, timer, None))
                if timer <= 0:
                    player1.toggle = True
                    player2.toggle = True
                    for bullet in bullets1:
                        bullet.toggle = True
                    for bullet in bullets2:
                        bullet.toggle = True
                    Media.die.play()
                    Media.music.stop()
                    time = False
                    onEnd = False
                    textlocal = (190, 530)
                    txt = Global.font.render('Times Up!', True, Global.grey)
            if not time and keys[pygame.K_ESCAPE]:
                Global.superloop = False
                loop = False
            elif not time and keys[pygame.K_RETURN] and not confirm:
                Media.music.stop()
                loop = False
            # Player 1 Outcome
            if player1.health == 0:
                # typeOfFetch 1 playerType 2 toReturn 3 playerFill1 4, playerFill2 5)
                txt = Global.font.render('Player 2 Wins!', True, Fetch('playerColor', None, None, player2, player1))
                textlocal = (155, 530)
                time = False
                onEnd = False
                Media.music.stop()
                if keys[pygame.K_ESCAPE] and not confirm:
                    Global.superloop = False
                    loop = False
                elif keys[pygame.K_RETURN] and not confirm:
                    Media.music.stop()
                    loop = False
            # Player 2 Outcome
            if player2.health == 0:
                txt = Global.font.render('Player 1 Wins!', True, Fetch('playerColor', None, None, player2, player1))
                textlocal = (155, 530)
                time = False
                onEnd = False
                Media.music.stop()
                if keys[pygame.K_ESCAPE] and not confirm:
                    Global.superloop = False
                    loop = False
                elif keys[pygame.K_RETURN] and not confirm:
                    Media.music.stop()
                    loop = False
            # Draw Outcome
            if player1.health == 0 and player2.health == 0:
                txt = Global.font.render('Draw!', True, Global.grey)
                textlocal = (210, 530)
                time = False
                onEnd = False
                Media.music.stop()
                if keys[pygame.K_ESCAPE] and not confirm:
                    Global.superloop = False
                    loop = False
                elif keys[pygame.K_RETURN] and not confirm:
                    Media.music.stop()
                    loop = False
            # Drawing
            all_sprites.update()
            screen.fill(Global.black)
            screen.blit(Media.wall,(0, 0))
            screen.blit(Fetch('hp', 'player1', None, player1, player2), (20, 530))
            screen.blit(Fetch('hp', 'player2', None, player1, player2), (380, 530))
            screen.blit(txt, (textlocal))
            screen.blit(textstatic1, (19, 515))
            screen.blit(textstatic2, (429, 515))
            all_sprites.draw(screen)
            if not onEnd:
                screen.blit(textstatic3, (395, 10))
                screen.blit(textstatic4, (10, 10))
            if confirm:
                screen.blit(Media.paused, (154, 165))
            pygame.display.flip()
            clock.tick(60)
if __name__ == '__main__':
    Game.Title()
    Game.CharSelect()
    while Global.superloop:
        Game.Main()
    pygame.quit()

Entire Game w/media is on https://github.com/Pygasm/Rects-Fight

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Great job! Creating a game is always a big accomplishment. Now let's review the code.

Major issues

Scenes/states: I'd use separate classes for the different scenes, each with its own handle_event, run_logic and draw method. Then you'll need only one main and event loop for the entire game and can create scene instances which could also have persistent data.

class SceneA:  # Could inherit from a BaseScene.

    def __init__(self):
        self.background = pg.Surface((640, 480))
        self.background.fill((30, 50, 50))
        self.player_pos = [100, 200]
        self.next_scene = None

    def handle_event(self, event):  # Events get passed from the SceneManager.
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_d:
                self.player_pos[0] += 5
            elif event.key == pg.K_r:
                # Switch to the next scene. Persistent data could
                # be passed as an argument.
                self.next_scene = SceneB()

    def run_logic(self):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        pg.draw.rect(screen, (10, 100, 200), (self.player_pos, [20, 20]))


class SceneManager:

    def __init__(self):
        self.screen = pg.display.set_mode((640, 480))
        self.clock = pg.time.Clock()
        self.scene = SceneA()  # The current scene instance.
        self.done = False

    def run(self):
        # The main loop of the game. You only need one while and event loop.
        while not self.done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    self.done = True
                # Pass each event to the scene's event method.
                self.scene.handle_event(event)

            # Switch the scene. You could also store the other
            # scenes as an attribute, for example in a dict, and then
            # set the scene.next_scene attribute to the desired key.
            if self.scene.next_scene is not None:
                self.scene = self.scene.next_scene

            self.scene.run_logic()  # Update everything.
            self.scene.draw(self.screen)  # Draw everything.

            pg.display.flip()
            self.clock.tick(30)

Classes as containers: You're using some classes just as containers, but that's not really their purpose. They are usually deployed to combine state and behavior (to avoid global variables and for code reuse), that means classes should have attributes and methods that can use and modify these encapsulated attributes.

You should rather use modules to create new namespaces or put the data into a dictionary. So instead of the class Media you could have a media.py file.

And don't nest classes inside of other classes (Player in the Sprite class). Put the Player and Bullet into another module (or modules) as well.


The big Fetch function looks rather pointless. You just use it to access different images and other resources which could be stored in the player and scene instances.

Minor issues

You could automatize the loading of your resources with the help of the glob module. https://pymotw.com/3/glob/

So you could iterate over all the .png files in the directory, load them and add them to a dictionary (the same for the .wav files).


Take a look at PEP 8 the Python style guide. It helps to make code more readable. IDEs like PyCharm or linting tools (pylint) will show you what can be improved.

Further examples

To load the files I use the glob module. It will find all the png and wav files which you can load and add to one or two dictionaries. I check if the file name ends with png or wav, then use image.load or mixer.Sound depending on the file extension and add all loaded media objects to a MEDIA dict.

MEDIA = {}
files = glob.glob(os.path.join('media', '*.png'))
files.extend(glob.glob(os.path.join('media', '*.wav')))

for file_name in files:
    if file_name.endswith('.png'):
        obj = pg.image.load(file_name).convert_alpha()
    elif file_name.endswith('.wav'):
        obj = pg.mixer.Sound(file_name)
    # [6:-4] removes 'media/' and '.png' from the file name.
    MEDIA[file_name[6:-4]] = obj

I could remove the whole Fetch function which was only used to access the different resources. It worked kind of similar to a dictionary, so I just created a PLAYER_MEDIA dict which maps the color names to subdictionaries with the actual color tuple, the player image and the bullet image.

PLAYER_MEDIA = {
    'Blue': {
        'color': BLUE,
        'player_image': MEDIA['blue'],
        'bullet_image': MEDIA['bulletblue']},
    'Orange': {
        'color': ORANGE,
        'player_image': MEDIA['orange'],
        'bullet_image': MEDIA['bulletorange']},
    'Green': {
        'color': GREEN,
        'player_image': MEDIA['green'],
        'bullet_image': MEDIA['bulletgreen']},
    'Purple': {
        'color': PURPLE,
        'player_image': MEDIA['purple'],
        'bullet_image': MEDIA['bulletpurple']},
    'Red': {
        'color': RED,
        'player_image': MEDIA['red'],
        'bullet_image': MEDIA['bulletred']},
    }

Then I changed the char_select function. It returns the color names now which I pass to the main function and then to the player instances which use them to get their images and bullet images.

def get_images(color_name):
    image = PLAYER_MEDIA[color_name]['player_image']
    color = PLAYER_MEDIA[color_name]['color']
    text = font.render(color_name, True, color)
    return image, text


def char_select():
    color_choices = ['Blue', 'Orange', 'Green', 'Purple', 'Red']
    player1 = 0
    player2 = 1
    # No need to re-render these text surfaces.
    textS1 = font.render('Choose Your Character', True, WHITE)
    textS2 = font.render('Space To Continue', True, WHITE)
    textS3 = font.render('Player 1: ', True, WHITE)
    textS4 = font.render('Player 2: ', True, WHITE)
    player1_image, text1 = get_images(color_choices[player1])
    player2_image, text2 = get_images(color_choices[player2])
    clock = pg.time.Clock()

    while True:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                sys.exit()
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_w:
                    player1 += 1
                elif event.key == pg.K_s:
                    player1 -= 1
                if event.key == pg.K_UP:
                    player2 += 1
                elif event.key == pg.K_DOWN:
                    player2 -= 1
                if event.key in (pg.K_w, pg.K_s, pg.K_UP, pg.K_DOWN):
                    player1 %= len(color_choices)
                    player2 %= len(color_choices)
                    player1_image, text1 = get_images(color_choices[player1])
                    player2_image, text2 = get_images(color_choices[player2])
                    MEDIA['select'].play()
                if event.key == pg.K_SPACE:
                    return color_choices[player1], color_choices[player2]

        screen.fill(BLACK)
        screen.blit(textS1, (100, 50))
        screen.blit(textS2, (125, 500))
        screen.blit(textS3, (115, 225))
        screen.blit(textS4, (115, 325))
        screen.blit(text1, (240, 225))
        screen.blit(text2, (240, 325))
        screen.blit(player1_image, (355, 210))
        screen.blit(player2_image, (355, 310))

        pg.display.flip()
        clock.tick(60)

class Player(pg.sprite.Sprite):

    def __init__(self, pos, enemy_bullets, direction, color, *groups):
        super().__init__(*groups)
        self.image = PLAYER_MEDIA[color]['player_image']
        self.rect = self.image.get_rect(center = pos)
        self.vel = pg.math.Vector2(0, 0)
        self.pos = pg.math.Vector2(pos)
        self.fire_direction = pg.math.Vector2(direction)
        self.health = 3
        self.enemy_bullets = enemy_bullets
        self.toggle = False
        self.color = PLAYER_MEDIA[color]['color']
        self.bullet_image = PLAYER_MEDIA[color]['bullet_image']
\$\endgroup\$
14
  • \$\begingroup\$ Thanks for the feedback! For the scene feedback, I've tried writing in that style but It is extremely hard and confusing for me, several scene classes with everything split up makes it really hard to maintain, and i'm more prone to silly errors that i never pick up when running the debugger, plus I dont see the reason in doing that when it loads just fine with the scenes as functions method. I'm currently phasing out the classes as containers as they are early development leftovers that I never removed. The fetch function kinds acts as a way to link P1 and P2 char together as I dont see 1/2 \$\endgroup\$ Commented Nov 28, 2017 at 19:29
  • \$\begingroup\$ another way to get the character select to work, so having everything in a long function seems like the most convenient way, especially because you cant pass if statements as arguements. If there is a more convenient method I would love to hear that. The modules idea does not sound half-bad, albeit it would create alot of pycache items and be quite cluttered, also im afraid i would split it to sparsely to be readable. I dont see the point in the glob module, when the pygame.image.load + os.path.join seems more convenient and I would not have to fiddle with command prompt.Anyway, thanks @skrx \$\endgroup\$ Commented Nov 28, 2017 at 19:33
  • \$\begingroup\$ wait, said a wrong thing about the fetch() function, it actually links P1Char and P2Char to images, its effectively how the character select works. @skrx \$\endgroup\$ Commented Nov 28, 2017 at 19:38
  • \$\begingroup\$ I forgot to mention that you don't have to change anything in your program, since it works correctly and there are no obvious bugs. The suggestions above should only help to make the game more readable, maintainable and extendable in the future, but if you don't need to extend the program, there's no point in changing the code (except if you want to learn something new). I'll try to refactor a few of the things I mentioned and show you the results (probably) tomorrow. \$\endgroup\$
    – skrx
    Commented Nov 28, 2017 at 21:24
  • \$\begingroup\$ I'm going to take some of your more serious issues, I'm phasing out the classes as containers thing and I'm planning to possibly split fetch() off of the main file and just use it as a module, as it really clutters up my game, being a string of if statements \$\endgroup\$ Commented Nov 28, 2017 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.