0
\$\begingroup\$

Just wanted a few opinions on whether this game's code is efficient, from looking at it, it does look a bit all over the place but I just don't know how to 'tidy' it up to say so. Would love to hear your opinions and even better if you could show me how it's done.

#Here i am importing all necessary modules
import math,random,pygame,sys

#This class's purpose is to keep track of the current score
class Game():
        def __init__(self): #This is the class constructor
                self.score=0
                self.goalNumbers=0

#This is the gun's class
class Gun(pygame.sprite.Sprite): #Sprite class from the Pygame module
        def __init__(self): #This is the class constructor
                pygame.sprite.Sprite.__init__(self)
                self.image=pygame.image.load("turret.png") #Loading the gun's image
                self.rect = self.image.get_rect() #Getting the image's Rect
                self.rect.x = 240 #Setting the rect's X position
                self.rect.y = 630 #Setting the rect's Y position

        #This function allows the gun to move
        def moveGun(self,orientation):
                if orientation=="left" and self.rect.x>5: 
                        self.rect.x-=5
                if orientation=="right" and self.rect.x<(480-self.rect.width):
                        self.rect.x+=5


# Set up class for bullets

class Projectile(pygame.sprite.Sprite):
        def __init__(self,gun):
                pygame.sprite.Sprite.__init__(self)
                self.image=pygame.image.load("bullet.png")
                self.rect=self.image.get_rect()
                self.rect.x=gun.rect.x+(gun.rect.width/2)-(self.rect.width/2)
                self.rect.y=gun.rect.y-gun.rect.height

# Set up method to move bullets up the screen

        def updateProjectile(self):
                if self.rect.y>0-self.rect.height:
                        self.rect.y-=5
                else:
                        self.kill()


# Set up class for fruit

class Objects(pygame.sprite.Sprite):
        def __init__(self):
                pygame.sprite.Sprite.__init__(self)
                self.obj=random.randint(1,3) 
                if self.obj==1: imagefile="raspberry"
                if self.obj==2: imagefile="strawberry"
                if self.obj==3: imagefile="cherry"
                self.image=pygame.image.load(imagefile+".png")
                self.image=pygame.transform.rotate(self.image,-15+random.randint(0,20))
                self.rect=self.image.get_rect()
                self.rect.y=-0-self.rect.height
                self.rect.x=(random.randint(2,44)*10)


# Set up method to enable fruit to fall down the screen

        def updateProjectile(self,game):
                if self.rect.y<640:
                        self.rect.y+=3
                else:
                        if self.obj==1:
                                game.score+=10
                                game.goalNumbers+=1 
                        else:
                                game.score-=50
                        self.kill()

# Set up method to update score and remove fruit when shot

        def shot(self,game):
                if self.obj == 1:
                        game.score-=50
                else:
                        game.score+=10
                self.kill()


# Initialise the game

pygame.init()
pygame.key.set_repeat(1, 20)
countFont = pygame.font.Font(None,18)
statusFont = pygame.font.Font(None,18)
bColour = (52, 152, 219)
screen = pygame.display.set_mode([480, 640])
pygame.display.set_caption(' Game')


# Create initial object instances

game=Game()
gun=Gun()
sprites=pygame.sprite.Group()
sprites.add(gun)
obstacles=pygame.sprite.Group()
projectiles=pygame.sprite.Group()


# Initialise game over flag and timer

end_game=False
clock=pygame.time.Clock()
tick=0


# Main loop starts here

while end_game!=True:
        clock.tick(30) 
        tick+=1
        screen.fill(bColour)


# Process events

        for event in pygame.event.get():
                if event.type==pygame.QUIT:
                        sys.exit
                if event.type==pygame.KEYDOWN:
                        if event.key==pygame.K_LEFT:
                                gun.moveGun("left")
                        if event.key==pygame.K_RIGHT:
                                gun.moveGun("right")
                        if event.key==pygame.K_SPACE:
                                projectile=Projectile(gun)
                                projectiles.add(projectile)


# Move objects

        for projectile in projectiles:
                projectile.updateProjectile()

        for obstacle in obstacles:
                obstacle.updateProjectile(game)


# Add new fruit if 2 seconds has elapsed

        if tick>60: 
                if len(obstacles)<10:
                        obstacle=Objects()
                        obstacles.add(obstacle)
                tick=0


# Check for collisions

        collisions=pygame.sprite.groupcollide(obstacles,projectiles,False,True)
        if collisions: 
                for obstacle in collisions:
                        obstacle.shot(game)

# Update player score

        scoreText=countFont.render('Score:'+str(game.score),True,(255,255,255),(52, 152, 219))
        screen.blit(scoreText,(0,620))
        statusText=statusFont.render('Raspberries:'+str(10-game.goalNumbers),True,(255,210,210),(52, 152, 219))
        screen.blit(statusText,(0,10))


# Update the screen and check for game over

        sprites.draw(screen); projectiles.draw(screen); obstacles.draw(screen)
        pygame.display.flip()
        if game.goalNumbers>=10: 
                end_game=True


# Game over: display the player's final score

scoreCountHolder=pygame.image.load("scoreframe.png")
scoreCountHolder.convert_alpha()
left=90;top=250
screen.blit(scoreCountHolder,(left,top))
countFont=pygame.font.Font(None,52)
statusText=countFont.render('Your Score:'+str(game.score),True,(52, 152, 219),(231,230,33))
screen.blit(statusText,(105,300))
pygame.display.flip() 

# Wait for the player to close the game window

while True: 
        for event in pygame.event.get():
                if event.type==pygame.QUIT:
                        sys.exit()
\$\endgroup\$
1
\$\begingroup\$

I can't really comment on the performance since I found it difficult to read, especially the spaces around the operators throughout the code.

As you mention though, I would focus first on cleanup and applying PEP 8. There are many issues with spacing around operations, spacing between/after definitions, line length, etc. That would help with the readability.

The other part that seems difficult is the "main" logic near the bottom. It is good convention to place that in a "main" function and then use the "if main" at the bottom. So you would have somethning like this:

def main():
    pygame.init()
    pygame.key.set_repeat(1, 20)
    countFont = pygame.font.Font(None, 18)
    statusFont = pygame.font.Font(None, 18)
    bColour = (52, 152, 219)
    ...

if __name__ == '__main__':
    main()

Once you have that you can look to see if any of the parts in "main" need to be broken out into functions.

On the PEP 8 side, here is an example of some of your code with Pep 8 type formatting applied so you can see the difference in how it visually looks.

""" Pygame - Shooting fruit game. """
import random
import sys
import pygame


class Game():
    """ The Game class's purpose is to keep track of the current score. """
    def __init__(self):
        self.score = 0
        self.goalNumbers = 0


class Gun(pygame.sprite.Sprite):
    """ This is the gun that the user moves to shoot the fruit. """
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("turret.png")
        self.rect = self.image.get_rect()
        self.rect.x = 240
        self.rect.y = 630

    def moveGun(self, orientation):
        """ Move the gun on the screen. """
        if orientation == "left" and self.rect.x > 5:
            self.rect.x -= 5
        if orientation == "right" and self.rect.x < (480 - self.rect.width):
            self.rect.x += 5


class Projectile(pygame.sprite.Sprite):
    """ This is for the bullets. """
    def __init__(self, gun):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("bullet.png")
        self.rect = self.image.get_rect()
        self.rect.x = gun.rect.x + (gun.rect.width / 2) - (self.rect.width / 2)
        self.rect.y = gun.rect.y - gun.rect.height

    def updateProjectile(self):
        """ Move bullets up the screen. """
        if self.rect.y > 0 - self.rect.height:
            self.rect.y -= 5
        else:
            self.kill()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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