1
\$\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()
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 17, 2014 at 19:57
\$\endgroup\$

1 Answer 1

2
\$\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()
answered May 17, 2014 at 21:20
\$\endgroup\$

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.