#importing necessary features import pygame import sys from pygame.locals import * import random global won won=False global alive alive=True #global variables, temporary colours for sprites #will not be needed once designs are in place PINK=(255,77,151) PURPLE=(122, 52, 235) GREEN=(79, 235, 52) WHITE=(255,255,255) RED=(255,0,0) BLACK=(0,0,0) boss_no=[1] frame_count=0 frame_rate=60 start_time=120 #drawing lives function def draw_lives(surf, x, y, lives, img): for i in range(lives): img_rect = img.get_rect() img_rect.x = x + 40 * i img_rect.y = y surf.blit(img, img_rect) #player class class Player(pygame.sprite.Sprite): #set as sprite def __init__(self): super().__init__() #setting features like size, colour and spawn point self.image = pygame.image.load("canon.png") self.image = pygame.transform.scale(self.image, [90,120]) #will end up being the canon image self.rect = self.image.get_rect() self.rect.center =(170, 570) self.lives = 5 g_player.add(self) #adds class to group for the player #is used to make instances and for collision functions def moveLeft(self, pixels): #function for moving left self.rect.x -= pixels #x coordinate is reduced if self.rect.x < -3: #if the x coordinate is the left border... self.rect.x = -3 #player cannot move any further def moveRight(self, pixels): #function for moving right self.rect.x += pixels #x coordinate is increased if self.rect.x > 275: #if the x coordinate is the right border... self.rect.x = 275 #player cannot move any further def shoot(self): if not player.image==pygame.image.load("cool down.png"): bullet = Bullet(self.rect.centerx, self.rect.top) g_bullet.add(bullet) else: print("hot") #bullet sprite class Bullet(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("bullet.png") self.image = pygame.transform.scale(self.image, [20,60]) self.rect = self.image.get_rect() self.rect.bottom = y self.rect.centerx = x self.speedy = -10#speed variable def update(self): self.rect.y += self.speedy # kill if it moves off the top of the screen if self.rect.bottom < 0: self.kill() #if the bullet hits an enemy the bullet also disapears off screen def die(self): if pygame.sprite.spritecollide(self, g_enemies, True): print("boom") self.kill() #base class class Base(pygame.sprite.Sprite):#set as sprite def __init__(self): super().__init__() #setting features like size and spawn point self.image = pygame.image.load("base.png") self.image = pygame.transform.scale(self.image, [360,110]) #imports image design and scales it for the sprite self.rect = self.image.get_rect() self.rect.center = (180, 590) g_base.add(self)#adds class to group for the base #is used to make instances and for collision functions #singular class for the multiple enemies class enemies(pygame.sprite.Sprite): def __init__(self, type): super().__init__() #default features for the sprite self.image = pygame.image.load("enemy.png") self.image = pygame.transform.scale(self.image, [70,60]) self.rect = self.image.get_rect() self.type = type self.rect.x=random.randint(35, 320) self.rect.y=random.randint(-300, -10) #adds the sprite to a group for both kinds of enemies g_enemies.add(self) #the attributes of a regular enemy sprite #this is assigned to the object if it's type is declared as "enemy"... #...when it is initialised if self.type=="enemy": self.image = pygame.image.load("enemy.png") self.image = pygame.transform.scale(self.image, [70,60]) self.rect = self.image.get_rect() self.rect.y = random.randint(-300, -10) self.rect.x= random.randint(35, 320) #attributes of a superenemy #assigns to those declared as "s_enemy" when initialised if self.type=="s_enemy": self.image = pygame.image.load("s_enemy.png") self.image = pygame.transform.scale(self.image, [70,60]) self.rect = self.image.get_rect() self.rect.y = random.randint(-300, -10) self.rect.x= random.randint(35, 320) #methods for both kinds of sprites... #may differ if condition is given for type def resetpos(self):#method for respawning offscreen self.rect.y = random.randint(-300, -10) self.rect.x= random.randint(35, 320) def update(self):#method for moving downscreen if self.type=="enemy":#differing rate of pixel movement for different enemy types self.rect.y+=1 if self.type=="s_enemy": self.rect.y+=2 def collide(self):#method for if any enemy collides with the base if pygame.sprite.spritecollide(self, g_base, False): self.resetpos()#calls respawn method player.lives-=1#player removes lives print(player.lives)#validation for lives counter def been_shot(self, bullet):#method for if any enemy is shot if pygame.sprite.spritecollide(self, g_bullet, False): print("HIT")#validation for if above condition is true self.resetpos()#calls respawn method g_bullet.empty() def overlap(self):#function to reduce enemies from overlapping for i in g_sEnemy: if i.rect.y<0:#checks if the harder enemy is off screen if pygame.sprite.spritecollide(i, g_enemy, False):#checks if its touching a regular enemy i.resetpos() for i in g_enemy:#does the same as above visa versa if i.rect.y<0: if pygame.sprite.spritecollide(i, g_sEnemy, False): i.resetpos() class Boss(pygame.sprite.Sprite): def __init__(self): super().__init__() #sets all the necessary features of the boss self.image = pygame.image.load("boss3.png") self.image = pygame.transform.scale(self.image, [130,110]) self.rect = self.image.get_rect() self.rect.y = -9 self.rect.x=90 self.hits=9#highest number of hits for the hardest level g_boss.add(self)#adds it to the boss group def update(self):#function to float down self.rect.y+=1 def random_move(self):#function to randomly change position... #... where the x and y coordinates are selected as random self.rect.x=random.randint(30, 50) self.rect.y=random.randint(40, 300) self.update() def b_hit(self):#function for managing boss's hits if pygame.sprite.spritecollide(self, g_bullet, False) and self.hits!=0: #if a boss is hit... self.hits-=1#...a hit is deducted... self.random_move()#...and it moves randomly if self.hits==0:#if the boss's hits reaches 0... global won won=True#... won boolean is set to true def game_over(self):#function for if the boss hits the base if pygame.sprite.spritecollide(self, g_base, False): #^if the boss and base collide... global alive alive=False#...alive bool is set to false pygame.init() #sets the size of the screen screen = pygame.display.set_mode([360, 640]) clock=pygame.time.Clock() #sets variable for background image and scales it to fit ratio background_image = pygame.image.load("level3_bg.png") background_image = pygame.transform.scale(background_image, [360,640]) #creates an image variable to show the lives and scales it like the background lives_img=pygame.image.load("lives.png") lives_img = pygame.transform.scale(lives_img, [40,40]) timerbg=pygame.image.load("timer safe.png") timerbg=pygame.transform.scale(timerbg, [130,30]) #creates the groups for the sprites g_enemy=pygame.sprite.Group() g_sEnemy=pygame.sprite.Group() g_enemies=pygame.sprite.Group() g_base=pygame.sprite.Group() g_player=pygame.sprite.Group() g_bullet=pygame.sprite.Group() g_lives=pygame.sprite.Group() g_boss=pygame.sprite.Group() #creates instances of the classes to be used in the main game loop player=Player() base=Base() bullet=Bullet(x=1,y=1) #initialises eight enemies in total so that the dificulty has grown from level 2 for e in range (4): enemy=enemies(type="enemy") g_enemies.add(enemy)#also adds them to the necessary groups g_enemy.add(enemy) for s in range(4): superenemy=enemies(type="s_enemy") g_enemies.add(superenemy) g_sEnemy.add(superenemy) if pygame.sprite.spritecollideany(enemy, g_enemies): enemy.resetpos() cantshoot=False done = False #creates condition for main game loop import time start = time.time() #main game loop while done==False: clock.tick(60) #sets the games frame rate #screen.blit(text, textRect) for event in pygame.event.get(): if event.type == pygame.QUIT: done==True sys.exit() #the game closes if pygame is closed space = pygame.key.get_pressed() shot = space[pygame.K_SPACE] if cantshoot==False: if event.type == pygame.KEYDOWN: if event.key==pygame.K_SPACE: player.shoot() print("shot") else: print("too hot") if len(g_bullet)>5:#five bullets are on screen... player.image = pygame.image.load("cool down.png")#... image changes player.image = pygame.transform.scale(player.image, [90,120]) cantshoot=True#can't shoot bool is set to true, shoot function no longer works #checks the time since last shot if cantshoot==True: new_time = time.time() if new_time - start >=3:#if it is 3 seconds turns can't shoot bool false cantshoot=False start=new_time mx, my = pygame.mouse.get_pos() pygame.init() keys = pygame.key.get_pressed()#gets the keys of the keypad if keys[pygame.K_LEFT]:#if the left key is pressed player.moveLeft(5)#moveLeft is called where pixels=5 pixels on the screen if keys[pygame.K_RIGHT]:#if the right key is pressed player.moveRight(5)#moveRight is called where pixels=5 pixels on the screen #calls necessary functions that need to be checked throughout the game for c in g_enemies: c.collide() for s in g_enemies: s.been_shot() for r in g_enemies: r.overlap() total_seconds = start_time - (frame_count // frame_rate) if total_seconds < 0: total_seconds = 0 #creates variables to store time total_seconds = start_time - (frame_count // frame_rate) if total_seconds < 0: total_seconds = 0 #divides by 60 to get total minutes minutes = total_seconds // 60 #uses modulus (division to get seconds seconds = total_seconds % 60 #uses python string formatting to get time output_string = "Time left: {0:02}:{1:02}".format(minutes, seconds) #blits to the screen sysfont = pygame.font.get_default_font() font = pygame.font.SysFont(None, 48) font1 = pygame.font.SysFont('chalkduster.ttf', 25) img1 = font1.render(output_string, True, WHITE) frame_count += 1 g_base.update() g_player.update() g_bullet.update() g_lives.update() g_enemies.update() g_boss.update() #adds background to screen with sprites drawn on top of the background screen.blit(background_image, [0, 0]) screen.blit(timerbg, [225, 7]) screen.blit(img1, [226, 14]) g_base.draw(screen) g_player.draw(screen) g_bullet.draw(screen) g_lives.draw(screen) g_enemies.draw(screen) g_boss.draw(screen) #initializes lives draw_lives(screen, 10, 5, player.lives, lives_img) #if statement for the boss to be spawned. Makes sure only one boss is spawned if minutes==0 and seconds==0 and len(g_boss)<1 and won==False: boss=Boss() #more necessary functions for b in g_boss: b.b_hit() if player.lives==0: alive=False for d in g_boss: d.game_over() #same circular import technicalities as before... if alive==False: #^... if the player has lost.. import gameover old = gameover import gameover new = gameover assert old is new import gameover old = gameover del sys.modules['gameover'] import gameover new=gameover#... they'll be taken to the game over page if won==True: #^... and if the player has won g_boss.empty() import finished old = finished import finished new = finished assert old is new import finished old = finished del sys.modules['finished'] import finished new=finished assert not old is new#... they'll be taken to the level transition page pygame.display.flip() pygame.display.update() pygame.quit()