import pygame import random import os # 解决图片旋转不顺畅问题 # 采用随机图片 # 得分 # 加入音效 # 加入盾牌 # 加入爆炸效果 # 加入玩家爆炸效果 # 加入几条命 # Game Over WIDTH = 480 HEIGHT = 560 FPS = 60 # 定义颜色 WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) YELLOW = (255, 255, 0) # 图片名称 enemy_imgs = ["meteorBrown_big1.png", "meteorBrown_big2.png", "meteorBrown_med1.png", "meteorBrown_med2.png", "meteorBrown_small1.png", "meteorBrown_small2.png", "meteorBrown_tiny1.png"] enemy_pics = [] # 初始化 pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Space War") clock = pygame.time.Clock() # 图片文件路径,注意别写死,应该用对应函数去取 # img_path = os.path.join(os.path.dirname(__file__), "img") # 加载图片 background = pygame.image.load("starfield.png").convert() background_rect = background.get_rect() print(background_rect[0]) player_img = pygame.image.load("playerShip1_orange.png") # 用于展示几条命的小图 player_mini_img = pygame.transform.scale(player_img, (25, 19)) # player_mini_img.set_colorkey(BLACK) bullet_img = pygame.image.load("laserRed16.png") # med_img = pygame.image.load("meteorBrown_med1.png")) # 加载敌军图片,放到一个列表 for img in enemy_imgs: enemy_pics.append(pygame.image.load(img)) # 音效文件 # snd_path = os.path.join(os.path.dirname(__file__), "snd") shoot_sound = pygame.mixer.Sound("pew.wav") # 爆炸声音 explore_snds = [] for snd in ["expl3.wav", "expl6.wav"]: explore_snds.append(pygame.mixer.Sound(snd)) # 背景音乐 # pygame.mixer.music.load('Summer.mp3') # 'tgfcoder-FrozenJam-SeamlessLoop.ogg')) # pygame.mixer.music.set_volume(0.4) # 爆炸效果 exp_file_name = ['regularExplosion00.png', 'regularExplosion01.png', 'regularExplosion02.png', 'regularExplosion03.png', 'regularExplosion04.png', 'regularExplosion05.png', 'regularExplosion06.png', 'regularExplosion07.png', 'regularExplosion08.png'] exp_imgs = [] for i in exp_file_name: img = pygame.image.load(i) exp_imgs.append(img) # Player爆炸效果 player_exp_file_name = ['sonicExplosion00.png', 'sonicExplosion01.png', 'sonicExplosion02.png', 'sonicExplosion03.png', 'sonicExplosion04.png', 'sonicExplosion05.png', 'sonicExplosion06.png', 'sonicExplosion07.png', 'sonicExplosion08.png'] player_exp_imgs = [] for i in player_exp_file_name: img = pygame.image.load(i) player_exp_imgs.append(img) # 爆炸效果Sprite class Explosion(pygame.sprite.Sprite): def __init__(self, center, imgs): pygame.sprite.Sprite.__init__(self) self.imgs = imgs self.image = self.imgs[0] self.rect = self.image.get_rect() self.rect.center = center self.frame = 0 self.last_update = pygame.time.get_ticks() self.frame_rate = 50 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(self.imgs): self.kill() else: center = self.rect.center self.image = self.imgs[self.frame] self.rect = self.image.get_rect() self.rect.center = center class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) # self.image = pygame.Surface((50, 40)) # self.image.fill(GREEN) self.image = player_img self.rect = self.image.get_rect() self.radius = 30 # pygame.draw.circle(self.image, RED, self.rect.center, self.radius) self.rect.centerx = WIDTH / 2 self.rect.bottom = HEIGHT - 10 self.speedx = 0 # 加入盾牌 self.shield = 1000 # 加入几条命 self.lives = 3 self.hidden = False self.hide_timer = pygame.time.get_ticks() def hide(self): self.hidden = True self.hide_timer = pygame.time.get_ticks() self.rect.center = (WIDTH / 2, HEIGHT + 200) # 隐藏到屏幕外 def update(self): if self.hidden and pygame.time.get_ticks() - self.hide_timer > 1000: self.hidden = False self.rect.center = (WIDTH / 2, HEIGHT - 10) self.speedx = 0 keystate = pygame.key.get_pressed() if keystate[pygame.K_LEFT]: self.speedx = -8 if keystate[pygame.K_RIGHT]: 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 def shoot(self): bullet = Bullet(self.rect.centerx, self.rect.top) all_sprites.add(bullet) bullets.add(bullet) # 播放声音 shoot_sound.play() # 敌军 class Enemy(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) # self.image_orig = med_img # 改成随机选择一张图片 self.image_orig = random.choice(enemy_pics) self.image = self.image_orig.copy() self.rect = self.image.get_rect() # self.radius = 15 # 半径改成不写死,而是图片矩形宽度的80%(再除以2是半径) self.radius = int(self.rect.width * 0.8 / 2) # pygame.draw.circle(self.image, RED, self.rect.center, self.radius) self.rect.x = random.randrange(WIDTH - self.rect.width) self.rect.y = random.randrange(-100, -40) self.speedy = random.randrange(1, 8) self.speedx = random.randrange(-3, 3) # Rotate self.rot = 0 self.rotate_speed = random.randint(-8, 8) self.last_update = pygame.time.get_ticks() def rotate(self): # 旋转方法 now = pygame.time.get_ticks() if now - self.last_update > 50: self.last_update = now self.rot = (self.rot + self.rotate_speed) % 360 # self.image = pygame.transform.rotate(self.image,self.rotate_speed) # self.image = pygame.transform.rotate(self.image_orig, self.rot) #改成下面的方式 new_image = pygame.transform.rotate(self.image_orig, self.rot) old_center = self.rect.center self.image = new_image self.rect = self.image.get_rect() self.rect.center = old_center def update(self): self.rotate() # 旋转方法 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 + 20: self.rect.x = random.randrange(WIDTH - self.rect.width) self.rect.y = random.randrange(-100, -40) self.speedy = random.randrange(1, 8) # 子弹 class Bullet(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) # self.image = pygame.Surface((10, 20)) # self.image.fill(YELLOW) self.image = bullet_img self.rect = self.image.get_rect() self.rect.bottom = y self.rect.centerx = x self.speedy = -15 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() # 找一个最匹配的字体 font_name = pygame.font.match_font('arial') # 绘制几条命 def draw_lives(surf, x, y, lives, pimg): for i in range(lives): img_rect = pimg.get_rect() img_rect.x = x + 30 * i img_rect.y = y surf.blit(pimg, img_rect) # 绘制文字 def draw_text(surf, text, size, x, y): # 得到字体,中文显示,需要明确指明字体位置 # font = pygame.font.Font("/Library/Fonts/Microsoft/Kaiti.ttf", size) font = pygame.font.Font("/System/Library/Fonts/PingFang.ttc", size) # font = pygame.font.Font(font_name, size) # 使用字体绘制,第二个参数是 是否抗锯齿的设置 text_surface = font.render(text, True, WHITE) text_rect = text_surface.get_rect() text_rect.midtop = (x, y) surf.blit(text_surface, text_rect) # 绘制生命值 BAR_LENGTH = 100 BAR_HEIGHT = 10 def draw_shield_bar(surf, x, y, pct): if pct < 0: pct = 0 fill = (pct / 1000) * BAR_LENGTH outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT) fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT) pygame.draw.rect(surf, GREEN, fill_rect) pygame.draw.rect(surf, WHITE, outline_rect, 2) # ################Game Over############### def show_go_screen(): screen.blit(background, background_rect) draw_text(screen, "Space War", 64, WIDTH / 2, HEIGHT / 4) draw_text(screen, u"左右箭头移动飞船,空格键发射子弹", 22, WIDTH / 2, HEIGHT / 2) draw_text(screen, u"按任意键开始游戏", 18, WIDTH / 2, HEIGHT * 3 / 4) pygame.display.flip() waiting = True while waiting: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() if event.type == pygame.KEYUP: waiting = False ######################################## # 播放背景音乐 # pygame.mixer.music.play(-1) game_over = True # Game loop running = True while running: if game_over: show_go_screen() game_over = False # 下面就是原来初始化游戏的代码 all_sprites = pygame.sprite.Group() enemies = pygame.sprite.Group() bullets = pygame.sprite.Group() player = Player() all_sprites.add(player) for i in range(8): m = Enemy() all_sprites.add(m) enemies.add(m) score = 0 clock.tick(FPS) # 按键事件处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: # 空格 player.shoot() # 更新状态 all_sprites.update() # 监测子弹是否集中了敌军,击中,则子弹和敌军均消失 hits = pygame.sprite.groupcollide(enemies, bullets, True, True) for hit in hits: # 补充敌军到列表 m = Enemy() all_sprites.add(m) enemies.add(m) score += (50 - hit.radius) # 随机选择一个爆炸声播放 random.choice(explore_snds).play() # 加入爆炸效果 exp = Explosion(hit.rect.center, exp_imgs) all_sprites.add(exp) # 监测敌军是否撞上Player hits = pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_circle) # if hits: for hit in hits: # running = False #game over # pass e = Enemy() all_sprites.add(e) enemies.add(e) # 每次降低一定的生命值 player.shield -= hit.radius if player.shield <= 0: # running = False # player.kill() #改成kill(),不退出游戏 # 爆炸 death_exp = Explosion(player.rect.center, player_exp_imgs) all_sprites.add(death_exp) player.hide() player.lives -= 1 player.shield = 100 # 绘制 screen.fill(BLACK) screen.blit(background, background_rect) all_sprites.draw(screen) draw_text(screen, str(score), 18, WIDTH / 2, 10) # 绘制盾牌值 draw_shield_bar(screen, 5, 5, player.shield) # 绘制几条命 draw_lives(screen, WIDTH - 100, 5, player.lives, player_mini_img) # 输出到屏幕 pygame.display.flip() # 如果生命只剩0条,则把player 杀死 if player.lives == 0: player.kill() # 退出游戏 if not player.alive() and not death_exp.alive(): # running = False game_over = True pygame.quit()
settings
unfold_less visibility play_arrow