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

asked Nov 28, 2017 at 0:32
\$\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']
answered Nov 28, 2017 at 17:00
\$\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\$ 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

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.