Article catalog
Classic aircraft battle
The source code and material materials (pictures and audio) can be downloaded from the following github:
----------------------------—
I don't know if you've ever flown. Do you like flying. When I first touched this thing, my heart was shocked. The first time I was in touch with the author, I was physically and mentally happy, because the friends around me were flying, and they would subconsciously compete with each other every time to see who played better. It also needs some skills to fight the plane. A skilled friend can fight for half an hour, while a stranger can lose in 35 minutes.
1, Game settings
The game interface is shown in the figure below
Basic settings of the game:
- The enemy has three types of aircraft, large, medium and small, which are divided into three speeds: high, medium and low;
- The range of the bullet is not full screen, but about 80% of the screen length;
- It takes one bullet to kill a small plane, eight for a medium plane and 20 for a large plane;
- 1000 points for each small aircraft eliminated, 6000 points for medium aircraft and 10000 points for large aircraft;
- Every 30 seconds there is a random props supply, divided into two props, full screen bombs and double bullets;
- Full screen bombs can only store up to three, double bullets can maintain the effect of 18 seconds;
- The game will gradually increase the difficulty according to the score, and the increase of the difficulty is reflected in the increase of the number of aircraft and the acceleration of the speed.
In addition, some improvements have been made to the game, such as adding a blood tank display for medium and large airplanes, so that players can intuitively know whether the enemy aircraft is about to be eliminated; we have three opportunities, each time the enemy destroys, the newly born aircraft will have a three second security period; after the end of the game, the highest score in history will be displayed.
This game and the basic comment code amount in about 800 lines, the code looks more, mainly because the author pursues the development principle of "more code and less brain". So don't be afraid. The more code you have, the easier it will be to see the logic clearly, and the better you will learn. Well, let's build this game from scratch, from simple to complex!
2, Our plane
First, create a myplane. py module to define our aircraft:
import pygame class MyPlane(pygame.sprite.Sprite): def __init__(self, bg_size): pygame.sprite.Sprite.__init__(self) self.image1 = pygame.image.load("images/me1.png").convert_alpha() self.image2 = pygame.image.load("images/me2.png").convert_alpha() self.destroy_images = [] self.destroy_images.extend([\ pygame.image.load("images/me_destroy_1.png").convert_alpha(), \ pygame.image.load("images/me_destroy_2.png").convert_alpha(), \ pygame.image.load("images/me_destroy_3.png").convert_alpha(), \ pygame.image.load("images/me_destroy_4.png").convert_alpha() \ ]) self.rect = self.image1.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.rect.left, self.rect.top = \ (self.width - self.rect.width) // 2, \ self.height - self.rect.height - 60 self.speed = 10 self.active = True self.invincible = False self.mask = pygame.mask.from_surface(self.image1) # Define moveUp(), moveDown(), moveLeft() and moveRight() respectively to control the up, down, left and right movements of our aircraft: def moveUp(self): if self.rect.top > 0: self.rect.top -= self.speed else: self.rect.top = 0 def moveDown(self): if self.rect.bottom < self.height - 60: self.rect.top += self.speed else: self.rect.bottom = self.height - 60 def moveLeft(self): if self.rect.left > 0: self.rect.left -= self.speed else: self.rect.left = 0 def moveRight(self): if self.rect.right < self.width: self.rect.left += self.speed else: self.rect.right = self.width def reset(self): self.rect.left, self.rect.top = \ (self.width - self.rect.width) // 2, \ self.height - self.rect.height - 60 self.active = True self.invincible = True
3, Enemy aircraft
Now that heroes have been created, it's time to create enemies. The enemy planes are divided into three sizes: small, medium and large. Their speed is fast, medium and slow in turn. Creating random enemy planes at the top of the game interface can make them not appear in the same row. Write the definition of enemy aircraft in the enemy. py module:
import pygame from random import * class SmallEnemy(pygame.sprite.Sprite): def __init__(self, bg_size): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("images/enemy1.png").convert_alpha() self.destroy_images = [] self.destroy_images.extend([ \ pygame.image.load("images/enemy1_down1.png").convert_alpha(), \ pygame.image.load("images/enemy1_down2.png").convert_alpha(), \ pygame.image.load("images/enemy1_down3.png").convert_alpha(), \ pygame.image.load("images/enemy1_down4.png").convert_alpha() \ ]) self.rect = self.image.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.speed = 2 self.active = True self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-5 * self.height, 0) self.mask = pygame.mask.from_surface(self.image) def move(self): if self.rect.top < self.height: self.rect.top += self.speed else: self.reset() def reset(self): self.active = True self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-5 * self.height, 0) class MidEnemy(pygame.sprite.Sprite): energy = 8 def __init__(self, bg_size): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("images/enemy2.png").convert_alpha() self.image_hit = pygame.image.load("images/enemy2_hit.png").convert_alpha() self.destroy_images = [] self.destroy_images.extend([ \ pygame.image.load("images/enemy2_down1.png").convert_alpha(), \ pygame.image.load("images/enemy2_down2.png").convert_alpha(), \ pygame.image.load("images/enemy2_down3.png").convert_alpha(), \ pygame.image.load("images/enemy2_down4.png").convert_alpha() \ ]) self.rect = self.image.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.speed = 1 self.active = True self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-10 * self.height, -self.height) self.mask = pygame.mask.from_surface(self.image) self.energy = MidEnemy.energy self.hit = False def move(self): if self.rect.top < self.height: self.rect.top += self.speed else: self.reset() def reset(self): self.active = True self.energy = MidEnemy.energy self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-10 * self.height, -self.height) class BigEnemy(pygame.sprite.Sprite): energy = 20 def __init__(self, bg_size): pygame.sprite.Sprite.__init__(self) self.image1 = pygame.image.load("images/enemy3_n1.png").convert_alpha() self.image2 = pygame.image.load("images/enemy3_n2.png").convert_alpha() self.image_hit = pygame.image.load("images/enemy3_hit.png").convert_alpha() self.destroy_images = [] self.destroy_images.extend([ \ pygame.image.load("images/enemy3_down1.png").convert_alpha(), \ pygame.image.load("images/enemy3_down2.png").convert_alpha(), \ pygame.image.load("images/enemy3_down3.png").convert_alpha(), \ pygame.image.load("images/enemy3_down4.png").convert_alpha(), \ pygame.image.load("images/enemy3_down5.png").convert_alpha(), \ pygame.image.load("images/enemy3_down6.png").convert_alpha() \ ]) self.rect = self.image1.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.speed = 1 self.active = True self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-15 * self.height, -5 * self.height) self.mask = pygame.mask.from_surface(self.image1) self.energy = BigEnemy.energy self.hit = False def move(self): if self.rect.top < self.height: self.rect.top += self.speed else: self.reset() def reset(self): self.active = True self.energy = BigEnemy.energy self.rect.left, self.rect.top = \ randint(0, self.width - self.rect.width), \ randint(-15 * self.height, -5 * self.height)
4, To fire a bullet
The current situation is that our plane is in a state of backwardness and being attacked. The enemy is strong and weak, so we should take up arms to fight back! Next, we define bullets, which are divided into two types: one is that ordinary bullets can only fire one at a time; the other is that the super bullets issued by supply can fire two at a time.
We define bullets as separate modules bullet.py :
import pygame class Bullet1(pygame.sprite.Sprite): def __init__(self, position): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("images/bullet1.png").convert_alpha() self.rect = self.image.get_rect() self.rect.left, self.rect.top = position self.speed = 12 self.active = False self.mask = pygame.mask.from_surface(self.image) def move(self): self.rect.top -= self.speed if self.rect.top < 0: self.active = False def reset(self, position): self.rect.left, self.rect.top = position self.active = True class Bullet2(pygame.sprite.Sprite): def __init__(self, position): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("images/bullet2.png").convert_alpha() self.rect = self.image.get_rect() self.rect.left, self.rect.top = position self.speed = 14 self.active = False self.mask = pygame.mask.from_surface(self.image) def move(self): self.rect.top -= self.speed if self.rect.top < 0: self.active = False def reset(self, position): self.rect.left, self.rect.top = position self.active = True
5, Issue supply package
The game design randomly issues a supply bag every 30 seconds, which may be a super bullet or a full screen bomb. The replenishment package has its own image and motion track, so it is better to define a module for it separately supply.py :
import pygame from random import * class Bullet_Supply(pygame.sprite.Sprite): def __init__(self, bg_size): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("images/bullet_supply.png").convert_alpha() self.rect = self.image.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.rect.left, self.rect.bottom = \ randint(0, self.width - self.rect.width), -100 self.speed = 5 self.active = False self.mask = pygame.mask.from_surface(self.image) def move(self): if self.rect.top < self.height: self.rect.top += self.speed else: self.active = False def reset(self): self.active = True self.rect.left, self.rect.bottom = \ randint(0, self.width - self.rect.width), -100 class Bomb_Supply(pygame.sprite.Sprite): def __init__(self, bg_size): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("images/bomb_supply.png").convert_alpha() self.rect = self.image.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.rect.left, self.rect.bottom = \ randint(0, self.width - self.rect.width), -100 self.speed = 5 self.active = False self.mask = pygame.mask.from_surface(self.image) def move(self): if self.rect.top < self.height: self.rect.top += self.speed else: self.active = False def reset(self): self.active = True self.rect.left, self.rect.bottom = \ randint(0, self.width - self.rect.width), -100
6, Main module
All the modules are complete, and then it's time to implement our main module
# main.py import pygame import sys import traceback import myplane import enemy import bullet import supply from pygame.locals import * from random import * pygame.init() pygame.mixer.init() bg_size = width, height = 480, 700 screen = pygame.display.set_mode(bg_size) pygame.display.set_caption("Aircraft battle -- FishC Demo") background = pygame.image.load("images/background.png").convert() BLACK = (0, 0, 0) WHITE = (255, 255, 255) GREEN = (0, 255, 0) RED = (255, 0, 0) # Load game music pygame.mixer.music.load("sound/game_music.ogg") pygame.mixer.music.set_volume(0.2) bullet_sound = pygame.mixer.Sound("sound/bullet.wav") bullet_sound.set_volume(0.2) bomb_sound = pygame.mixer.Sound("sound/use_bomb.wav") bomb_sound.set_volume(0.2) supply_sound = pygame.mixer.Sound("sound/supply.wav") supply_sound.set_volume(0.2) get_bomb_sound = pygame.mixer.Sound("sound/get_bomb.wav") get_bomb_sound.set_volume(0.2) get_bullet_sound = pygame.mixer.Sound("sound/get_bullet.wav") get_bullet_sound.set_volume(0.2) upgrade_sound = pygame.mixer.Sound("sound/upgrade.wav") upgrade_sound.set_volume(0.2) enemy3_fly_sound = pygame.mixer.Sound("sound/enemy3_flying.wav") enemy3_fly_sound.set_volume(0.2) enemy1_down_sound = pygame.mixer.Sound("sound/enemy1_down.wav") enemy1_down_sound.set_volume(0.2) enemy2_down_sound = pygame.mixer.Sound("sound/enemy2_down.wav") enemy2_down_sound.set_volume(0.2) enemy3_down_sound = pygame.mixer.Sound("sound/enemy3_down.wav") enemy3_down_sound.set_volume(0.5) me_down_sound = pygame.mixer.Sound("sound/me_down.wav") me_down_sound.set_volume(0.2) def add_small_enemies(group1, group2, num): for i in range(num): e1 = enemy.SmallEnemy(bg_size) group1.add(e1) group2.add(e1) def add_mid_enemies(group1, group2, num): for i in range(num): e2 = enemy.MidEnemy(bg_size) group1.add(e2) group2.add(e2) def add_big_enemies(group1, group2, num): for i in range(num): e3 = enemy.BigEnemy(bg_size) group1.add(e3) group2.add(e3) def inc_speed(target, inc): for each in target: each.speed += inc def main(): pygame.mixer.music.play(-1) # Generate our aircraft me = myplane.MyPlane(bg_size) enemies = pygame.sprite.Group() # Generate enemy small aircraft small_enemies = pygame.sprite.Group() add_small_enemies(small_enemies, enemies, 15) # Generate enemy medium aircraft mid_enemies = pygame.sprite.Group() add_mid_enemies(mid_enemies, enemies, 4) # Generate enemy large aircraft big_enemies = pygame.sprite.Group() add_big_enemies(big_enemies, enemies, 2) # Generate normal bullets bullet1 = [] bullet1_index = 0 BULLET1_NUM = 4 for i in range(BULLET1_NUM): bullet1.append(bullet.Bullet1(me.rect.midtop)) # Generate superbullets bullet2 = [] bullet2_index = 0 BULLET2_NUM = 8 for i in range(BULLET2_NUM // 2): bullet2.append(bullet.Bullet2((me.rect.centerx - 33, me.rect.centery))) bullet2.append(bullet.Bullet2((me.rect.centerx + 30, me.rect.centery))) clock = pygame.time.Clock() # Bullet picture index e1_destroy_index = 0 e2_destroy_index = 0 e3_destroy_index = 0 me_destroy_index = 0 # Statistical score score = 0 score_font = pygame.font.Font("font/font.ttf", 36) # Flag whether to pause the game paused = False pause_nor_image = pygame.image.load("images/pause_nor.png").convert_alpha() pause_pressed_image = pygame.image.load("images/pause_pressed.png").convert_alpha() resume_nor_image = pygame.image.load("images/resume_nor.png").convert_alpha() resume_pressed_image = pygame.image.load("images/resume_pressed.png").convert_alpha() paused_rect = pause_nor_image.get_rect() paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10 paused_image = pause_nor_image # Set difficulty level level = 1 # Full screen bomb bomb_image = pygame.image.load("images/bomb.png").convert_alpha() bomb_rect = bomb_image.get_rect() bomb_font = pygame.font.Font("font/font.ttf", 48) bomb_num = 3 # One supply pack every 30 seconds bullet_supply = supply.Bullet_Supply(bg_size) bomb_supply = supply.Bomb_Supply(bg_size) SUPPLY_TIME = USEREVENT pygame.time.set_timer(SUPPLY_TIME, 30 * 1000) # Super bullet timer DOUBLE_BULLET_TIME = USEREVENT + 1 # Mark whether to use super bullet is_double_bullet = False # Remove our invincible state timer INVINCIBLE_TIME = USEREVENT + 2 # Number of lives life_image = pygame.image.load("images/life.png").convert_alpha() life_rect = life_image.get_rect() life_num = 3 # Used to prevent duplicate opening of log files recorded = False # Game ending screen gameover_font = pygame.font.Font("font/font.TTF", 48) again_image = pygame.image.load("images/again.png").convert_alpha() again_rect = again_image.get_rect() gameover_image = pygame.image.load("images/gameover.png").convert_alpha() gameover_rect = gameover_image.get_rect() # Use to switch pictures switch_image = True # For delay delay = 100 running = True while running: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == MOUSEBUTTONDOWN: if event.button == 1 and paused_rect.collidepoint(event.pos): paused = not paused if paused: pygame.time.set_timer(SUPPLY_TIME, 0) pygame.mixer.music.pause() pygame.mixer.pause() else: pygame.time.set_timer(SUPPLY_TIME, 30 * 1000) pygame.mixer.music.unpause() pygame.mixer.unpause() elif event.type == MOUSEMOTION: if paused_rect.collidepoint(event.pos): if paused: paused_image = resume_pressed_image else: paused_image = pause_pressed_image else: if paused: paused_image = resume_nor_image else: paused_image = pause_nor_image elif event.type == KEYDOWN: if event.key == K_SPACE: if bomb_num: bomb_num -= 1 bomb_sound.play() for each in enemies: if each.rect.bottom > 0: each.active = False elif event.type == SUPPLY_TIME: supply_sound.play() if choice([True, False]): bomb_supply.reset() else: bullet_supply.reset() elif event.type == DOUBLE_BULLET_TIME: is_double_bullet = False pygame.time.set_timer(DOUBLE_BULLET_TIME, 0) elif event.type == INVINCIBLE_TIME: me.invincible = False pygame.time.set_timer(INVINCIBLE_TIME, 0) # Increase difficulty according to user's score if level == 1 and score > 50000: level = 2 upgrade_sound.play() # Increase 3 small, 2 medium and 1 large enemy aircraft add_small_enemies(small_enemies, enemies, 3) add_mid_enemies(mid_enemies, enemies, 2) add_big_enemies(big_enemies, enemies, 1) # Speed up small enemy aircraft inc_speed(small_enemies, 1) elif level == 2 and score > 300000: level = 3 upgrade_sound.play() # Add 5 small, 3 medium and 2 large enemy aircraft add_small_enemies(small_enemies, enemies, 5) add_mid_enemies(mid_enemies, enemies, 3) add_big_enemies(big_enemies, enemies, 2) # Speed up small enemy aircraft inc_speed(small_enemies, 1) inc_speed(mid_enemies, 1) elif level == 3 and score > 600000: level = 4 upgrade_sound.play() # Add 5 small, 3 medium and 2 large enemy aircraft add_small_enemies(small_enemies, enemies, 5) add_mid_enemies(mid_enemies, enemies, 3) add_big_enemies(big_enemies, enemies, 2) # Speed up small enemy aircraft inc_speed(small_enemies, 1) inc_speed(mid_enemies, 1) elif level == 4 and score > 1000000: level = 5 upgrade_sound.play() # Add 5 small, 3 medium and 2 large enemy aircraft add_small_enemies(small_enemies, enemies, 5) add_mid_enemies(mid_enemies, enemies, 3) add_big_enemies(big_enemies, enemies, 2) # Speed up small enemy aircraft inc_speed(small_enemies, 1) inc_speed(mid_enemies, 1) screen.blit(background, (0, 0)) if life_num and not paused: # Detect user's keyboard operation key_pressed = pygame.key.get_pressed() if key_pressed[K_w] or key_pressed[K_UP]: me.moveUp() if key_pressed[K_s] or key_pressed[K_DOWN]: me.moveDown() if key_pressed[K_a] or key_pressed[K_LEFT]: me.moveLeft() if key_pressed[K_d] or key_pressed[K_RIGHT]: me.moveRight() # Draw full screen bomb supply and check if it is obtained if bomb_supply.active: bomb_supply.move() screen.blit(bomb_supply.image, bomb_supply.rect) if pygame.sprite.collide_mask(bomb_supply, me): get_bomb_sound.play() if bomb_num < 3: bomb_num += 1 bomb_supply.active = False # Draw super bullet supply and check if it is available if bullet_supply.active: bullet_supply.move() screen.blit(bullet_supply.image, bullet_supply.rect) if pygame.sprite.collide_mask(bullet_supply, me): get_bullet_sound.play() is_double_bullet = True pygame.time.set_timer(DOUBLE_BULLET_TIME, 18 * 1000) bullet_supply.active = False # To fire a bullet if not (delay % 10): bullet_sound.play() if is_double_bullet: bullets = bullet2 bullets[bullet2_index].reset((me.rect.centerx - 33, me.rect.centery)) bullets[bullet2_index + 1].reset((me.rect.centerx + 30, me.rect.centery)) bullet2_index = (bullet2_index + 2) % BULLET2_NUM else: bullets = bullet1 bullets[bullet1_index].reset(me.rect.midtop) bullet1_index = (bullet1_index + 1) % BULLET1_NUM # Check if the bullet hit the enemy plane for b in bullets: if b.active: b.move() screen.blit(b.image, b.rect) enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask) if enemy_hit: b.active = False for e in enemy_hit: if e in mid_enemies or e in big_enemies: e.hit = True e.energy -= 1 if e.energy == 0: e.active = False else: e.active = False # Draw large enemy aircraft for each in big_enemies: if each.active: each.move() if each.hit: screen.blit(each.image_hit, each.rect) each.hit = False else: if switch_image: screen.blit(each.image1, each.rect) else: screen.blit(each.image2, each.rect) # Draw blood groove pygame.draw.line(screen, BLACK, \ (each.rect.left, each.rect.top - 5), \ (each.rect.right, each.rect.top - 5), \ 2) # Green when life is greater than 20%, red otherwise energy_remain = each.energy / enemy.BigEnemy.energy if energy_remain > 0.2: energy_color = GREEN else: energy_color = RED pygame.draw.line(screen, energy_color, \ (each.rect.left, each.rect.top - 5), \ (each.rect.left + each.rect.width * energy_remain, \ each.rect.top - 5), 2) # About to appear in the screen, play the sound effect if each.rect.bottom == -50: enemy3_fly_sound.play(-1) else: # ruin if not (delay % 3): if e3_destroy_index == 0: enemy3_down_sound.play() screen.blit(each.destroy_images[e3_destroy_index], each.rect) e3_destroy_index = (e3_destroy_index + 1) % 6 if e3_destroy_index == 0: enemy3_fly_sound.stop() score += 10000 each.reset() # Draw medium enemy aircraft: for each in mid_enemies: if each.active: each.move() if each.hit: screen.blit(each.image_hit, each.rect) each.hit = False else: screen.blit(each.image, each.rect) # Draw blood groove pygame.draw.line(screen, BLACK, \ (each.rect.left, each.rect.top - 5), \ (each.rect.right, each.rect.top - 5), \ 2) # Green when life is greater than 20%, red otherwise energy_remain = each.energy / enemy.MidEnemy.energy if energy_remain > 0.2: energy_color = GREEN else: energy_color = RED pygame.draw.line(screen, energy_color, \ (each.rect.left, each.rect.top - 5), \ (each.rect.left + each.rect.width * energy_remain, \ each.rect.top - 5), 2) else: # ruin if not (delay % 3): if e2_destroy_index == 0: enemy2_down_sound.play() screen.blit(each.destroy_images[e2_destroy_index], each.rect) e2_destroy_index = (e2_destroy_index + 1) % 4 if e2_destroy_index == 0: score += 6000 each.reset() # Draw small enemy aircraft: for each in small_enemies: if each.active: each.move() screen.blit(each.image, each.rect) else: # ruin if not (delay % 3): if e1_destroy_index == 0: enemy1_down_sound.play() screen.blit(each.destroy_images[e1_destroy_index], each.rect) e1_destroy_index = (e1_destroy_index + 1) % 4 if e1_destroy_index == 0: score += 1000 each.reset() # Check if our plane was hit enemies_down = pygame.sprite.spritecollide(me, enemies, False, pygame.sprite.collide_mask) if enemies_down and not me.invincible: me.active = False for e in enemies_down: e.active = False # Draw our plane if me.active: if switch_image: screen.blit(me.image1, me.rect) else: screen.blit(me.image2, me.rect) else: # ruin if not (delay % 3): if me_destroy_index == 0: me_down_sound.play() screen.blit(me.destroy_images[me_destroy_index], me.rect) me_destroy_index = (me_destroy_index + 1) % 4 if me_destroy_index == 0: life_num -= 1 me.reset() pygame.time.set_timer(INVINCIBLE_TIME, 3 * 1000) # Draw the number of full screen bombs bomb_text = bomb_font.render("× %d" % bomb_num, True, WHITE) text_rect = bomb_text.get_rect() screen.blit(bomb_image, (10, height - 10 - bomb_rect.height)) screen.blit(bomb_text, (20 + bomb_rect.width, height - 5 - text_rect.height)) # Draw life remaining if life_num: for i in range(life_num): screen.blit(life_image, \ (width - 10 - (i + 1) * life_rect.width, \ height - 10 - life_rect.height)) # Draw score score_text = score_font.render("Score : %s" % str(score), True, WHITE) screen.blit(score_text, (10, 5)) # Draw the end of the game elif life_num == 0: # Background music stop pygame.mixer.music.stop() # Stop all sound effects pygame.mixer.stop() # Stop supply pygame.time.set_timer(SUPPLY_TIME, 0) if not recorded: recorded = True # Read the highest score in history with open("record.txt", "r") as f: record_score = int(f.read()) # If the player's score is higher than the highest score in history, save if score > record_score: with open("record.txt", "w") as f: f.write(str(score)) # Draw end screen record_score_text = score_font.render("Best : %d" % record_score, True, (255, 255, 255)) screen.blit(record_score_text, (50, 50)) gameover_text1 = gameover_font.render("Your Score", True, (255, 255, 255)) gameover_text1_rect = gameover_text1.get_rect() gameover_text1_rect.left, gameover_text1_rect.top = \ (width - gameover_text1_rect.width) // 2, height // 3 screen.blit(gameover_text1, gameover_text1_rect) gameover_text2 = gameover_font.render(str(score), True, (255, 255, 255)) gameover_text2_rect = gameover_text2.get_rect() gameover_text2_rect.left, gameover_text2_rect.top = \ (width - gameover_text2_rect.width) // 2, \ gameover_text1_rect.bottom + 10 screen.blit(gameover_text2, gameover_text2_rect) again_rect.left, again_rect.top = \ (width - again_rect.width) // 2, \ gameover_text2_rect.bottom + 50 screen.blit(again_image, again_rect) gameover_rect.left, gameover_rect.top = \ (width - again_rect.width) // 2, \ again_rect.bottom + 10 screen.blit(gameover_image, gameover_rect) # Detect user mouse actions # If the user presses the left mouse button if pygame.mouse.get_pressed()[0]: # Get mouse coordinates pos = pygame.mouse.get_pos() # If the user clicks "restart" if again_rect.left < pos[0] < again_rect.right and \ again_rect.top < pos[1] < again_rect.bottom: # Call the main function to restart the game main() # If the user clicks "end game" elif gameover_rect.left < pos[0] < gameover_rect.right and \ gameover_rect.top < pos[1] < gameover_rect.bottom: # Quit the game pygame.quit() sys.exit() # Draw pause button screen.blit(paused_image, paused_rect) # Toggle picture if not (delay % 5): switch_image = not switch_image delay -= 1 if not delay: delay = 100 pygame.display.flip() clock.tick(60) if __name__ == "__main__": try: main() except SystemExit: pass except: traceback.print_exc() pygame.quit() input()
Remember: all modules should be in the same folder
Finally, running our main module is finished!
Here are the results: