Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Shmup
#1
Been a while since I've been here and posted anything so, here is a little game that I've been playing around with.
Works on windows 10. I've not had a chance to modify to work on linux. You can download the files from github
Shmup. Uses pygame 1.9.6 and tkinter



Here is the coding.
# Import needed modules
import pygame
import os
import random as rnd
import tkinter as tk
from functools import partial

try:
    import pygame.freetype as freetype
except ImportError:
    print ("No FreeType support compiled")
    sys.exit ()

# Initialize pygame and the sound mixer
pygame.init()
if pygame.get_sdl_version()[0] == 2:
    pygame.mixer.pre_init(44100, 32, 2, 1024)
pygame.mixer.init()

# Screen and framerate setup
width = 800
height = 600
fps = 60

screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Shoot \'m Up!')
clock = pygame.time.Clock()

# Load font ttf file
fontdir = os.path.dirname(os.path.abspath (__file__))
# font = freetype.Font(os.path.join (fontdir, "fonts", "comicbd.ttf"))

# Set some colors note: all are not used
black = (0, 0, 0)
white = (255, 255, 255)
palewhite = (240, 240, 240)
grayish = (195, 195, 190)
tomato = (250, 80, 100)
skyblue = (0, 180, 255)
green = (0, 255, 0)
red = (255, 0, 0)
yellow = (255, 255, 0)
orange = (250, 80, 0)
purple = (255, 0, 255)
peru = (205, 133, 63)
limegreen = (50, 205, 50)
yellowgreen = (154, 205, 50)

# Set the path for the image, music and sound directories
imgdir = os.path.join(os.path.dirname(__file__), 'images')
snddir = os.path.join(os.path.dirname(__file__), 'sounds')
musicdir = os.path.join(os.path.dirname(__file__), 'music')

# Set the background image
background = pygame.image.load(f'{imgdir}/backgrounds/space.png')
background_rect = background.get_rect()

# Load all images used by the player
player_img = pygame.image.load(f'{imgdir}/ships/myship.png').convert()
mini_img = pygame.transform.scale(player_img, (25, 25))
mini_img.set_colorkey(black)
shipbmp = pygame.image.load(f'{imgdir}/icons/myship.bmp')

icon = pygame.transform.scale(shipbmp, (32, 32))
pygame.display.set_icon(icon)
pygame.mouse.set_visible(0)

# Load the missile image
missile_img = pygame.image.load(f'{imgdir}/ammo/missile.png').convert()

# Load shield images
shield_100 = pygame.image.load(f'{imgdir}/shield/shield_100.png').convert()
shield_75 = pygame.image.load(f'{imgdir}/shield/shield_75.png').convert()
shield_50 = pygame.image.load(f'{imgdir}/shield/shield_50.png').convert()
shield_25 = pygame.image.load(f'{imgdir}/shield/shield_25.png').convert()

# Load powerup images
power_imgs = {}
power_imgs['shield_img'] = pygame.image.load(f'{imgdir}/powerups/shield.png').convert()
power_imgs['full_life_img'] = pygame.image.load(f'{imgdir}/powerups/full_life.png').convert()
power_imgs['partial_life_img'] = pygame.image.load(f'{imgdir}/powerups/partial_life.png').convert()

# Load sound effects
shoot_sound = pygame.mixer.Sound(f'{snddir}/rocket_fire.wav')
enemy_explode = pygame.mixer.Sound(f'{snddir}/explosion.wav')
player_hit = pygame.mixer.Sound(os.path.join(snddir, "myexplosion.wav"))
player_die = pygame.mixer.Sound(os.path.join(snddir, 'player_die.wav'))
shield_up = pygame.mixer.Sound(os.path.join(snddir, 'shield_up.wav'))
partial_heal = pygame.mixer.Sound(os.path.join(snddir, 'partial_heal.wav'))
full_heal = pygame.mixer.Sound(os.path.join(snddir, 'full_heal.wav'))


# Explosion animations containers
explosion_animation = {}
explosion_animation['lg'] = []
explosion_animation['sm'] = []
explosion_animation['player'] = []

# Load explosion images for animation
for i in range(90):
    filename = f'explosion1_{i}.png'
    img = pygame.image.load(os.path.join(f'{imgdir}/animation/enemy_explosion', filename))
    img.set_colorkey(black)
    img_lg = pygame.transform.scale(img, (75, 75))
    explosion_animation['lg'].append(img_lg)
    img_sm = pygame.transform.scale(img, (32, 32))
    explosion_animation['sm'].append(img_sm)

for i in range(9):
    filename = f'explosion_{i}.png'
    img = pygame.image.load(os.path.join(f'{imgdir}/animation/player_explosion', filename))
    img.set_colorkey(black)
    explosion_animation['player'].append(img)

# Number of enemy ships to display on the screen
how_many_enemy_ships = 10

# Function for displaying text on the screen
def draw_text(surface, xpos, ypos, text, color, size, myfont, style):
    font = freetype.Font(os.path.join(fontdir, 'fonts', myfont))
    return font.render_to(surface, (round(xpos), round(ypos)), text, color, size=size, style=style)


# Class for the background music.
class BgMusic:
    def __init__(self):
        music_list = os.listdir(musicdir)
        file = rnd.choice(music_list)
        music = pygame.mixer.Sound(f'{musicdir}/{file}')
        music.play(-1)


# Class for the explosion effects
class Explosion(pygame.sprite.Sprite):
    def __init__(self, center, size):
        pygame.sprite.Sprite.__init__(self)
        self.size = size
        self.image = explosion_animation[self.size][0]
        self.rect = self.image.get_rect()
        self.rect.center = center
        self.frame = 0
        self.last_update = pygame.time.get_ticks()
        self.frame_rate = 20

    def update(self):
        now = pygame.time.get_ticks()
        if now - self.last_update > self.frame_rate:
            self.last_update = now
            self.frame += 1
            if self.frame == len(explosion_animation[self.size]):
                self.kill()
            else:
                center = self.rect.center
                self.image = explosion_animation[self.size][self.frame]
                self.rect = self.image.get_rect()
                self.rect.center = center


# Class for displaying various information
class Display:
    def __init__(self):
        pass

    def rotate_image(self, rotate, x, y, ship):
        img = pygame.image.load(os.path.join(imgdir, ship)).convert()
        img = pygame.transform.scale(img, (64, 64))
        img = pygame.transform.rotate(img, rotate)
        img.set_colorkey(black)
        screen.blit(img, (x, y))

    # Define the title screen
    def title_screen(self):
        # Set the background
        screen.blit(background, background_rect)

        # Background music
        BgMusic()
        # Draw text to the screen
        draw_text(screen, 225, 15, 'Shmup!', purple, 100, 'comicbd.ttf', freetype.STYLE_NORMAL)
        draw_text(screen, 230, 130, 'Beta Version 0.04', grayish, 15, 'comic.ttf', freetype.STYLE_NORMAL)
        draw_text(screen, 410, 130, 'Powered by Pygame 1.9.6', \
        green, 15, 'comic.ttf', freetype.STYLE_NORMAL|freetype.STYLE_OBLIQUE)
        draw_text(screen, 225, 180, 'Top Five High Scores', red, 30, 'comicbd.ttf', freetype.STYLE_UNDERLINE)

        # Initialize the Scores class
        scores = Scores()

        # Check for a score text file
        scores.check_for_score_file()

        # Display the top five scores
        i = 0
        n = 1
        for score in scores.get_scores(5):
            draw_text(screen, 225, 240+i, f'{n}. {score[1].upper()}', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
            draw_text(screen, 425, 240+i, f'{score[0]}', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
            i += 35
            n += 1

        # Draw game contols on the title screen
        draw_text(screen, 225, 430, f'Press Spacebar to Start', yellow, 25, 'comic.ttf', freetype.STYLE_NORMAL)
        draw_text(screen, 220, 460, f'Arrow or A and D keys to move, spacebar to fire.', yellow, 20, 'comic.ttf', freetype.STYLE_NORMAL)

        # Draw power icons and text
        screen.blit(power_imgs['shield_img'], (50,height-100))
        draw_text(screen, 100, height-90, f'Gives a shield', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
        screen.blit(power_imgs['full_life_img'], (260,  height-100))
        draw_text(screen, 310,height-90, f'Restores Full Life', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
        screen.blit(power_imgs['partial_life_img'], (500, height-100))
        draw_text(screen, 550, height-90, f'Restores Partial Life', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)

        # The footer
        draw_text(screen, 280, height-30, \
         f'GamingRat Productions 2020 {chr(169)}', \
         peru, 15, 'comic.ttf', freetype.STYLE_NORMAL|freetype.STYLE_OBLIQUE)
        img = pygame.image.load(os.path.join(f'{imgdir}/icons', 'ratt2b.bmp'))
        img.set_colorkey(black)
        img = pygame.transform.scale(img, (50, 50))
        screen.blit(img, (220, height-50))

        # The two ships on the title screen
        ships = os.listdir(f'{imgdir}/ships')
        self.rotate_image(-130, 25, 25, f'ships/{rnd.choice(ships)}')
        self.rotate_image(130, 675, 25, f'ships/{rnd.choice(ships)}')

        pygame.display.flip()

        # Keeps player on the title screen until the spacebar is pressed
        waiting = True
        while waiting:
            clock.tick(fps)

            try:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()

                keystate = pygame.key.get_pressed()
                if keystate[pygame.K_SPACE]:
                    waiting = False
            except pygame.error:
                break

    # define the lives bar. The three small ships on the right top
    def lives_bar(self, surface, x, y, lives, img):
        for i in range(lives):
            img_rect = img.get_rect()
            img_rect.x = x + 30 * i
            img_rect.y = y
            surface.blit(img, img_rect)

    # Define the life and shield bar.
    # Changes color depending on hits taken
    def status_bar(self, surface, x, y, obj):
        length = 100
        height = 15
        fill = (obj/length) * length
        if fill >= 75:
            color = green
        elif fill < 75 and fill >= 60:
            color = yellow
        elif fill < 60 and fill >= 30:
            color = orange
        elif fill <= 0:
            color = black
        else:
            color = red

        fill_rect = pygame.Rect(round(x), round(y), round(fill), round(height))
        pygame.draw.rect(surface, color, fill_rect)
        outline_rect = pygame.Rect(round(x), round(y), length, height)
        pygame.draw.rect(surface, palewhite, outline_rect, 1)


# Define the class for the player
class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.transform.scale(player_img, (50, 50))
        self.image.set_colorkey(black)
        self.rect = self.image.get_rect()
        self.radius = 25
        self.rect.centerx = round(width / 2)
        self.rect.bottom = height - 10
        self.speedx = 0
        self.hidden = False
        self.life = 100
        self.lives = 3
        self.hide_timer = pygame.time.get_ticks()

    # Defines the player bullets
    def shoot(self, bullet_sprites):
        bullet = Bullets(self.rect.centerx, self.rect.top)
        bullet_sprites.add(bullet)
        shoot_sound.play()

    # Hides the player for a momment when destroyed
    def hide(self):
        self.hidden = True
        self.hide_timer = pygame.time.get_ticks()
        self.rect.center = (round(width / 2), height + 200)

    # Restores player after being destroyed and handles player movement.
    def update(self):
        if self.hidden and pygame.time.get_ticks() - self.hide_timer > 1000:
            self.hidden = False
            self.rect.centerx = round(width / 2)
            self.rect.bottom = height - 10
        self.speedx = 0
        keystate = pygame.key.get_pressed()
        if keystate[pygame.K_LEFT] or keystate[pygame.K_a]:
            self.speedx = -8
        if keystate[pygame.K_RIGHT] or keystate[pygame.K_d]:
            self.speedx = 8
        self.rect.x += self.speedx
        if self.rect.right > width - 15:
            self.rect.right = width - 15
        if self.rect.left < 15:
            self.rect.left = 15


# Class for defining the bullets/missile beng shot
class Bullets(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.transform.scale(missile_img, (18, 32))
        self.image.set_colorkey(black)
        self.rect = self.image.get_rect()
        self.rect.bottom = y + 10
        self.rect.centerx = x
        self.speedy = -10

    # Update bullet movement
    def update(self):
        self.rect.y += self.speedy
        # Kill it if it moves off the top of the screen
        if self.rect.bottom < 0:
            self.kill()


# Class for defining the shield
class Shield(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.shield_img = shield_100
        self.image = pygame.transform.scale(self.shield_img, (80, 50))
        self.image.set_colorkey(black)
        self.rect = self.image.get_rect()
        self.radius = 30
        self.rect.centerx = round(width/2)
        self.rect.top = height + 50
        self.strength = 0
        self.hidden = True

    # Defines the shield
    def raise_shield(self, x, y, sprite):
        shield = self
        sprite.add(shield)
        shield.rect.centerx = x
        shield.rect.top = y - 20

    # Defines shield movement and kills it when not on use
    def update(self):
        if self.hidden:
            self.kill()
        self.speedx = 0
        keystate = pygame.key.get_pressed()
        if keystate[pygame.K_LEFT] or keystate[pygame.K_a]:
            self.speedx = -8
        if keystate[pygame.K_RIGHT] or keystate[pygame.K_d]:
            self.speedx = 8
        self.rect.x += self.speedx
        if self.rect.right > width:
            self.rect.right = width
        if self.rect.left < 0:
            self.rect.left = 0


# Class for defining mob attributes
class Mob(pygame.sprite.Sprite):
    def __init__(self):
        excludes = ['myship.png', 'myship2.png']
        pygame.sprite.Sprite.__init__(self)
        ships = os.listdir(f'{imgdir}/ships')
        enemy_ships = []
        for ship in ships:
            if ship not in excludes:
                enemy_ships.append(pygame.image.load(os.path.join(f'{imgdir}/ships', ship)))

        self.image_orig = pygame.transform.scale(rnd.choice(enemy_ships), (rnd.randint(20, 40), rnd.randint(20, 40)))
        self.image_orig.set_colorkey(black)
        self.image = self.image_orig.copy()
        self.rect = self.image.get_rect()
        self.radius = int(self.rect.width * .80 / 2)
        self.rect.x = rnd.randrange(width - self.rect.width)
        self.rect.y = rnd.randrange(-100, -40)
        self.speedy = rnd.randrange(1, 5)
        self.speedx = rnd.randrange(-3, 3)
        # Can use this to rorate objects
        self.rot = 0
        self.rot_speed = rnd.randrange(-8, 8)
        self.last_update = pygame.time.get_ticks()

    # Creates mobs
    def newmob(self, mob_sprites):
        mob = self
        mob_sprites.add(mob)

    # Update mob movement and placement
    def update(self):
        self.rect.x += self.speedx
        self.rect.y += self.speedy
        if self.rect.top > height + 10 or self.rect.left < -25 or self.rect.right > width + 25:
            self.rect.x = rnd.randrange(width - self.rect.width)
            self.rect.y = rnd.randrange(-100, -40)
            self.speedy = rnd.randrange(1, 8)
            self.speedx = rnd.randrange(-3, 3)


# Class for the powerups
class PowerUps(pygame.sprite.Sprite):
    def __init__(self, center):
        pygame.sprite.Sprite.__init__(self)
        self.type = rnd.choice(['shield_img', 'full_life_img', 'partial_life_img'])
        self.image = power_imgs[self.type]
        self.image.set_colorkey(black)
        self.rect = self.image.get_rect()
        self.rect.center = center
        self.speedy = 2

    def update(self):
        self.rect.y += self.speedy
        # Kill it if it moves off the bottom of the screen
        if self.rect.top > height:
            self.kill()


# Class for handling writing to the scores.txt file and also reads
# the file for displaying the scores on the title screen
class Scores:
    def __init__(self):

        # Set the text file for writing scores
        self.score_file = 'scores.txt'

    # Write scores and name to text file
    # If the file contains more than 25 lines, the lowest score is deleted.
    def write_score(self, name, score):
        with open(self.score_file, 'a')as data:
            data.write(f'{name[0:3]}:{score}\n')
        self.get_scores(25)

    # Display scores
    def get_scores(self, howmany):
        mydict = {}
        with open(self.score_file, 'r') as lines:
            for line in lines:
                line = line.split(':')
                mydict[int(line[1].strip())] = line[0].strip()
        sorted_dict = sorted(mydict.items(), reverse=True)
        while len(sorted_dict) > howmany:
            sorted_dict.pop()
        return sorted_dict

    # Check if file exists. If not create it.
    def check_for_score_file(self):
        if os.path.isfile(self.score_file):
            pass
        else:
            with open(self.score_file, 'w') as scores:
                pass

    # tkinter form for getting player intials
    def form(self, score):
        self.root = tk.Tk()
        self.root.geometry('347x124')
        self.root.resizable(width=False, height=False)
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)

        img = tk.PhotoImage(file='images/backgrounds/bg2b.png')
        img.img = img
        imlabel = tk.Label(self.root, image=img)
        imlabel.pack(expand=1, fill='both')

        self.entry = tk.Entry(imlabel)
        self.entry.focus()
        self.entry['bg'] = '#555'
        self.entry['fg'] = 'whitesmoke'
        self.entry.place(x=140, y=8)

        btn = tk.Button(imlabel, text='Submit')
        btn['fg'] = '#fff'
        btn['bg'] = '#111'
        btn['activebackground'] = '#222'
        btn['activeforeground'] = 'tomato'
        btn['cursor'] = 'hand2'
        btn['command'] = partial(self.callback, score)
        btn.place(x=230, y=60)

        self.root.bind('<Return>', partial(self.callback, score))
        self.root.bind('<KP_Enter>', partial(self.callback, score))

        self.root.mainloop()

    # Callback for writing initials and score to text file
    def callback(self, score, event=None):
        name = self.entry.get()
        self.write_score(name, score)
        self.root.destroy()


# Class for defining all the sprite collisions
class Hit:
    def __init__(self):
        pass

    # define the method
    def hit(self, kwargs):
        # Change kwargs to simple name variables
        player = kwargs['player']
        shield = kwargs['shield']
        shield_sprites = kwargs['shield_sprites']
        bullet_sprites = kwargs['bullet_sprites']
        player_sprites = kwargs['player_sprites']
        mob_sprites = kwargs['mob_sprites']
        score = kwargs['score']
        power_sprites = kwargs['power_sprites']
        explosion_sprites = kwargs['explosion_sprites']


        # Mob hits player
        # Set to false so player does not die in one hit
        # If player life reaches zero, destroy the ship
        ship_destroy = False
        if player.life <= 0:
            ship_destroy = True

        # Get all the sprite collisions and loop through for needed information
        player_hits = pygame.sprite.groupcollide(mob_sprites, player_sprites, True, ship_destroy)
        for hit in player_hits:
            # Play the explosion sound and image files
            player_hit.play()
            explosion = Explosion(hit.rect.center, 'sm')
            explosion_sprites.add(explosion)

            # Create a new mob to replace the one destroyed
            mob = Mob()
            mob.newmob(mob_sprites)
            mob_sprites.add(mob)

            # Player was destroyed, play sound and animation files
            # Hide the player for a momment, subtract one life
            # Restore life bar to full
            player.life -= hit.radius
            if player.life <= 0:
                player_die.play()
                global death_explosion
                death_explosion = Explosion(hit.rect.center, 'player')
                explosion_sprites.add(death_explosion)
                player.hide()
                player. lives -= 1
                player.life = 100

        # Player shoots mob
        # Same as above. Get loop through sprite information
        # Player the sound and animation files
        # Add score to player for destroyed mobs
        # Replace destroyed mobs
        hits = pygame.sprite.groupcollide(mob_sprites, bullet_sprites, True, True)

        for hit in hits:
            enemy_explode.play()
            enemy_explosion = Explosion(hit.rect.center, 'lg')
            explosion_sprites.add(enemy_explosion)

            score += (20 - hit.radius)
            mob = Mob()
            mob.newmob(mob_sprites)
            mob_sprites.add(mob)

            # Random drop of power icons
            if rnd.random() > 0.9:
                power = PowerUps(hit.rect.center)
                power_sprites.add(power)

        # Power icons fall and hit player
        # Same as above.
        powerhits = pygame.sprite.spritecollide(player, power_sprites, True)
        for hit in powerhits:
            # If the shield hits player, give the shield
            if hit.type == 'shield_img':
                shield_up.play()
                shield.strength = 100
                shield.hidden = False
                shield.raise_shield(player.rect.centerx, player.rect.top, shield_sprites)
            # If partial life icon hits player, restore part of player life
            # based on mob size. If the player has full life, it's added to
            # the score instead
            elif hit.type == 'partial_life_img':
                partial_heal.play()
                if player.life == 100:
                    score += player.life * 0.25
                else:
                    player.life += player.life * 0.25
                    if player.life > 100:
                        player.life = 100

            # Sames as the partial life but restores full life instead
            # and gives 50 points to player score
            elif hit.type == 'full_life_img':
                full_heal.play()
                if player.life == 100:
                    score += 50
                else:
                    player.life = 100

        # Mob hits shield
        # Same as above, collects the sprite collision information
        # Plays the sound and animation files
        shield_hits = pygame.sprite.groupcollide(mob_sprites, shield_sprites, True, False)
        for hit in shield_hits:
            player_hit.play()
            explosion = Explosion(hit.rect.center, 'sm')
            explosion_sprites.add(explosion)

            # Create new mob to replace the one destroyed
            mob = Mob()
            mob.newmob(mob_sprites)
            mob_sprites.add(mob)
            # Subtract from the shield. If it reaches zero, hide and destroy
            shield.strength -= 20
            if shield.strength <= 0:
                shield.strength = 0
                shield.hidden = True
        # Return the score for displaying on the screen
        return round(score)

# Define the main program
def main():
    # Initialize the Display class and set some variables
    status = Display()
    game_over = True
    running = True
    while running:
        # Not playing the game, stay on the title screen
        # Reset the score to zero
        if game_over:
            status.title_screen()
            game_over = False

            score = 0

            # Initialize player and shield sprite groups
            # Initialize player and shield class
            player_sprites = pygame.sprite.Group()
            player = Player()
            player_sprites.add(player)
            shield_sprites = pygame.sprite.Group()
            shield = Shield()
            # Initialize the rest of the sprite groups
            power_sprites = pygame.sprite.Group()
            mob_sprites = pygame.sprite.Group()
            bullet_sprites = pygame.sprite.Group()
            explosion_sprites = pygame.sprite.Group()

            # Put the mobs on the screen
            for i in range(how_many_enemy_ships):
                mob = Mob()
                mob.newmob(mob_sprites)
                mob_sprites.add(mob)
        # Try except to prevent the console error when exiting game
        try:
            # Loop through pygame events
            for event in pygame.event.get():
                # Exit game
                if event.type == pygame.QUIT:
                    running = False
                # Spacebar pressed, play game
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        player.shoot(bullet_sprites)
        except pygame.error:
            break


        # Set some dict variables needed in the Hits class
        kwargs = {}
        kwargs['player'] = player
        kwargs['shield'] = shield
        kwargs['player_sprites'] = player_sprites
        kwargs['mob'] = mob
        kwargs['bullet_sprites'] = bullet_sprites
        kwargs['mob_sprites'] = mob_sprites
        kwargs['power_sprites'] = power_sprites
        kwargs['shield_sprites'] = shield_sprites
        kwargs['explosion_sprites'] = explosion_sprites
        kwargs['score'] = score

        # Initialize the Hit class. Put in a variable to get the score
        # for display
        score = Hit().hit(kwargs)

        # Update all sprites
        player_sprites.update()
        mob_sprites.update()
        shield_sprites.update()
        bullet_sprites.update()
        power_sprites.update()
        explosion_sprites.update()

        # Player lost last life, write score to text file
        if player.lives == 0 and not death_explosion.alive():
            game_over = True
            write_score = Scores()
            write_score.form(score)

        # Fill the pygame screen background with color and image
        screen.fill(black)
        screen.blit(background, background_rect)

        # Draw all sprites to the screen
        player_sprites.draw(screen)
        mob_sprites.draw(screen)
        shield_sprites.draw(screen)
        bullet_sprites.draw(screen)
        power_sprites.draw(screen)
        explosion_sprites.draw(screen)

        # Draw all bars and text to the screen
        draw_text(screen, 18, 15, f'Life', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
        status.status_bar(screen, 90, 15, player.life)

        draw_text(screen, 18, 45, f'Shield', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
        status.status_bar(screen, 90, 45, shield.strength)

        draw_text(screen, width/2-20, 15, f'Score: {score}', palewhite, 20, 'comic.ttf', freetype.STYLE_NORMAL)
        status.lives_bar(screen, width - 95, 15, player.lives, mini_img)

        pygame.display.flip()
        clock.tick(fps)

if __name__ == '__main__':
    main()
BashBedlam likes this post
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#2
To get it to work on a linux system, I changed

# Set the path for the image, music and sound directories
imgdir = os.path.join(os.path.dirname(__file__), 'images')
snddir = os.path.join(os.path.dirname(__file__), 'sounds')
musicdir = os.path.join(os.path.dirname(__file__), 'music')
to...

# Set the path for the image, music and sound directories
current_working_directory = os.getcwd ()
imgdir = f'{current_working_directory}/images'
snddir = f'{current_working_directory}/sounds'
musicdir = f'{current_working_directory}/music'
and explosions in player_explosion all started with a capital E so I changed

    filename = f'explosion_{i}.png'
    img = pygame.image.load(os.path.join(f'{imgdir}/animation/player_explosion', filename))
to...

    filename = f'Explosion_{i}.png'
    img = pygame.image.load(os.path.join(f'{imgdir}/animation/player_explosion', filename))
Now it all works on my system (ubuntu) and I must say that I am VERY impressed! Nice Job!
menator01 likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Shmup version 0.02 menator01 0 813 Oct-29-2023, 01:20 PM
Last Post: menator01

Forum Jump:

User Panel Messages

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